/**
 * @file hv_pm51_driver_GPIO.c
 * @brief HT7135 GPIO Driver.
 * @details 
 * @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 "HS_PAGE_HT7315_8051_reg.h"
#include "hv_pm51_Reg.h"
#include "hv_pm51_Setting.h"
#include "hv_pm51_driver_Reg.h"
#include "hv_pm51_driver_GPIO.h"
#include "hv_pm51_driver_UART.h"
#include "hv_pm51_driver_Interrupt.h"

#if GPIO_ENABLE

static xdata UCHAR8 ucGpioInitDone = HV_FALSE;

void Hv_PM51_Gpio_Init(void)
{
    if(!ucGpioInitDone)
    {
        USHORT16 usOffset;
        /* Disable all GPIO interrupt. */
        Hv_PM51_Gpio_DisableInt(GPIO_ALL);
        /* Clear all GPIO interrupt state. */
        Hv_PM51_Gpio_ClearIntState(GPIO_ALL);    
        /* GPIO filter,deglitch.magic num. */
        for(usOffset = 0; usOffset < GPIO_ALL; usOffset++)
        {
            Hv_PM51_Reg_Write(HS_Standby__standby_peri_reg__reg_gp0_filter_num_ADDR + usOffset * 4,
                          IO_DEGLITCH_NUM);
        }
        Hv_PM51_Reg_Write(HS_Standby__standby_peri_reg__reg_gp6_filter_num_ADDR, 0x20000);
        Hv_PM51_Reg_Write(HS_Standby__standby_peri_reg__reg_gp7_filter_num_ADDR, 0x20000);
        ucGpioInitDone = HV_TRUE;
    }
    
    return;
}

void Hv_PM51_Gpio_InitPin(GpioEn enGpioSel)
{
    if(enGpioSel >= GPIO_ALL)
    {
        return;
    }

    /* for gpio output */
    Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_other_pin_sel_ADDR,
                      HS_Standby__SH08_TOP_STBY__reg_other_pin_sel_BITSTART,
                      HS_Standby__SH08_TOP_STBY__reg_other_pin_sel_BITEND, 0x0);
    /* for gpio input */
    Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gpio_i_in_sel_ADDR,
                      HS_Standby__SH08_TOP_STBY__reg_stby_gpio_i_in_sel_BITSTART,
                      HS_Standby__SH08_TOP_STBY__reg_stby_gpio_i_in_sel_BITEND, 0x0);

}

void Hv_PM51_Gpio_ClearIntState(GpioEn enGpioSel)
{
    xULONG32 ulTempData = 0;
    
    if(enGpioSel < GPIO_ALL)
    {
        ulTempData = Hv_PM51_Reg_Read(HS_Standby__standby_mcu_reg__reg_event_int_clr_ADDR);
        /* set clear bit */
        ulTempData = ulTempData | (BIT_0 << enGpioSel);
        Hv_PM51_Reg_Write(HS_Standby__standby_mcu_reg__reg_event_int_clr_ADDR, ulTempData);
    }
    else if(enGpioSel == GPIO_ALL)
    {
        /* set clear bit */
        ulTempData = 0xff;
        Hv_PM51_Reg_Write(HS_Standby__standby_mcu_reg__reg_event_int_clr_ADDR, ulTempData);
    }
    else
    {
        /* do nothing */
    }

    return;
}

