#include <windows.h>
#include <bsp_cfg.h>
#include <register_map.h>
#include "button.h"
#include <bsp.h>
#include <drvmsg.h>
#include <Drvlib_mem.h>

#define EINT_POWER_BUTTON   EXT_INT_31
#define EINT_RST_BUTTON   EXT_INT_4

static volatile GPIO_REG *g_pGPIOReg = NULL;

BOOL Button_initialize_register_address(void *pGPIOReg)
{
    DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] ++Button_initialize_register_address(0x%08x)\n\r"), pGPIOReg));

    if (pGPIOReg == NULL)
    {
        ERRMSG((_T("[BTN:ERR] Button_initialize_register_address() : NULL pointer parameter\n\r"))) ;
        return FALSE;
    }
    else
    {
        g_pGPIOReg = (GPIO_REG *)pGPIOReg;
    }

    DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] --Button_initialize_register_address()\n\r")));

    return TRUE;
}

void Button_port_initialize(void)
{
    DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] ++Button_port_initialize()\n\r")));
    
#ifndef ENABLE_VOLTAGE_CONTROL
    // Reset Button -> GPH0_4 : EINT4 
    Set_PinFunction(g_pGPIOReg, RESET_BUTTON);        
    Set_PinPullUD(g_pGPIOReg, RESET_BUTTON, sgip_PULL_UP);
#endif


    // Power Button -> GPH3_7 : EINT31
    Set_PinFunction(g_pGPIOReg, PWR_BUTTON); 
    Set_PinPullUD(g_pGPIOReg, PWR_BUTTON, sgip_PULL_UP);

    DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] --Button_port_initialize()\n\r")));
}


BOOL Button_pwrbtn_set_interrupt_method(EINT_SIGNAL_METHOD eMethod)
{
    BOOL bRet =TRUE;

    DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] ++Button_pwrbtn_set_interrupt_method(%d)\n\r"), eMethod));

    // Power Button -> GPH3_7 : EINT31
    switch(eMethod)
    {
    case EINT_SIGNAL_LOW_LEVEL:
            Set_EXTINT_TRLVL(g_pGPIOReg, EINT_POWER_BUTTON, sgip_LOW_LEVEL);
            //g_pGPIOReg->EINTCON.EXT_INT3_CON = (g_pGPIOReg->EINTCON.EXT_INT3_CON & ~(0x7<<28));
        break;
    case EINT_SIGNAL_HIGH_LEVEL:
            Set_EXTINT_TRLVL(g_pGPIOReg, EINT_POWER_BUTTON, sgip_HIGH_LEVEL);
            //g_pGPIOReg->EINTCON.EXT_INT3_CON = (g_pGPIOReg->EINTCON.EXT_INT3_CON & ~(0x7<<28)) | (0x1<<28);
        break;
    case EINT_SIGNAL_FALL_EDGE:
           Set_EXTINT_TRLVL(g_pGPIOReg, EINT_POWER_BUTTON, sgip_FALLING_EDGE);
            //g_pGPIOReg->EINTCON.EXT_INT3_CON = (g_pGPIOReg->EINTCON.EXT_INT3_CON & ~(0x7<<28)) | (0x2<<28);
        break;
    case EINT_SIGNAL_RISE_EDGE:
            Set_EXTINT_TRLVL(g_pGPIOReg, EINT_POWER_BUTTON, sgip_RISING_EDGE);
            //g_pGPIOReg->EINTCON.EXT_INT3_CON = (g_pGPIOReg->EINTCON.EXT_INT3_CON & ~(0x7<<28)) | (0x3<<28);
        break;
    case EINT_SIGNAL_BOTH_EDGE:
            Set_EXTINT_TRLVL(g_pGPIOReg, EINT_POWER_BUTTON, sgip_BOTH_EDGE);
            //g_pGPIOReg->EINTCON.EXT_INT3_CON = (g_pGPIOReg->EINTCON.EXT_INT3_CON & ~(0x7<<28)) | (0x7<<28);
        break;
    default:
		ERRMSG((_T("[BTN:ERR] Button_pwrbtn_set_interrupt_method() : Unknown Method = %d\n\r"), eMethod));
        bRet = FALSE;
        break;
    }

    DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] --Button_pwrbtn_set_interrupt_method() = %d\n\r"), bRet));

    return bRet;
}

