/**
 * @file hv_pm51_driver_Reg.c
 * @brief PM51 register read and write API.
 * @details Never use "xdata" while read/write registers!
 * @author HiView SoC Software Team
 * @version 0.0.1
 * @date 20230301
 * @copyright Copyright(c),2023-3, Hiview Software. All rights reserved.
 * @par History: 
 * <table>
 * <tr><th>author                     <th>date           <th>description
 * <tr><td>HiView SoC Software Team   <td>20230301       <td>Create and first Version.
 * </table>
**/

#include "hv_pm51_Base.h"
#include "hv_pm51_Reg.h"
#include "hv_pm51_Assert.h"
#include "hv_pm51_driver_Reg.h"
#include "hv_pm51_driver_UART.h"
#include "hv_pm51_driver_Interrupt.h"

void Hv_PM51_Reg_Init(void)
{
    APB_AddrReg_Low = 0;
    APB_AddrReg_High = 0;
}

ULONG32 Hv_PM51_Reg_Read(ULONG32 ulRegAddr) reentrant
{
    ULONG32 ulRData;

    HV_PM51_ASSERT(ulRegAddr != 0);

    APB_AddrReg_Low    = (ulRegAddr >> 16) & 0xFF;
    APB_AddrReg_High   = (ulRegAddr >> 24) & 0xFF;

    ulRData = Read_XDATARegDWORD(ulRegAddr);
    ulRData = (((ulRData >> 0) & 0xFF) << 24) |
            (((ulRData >> 8) & 0xFF) << 16) |
            (((ulRData >> 16) & 0xFF) << 8) |
            (((ulRData >> 24) & 0xFF) << 0);

    APB_AddrReg_Low    = 0x0;
    APB_AddrReg_High   = 0x0;
    
    return ulRData;
}

void Hv_PM51_Reg_Write(ULONG32 ulRegAddr, ULONG32 ulVal) reentrant
{
    HV_PM51_ASSERT(ulRegAddr != 0);

    APB_AddrReg_Low    = (ulRegAddr >> 16) & 0xFF;
    APB_AddrReg_High   = (ulRegAddr >> 24) & 0xFF;

    ulVal = (((ulVal >> 0) & 0xFF) << 24) |
            (((ulVal >> 8) & 0xFF) << 16) |
            (((ulVal >> 16) & 0xFF) << 8) |
            (((ulVal >> 24) & 0xFF) << 0);
    Write_XDATARegDWORD(ulRegAddr, ulVal);
    
    APB_AddrReg_Low    = 0x0;
    APB_AddrReg_High   = 0x0;
    
    return;
}

ULONG32 Hv_PM51_Reg_ReadArray(ULONG32 ulRegAddr)
{
    ULONG32 ulRData;

    HV_PM51_ASSERT(ulRegAddr != 0);   

    APB_AddrReg_Low    = (ulRegAddr >> 16) & 0xFF;
    APB_AddrReg_High   = (ulRegAddr >> 24) & 0xFF;

    ulRData = Read_XDATARegDWORD(ulRegAddr);

    APB_AddrReg_Low    = 0x0;
    APB_AddrReg_High   = 0x0;
    
    return ulRData;
}

void Hv_PM51_Reg_WriteArray(ULONG32 ulRegAddr, ULONG32 ulVal)
{
    HV_PM51_ASSERT(ulRegAddr != 0); 
    
    APB_AddrReg_Low    = (ulRegAddr >> 16) & 0xFF;
    APB_AddrReg_High   = (ulRegAddr >> 24) & 0xFF;

    Write_XDATARegDWORD(ulRegAddr, ulVal);

    APB_AddrReg_Low    = 0x0;
    APB_AddrReg_High   = 0x0;

    return;
}

ULONG32 Hv_PM51_Reg_ReadMask(ULONG32 ulRegAddr, UCHAR8 ucBitStartLow, UCHAR8 ucBitEndHigh)
{
    ULONG32 ulRData;
    ULONG32 ulMask = 0xFFFFFFFF;

    HV_PM51_ASSERT(ulRegAddr != 0); 
    
    if((ucBitStartLow > ucBitEndHigh) ||
        (ucBitStartLow > 31) ||
        (ucBitEndHigh > 31))
    {
        return 0xFFFFFFFF;
    }

    ulMask = ulMask << (31 - ucBitEndHigh);
    ulMask = ulMask >> (31 - ucBitEndHigh);
    ulMask = ulMask >> ucBitStartLow;
    ulMask = ulMask << ucBitStartLow;

    ulRData = Hv_PM51_Reg_Read(ulRegAddr);
    ulRData &= ulMask;
    ulRData = ulRData >> ucBitStartLow;
    
    return ulRData;
}

void Hv_PM51_Reg_WriteMask(ULONG32 ulRegAddr, UCHAR8 ucBitStartLow, UCHAR8 ucBitEndHigh, ULONG32 ulVal)
{
    ULONG32 ulRData;
    ULONG32 ulMask = 0xFFFFFFFF;

    HV_PM51_ASSERT(ulRegAddr != 0); 
    
    if((ucBitStartLow > ucBitEndHigh) ||
        (ucBitStartLow > 31) ||
        (ucBitEndHigh > 31))
    {
        return ;
    }
    ulMask = ulMask << (31 - ucBitEndHigh);
    ulMask = ulMask >> (31 - ucBitEndHigh);
    ulMask = ulMask >> ucBitStartLow;
    ulVal &= ulMask;

    ulVal = ulVal << ucBitStartLow;
    ulMask = ulMask << ucBitStartLow;
    ulMask = ~ulMask;

    ulRData = Hv_PM51_Reg_Read(ulRegAddr);
    
    ulRData &= ulMask;
    ulRData |= ulVal;
    
    Hv_PM51_Reg_Write(ulRegAddr, ulRData);
    
    return;
}

UCHAR8 Hv_PM51_Reg_ReadByte(ULONG32 ulRegAddr) reentrant
{
    UCHAR8 ucRData;
    
    APB_AddrReg_Low    = (ulRegAddr >> 16) & 0xFF;
    APB_AddrReg_High   = (ulRegAddr >> 24) & 0xFF;
    
    ucRData = Read_XDATAReg(ulRegAddr);
    
    APB_AddrReg_Low    = 0x0;
    APB_AddrReg_High   = 0x0;
    
    return ucRData;
}

void Hv_PM51_Reg_WriteByte(ULONG32 ulRegAddr, UCHAR8 ucVal) reentrant
{
    APB_AddrReg_Low    = (ulRegAddr >> 16) & 0xFF;
    APB_AddrReg_High   = (ulRegAddr >> 24) & 0xFF;
    
    Write_XDATAReg(ulRegAddr, ucVal);
    
    APB_AddrReg_Low    = 0x0;
    APB_AddrReg_High   = 0x0;
    
    return ;
}