void Hv_PM51_Gpio_EnableInt(GpioEn enGpioSel, GpioIntEn enGpioInt)
{
    if(enGpioSel < GPIO_ALL)
    {
        if(enGpioInt >= GPIO_INTR_TPYE_NUM)
        {
            return;
        }
        switch (enGpioInt)
        {
            case GPIO_INTR_LEVEL_P:
                Hv_PM51_Reg_WriteMask(HS_Standby__standby_mcu_reg__reg_event_int_level_p_ADDR,
                                      enGpioSel, enGpioSel, 0x1);
                break;
            case GPIO_INTR_LEVEL_N:
                Hv_PM51_Reg_WriteMask(HS_Standby__standby_mcu_reg__reg_event_int_level_n_ADDR,
                                  16 + enGpioSel, 16 + enGpioSel, 0x1);
                break;
            case GPIO_INTR_EDGE_P:
                Hv_PM51_Reg_WriteMask(HS_Standby__standby_mcu_reg__reg_event_int_edge_p_ADDR,
                                enGpioSel, enGpioSel, 0x1);
                break;
            case GPIO_INTR_EDGE_N:
                Hv_PM51_Reg_WriteMask(HS_Standby__standby_mcu_reg__reg_event_int_edge_n_ADDR,
                                16 + enGpioSel, 16 + enGpioSel, 0x1);
                break;
            default:
                break;
        }
        /* clear event interrupt */
        Hv_PM51_Reg_WriteMask(HS_Standby__standby_mcu_reg__reg_event_int_clr_ADDR,
                HS_Standby__standby_mcu_reg__reg_event_int_clr_BITSTART, 
                HS_Standby__standby_mcu_reg__reg_event_int_clr_BITSTART + GPIO7, 0xFF);
        
        Hv_PM51_Reg_WriteMask(HS_Standby__standby_mcu_reg__reg_event_int_en_ADDR, 
                          16 + enGpioSel, 16 + enGpioSel, 0x1);               
    }
    else if(enGpioSel == GPIO_ALL)
    {
        if(enGpioInt >= GPIO_INTR_TPYE_NUM)
        {
            return;
        }    
        switch (enGpioInt)
        {
            case GPIO_INTR_LEVEL_P:
                Hv_PM51_Reg_WriteMask(HS_Standby__standby_mcu_reg__reg_event_int_level_p_ADDR,
                                      GPIO0, GPIO7, 0xFF);
                break;
            case GPIO_INTR_LEVEL_N:
                Hv_PM51_Reg_WriteMask(HS_Standby__standby_mcu_reg__reg_event_int_level_n_ADDR,
                                      16 + GPIO0, 16 + GPIO7, 0xFF);
                break;
            case GPIO_INTR_EDGE_P:
                Hv_PM51_Reg_WriteMask(HS_Standby__standby_mcu_reg__reg_event_int_edge_p_ADDR,
                                      GPIO0, GPIO7, 0xFF);
                break;
            case GPIO_INTR_EDGE_N:
                Hv_PM51_Reg_WriteMask(HS_Standby__standby_mcu_reg__reg_event_int_edge_n_ADDR,
                                      16 + GPIO0, 16 + GPIO7, 0xFF);
                break;
            default:
                break;
        }

        /* clear event interrupt */
        Hv_PM51_Reg_WriteMask(HS_Standby__standby_mcu_reg__reg_event_int_clr_ADDR,
                HS_Standby__standby_mcu_reg__reg_event_int_clr_BITSTART, 
                HS_Standby__standby_mcu_reg__reg_event_int_clr_BITSTART + GPIO7, 0xFF);
        
        Hv_PM51_Reg_WriteMask(HS_Standby__standby_mcu_reg__reg_event_int_en_ADDR, 
                          16 + GPIO0, 16 + GPIO7, 0xFF);    
    }
    else
    {
        return;
    }
}