BOOL Button_pwrbtn_set_filter_method(EINT_FILTER_METHOD eMethod, unsigned int uiFilterWidth)
{
    BOOL bRet =TRUE;

    DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] ++Button_pwrbtn_set_filter_method(%d, %d)\n\r"), eMethod, uiFilterWidth));

     // Power Button -> GPH3_7 : EINT31
    switch(eMethod)
    {
    case EINT_FILTER_DISABLE:
        Clr_EXTINT_FILTER(g_pGPIOReg, EINT_POWER_BUTTON);
        //g_pGPIOReg->EINTFLT.EXT_FLT3_CON._FLT_CON1 = (g_pGPIOReg->EINTFLT.EXT_FLT3_CON._FLT_CON1 & ~(0x1<<31));
        //g_pGPIOReg->WEINT3_FLTCON1 &= ~(0x1<<31);
        break;
    case EINT_FILTER_DELAY:
        Set_EXTINT_FILTER(g_pGPIOReg, EINT_POWER_BUTTON, sgip_DELAY_FLT, 0);
        //g_pGPIOReg->EINTFLT.EXT_FLT3_CON._FLT_CON1 = (g_pGPIOReg->EINTFLT.EXT_FLT3_CON._FLT_CON1 & ~(0x3<<30)) | (0x2<<30);
        //g_pGPIOReg->WEINT3_FLTCON1 = (g_pGPIOReg->WEINT3_FLTCON1 & ~(0x3<<30)) | (0x0<<30);
        break;
    case EINT_FILTER_DIGITAL:
        Set_EXTINT_FILTER(g_pGPIOReg, EINT_POWER_BUTTON, sgip_DIGITAL_FLT, uiFilterWidth);
        //g_pGPIOReg->EINTFLT.EXT_FLT3_CON._FLT_CON1 = (g_pGPIOReg->EINTFLT.EXT_FLT3_CON._FLT_CON1 & ~(0x3<<30)) | (0x3<<30);
        //g_pGPIOReg->EINTFLT.EXT_FLT3_CON._FLT_CON1 = (g_pGPIOReg->EINTFLT.EXT_FLT3_CON._FLT_CON1 & ~(0x3f<<24)) | (uiFilterWidth<<24);
        break;
    default:
		ERRMSG((_T("[BTN:ERR] Button_pwrbtn_set_filter_method() : Unknown Method = %d\n\r"), eMethod));
        bRet = FALSE;
        break;
    }

    DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] --Button_pwrbtn_set_filter_method() = %d\n\r"), bRet));

    return bRet;
}


void Button_pwrbtn_enable_interrupt(void)
{
    DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] ++Button_pwrbtn_enable_interrupt()\n\r")));

    // Power Button -> GPH3_7 : EINT31
    Unmask_EXTINT(g_pGPIOReg, EINT_POWER_BUTTON);
    //g_pGPIOReg->EINTMSK.EXT_INT3_MASK &= ~(0x1<<7);    // Unmask EINT31

	DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] --Button_pwrbtn_enable_interrupt()\n\r")));
}

void Button_pwrbtn_disable_interrupt(void)
{
    DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] ++Button_pwrbtn_disable_interrupt()\n\r")));

    // Power Button -> GPH3_7 : EINT31
    Mask_EXTINT(g_pGPIOReg, EINT_POWER_BUTTON);
    //g_pGPIOReg->EINTMSK.EXT_INT3_MASK |= (0x1<<7);    // Mask EINT31

    DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] --Button_pwrbtn_disable_interrupt()\n\r")));
}

void Button_pwrbtn_clear_interrupt_pending(void)
{
    DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] ++Button_pwrbtn_clear_interrupt_pending()\n\r")));

     // Power Button -> GPH3_7 : EINT31
    //g_pGPIOReg->WEINT3_PEND = (0x1<<7);        // Clear pending EINT31
    Clear_EXTINT(g_pGPIOReg, EINT_POWER_BUTTON);
    //g_pGPIOReg->EINTPND.EXT_INT3_PEND |= (0x1<<7); 

	DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] --Button_pwrbtn_clear_interrupt_pending()\n\r")));
}

