/*
    (C) 2017 Renesas Electronics Corporation.
     This software is released under the terms and conditions described in LICENSE_RENESAS.TXT included in the project.
*/
/**
  * @file    rl78g14_gpio.c
  * @author  Renesas Electronics Corporation
  * @brief   Sample I/O port program header.
**/

#include "board.h"

#if defined(__CCRL__)
    #pragma interrupt RpMcuIntp0Interrupthandler(vect=INTP0)
    #pragma interrupt RpMcuIntp1Interrupthandler(vect=INTP1)
    #pragma interrupt RpMcuIntp2Interrupthandler(vect=INTP2)
    #pragma interrupt RpMcuIntp3Interrupthandler(vect=INTP3)
    #pragma interrupt RpMcuIntp4Interrupthandler(vect=INTP4)
    #pragma interrupt RpMcuIntp5Interrupthandler(vect=INTP5)
    #pragma interrupt RpMcuIntp6Interrupthandler(vect=INTP6)
#if defined(INTP7)
    #pragma interrupt RpMcuIntp7Interrupthandler(vect=INTP7)
#endif // #if defined(INTP7)
    #pragma interrupt RpMcuIntp8Interrupthandler(vect=INTP8)
    #pragma interrupt RpMcuIntp9Interrupthandler(vect=INTP9)
#if defined(INTP10)
    #pragma interrupt RpMcuIntp10Interrupthandler(vect=INTP10)
#endif // #if defined(INTP10)
#if defined(INTP11)
    #pragma interrupt RpMcuIntp11Interrupthandler(vect=INTP11)
#endif // #if defined(INTP11)
#elif defined(__ICCRL78__)
    #pragma vector = INTP0_vect
    __interrupt void RpMcuIntp0Interrupthandler(void);
    #pragma vector = INTP1_vect
    __interrupt void RpMcuIntp1Interrupthandler(void);
    #pragma vector = INTP2_vect
    __interrupt void RpMcuIntp2Interrupthandler(void);
    #pragma vector = INTP3_vect
    __interrupt void RpMcuIntp3Interrupthandler(void);
    #pragma vector = INTP4_vect
    __interrupt void RpMcuIntp4Interrupthandler(void);
    #pragma vector = INTP5_vect
    __interrupt void RpMcuIntp5Interrupthandler(void);
    #pragma vector = INTP6_vect
    __interrupt void RpMcuIntp6Interrupthandler(void);
#if defined(INTP7)
    #pragma vector = INTP7_vect
    __interrupt void RpMcuIntp7Interrupthandler(void);
#endif // #if defined(INTP7)
    #pragma vector = INTP8_vect
    __interrupt void RpMcuIntp8Interrupthandler(void);
    __interrupt void RpMcuIntp6Interrupthandler(void);
    #pragma vector = INTP9_vect
    __interrupt void RpMcuIntp9Interrupthandler(void);
#if defined(INTP10)
    #pragma vector = INTP10_vect
    __interrupt void RpMcuIntp10Interrupthandler(void);
#endif // #if defined(INTP10)
#if defined(INTP11)
    #pragma vector = INTP11_vect
    __interrupt void RpMcuIntp11Interrupthandler(void);
#endif // #if defined(INTP11)
#endif // #if defined(__CCRL__ )

/* functions */
void GpioMcuSetInterrupt( Gpio_t *obj, IrqModes irqMode, IrqPriorities irqPriority, GpioIrqHandler *pIntpHandler );

/* static functions */
static void RpMcuIntpXCallbackDefault (void* context);
static void RpMcuSetIntpCallback(uint16_t intNo, GpioIrqHandler * pIntpHandler, void* context);

enum {
#if defined(INTP11)
    INTMAX = 11,
#elif defined(INTP10)
    INTMAX = 10,
#else
    INTMAX = 9,
#endif
    INT_TOTAL = INTMAX+1,
};

DioIrqHandler * pRpMcuIntpCallback[INT_TOTAL];
void*           pRpMcuIntpCtx[INT_TOTAL];



static
uint8_t portIntNo(uint8_t port){
    uint8_t  intpNo;
    switch(port)
    {
        case 0xd7U: // P137 @ INTP0
                  intpNo = 0U;
                  break;
        case 0x50U: // P50 @ INTP1
                  intpNo = 1U;
                  break;
        case 0x51U: // P51 @ INTP2
                  intpNo = 2U;
                  break;
        case 0x30U: // P30 @ INTP3
                  intpNo = 3U;
                  break;
        case 0x31U: // P31 @ INTP4
                  intpNo = 4U;
                  break;
        case 0x16U: // P16 @ INTP5
                  intpNo = 5U;
                  break;
        case 0xe0U: // P140 @ INTP6
                  intpNo = 6U;
                  break;
        case 0xe1U: // P141 @ INTP7
                  intpNo = 7U;
                break;
        case 0x74U: // P74 @ INTP8
                  intpNo = 8U;
                  break;
        case 0x75U: // P75 @ INTP9
                  intpNo = 9U;
                  break;
        case 0x76U: // P76 @ INTP10
                  intpNo = 10U;
                  break;
        case 0x77U: // P77 @ INTP11
                  intpNo = 11U;
                  break;
        default:    // Port unavailable for external interrupt
                  intpNo = 0xffU;
                  break;
    }
    return intpNo;
}

