/* Copyright Statement:
 *
 * This software/firmware and related documentation ("AutoChips Software") are
 * protected under relevant copyright laws. The information contained herein is
 * confidential and proprietary to AutoChips Inc. and/or its licensors. Without
 * the prior written permission of AutoChips inc. and/or its licensors, any
 * reproduction, modification, use or disclosure of AutoChips Software, and
 * information contained herein, in whole or in part, shall be strictly
 * prohibited.
 *
 * AutoChips Inc. (C) 2022. All rights reserved.
 *
 * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
 * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("AUTOCHIPS SOFTWARE")
 * RECEIVED FROM AUTOCHIPS AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
 * ON AN "AS-IS" BASIS ONLY. AUTOCHIPS EXPRESSLY DISCLAIMS ANY AND ALL
 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
 * NONINFRINGEMENT. NEITHER DOES AUTOCHIPS PROVIDE ANY WARRANTY WHATSOEVER WITH
 * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
 * INCORPORATED IN, OR SUPPLIED WITH THE AUTOCHIPS SOFTWARE, AND RECEIVER AGREES
 * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
 * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
 * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN AUTOCHIPS
 * SOFTWARE. AUTOCHIPS SHALL ALSO NOT BE RESPONSIBLE FOR ANY AUTOCHIPS SOFTWARE
 * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
 * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND AUTOCHIPS'S
 * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE AUTOCHIPS SOFTWARE
 * RELEASED HEREUNDER WILL BE, AT AUTOCHIPS'S OPTION, TO REVISE OR REPLACE THE
 * AUTOCHIPS SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
 * CHARGE PAID BY RECEIVER TO AUTOCHIPS FOR SUCH AUTOCHIPS SOFTWARE AT ISSUE.
 */

#ifndef _AC780X_UART_REG_H
#define _AC780X_UART_REG_H
/*!
 * @file ac780x_uart_reg.h
 *
 * @brief Uart access register inline function definition.
 *
 */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/* ===========================================  Includes  =========================================== */
#include "ac780x_uart.h"

/* ============================================  Define  ============================================ */
#define     UART_BUSCLK        APB_BUS_FREQ

/* ===========================================  Typedef  ============================================ */

/* ==========================================  Variables  =========================================== */

/* ====================================  Functions declaration  ===================================== */

/* ======================================  Functions define  ======================================== */
/*!
* @brief Set UART Divisor Latch
*
* @param[in] UARTx: UART type pointer, x value can be 0 to 1
*                         - UART0
*                         - UART1
* @param[in] div: UART divisor data
* @return  none
*/
__STATIC_INLINE void UART_SetDivisor(UART_Type *UARTx, float div)
{
    uint32_t intDiv = (uint64_t)div;
    uint32_t fracDiv = (uint32_t)((div - intDiv) * 32);

    UARTx->DIV_L = intDiv & 0xFF;
    UARTx->DIV_H = (intDiv >> 8UL) & 0xFF;

    UARTx->DIV_FRAC = fracDiv;
}

/*!
* @brief Set UART Sample counter
*
* @param[in] UARTx: UART type pointer, x value can be 0 to 1
*                         - UART0
*                         - UART1
* @param[in] sampleCounter: UART Sample counter, value can be 0 to 3
*                         - UART_SMP_CNT0: baud_rate = APB CLOCK/16/{DLH, DLL}
*                         - UART_SMP_CNT1: baud_rate = APB CLOCK/8/{DLH, DLL}
*                         - UART_SMP_CNT2: baud_rate = APB CLOCK/4/{DLH, DLL}
*                         - UART_SMP_CNT3: baud_rate = APB CLOCK/16/{DLM, DLL}
* @return none
*/
__STATIC_INLINE void UART_SetSampleCounter(UART_Type *UARTx, UART_SampleCntType sampleCnt)
{
    UARTx->SMP_CNT = (sampleCnt & UART_SMP_CNT_SMP_CNT_Msk);
}