void Hv_PM51_Gpio_DisableInt(GpioEn enGpioSel)
{
    if(enGpioSel < GPIO_ALL)
    {
        Hv_PM51_Reg_WriteMask(HS_Standby__standby_mcu_reg__reg_event_int_en_ADDR,
                          16 + enGpioSel, 16 + enGpioSel, 0x0);
        Hv_PM51_Reg_WriteMask(HS_Standby__standby_mcu_reg__reg_event_int_level_p_ADDR,
                          enGpioSel, enGpioSel, 0x0);
        Hv_PM51_Reg_WriteMask(HS_Standby__standby_mcu_reg__reg_event_int_level_p_ADDR,
                          16 + enGpioSel, 16 + enGpioSel, 0x0);
        Hv_PM51_Reg_WriteMask(HS_Standby__standby_mcu_reg__reg_event_int_edge_p_ADDR,
                          enGpioSel, enGpioSel, 0x0);
        Hv_PM51_Reg_WriteMask(HS_Standby__standby_mcu_reg__reg_event_int_edge_p_ADDR,
                          16 + enGpioSel, 16 + enGpioSel, 0x0);
    }
    else if(enGpioSel == GPIO_ALL)
    {
        Hv_PM51_Reg_WriteMask(HS_Standby__standby_mcu_reg__reg_event_int_en_ADDR,
                          16 + GPIO0, 16 + GPIO7, 0x0);
        Hv_PM51_Reg_WriteMask(HS_Standby__standby_mcu_reg__reg_event_int_level_p_ADDR,
                          GPIO0, GPIO7, 0x0);
        Hv_PM51_Reg_WriteMask(HS_Standby__standby_mcu_reg__reg_event_int_level_p_ADDR,
                          16 + GPIO0, 16 + GPIO7, 0x0);
        Hv_PM51_Reg_WriteMask(HS_Standby__standby_mcu_reg__reg_event_int_edge_p_ADDR,
                          GPIO0, GPIO7, 0x0);
        Hv_PM51_Reg_WriteMask(HS_Standby__standby_mcu_reg__reg_event_int_edge_p_ADDR,
                          16 + GPIO0, 16 + GPIO7, 0x0);
    }
    else
    {
        return;
    }
}