unsigned GpioMcuRead( Gpio_t *obj )
{  
    uint8_t  portNum;
    uint8_t  portVal;
    uint16_t basePortAddr = 0xFF00;
    uint16_t portGroup;

    if( ( obj == NULL ) || (obj->pin == NC))
    {
        return 0;
    }
   
    portGroup = ((uint16_t)obj->pin & 0xf0) >> 4;				//memorize port group no. (P0 to P14)
    portNum   =  (uint8_t) obj->pin & 0x0f;					//memorize port no.
    portVal   = *(RP_SFR_CHAR)(basePortAddr + portGroup);	//fetch current port value
   
    return (0x01 & (portVal >> portNum));
}


void GpioMcuWrite( Gpio_t *obj, unsigned value )
{ 
    uint8_t  portNum;
    uint8_t  portVal;
    uint16_t basePortAddr = 0xFF00;
    uint16_t portGroup;
   
    if( ( obj == NULL ) || (obj->pin == NC))
    {
        return;
    }
    
    value     = value & 0x00000001U;						//sort port value to write
    portGroup = ((uint16_t)obj->pin & 0xf0U) >> 4;				//memorize port group no. (P0 to P14)
    portNum   =  (uint8_t) obj->pin & 0x0fU;					//memorize port no.
    portVal   = *(RP_SFR_CHAR)(basePortAddr + portGroup);	//fetch current port value
    
    if(value == 0U)
    {
        *(RP_SFR_CHAR)(basePortAddr + portGroup) = portVal & ~(0x01 << portNum);
    }
    else // value == 1
    {
        *(RP_SFR_CHAR)(basePortAddr + portGroup) = portVal |  (0x01 << portNum);   
    }
}


void GpioMcuToggle( Gpio_t *obj )
{ 	
   uint8_t  portNum;
   uint8_t  portVal;
   uint16_t basePortAddr = 0xFF00;	//address of P0 (__near)
   uint16_t portGroup;
   
   if( ( obj == NULL ) || (obj->pin == NC))
   {
        return;
   }
   
   portGroup = ((uint16_t)obj->pin & 0xf0U) >> 4;				//memorize port group no. (P0 to P14)
   portNum   = (uint8_t) obj->pin & 0x0fU;					//memorize port no.
   portVal   = *(RP_SFR_CHAR)(basePortAddr + portGroup);	//fetch current port value
   portVal   = portVal ^ (0x01U << portNum);					//xor port value of the port to toggle
   
   *(RP_SFR_CHAR)(basePortAddr + portGroup) = portVal;
}

void RpMcuIntpInit(void)
{
    for (char i=0; i <= INTMAX; i++){
        pRpMcuIntpCallback[i]   = RpMcuIntpXCallbackDefault;
        pRpMcuIntpCtx[i]        = NULL;
    }
}

/*
void GpioMcuSetContext( Gpio_t *obj, void* context ){
    obj->Context = context;
    uint8_t intno = portIntNo(obj->pin);
    if (intno <= INTMAX){
        pRpMcuIntpCtx[intno]        = context;
    }
}
*/