/*!
* @brief Set UART Guart Time and set Guard enable
*
* @param[in] UARTx: UART type pointer, x value can be 0 to 1
*                         - UART0
*                         - UART1
* @param[in] guardTime: UART GuardTime and Guard enable
*                       bit[4]:  1: enable  0: disable
*                       bit[3:0]: GuardTime: 0 to 15
* @return none
*/
__STATIC_INLINE void UART_SetGuard(UART_Type *UARTx, uint8_t guardTime)
{
    if (guardTime & UART_GUARD_GUARD_EN_Msk)
    {
        UARTx->GUARD |= UART_GUARD_GUARD_EN_Msk;
        MODIFY_REG32(UARTx->GUARD, UART_GUARD_GUARD_CNT_Msk, UART_GUARD_GUARD_CNT_Pos, guardTime);
    }
    else
    {
        UARTx->GUARD &= ~UART_GUARD_GUARD_EN_Msk;
        UARTx->GUARD &= ~UART_GUARD_GUARD_CNT_Msk;
    }
}

/*!
* @brief Set UART Data Bits Length
*
* @param[in] UARTx: UART type pointer, x value can be 0 to 1
*                         - UART0
*                         - UART1
* @param[in] bits: UART Data Bits length, value can be 5 to 9
*                         - UART_WORD_LEN_5BIT
*                         - UART_WORD_LEN_6BIT
*                         - UART_WORD_LEN_7BIT
*                         - UART_WORD_LEN_8BIT
*                         - UART_WORD_LEN_9BIT
* @return none
*/
__STATIC_INLINE void UART_SetDataBits(UART_Type *UARTx, UART_WordLenType bits)
{
    if ((UART_WORD_LEN_5BIT <= bits) && (bits <= UART_WORD_LEN_8BIT))
    {
        MODIFY_REG32(UARTx->LCR0, UART_LCR0_WLS1_WLS0_Msk, UART_LCR0_WLS1_WLS0_Pos, (bits - 5));  /* set WLS1_WLS0 */
        UARTx->LCR1 &= ~UART_LCR1_WLS2_Msk;      /* set WLS2 */
    }
    else if (bits == UART_WORD_LEN_9BIT)
    {
        UARTx->LCR0 &= ~UART_LCR0_WLS1_WLS0_Msk;       /* set WLS1_WLS0 */
        UARTx->LCR1 |= UART_LCR1_WLS2_Msk;             /* set WLS2 */
    }
    else
    {
        /* do nothing */
    }
}

/*!
* @brief Set UART stop bit
*
* @param[in] UARTx: UART type pointer, x value can be 0 to 1
*                         - UART0
*                         - UART1
* @param[in] stopBit: UART StopBit. value can be
*                         - UART_STOP_2BIT: 2 stop bit
*                         - UART_STOP_1BIT: 1 stop bit
* @return none
*/
__STATIC_INLINE void UART_SetStopBit(UART_Type *UARTx, UART_StopBitType stopBit)
{
    MODIFY_REG32(UARTx->LCR0, UART_LCR0_STB_Msk, UART_LCR0_STB_Pos, stopBit);
}

/*!
* @brief Set UART Inverse the tx output
*
* @param[in] UARTx: UART type pointer, x value can be 0 to 1
*                         - UART0
*                         - UART1
* @param[in] InvTx: UART invTx.
*                         -ENABLE: inverse tx output
*                         -DISABLE: don't inverse tx output
* @return none
*/
__STATIC_INLINE void UART_SetInvTx(UART_Type *UARTx, ACTION_Type state)
{
    MODIFY_REG32(UARTx->LCR1, UART_LCR1_INVTX_Msk, UART_LCR1_INVTX_Pos, state);
}

/*!
* @brief Set UART Inverse the rx input
*
* @param[in] UARTx: UART type pointer, x value can be 0 to 1
*                         - UART0
*                         - UART1
* @param[in] invRx: UART invRx.
*                         -ENABLE: inverse rx input
*                         -DISABLE: don't inverse rx input
* @return none
*/
__STATIC_INLINE void UART_SetInvRx(UART_Type *UARTx, ACTION_Type state)
{
    MODIFY_REG32(UARTx->LCR1, UART_LCR1_INVRX_Msk, UART_LCR1_INVRX_Pos, state);
}