BOOL Button_pwrbtn_is_pushed(void)
{
    DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] ++Button_pwrbtn_is_pushed()\n\r")));

     // Power Button -> GPH3_7 : EINT31
    if (Get_PinData(g_pGPIOReg, PWR_BUTTON))        // We can read GPH3DAT pin level when configured as EINT
    //if (g_pGPIOReg->GPH3.GP_DAT & (0x1<<7))        // We can read GPH3DAT pin level when configured as EINT
    {
        DBGMSG(PWRBTN_INFO, (TEXT("[BTN] Pwrbtn is not pushed\n\r")));
        return FALSE;    // Low Active Switch (Pull-up switch)
    }
    else
    {
        DBGMSG(PWRBTN_INFO, (TEXT("[BTN] Pwrbtn is pushed\n\r")));
        return TRUE;
    }

    DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] --Button_pwrbtn_is_pushed()\n\r")));
    return TRUE;
}




BOOL Button_rstbtn_set_interrupt_method(EINT_SIGNAL_METHOD eMethod)
{
    BOOL bRet =TRUE;

    DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] ++Button_rstbtn_set_interrupt_method(%d)\n\r"), eMethod));

    // Reset Button -> GPH0_4 : EINT4
    switch(eMethod)
    {
    case EINT_SIGNAL_LOW_LEVEL:
            Set_EXTINT_TRLVL(g_pGPIOReg, EINT_RST_BUTTON, sgip_LOW_LEVEL);
            //g_pGPIOReg->EINTCON.EXT_INT0_CON = (g_pGPIOReg->EINTCON.EXT_INT0_CON & ~(0x7<<16));
        break;
    case EINT_SIGNAL_HIGH_LEVEL:
            Set_EXTINT_TRLVL(g_pGPIOReg, EINT_RST_BUTTON, sgip_HIGH_LEVEL);
            //g_pGPIOReg->EINTCON.EXT_INT0_CON = (g_pGPIOReg->EINTCON.EXT_INT0_CON & ~(0x7<<16)) | (0x1<<16);
        break;
    case EINT_SIGNAL_FALL_EDGE:
            Set_EXTINT_TRLVL(g_pGPIOReg, EINT_RST_BUTTON, sgip_FALLING_EDGE);
            //g_pGPIOReg->EINTCON.EXT_INT0_CON = (g_pGPIOReg->EINTCON.EXT_INT0_CON & ~(0x7<<16)) | (0x2<<16);
        break;
    case EINT_SIGNAL_RISE_EDGE:
            Set_EXTINT_TRLVL(g_pGPIOReg, EINT_RST_BUTTON, sgip_RISING_EDGE);
            //g_pGPIOReg->EINTCON.EXT_INT0_CON = (g_pGPIOReg->EINTCON.EXT_INT0_CON & ~(0x7<<16)) | (0x3<<16);
        break;
    case EINT_SIGNAL_BOTH_EDGE:
            Set_EXTINT_TRLVL(g_pGPIOReg, EINT_RST_BUTTON, sgip_BOTH_EDGE);
            //g_pGPIOReg->EINTCON.EXT_INT0_CON = (g_pGPIOReg->EINTCON.EXT_INT0_CON & ~(0x7<<16)) | (0x4<<16);
        break;
    default:
		ERRMSG((_T("[BTN:ERR] Button_rstbtn_set_interrupt_method() : Unknown Method = %d\n\r"), eMethod));
        bRet = FALSE;
        break;
    }

    DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] --Button_rstbtn_set_interrupt_method() = %d\n\r"), bRet));

    return bRet;
}