void RpMcuGpioMcuInit(  Gpio_t *obj, PinNames pin, PinModes mode, PinConfigs config, PinTypes type
                        , unsigned value  )
{
    uint8_t portGroup, pinNo, sfrVal;
    uint16_t sfrAddrPim, sfrAddrPm, sfrAddrP, sfrAddrPu, sfrAddrPom, sfrAddrPmc;
    
    portGroup = (uint8_t)( (pin & 0xf0) >> 4);
    pinNo     = (uint8_t)(pin & 0x0f);
    obj->pin  = pin;
    
    if( pin == NC )
    {
        return;
    }
    
    obj->pull = type;
    
    sfrAddrPim = portGroup + RP_MCU_PIM0_ADDR;
    sfrAddrPom = portGroup + RP_MCU_POM0_ADDR;
    sfrAddrPm  = portGroup + RP_MCU_PM0_ADDR;
    sfrAddrPu  = portGroup + RP_MCU_PU0_ADDR;
    sfrAddrP   = portGroup + RP_MCU_P0_ADDR;
    sfrAddrPmc = portGroup + RP_MCU_PMC0_ADDR;


    if( mode == PIN_INPUT )
    {
        switch (portGroup)
        {
            case 0U:	// P0x
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPim;
                    (config == PIN_TTL) ? (sfrVal |= (0x01 << pinNo)) : (sfrVal &= ~(0x01 << pinNo));
                    *(RP_SFR_CHAR)sfrAddrPim = RP_PIM0_BITMASK & sfrVal;					// PIMxx : 1'b1 if TTL. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPm;
                    *(RP_SFR_CHAR)sfrAddrPm  = RP_PM0_BITMASK & (sfrVal | (0x01 << pinNo));		// PMxx : 1'b1 if input. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPu;
                    (type == PIN_PULL_UP) ? (sfrVal |= (0x01 << pinNo)) : (sfrVal &= ~(0x01 << pinNo));
                    *(RP_SFR_CHAR)sfrAddrPu  = RP_PU0_BITMASK & sfrVal;					// PUxx : 1'b1 if input. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPmc;
                    *(RP_SFR_CHAR)sfrAddrPmc  = RP_PMC0_BITMASK & (sfrVal & ~(0x01 << pinNo));		// PMCxx : 1'b1 if analog.
                     // Pxx is not configured if input
                     break;
            case 1U:	// P1x
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPim;
                    (config == PIN_TTL) ? (sfrVal |= (0x01 << pinNo)) : (sfrVal &= ~(0x01 << pinNo));
                    *(RP_SFR_CHAR)sfrAddrPim = RP_PIM1_BITMASK & sfrVal;					// PIMxx : 1'b1 if TTL. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPm;
                    *(RP_SFR_CHAR)sfrAddrPm  = RP_PM1_BITMASK & (sfrVal | (0x01 << pinNo));		// PMxx : 1'b1 if input. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPu;
                    (type == PIN_PULL_UP) ? (sfrVal |= (0x01 << pinNo)) : (sfrVal &= ~(0x01 << pinNo));
                    *(RP_SFR_CHAR)sfrAddrPu  = RP_PU1_BITMASK & sfrVal;					// PUxx : 1'b1 if input.
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPmc;
                    *(RP_SFR_CHAR)sfrAddrPmc  = RP_PMC1_BITMASK & (sfrVal & ~(0x01 << pinNo));		// PMxx : 1'b1 if analog.
                     // Pxx is not configured if input
                     break;
            case 2U:	// P2x
                	sfrVal = *(RP_SFR_CHAR)sfrAddrPm;
                    *(RP_SFR_CHAR)sfrAddrPm  = RP_PM2_BITMASK & (sfrVal | (0x01 << pinNo));		// PMxx : 1'b1 if input. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPu;
                    /* ADPC and PMCxx not configured. May be implemented later */
                    break;
            case 3U:	// P3x
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPim;
                    (config == PIN_TTL) ? (sfrVal |= (0x01 << pinNo)) : (sfrVal &= ~(0x01 << pinNo));
                    *(RP_SFR_CHAR)sfrAddrPim = RP_PIM3_BITMASK & sfrVal;					// PIMxx : 1'b1 if TTL. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPm;
                    *(RP_SFR_CHAR)sfrAddrPm  = RP_PM3_BITMASK & (sfrVal | (0x01 << pinNo));		// PMxx : 1'b1 if input. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPu;
                    (type == PIN_PULL_UP) ? (sfrVal |= (0x01 << pinNo)) : (sfrVal &= ~(0x01 << pinNo));
                    *(RP_SFR_CHAR)sfrAddrPu  = RP_PU3_BITMASK & sfrVal;					// PUxx : 1'b1 if input.
                    break;
            case 4U:	// P4x
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPim;
                    (config == PIN_TTL) ? (sfrVal |= (0x01 << pinNo)) : (sfrVal &= ~(0x01 << pinNo));
                    *(RP_SFR_CHAR)sfrAddrPim = RP_PIM4_BITMASK & sfrVal;					// PIMxx : 1'b1 if TTL. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPm;
                    *(RP_SFR_CHAR)sfrAddrPm  = RP_PM4_BITMASK & (sfrVal | (0x01 << pinNo));		// PMxx : 1'b1 if input. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPu;
                    (type == PIN_PULL_UP) ? (sfrVal |= (0x01 << pinNo)) : (sfrVal &= ~(0x01 << pinNo));
                    *(RP_SFR_CHAR)sfrAddrPu  = RP_PU4_BITMASK & sfrVal;					// PUxx : 1'b1 if input.
                    break;
            case 5U:	// P5x
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPim;
                    (config == PIN_TTL) ? (sfrVal |= (0x01 << pinNo)) : (sfrVal &= ~(0x01 << pinNo));
                    *(RP_SFR_CHAR)sfrAddrPim = RP_PIM5_BITMASK & sfrVal;					// PIMxx : 1'b1 if TTL. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPm;
                    *(RP_SFR_CHAR)sfrAddrPm  = RP_PM5_BITMASK & (sfrVal | (0x01 << pinNo));		// PMxx : 1'b1 if input. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPu;
                    (type == PIN_PULL_UP) ? (sfrVal |= (0x01 << pinNo)) : (sfrVal &= ~(0x01 << pinNo));
                    *(RP_SFR_CHAR)sfrAddrPu  = RP_PU5_BITMASK & sfrVal;					// PUxx : 1'b1 if input.
                    break;
            case 6U:	// P6x
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPm;
                    *(RP_SFR_CHAR)sfrAddrPm  = RP_PM6_BITMASK & (sfrVal | (0x01 << pinNo));		// PMxx : 1'b1 if input. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPu;
                    (type == PIN_PULL_UP) ? (sfrVal |= (0x01 << pinNo)) : (sfrVal &= ~(0x01 << pinNo));
                    *(RP_SFR_CHAR)sfrAddrPu  = RP_PU6_BITMASK & sfrVal;					// PUxx : 1'b1 if input.
                    break;
            case 7U:	// P7x
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPm;
                    *(RP_SFR_CHAR)sfrAddrPm  = RP_PM7_BITMASK & (sfrVal | (0x01 << pinNo));		// PMxx : 1'b1 if input. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPu;
                    (type == PIN_PULL_UP) ? (sfrVal |= (0x01 << pinNo)) : (sfrVal &= ~(0x01 << pinNo));
                    *(RP_SFR_CHAR)sfrAddrPu  = RP_PU7_BITMASK & sfrVal;					// PUxx : 1'b1 if input.
                    break;
            case 12U:	// P12x
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPim;
                    (config == PIN_TTL) ? (sfrVal |= (0x01 << pinNo)) : (sfrVal &= ~(0x01 << pinNo));
                    *(RP_SFR_CHAR)sfrAddrPm  = RP_PM12_BITMASK & (sfrVal | (0x01 << pinNo));		// PMxx : 1'b1 if input. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPu;
                    (type == PIN_PULL_UP) ? (sfrVal |= (0x01 << pinNo)) : (sfrVal &= ~(0x01 << pinNo));
                    *(RP_SFR_CHAR)sfrAddrPu  = RP_PU12_BITMASK & sfrVal;					// PUxx : 1'b1 if input.
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPmc;
                    *(RP_SFR_CHAR)sfrAddrPmc  = RP_PMC12_BITMASK & (sfrVal & ~(0x01 << pinNo));		// PMCxx : 1'b1 if analog.
                    break;
            case 13U:	// P13x
                    /* No SFR to be configured */
                    break;
            case 14U:	// P14x
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPim;
                    (config == PIN_TTL) ? (sfrVal |= (0x01 << pinNo)) : (sfrVal &= ~(0x01 << pinNo));
                    *(RP_SFR_CHAR)sfrAddrPim = RP_PIM14_BITMASK & sfrVal;					// PIMxx : 1'b1 if TTL. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPm;
                    *(RP_SFR_CHAR)sfrAddrPm  = RP_PM14_BITMASK & (sfrVal | (0x01 << pinNo));		// PMxx : 1'b1 if input. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPu;
                    (type == PIN_PULL_UP) ? (sfrVal |= (0x01 << pinNo)) : (sfrVal &= ~(0x01 << pinNo));
                    *(RP_SFR_CHAR)sfrAddrPu  = RP_PU14_BITMASK & sfrVal;					// PUxx : 1'b1 if input.
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPmc;
                    *(RP_SFR_CHAR)sfrAddrPmc  = RP_PMC14_BITMASK & (sfrVal & ~(0x01 << pinNo));		// PMCxx : 1'b1 if analog.
                    break;
            default:
                    break;
        }
    }
    else if( mode == PIN_OUTPUT)
    {
        switch (portGroup)
        {
            case 0U:
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPom;
                    (config == PIN_OPEN_DRAIN) ? (sfrVal |= (0x01U << pinNo)) : (sfrVal &= ~(0x01U << pinNo));
                    *(RP_SFR_CHAR)sfrAddrPom = RP_POM0_BITMASK & sfrVal;					// POMxx : 1'b1 if n-ch open drain 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPm;
                    *(RP_SFR_CHAR)sfrAddrPm  = RP_PM0_BITMASK & (sfrVal & ~(0x01U << pinNo));		// PMxx : 1'b1 if input. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPmc;
                    *(RP_SFR_CHAR)sfrAddrPmc  = RP_PMC0_BITMASK & (sfrVal & ~(0x01U << pinNo));		// PMCxx : 1'b1 if analog.
                    sfrVal = *(RP_SFR_CHAR)sfrAddrP;
                    (value == 1U) ? (sfrVal |= (0x01U << pinNo)) : (sfrVal &= ~(0x01U << pinNo));
                    *(RP_SFR_CHAR)sfrAddrP  = RP_P0_BITMASK & sfrVal;					// Pxx : port latch value according to argument "value"
                    break;
            case 1U:
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPom;
                    (config == PIN_OPEN_DRAIN) ? (sfrVal |= (0x01U << pinNo)) : (sfrVal &= ~(0x01U << pinNo));
                    *(RP_SFR_CHAR)sfrAddrPom = RP_POM1_BITMASK & sfrVal;					// POMxx : 1'b1 if n-ch open drain 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPm;
                    *(RP_SFR_CHAR)sfrAddrPm  = RP_PM1_BITMASK & (sfrVal & ~(0x01U << pinNo));		// PMxx : 1'b1 if input. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPmc;
                    *(RP_SFR_CHAR)sfrAddrPmc  = RP_PMC1_BITMASK & (sfrVal & ~(0x01U << pinNo));		// PMCxx : 1'b1 if analog.
                    sfrVal = *(RP_SFR_CHAR)sfrAddrP;
                    (value == 1U) ? (sfrVal |= (0x01U << pinNo)) : (sfrVal &= ~(0x01U << pinNo));
                    *(RP_SFR_CHAR)sfrAddrP  = RP_P1_BITMASK & sfrVal;					// Pxx : port latch value according to argument "value"
                    break;
            case 2U:	// P2x
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPm;
                    *(RP_SFR_CHAR)sfrAddrPm  = RP_PM2_BITMASK & (sfrVal & ~(0x01 << pinNo));		// PMxx : 1'b1 if input. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrP;
                    (value == 1U) ? (sfrVal |= (0x01U << pinNo)) : (sfrVal &= ~(0x01U << pinNo));
                    *(RP_SFR_CHAR)sfrAddrP  = RP_P2_BITMASK & sfrVal;					// Pxx : port latch value according to argument "value"
                    break;
            case 3U:
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPom;
                    (config == PIN_OPEN_DRAIN) ? (sfrVal |= (0x01U << pinNo)) : (sfrVal &= ~(0x01U << pinNo));
                    *(RP_SFR_CHAR)sfrAddrPom = RP_POM3_BITMASK & sfrVal;					// POMxx : 1'b1 if n-ch open drain 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPm;
                    *(RP_SFR_CHAR)sfrAddrPm  = RP_PM3_BITMASK & (sfrVal & ~(0x01U << pinNo));		// PMxx : 1'b1 if input. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrP;
                    (value == 1U) ? (sfrVal |= (0x01U << pinNo)) : (sfrVal &= ~(0x01 << pinNo));
                    *(RP_SFR_CHAR)sfrAddrP  = RP_P3_BITMASK & sfrVal;					// Pxx : port latch value according to argument "value"
                    break;
            case 4U:
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPom;
                    (config == PIN_OPEN_DRAIN) ? (sfrVal |= (0x01U << pinNo)) : (sfrVal &= ~(0x01U << pinNo));
                    *(RP_SFR_CHAR)sfrAddrPom = RP_POM4_BITMASK & sfrVal;					// POMxx : 1'b1 if n-ch open drain 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPm;
                    *(RP_SFR_CHAR)sfrAddrPm  = RP_PM4_BITMASK & (sfrVal & ~(0x01U << pinNo));		// PMxx : 1'b1 if input. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrP;
                    (value == 1U) ? (sfrVal |= (0x01U << pinNo)) : (sfrVal &= ~(0x01U << pinNo));
                    *(RP_SFR_CHAR)sfrAddrP  = RP_P4_BITMASK & sfrVal;					// Pxx : port latch value according to argument "value"
                    break;
            case 5U:
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPom;
                    (config == PIN_OPEN_DRAIN) ? (sfrVal |= (0x01U << pinNo)) : (sfrVal &= ~(0x01U << pinNo));
                    *(RP_SFR_CHAR)sfrAddrPom = RP_POM5_BITMASK & sfrVal;					// POMxx : 1'b1 if n-ch open drain 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPm;
                    *(RP_SFR_CHAR)sfrAddrPm  = RP_PM5_BITMASK & (sfrVal & ~(0x01U << pinNo));		// PMxx : 1'b1 if input. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrP;
                    (value == 1U) ? (sfrVal |= (0x01U << pinNo)) : (sfrVal &= ~(0x01U << pinNo));
                    *(RP_SFR_CHAR)sfrAddrP  = RP_P5_BITMASK & sfrVal;					// Pxx : port latch value according to argument "value"
                    break;
            case 6U:	// P6x
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPm;
                    *(RP_SFR_CHAR)sfrAddrPm  = RP_PM6_BITMASK & (sfrVal & ~(0x01U << pinNo));		// PMxx : 1'b1 if input. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrP;
                    (value == 1U) ? (sfrVal |= (0x01U << pinNo)) : (sfrVal &= ~(0x01U << pinNo));
                    *(RP_SFR_CHAR)sfrAddrP  = RP_P6_BITMASK & sfrVal;					// Pxx : port latch value according to argument "value"
                    break;
            case 7U:	// P7x
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPom;
                    (config == PIN_OPEN_DRAIN) ? (sfrVal |= (0x01U << pinNo)) : (sfrVal &= ~(0x01U << pinNo));
                    *(RP_SFR_CHAR)sfrAddrPom = RP_POM7_BITMASK & sfrVal;					// POMxx : 1'b1 if n-ch open drain 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPm;
                    *(RP_SFR_CHAR)sfrAddrPm  = RP_PM7_BITMASK & (sfrVal & ~(0x01U << pinNo));		// PMxx : 1'b1 if input. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrP;
                    (value == 1U) ? (sfrVal |= (0x01U << pinNo)) : (sfrVal &= ~(0x01U << pinNo));
                    *(RP_SFR_CHAR)sfrAddrP  = RP_P7_BITMASK & sfrVal;					// Pxx : port latch value according to argument "value"
                    break;
            case 12U:	// P12x
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPm;
                    *(RP_SFR_CHAR)sfrAddrPm  = RP_PM12_BITMASK & (sfrVal | (0x01U << pinNo));		// PMxx : 1'b1 if input. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPmc;
                    *(RP_SFR_CHAR)sfrAddrPmc  = RP_PMC12_BITMASK & (sfrVal & ~(0x01U << pinNo));		// PMCxx : 1'b1 if analog.
                    sfrVal = *(RP_SFR_CHAR)sfrAddrP;
                    (value == 1U) ? (sfrVal |= (0x01U << pinNo)) : (sfrVal &= ~(0x01U << pinNo));
                    *(RP_SFR_CHAR)sfrAddrP  = RP_P12_BITMASK & sfrVal;					// Pxx : port latch value according to argument "value"
                    break;
            case 14U:	// P14x
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPom;
                    (config == PIN_OPEN_DRAIN) ? (sfrVal |= (0x01U << pinNo)) : (sfrVal &= ~(0x01U << pinNo));
                    *(RP_SFR_CHAR)sfrAddrPom = RP_POM14_BITMASK & sfrVal;					// POMxx : 1'b1 if n-ch open drain 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPm;
                    *(RP_SFR_CHAR)sfrAddrPm  = RP_PM14_BITMASK & (sfrVal & ~(0x01U << pinNo));		// PMxx : 1'b1 if input. 
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPmc;
                    *(RP_SFR_CHAR)sfrAddrPmc  = RP_PMC14_BITMASK & (sfrVal & ~(0x01U << pinNo));		// PMCxx : 1'b1 if analog.
                    sfrVal = *(RP_SFR_CHAR)sfrAddrP;
                    (value == 1U) ? (sfrVal |= (0x01U << pinNo)) : (sfrVal &= ~(0x01U << pinNo));
                    *(RP_SFR_CHAR)sfrAddrP  = RP_P14_BITMASK & sfrVal;					// Pxx : port latch value according to argument "value"
                    break;
            default:
                    break;
        }
    }
    else if( mode == PIN_ANALOGIC )
    {
        switch (portGroup)
        {
            case 0U:
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPmc;
                    *(RP_SFR_CHAR)sfrAddrPmc  = RP_PMC0_BITMASK & (sfrVal | (0x01U << pinNo));		// PMCxx : 1'b1 if analog.
                    break;
        
            case 1U:
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPmc;
                    *(RP_SFR_CHAR)sfrAddrPmc  = RP_PMC1_BITMASK & (sfrVal | (0x01U << pinNo));		// PMCxx : 1'b1 if analog.
                    break;
            case 2U:
                    /* ADPC congiguration not implemented for now */
                    break;
            case 12U:
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPmc;
                    *(RP_SFR_CHAR)sfrAddrPmc  = RP_PMC12_BITMASK & (sfrVal | (0x01U << pinNo));		// PMCxx : 1'b1 if analog.
                    break;
            case 14U:
                    sfrVal = *(RP_SFR_CHAR)sfrAddrPmc;
                    *(RP_SFR_CHAR)sfrAddrPmc  = RP_PMC14_BITMASK & (sfrVal | (0x01U << pinNo));		// PMCxx : 1'b1 if analog.
                    break;
            default:
                break;
        }
    }
    else // mode == PIN_ALTERNATE_FCT etc.
    {
        /* none */
    }
        
}