/*!
* @brief Set UART loop mode
*
* @param[in] UARTx: UART type pointer, x value can be 0 to 1
*                         - UART0
*                         - UART1
* @param[in] Loop: UART loop
*                         -ENABLE: loop mode
*                         -DISABLE: normal mode
* @return none
*/
__STATIC_INLINE void UART_SetLoop(UART_Type *UARTx, ACTION_Type state)
{
    MODIFY_REG32(UARTx->LCR1, UART_LCR1_LOOP_Msk, UART_LCR1_LOOP_Pos, state);
}

/*!
* @brief Set UART 2byte fifo enable
*
* @param[in] UARTx: UART type pointer, x value can be 0 to 1
*                         - UART0
*                         - UART1
* @param[in] fifoByteEn: UART FIFO2ByteEn.
*                         -ENABLE: enable both tx&rx fifo
*                         -DISABLE: disable both tx&rx fifo
* @return none
*/
__STATIC_INLINE void UART_Set2ByteFIFO(UART_Type *UARTx, ACTION_Type state)
{
    MODIFY_REG32(UARTx->FCR, UART_FCR_FIFOE_Msk, UART_FCR_FIFOE_Pos, state);
}

/*!
* @brief Set UART interrupt enable register, but doesnot set ETXE, ETC bit
*
* @param[in] UARTx: UART type pointer, x value can be 0 to 1
*                         - UART0
*                         - UART1
* @param[in] interruptEn: UART interrupt enable
* @return none
*/
__STATIC_INLINE void UART_SetInterruptEn(UART_Type *UARTx, uint16_t interruptEn)
{
    MODIFY_REG32(UARTx->IER, 0x1F9, 0, (interruptEn & 0x1F9));  /* set interrupt, but doesnot set ETXE, ETC bit   */
}

/*!
* @brief Set UART sleep enable
*
* @param[in] UARTx: UART type pointer, x value can be 0 to 1
*                         - UART0
*                         - UART1
* @param[in] sleepEn: UART sleepEn.
*                    -ENABLE: Activate hardware flow control according to software initial settings
*                             when the chip enters the sleep mode. Release the hardware flow
*                             when the chip wakes up.
*                    -DISABLE: Does not deal with sleep mode indication signal
* @return none
*/
__STATIC_INLINE void UART_SetSleepEn(UART_Type *UARTx, ACTION_Type state)
{
    MODIFY_REG32(UARTx->SLEEP_EN, UART_SLEEP_EN_SLEEP_EN_Msk, UART_SLEEP_EN_SLEEP_EN_Pos, state);
}

/*!
* @brief Set UART Idle line detect function enable.
*
* @param[in] UARTx: UART type pointer, x value can be 0 to 1
*                         - UART0
*                         - UART1
* @param[in] state: UART Idle line detect function enable/disable
*                         - ENABLE
*                         - DISABLE
* @return none
*/
__STATIC_INLINE void UART_SetIdleFuncEn(UART_Type *UARTx, ACTION_Type state)
{
    MODIFY_REG32(UARTx->IDLE, UART_IDLE_ILEN_Msk, UART_IDLE_ILEN_Pos, state);
}

/*!
* @brief Set UART idle interrupt enable.must set MULCOMEN=1
*
* @param[in] UARTx: UART type pointer, x value can be 0 to 1
*                         - UART0
*                         - UART1
* @param[in] state: idle interrupt enable/disable
*                         - ENABLE
*                         - DISABLE
* @return none
*/
__STATIC_INLINE void UART_SetIdleInterrupt(UART_Type *UARTx, ACTION_Type state)
{
    MODIFY_REG32(UARTx->IDLE, UART_IDLE_IDLEIE_Msk, UART_IDLE_IDLEIE_Pos, state);
}