BOOL Button_rstbtn_set_filter_method(EINT_FILTER_METHOD eMethod, unsigned int uiFilterWidth)
{
    BOOL bRet =TRUE;

	DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] Button_rstbtn_set_filter_method(%d, %d)\n\r"), eMethod, uiFilterWidth));

    // Reset Button -> GPH0_4 : EINT4

    switch(eMethod)
    {
    case EINT_FILTER_DISABLE:
        Clr_EXTINT_FILTER(g_pGPIOReg, EINT_RST_BUTTON);
        //g_pGPIOReg->EINTFLT.EXT_FLT0_CON._FLT_CON1 = (g_pGPIOReg->EINTFLT.EXT_FLT0_CON._FLT_CON1 & ~(0x1<<7));
        break;
    case EINT_FILTER_DELAY:
        Set_EXTINT_FILTER(g_pGPIOReg, EINT_RST_BUTTON, sgip_DELAY_FLT, 0);
        //g_pGPIOReg->EINTFLT.EXT_FLT0_CON._FLT_CON1 = (g_pGPIOReg->EINTFLT.EXT_FLT0_CON._FLT_CON1 & ~(0x3<<6)) | (0x2<<6);
        break;
    case EINT_FILTER_DIGITAL:
        Set_EXTINT_FILTER(g_pGPIOReg, EINT_RST_BUTTON, sgip_DIGITAL_FLT, uiFilterWidth);        
        //g_pGPIOReg->EINTFLT.EXT_FLT0_CON._FLT_CON1 = (g_pGPIOReg->EINTFLT.EXT_FLT0_CON._FLT_CON1 & ~(0x3<<6)) | (0x3<<6);
        //g_pGPIOReg->EINTFLT.EXT_FLT0_CON._FLT_CON1 = (g_pGPIOReg->EINTFLT.EXT_FLT0_CON._FLT_CON1 & ~(0x3f<<0)) | (uiFilterWidth<<0);
        break;
    default:
		ERRMSG((_T("[BTN:ERR] Button_rstbtn_set_filter_method() : Unknown Method = %d\n\r"), eMethod));
        bRet = FALSE;
        break;
    }

    DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] --Button_rstbtn_set_filter_method() = %d\n\r"), bRet));

    return bRet;
}


void Button_rstbtn_enable_interrupt(void)
{
    DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] ++Button_rstbtn_enable_interrupt()\n\r")));

    // Reset Button -> GPH0_4 : EINT4
    Unmask_EXTINT(g_pGPIOReg, EINT_RST_BUTTON);
    //g_pGPIOReg->EINTMSK.EXT_INT0_MASK &= ~(0x1<<4);    // Unmask EINT4

    DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] --Button_rstbtn_enable_interrupt()\n\r")));
    
}

void Button_rstbtn_disable_interrupt(void)
{
    DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] ++Button_rstbtn_disable_interrupt()\n\r")));

    // Reset Button -> GPH0_4 : EINT4 
    Mask_EXTINT(g_pGPIOReg, EINT_RST_BUTTON);
    //g_pGPIOReg->EINTMSK.EXT_INT0_MASK |= (0x1<<4);        // Mask EINT4

	DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] --Button_rstbtn_disable_interrupt()\n\r")));
}

void Button_rstbtn_clear_interrupt_pending(void)
{
    DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] ++Button_rstbtn_clear_interrupt_pending()\n\r")));

    // Reset Button -> GPH0_4 : EINT4 
    Clear_EXTINT(g_pGPIOReg, EINT_RST_BUTTON);
    //g_pGPIOReg->EINTPND.EXT_INT0_PEND |= (0x1<<4);      // Clear pending EINT4    
    
    DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] --Button_rstbtn_clear_interrupt_pending()\n\r")));
}

BOOL Button_rstbtn_is_pushed(void)
{
    DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] ++Button_rstbtn_is_pushed()\n\r")));

    // Reset Button -> GPH0_4 : EINT4 
    if (Get_PinData(g_pGPIOReg, RESET_BUTTON))        // We can read GPH1DAT pin level when configured as EINT
    {
        DBGMSG(PWRBTN_INFO, (TEXT("[BTN] Rstbtn is not pushed\n\r")));
        return FALSE;    // Low Active Switch (Pull-up switch)
    }
    else
    {
        DBGMSG(PWRBTN_INFO, (TEXT("[BTN] Rstbtn is pushed\n\r")));
        return TRUE;
    }
	DBGMSG(PWRBTN_FUNC, (TEXT("[BTN] --Button_rstbtn_is_pushed()\n\r")));
}