void GpioMcuRemoveInterrupt( Gpio_t *obj )
{
    if(obj == NULL)
    {
        return;
    }
    
    GpioMcuSetInterrupt( obj, NO_IRQ, IRQ_LOW_PRIORITY, NULL);
}

void GpioMcuSetInterrupt( Gpio_t *obj, IrqModes irqMode, IrqPriorities irqPriority, GpioIrqHandler *pIntpHandler )
{
    uint8_t  port, intpNo, priority0, priority1, intpMask;

    port = (uint8_t) obj->pin;

    if( pIntpHandler == NULL )
    {
        return;
    }

    intpNo = portIntNo(port);
    
    if (intpNo == 0xffU) // Invalid port is specified
    {
        return;
    }

    /* Set interrupt edge polarity */
    /* Rising edge */
    if( (irqMode == IRQ_RISING_EDGE) || (irqMode == IRQ_RISING_FALLING_EDGE) )
    {
        /* Enable interrupt by rising edge */
        if(intpNo < 8U) //INTP0 to INTP6
        {
            EGP0 = EGP0 | (0x01U << intpNo);
        }
        else //INTP8 to INTP11
        {
            EGP1 = EGP1 | (0x01U << (intpNo - 8U));
        }
    }
    else // irqMode == IRQ_FALLING_EDGE
    {
        /* Disable interrupt by rising edge */
        if(intpNo < 8U) //INTP0 to INTP6
        {
            EGP0 = EGP0 & ~(0x01U << intpNo);
        }
        else //INTP8 to INTP11
        {
            EGP1 = EGP1 & ~(0x01U << (intpNo - 8U));
        }
    }
    
    /* Falling edge */
    if( (irqMode == IRQ_FALLING_EDGE) || (irqMode == IRQ_RISING_FALLING_EDGE) )
    {
        /* Enable interrupt by falling edge */
        if(intpNo < 8U) //INTP0 to INTP6
        {
            EGN0 = EGN0 | (0x01U << intpNo);
        }
        else //INTP8 to INTP11
        {
            EGN1 = EGN1 | (0x01U << (intpNo - 8U));
        }
    }
    else // irqMode == IRQ_RISING_EDGE
    {
        /* Disable interrupt by falling edge */
        if(intpNo < 8U) //INTP0 to INTP6
        {
            EGN0 = EGN0 & ~(0x01U << intpNo);
        }
        else //INTP8 to INTP11
        {
            EGN1 = EGN1 & ~(0x01U << (intpNo - 8U));
        }
    }
    
    /* Decode interrupt priority */
    switch( irqPriority )
    {
        case IRQ_VERY_LOW_PRIORITY:
            priority1 = 0x01U;
            priority0 = 0x01U;
            break;
        case IRQ_LOW_PRIORITY:
            priority1 = 0x01U;
            priority0 = 0x01U;
            break;
        case IRQ_MEDIUM_PRIORITY:
            priority1 = 0x01U;
            priority0 = 0x00U;
            break;
        case IRQ_HIGH_PRIORITY:
            priority1 = 0x00U;
            priority0 = 0x01U;
            break;
        case IRQ_VERY_HIGH_PRIORITY:
            priority1 = 0x00U;
            priority0 = 0x00U;
            break;
        default:
            priority1 = 0x01U;
            priority0 = 0x01U;
            break;
    }
    
    /* Set interrupt priority */
    if(intpNo <= 5U)		// INTP0 to INTP5
    {
        PR00L = (PR00L & ~(0x01U << (intpNo + 2U))) | (priority0 << (intpNo + 2U));
        PR10L = (PR00L & ~(0x01U << (intpNo + 2U))) | (priority1 << (intpNo + 2U));
    }
    else if(intpNo <= 10U)	// INTP6 to INTP10
    {
        PR02L = (PR02L & ~(0x01U << ((intpNo - 6U) + 3U))) | (priority0 << ((intpNo - 6U) + 3U));
        PR12L = (PR02L & ~(0x01U << ((intpNo - 6U) + 3U))) | (priority1 << ((intpNo - 6U) + 3U));
    }
    else			// INTP11
    {
        PR02H = (PR02H & ~(0x01U << (intpNo - 11U))) | (priority0 << (intpNo - 11U));
        PR12H = (PR02H & ~(0x01U << (intpNo - 11U))) | (priority1 << (intpNo - 11U));
    }
    
    
    /* Enable or disable interrupt */
    if( irqMode == NO_IRQ )
    {
        intpMask = 0x01U;
    }
    else
    {
        intpMask = 0x00U;
    }
    
    /* INTP mask and flag configuration */
    if(intpNo <= 5U)		// INTP0 to INTP5
    {
        MK0L = (MK0L & ~(0x01U << (intpNo + 2U))) | (intpMask << (intpNo + 2U));	// PMK0 to PMK5
        IF0L = (IF0L & ~(0x01U << (intpNo + 2U)));					// PIF0 to PIF5
    }
    else if(intpNo <= 10U)	// INTP6 to INTP10
    {
        MK2L = (MK2L & ~(0x01U << ((intpNo - 6U) + 3U))) | (intpMask << ((intpNo - 6U) + 3U));	// PMK6 to PMK10
        IF2L = (IF2L & ~(0x01U << ((intpNo - 6U) + 3U)));					// PIF6 to PIF10
    }
    else			// INTP11
    {
        MK2H = (MK2H & ~(0x01U << (intpNo - 11U))) | (intpMask << (intpNo - 11U));	// PMK11
        IF2H = (IF2H & ~(0x01U << (intpNo - 11U)));					// PIF11
    }
    
    /* Configure callback functions */
    RpMcuSetIntpCallback((RP_MCU_INT_INTP0 + intpNo), pIntpHandler, obj->Context);
}

	
static void RpMcuSetIntpCallback(uint16_t intNo, GpioIrqHandler *pIntpHandler, void* context)
{
    if(pIntpHandler == NULL)
    {
         return;
    }

    if (intNo <= INTMAX){
        pRpMcuIntpCallback[intNo] = pIntpHandler;
        pRpMcuIntpCtx[intNo]      = context;
    }
}