/*!
* @brief Set UART Rx data is ready
*
* @param[in] UARTx: UART type pointer, x can be 0 to 2
*                         - UART0
*                         - UART1
* @return mul com idle line detect
*/
#define UART_IsIdle(UARTx)    ((uint32_t)((UARTx->LSR1 & UART_LSR1_IDLE_Msk) >> UART_LSR1_IDLE_Pos))

/*!
* @brief Check if rx buffer get new data
*
* @param[in] UARTx: UART type pointer, x can be 0 to 2
*                         - UART0
*                         - UART1
* @return 0:no date in buff or fifo,  1:RX buffer becoming full or RX FIFO not empty
*/
#define UART_RxIsDataReady(UARTx)    ((uint32_t)(((UARTx)->LSR0 & UART_LSR0_DR_Msk) >> UART_LSR0_DR_Pos))

/*!
* @brief Set UART Tx buffer is empty
*
* @param[in] UARTx: UART type pointer, x can be 0 to 2
*                         - UART0
*                         - UART1
* @return 0:TX holding register or FIFO is not empty   1:TX holding register or FIFO is empty
*/
#define UART_TxIsEmpty(UARTx)    ((uint32_t)(((UARTx)->LSR0 & UART_LSR0_THRE_Msk) >> UART_LSR0_THRE_Pos))

/*!
* @brief Set UART Tx buffer is empty
*
* @param[in] UARTx: UART type pointer, x can be 0 to 2
*                         - UART0
*                         - UART1
* @return Tx is full or not:
*                         0:TX holding register or FIFO is not empty
*                         1:TX holding register or FIFO is empty
*/
#define UART_TxIsFull(UARTx)    ((uint32_t)(((UARTx)->LSR0 & UART_LSR0_TXDF_Msk) >> UART_LSR0_TXDF_Pos))

/*!
* @brief Get UART Tx Finished or not
*
* @param[in] UARTx: UART type pointer, x can be 0 to 2
*                         - UART0
*                         - UART1
* @return Tx tranfer has finished nor not
*                         0:transmitter has not finished
*                         1:transmitter has finished
*/
#define UART_TxIsFinished(UARTx)    ((uint32_t)(((UARTx)->LSR0 & UART_LSR0_TC_Msk) >> UART_LSR0_TC_Pos))

/*!
* @brief Enable UART TX
*
* @param[in] UARTx: UART type pointer, x can be 0 to 2
*                         - UART0
*                         - UART1
* @param[in] Enable/Disable UART tx
*                         - ENABLE
*                         - DISABLE
* @return none
*/
__STATIC_INLINE void UART_EnableTX(UART_Type *UARTx, ACTION_Type state)
{
    MODIFY_REG32(UARTx->LCR1, UART_LCR1_TXEN_Msk, UART_LCR1_TXEN_Pos, state);
}

/*!
* @brief Enable UART RX
*
* @param[in] UARTx: UART type pointer, x can be 0 to 2
*                         - UART0
*                         - UART1
* @param[in] Enable/Disable UART rx
*                         - ENABLE
*                         - DISABLE
* @return none
*/
__STATIC_INLINE void UART_EnableRX(UART_Type *UARTx, ACTION_Type state)
{
    MODIFY_REG32(UARTx->LCR1, UART_LCR1_RXEN_Msk, UART_LCR1_RXEN_Pos, state);
}

/*!
* @brief Enable rx buffer not empty interrupt
*
* @param[in] UARTx: UART type pointer, x can be 0 to 2
*                         - UART0
*                         - UART1
* @param[in] Enable/Disable Rx not empty interrupt
*                         - ENABLE
*                         - DISABLE
* @return none
*/
__STATIC_INLINE void UART_SetRXNEInterrupt(UART_Type *UARTx, ACTION_Type state)
{
    MODIFY_REG32(UARTx->IER, UART_IER_ERXNE_Msk, UART_IER_ERXNE_Pos, state);
}

/*!
* @brief Enable tx holding register is empty interrupt
*
* @param[in] UARTx: UART type pointer, x can be 0 to 2
*                         - UART0
*                         - UART1
* @param[in] Enable/Disable Tx empty interrupt
*                         - ENABLE
*                         - DISABLE
*/
__STATIC_INLINE void UART_SetTXEInterrupt(UART_Type *UARTx, ACTION_Type state)
{
    MODIFY_REG32(UARTx->IER, UART_IER_ETXE_Msk, UART_IER_ETXE_Pos, state);
}