void Hv_PM51_Gpio_SetIODirection(GpioEn enGpioSel, GpioDirEn enGpioDir)
{
    if(enGpioSel >= GPIO_ALL)
    {
        return;
    }

    switch(enGpioSel)
    {
        case GPIO0:
        {
            if(enGpioDir == GPIO_OUTPUT)
            {
                /* clear IE */
                Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp0_io_ctrl_ADDR,
                                  22, 22, 0x0);
                /* set OE */
                Hv_PM51_Reg_WriteMask(HS_Standby__standby_peri_reg__reg_gpio_oe_ADDR,
                                  8, 8, 0x1);
            }
            else
            {
                /* set IE */
                Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp0_io_ctrl_ADDR,
                                  22, 22, 0x1);
                /* clear OE */
                Hv_PM51_Reg_WriteMask(HS_Standby__standby_peri_reg__reg_gpio_oe_ADDR,
                                  8, 8, 0x0);
            }
            break;
        }
        case GPIO1:
        {
            if(enGpioDir == GPIO_OUTPUT)
            {
                /* clear IE */
                Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp1_io_ctrl_ADDR,
                                  28, 28, 0x0);
                /* set OE */
                Hv_PM51_Reg_WriteMask(HS_Standby__standby_peri_reg__reg_gpio_oe_ADDR,
                                  9, 9, 0x1);
            }
            else
            {
                /* set IE */
                Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp1_io_ctrl_ADDR,
                                  28, 28, 0x1);
                /* clear OE */
                Hv_PM51_Reg_WriteMask(HS_Standby__standby_peri_reg__reg_gpio_oe_ADDR,
                                  9, 9, 0x0);
            }
            break;
        }
        case GPIO2:
        {
            if(enGpioDir == GPIO_OUTPUT)
            {
                /* clear IE */
                Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp2_io_ctrl_ADDR,
                                  4, 4, 0x0);
                /* set OE */
                Hv_PM51_Reg_WriteMask(HS_Standby__standby_peri_reg__reg_gpio_oe_ADDR,
                                  10, 10, 0x1);
            }
            else
            {
                /* set IE */
                Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp2_io_ctrl_ADDR,
                                  4, 4, 0x1);
                /* clear OE */
                Hv_PM51_Reg_WriteMask(HS_Standby__standby_peri_reg__reg_gpio_oe_ADDR,
                                  10, 10, 0x0);
            }
            break;
        }
        case GPIO3:
        {
            if(enGpioDir == GPIO_OUTPUT)
            {
                /* clear IE */
                Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp3_io_ctrl_ADDR,
                                  9, 9, 0x0);
                /* set OE */
                Hv_PM51_Reg_WriteMask(HS_Standby__standby_peri_reg__reg_gpio_oe_ADDR,
                                  11, 11, 0x1);
            }
            else
            {
                /* set IE */
                Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp3_io_ctrl_ADDR,
                                  9, 9, 0x1);
                /* clear OE */
                Hv_PM51_Reg_WriteMask(HS_Standby__standby_peri_reg__reg_gpio_oe_ADDR,
                                  11, 11, 0x0);
            }
            break;
        }
        case GPIO4:
        {
            if(enGpioDir == GPIO_OUTPUT)
            {
                /* clear IE */
                Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp4_io_ctrl_ADDR,
                                  22, 22, 0x0);
                /* set OE */
                Hv_PM51_Reg_WriteMask(HS_Standby__standby_peri_reg__reg_gpio_oe_ADDR,
                                  12, 12, 0x1);
            }
            else
            {
                /* set IE */
                Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp4_io_ctrl_ADDR,
                                  22, 22, 0x1);
                /* clear OE */
                Hv_PM51_Reg_WriteMask(HS_Standby__standby_peri_reg__reg_gpio_oe_ADDR,
                                  12, 12, 0x0);
            }
            break;
        }
        case GPIO5:
        {
            if(enGpioDir == GPIO_OUTPUT)
            {
                /* clear IE */
                Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp5_io_ctrl_ADDR,
                                  30, 30, 0x0);
                /* set OE */
                Hv_PM51_Reg_WriteMask(HS_Standby__standby_peri_reg__reg_gpio_oe_ADDR,
                                  13, 13, 0x1);
            }
            else
            {
                /* set IE */
                Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp5_io_ctrl_ADDR,
                                  30, 30, 0x1);
                /* clear OE */
                Hv_PM51_Reg_WriteMask(HS_Standby__standby_peri_reg__reg_gpio_oe_ADDR,
                                  13, 13, 0x0);
            }
            break;
        }
        case GPIO6:
        {
            if(enGpioDir == GPIO_OUTPUT)
            {
                /* clear IE */
                Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp6_io_ctrl_ADDR,
                                  4, 4, 0x0);
                /* set OE */
                Hv_PM51_Reg_WriteMask(HS_Standby__standby_peri_reg__reg_gpio_oe_ADDR,
                                  14, 14, 0x1);
            }
            else
            {
                /* set IE */
                Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp6_io_ctrl_ADDR,
                                  4, 4, 0x1);
                /* clear OE */
                Hv_PM51_Reg_WriteMask(HS_Standby__standby_peri_reg__reg_gpio_oe_ADDR,
                                  14, 14, 0x0);
            }
            break;
        }
        case GPIO7:
        {
            if(enGpioDir == GPIO_OUTPUT)
            {
                /* clear IE */
                Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp7_io_ctrl_ADDR,
                                  9, 9, 0x0);
                /* set OE */
                Hv_PM51_Reg_WriteMask(HS_Standby__standby_peri_reg__reg_gpio_oe_ADDR,
                                  15, 15, 0x1);
            }
            else
            {
                /* set IE */
                Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp7_io_ctrl_ADDR,
                                  9, 9, 0x1);
                /* clear OE */
                Hv_PM51_Reg_WriteMask(HS_Standby__standby_peri_reg__reg_gpio_oe_ADDR,
                                  15, 15, 0x0);
            }
            break;
        }        
        default:
            break;
    }
}