#ifdef __ICCRL78__
__interrupt static void RpMcuIntp0Interrupthandler(void)
#else
static void __near RpMcuIntp0Interrupthandler(void)
#endif
{
    BoardEnableMultipleInterrupt();
    PMK0 = 1;
    (*pRpMcuIntpCallback[0])(pRpMcuIntpCtx[0]);
    PIF0 = 0;
    PMK0 = 0;
}

#ifdef __ICCRL78__
__interrupt static void RpMcuIntp1Interrupthandler(void)
#else
static void __near RpMcuIntp1Interrupthandler(void)
#endif
{
    BoardEnableMultipleInterrupt();
    PMK1 = 1;
    (*pRpMcuIntpCallback[1])(pRpMcuIntpCtx[1]);
    PIF1 = 0;
    PMK1 = 0;
}

#ifdef __ICCRL78__
__interrupt static void RpMcuIntp2Interrupthandler(void)
#else
static void __near RpMcuIntp2Interrupthandler(void)
#endif
{
    BoardEnableMultipleInterrupt();
    PMK2 = 1;
    (*pRpMcuIntpCallback[2])(pRpMcuIntpCtx[2]);
    PIF2 = 0;
    PMK2 = 0;
}

#ifdef __ICCRL78__
__interrupt static void RpMcuIntp3Interrupthandler(void)
#else
static void __near RpMcuIntp3Interrupthandler(void)
#endif
{
    BoardEnableMultipleInterrupt();
    PMK3 = 1;
    (*pRpMcuIntpCallback[3])(pRpMcuIntpCtx[3]);
    PIF3 = 0;
    PMK3 = 0;
}