/*!
* @brief Check UART Data Bits is 9 bits or not
*
* @param[in] UARTx: UART type pointer, x value can be 0 to 1
*                         - UART0
*                         - UART1
* @return 1: 9 bits
*         0: 5~8 bits
*/
__STATIC_INLINE uint8_t UART_IsNineDataBits(UART_Type *UARTx)
{
    return (uint8_t)(((UARTx->LCR1 & UART_LCR1_WLS2_Msk) >> UART_LCR1_WLS2_Pos));
}

/*!
* @brief Set UART LIN control.
*
* @param[in] UARTx: UART type pointer
* @param[in] linCtrl: UART linCtrl, the corresponding control bit means
*                   - bit7: LIN Mode enable
*                   - bit6: LIN break character detect interrupt enable
*                   - bit5: LIN break detect threshold 0:10bits 1:11bits
*                   - bit3: LIN auto sync baudrate enable
*                   - bit2: LIN sync byte error interrupt enable
*                   - bit1: LIN wake up interrupt enable
*                   - bit0: LIN sleep mode enable
* @return none
*/
__STATIC_INLINE void UART_SetLIN(UART_Type *UARTx, uint8_t linCtrl)
{
    MODIFY_REG32(UARTx->LINCR, 0xFFU, 0U, linCtrl);
}

/*!
 * @brief Set LIN sleep enable.
 *
 * @param[in] UARTx: UART type pointer
 * @param[in] enable: LIN sleep mode enable
 * @return none
 */
__STATIC_INLINE void UART_SetLINSleep(UART_Type *UARTx, ACTION_Type enable)
{
    MODIFY_REG32(UARTx->LINCR, UART_LINCR_LINSLP_Msk, UART_LINCR_LINSLP_Pos, enable);
}

/*!
 * @brief Get LIN sleep enable.
 *
 * @param[in] UARTx: UART type pointer
 * @return LIN sleep mode state
 */
__STATIC_INLINE uint8_t UART_GetLINSleepState(UART_Type *UARTx)
{
    return (UARTx->LINCR & UART_LINCR_LINSLP_Msk) >> UART_LINCR_LINSLP_Pos;
}

/*!
 * @brief Set LIN wakeup interrupt enable.
 *
 * @param[in] UARTx: UART type pointer
 * @param[in] enable: LIN wakeup enable
 * @return none
 */
__STATIC_INLINE void UART_SetLINWakeInt(UART_Type *UARTx, ACTION_Type enable)
{
    MODIFY_REG32(UARTx->LINCR, UART_LINCR_LINWAKIE_Msk, UART_LINCR_LINWAKIE_Pos, enable);
}

/*!
* @brief Send LIN break.
*
* @param[in] UARTx: UART type pointer
* @return none
*/
__STATIC_INLINE void UART_SendLINBreak(UART_Type *UARTx)
{
    UARTx->LINCR |= UART_LINCR_SDBRK_Msk;
}

/*!
 * @brief Set LIN break threshold length for slave detect.
 *
 * @param[in] UARTx: UART type pointer
 * @param[in] length:LIN break threshold length
 * @return none
 */
__STATIC_INLINE void UART_SetLINBreakThreshold(UART_Type *UARTx, uint8_t length)
{
    MODIFY_REG32(UARTx->LINCR, UART_LINCR_LBRKDL_Msk, UART_LINCR_LBRKDL_Pos, length);
}

/*!
* @brief Lin break length for master
*
* @param[in] UARTx: UART type pointer
* @param[in] length:LIN break length
* @return none
*/
__STATIC_INLINE void UART_SetLINBreakLength(UART_Type *UARTx, uint8_t length)
{
    UARTx->BRKLGH = (length & UART_BRKLGH_BRKLGH_Msk);
}

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* _AC780X_UART_REG_H */

/* =============================================  EOF  ============================================== */