void Hv_PM51_Gpio_SetIODC(GpioEn enGpioSel, GpioDcEn enGpioDc)
{
    if((enGpioSel >= GPIO_ALL) || (enGpioDc >= GPIO_DC_NUM))
    {
        return;
    }

    switch(enGpioSel)
    {
        case GPIO0:
        {
            Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp0_io_ctrl_ADDR,
                                  17, 18, enGpioDc);
            break;
        }
        case GPIO1:
        {
            Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp1_io_ctrl_ADDR,
                                  25, 26, enGpioDc);
            break;
        }
        case GPIO2:
        {
            Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp2_io_ctrl_ADDR,
                                  1, 2, enGpioDc);
            break;
        }
        case GPIO3:
        {
            Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp3_io_ctrl_ADDR,
                                  6, 7, enGpioDc);
            break;
        }
        case GPIO4:
        {
            Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp4_io_ctrl_ADDR,
                                  17, 18, enGpioDc);
            break;
        }
        case GPIO5:
        {
            Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp5_io_ctrl_ADDR,
                                  25, 26, enGpioDc);
            break;
        }
        case GPIO6:
        {
            Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp6_io_ctrl_ADDR,
                                  1, 2, enGpioDc);
            break;
        }
        case GPIO7:
        {
            Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp7_io_ctrl_ADDR,
                                  6, 7, enGpioDc);
            break;
        }        
        default:
            break;
    }
}

void Hv_PM51_Gpio_SetOutputLevel(GpioEn enGpioSel, GpioLevelEn enGpioLevel)
{
    xULONG32 ulTempData;
    
    if(enGpioSel >= GPIO_ALL)
    {
        return;
    }
    
    ulTempData=Hv_PM51_Reg_Read(HS_Standby__standby_peri_reg__reg_gpio_o_ADDR);
    Hv_PM51_Reg_Write(HS_Standby__standby_peri_reg__reg_gpio_o_ADDR,
                  (enGpioLevel == GPIO_LEVEL_HIGH)? \
                  (ulTempData | (BIT_0 << enGpioSel)):(ulTempData & ~(BIT_0 << enGpioSel)));    

    return;
}

void Hv_PM51_Gpio_GetInputLevel(GpioEn enGpioSel, GpioLevelEn *penGpioLevel)
{
    xULONG32 ulTempData;

    if((enGpioSel >= GPIO_ALL) || (penGpioLevel == NULL))
    {
        return;
    }

    ulTempData = Hv_PM51_Reg_Read(HS_Standby__standby_peri_reg__regr_gpio_i_ADDR);

    if((ulTempData & (BIT_16 << enGpioSel)) > 0)
    {
        *penGpioLevel = GPIO_LEVEL_HIGH;
    }
    else
    {
        *penGpioLevel = GPIO_LEVEL_LOW;
    }
    
    return ;
}

void Hv_PM51_Gpio_SetPuPd(GpioEn enGpioSel, GpioPuPdEn enGpioPuPd)
{
    if(enGpioSel >= GPIO_ALL)
    {
        return;
    }

    switch(enGpioSel)
    {
        case GPIO0:
        {
            if(enGpioPuPd == GPIO_PU)
                Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp1_io_ctrl_ADDR,
                                  20, 21, 0x1);
            else
                Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp1_io_ctrl_ADDR,
                                  20, 21, 0x2);
            break;
        }
        case GPIO4:
        {
            if(enGpioPuPd == GPIO_PU)
                Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp4_io_ctrl_ADDR,
                                  20, 21, 0x1);
            else
                Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp4_io_ctrl_ADDR,
                                  20, 21, 0x2);
            break;
        }
        case GPIO5:
        {
            if(enGpioPuPd == GPIO_PU)
                Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp5_io_ctrl_ADDR,
                                  28, 29, 0x1);
            else
                Hv_PM51_Reg_WriteMask(HS_Standby__SH08_TOP_STBY__reg_stby_gp5_io_ctrl_ADDR,
                                  28, 29, 0x2);
            break;
        }
        case GPIO1:
        case GPIO2:
        case GPIO3:
        case GPIO6:
        case GPIO7:
        {
            break;
        }
        default:
            break;
    }
    
    return;
}
#endif