#if defined(__ICCRL78__)
__interrupt static void RpMcuIntp4Interrupthandler(void)
#else
static void __near RpMcuIntp4Interrupthandler(void)
#endif
{
    BoardEnableMultipleInterrupt();
    PMK4 = 1;
    (*pRpMcuIntpCallback[4])(pRpMcuIntpCtx[4]);
    PIF4 = 0;
    PMK4 = 0;
}

#ifdef __ICCRL78__
__interrupt static void RpMcuIntp5Interrupthandler(void)
#else
static void __near RpMcuIntp5Interrupthandler(void)
#endif
{
    BoardEnableMultipleInterrupt();
    PMK5 = 1;
    (*pRpMcuIntpCallback[5])(pRpMcuIntpCtx[5]);
    PIF5 = 0;
    PMK5 = 0;
}

#ifdef __ICCRL78__
__interrupt static void RpMcuIntp6Interrupthandler(void)
#else
static void __near RpMcuIntp6Interrupthandler(void)
#endif
{
    BoardEnableMultipleInterrupt();
    PMK6 = 1;
    (*pRpMcuIntpCallback[6])(pRpMcuIntpCtx[6]);
    PIF6 = 0;
    PMK6 = 0;
}

#if defined( INTP7 )
#ifdef __ICCRL78__
__interrupt static void RpMcuIntp7Interrupthandler(void)
#else
static void __near RpMcuIntp7Interrupthandler(void)
#endif
{
    BoardEnableMultipleInterrupt();
    PMK7 = 1;
    (*pRpMcuIntpCallback[7])(pRpMcuIntpCtx[7]);
    PIF7 = 0;
    PMK7 = 0;
}
#endif //#if defined( INTP7 )

#ifdef __ICCRL78__
__interrupt static void RpMcuIntp8Interrupthandler(void)
#else
static void __near RpMcuIntp8Interrupthandler(void)
#endif
{
    BoardEnableMultipleInterrupt();
    PMK8 = 1;
    (*pRpMcuIntpCallback[8])(pRpMcuIntpCtx[8]);
    PIF8 = 0;
    PMK8 = 0;
}

#ifdef __ICCRL78__
__interrupt static void RpMcuIntp9Interrupthandler(void)
#else
static void __near RpMcuIntp9Interrupthandler(void)
#endif
{
    BoardEnableMultipleInterrupt();
    PMK9 = 1;
    (*pRpMcuIntpCallback[9])(pRpMcuIntpCtx[9]);
    PIF9 = 0;
    PMK9 = 0;
}

#if defined( INTP10 )
#ifdef __ICCRL78__
__interrupt static void RpMcuIntp10Interrupthandler(void)
#else
static void __near RpMcuIntp10Interrupthandler(void)
#endif
{
    BoardEnableMultipleInterrupt();
    PMK10 = 1;
    (*pRpMcuIntpCallback[10])(pRpMcuIntpCtx[10]);
    PIF10 = 0;
    PMK10 = 0;
}
#endif //#if defined( INTP10 )

#if defined( INTP11 )
#ifdef __ICCRL78__
__interrupt static void RpMcuIntp11Interrupthandler(void)
#else
static void __near RpMcuIntp11Interrupthandler(void)
#endif
{
    BoardEnableMultipleInterrupt();
    PMK11 = 1;
    (*pRpMcuIntpCallback[11])(pRpMcuIntpCtx[11]);
    PIF11 = 0;
    PMK11 = 0;
}
#endif //#if defined( INTP11 )

static void RpMcuIntpXCallbackDefault (void* context)
{
	(void)context;
    /* none */
}

