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

#ifndef __GPIO_H__
#define __GPIO_H__

#define RP_PORT_DIRECTION_OUTPUT       (0U)
#define RP_PORT_DIRECTION_INPUT        (1U)
#define RP_PORT_OUTPUT_HI              (1U)
#define RP_PORT_OUTPUT_LO              (0U)

#include <stdint.h>		// for int32_t
#include "pinName-board.h"

#define RP_INTP1_INTLEVEL              (1U)		// 0U (highest) to 3U (lowest)
#define RP_INTP2_INTLEVEL              (1U)		// 0U (highest) to 3U (lowest)
#define RP_INTP3_INTLEVEL              (1U)		// 0U (highest) to 3U (lowest)
#define RP_INTP4_INTLEVEL              (1U)		// 0U (highest) to 3U (lowest)
#define RP_INTP10_INTLEVEL             (1U)		// 0U (highest) to 3U (lowest)
#define RP_INTP11_INTLEVEL             (1U)		// 0U (highest) to 3U (lowest)

#define RP_INTP1_PPR11                 ((RP_INTP1_INTLEVEL & 0x02U) >> 1)
#define RP_INTP1_PPR01                  (RP_INTP1_INTLEVEL & 0x01U)
#define RP_INTP2_PPR11                 ((RP_INTP2_INTLEVEL & 0x02U) >> 1)
#define RP_INTP2_PPR01                  (RP_INTP2_INTLEVEL & 0x01U)
#define RP_INTP3_PPR11                 ((RP_INTP3_INTLEVEL & 0x02U) >> 1)
#define RP_INTP3_PPR01                  (RP_INTP3_INTLEVEL & 0x01U)
#define RP_INTP4_PPR11                 ((RP_INTP4_INTLEVEL & 0x02U) >> 1)
#define RP_INTP4_PPR01                  (RP_INTP4_INTLEVEL & 0x01U)
#define RP_INTP10_PPR11                ((RP_INTP10_INTLEVEL & 0x02U) >> 1)
#define RP_INTP10_PPR01                 (RP_INTP10_INTLEVEL & 0x01U)
#define RP_INTP11_PPR11                ((RP_INTP11_INTLEVEL & 0x02U) >> 1)
#define RP_INTP11_PPR01                 (RP_INTP11_INTLEVEL & 0x01U)

#define RP_MCU_P0_ADDR                 (0xff00U)	//address of P0 (__near)
#define RP_MCU_PM0_ADDR                (0xff20U)	//address of PM0 (__near)
#define RP_MCU_PU0_ADDR                (0x0030U)	//address of PU0 (__near)
#define RP_MCU_PIM0_ADDR               (0x0040U)	//address of PIM0 (__near)
#define RP_MCU_POM0_ADDR               (0x0050U)	//address of POM0 (__near)
#define RP_MCU_PMC0_ADDR               (0x0060U)	//address of PMC0 (__near)
#define RP_MCU_ADPC_ADDR               (0x0076U)	//address of ADPC0 (__near)

#define RP_P0_BITMASK                  (0x7fU)
#define RP_P1_BITMASK                  (0xffU)
#define RP_P2_BITMASK                  (0xffU)
#define RP_P3_BITMASK                  (0x03U)
#define RP_P4_BITMASK                  (0xffU)
#define RP_P5_BITMASK                  (0xffU)
#define RP_P6_BITMASK                  (0xffU)
#define RP_P7_BITMASK                  (0xffU)
#define RP_P12_BITMASK                 (0x1fU)
#define RP_P13_BITMASK                 (0x81U)
#define RP_P14_BITMASK                 (0xffU)

#define RP_PM0_BITMASK                 (0x7fU)
#define RP_PM1_BITMASK                 (0xffU)
#define RP_PM2_BITMASK                 (0xffU)
#define RP_PM3_BITMASK                 (0x03U)
#define RP_PM4_BITMASK                 (0xffU)
#define RP_PM5_BITMASK                 (0xffU)
#define RP_PM6_BITMASK                 (0xffU)
#define RP_PM7_BITMASK                 (0xffU)
#define RP_PM12_BITMASK                (0x01U)
#define RP_PM14_BITMASK                (0xffU)

#define RP_PU0_BITMASK                 (0x7fU)
#define RP_PU1_BITMASK                 (0xffU)
#define RP_PU3_BITMASK                 (0x03U)
#define RP_PU4_BITMASK                 (0xffU)
#define RP_PU5_BITMASK                 (0xffU)
#define RP_PU6_BITMASK                 (0xf0U)
#define RP_PU7_BITMASK                 (0xffU)
#define RP_PU12_BITMASK                (0x01U)
#define RP_PU14_BITMASK                (0xffU)

#define RP_PIM0_BITMASK                (0x1aU)
#define RP_PIM1_BITMASK                (0xf1U)
#define RP_PIM3_BITMASK                (0x01U)
#define RP_PIM4_BITMASK                (0x18U)
#define RP_PIM5_BITMASK                (0x39U)
#define RP_PIM14_BITMASK               (0x0cU)

#define RP_POM0_BITMASK                (0x1dU)
#define RP_POM1_BITMASK                (0xbbU)
#define RP_POM3_BITMASK                (0x01U)
#define RP_POM4_BITMASK                (0x38U)
#define RP_POM5_BITMASK                (0x3fU)
#define RP_POM7_BITMASK                (0x12U)
#define RP_POM14_BITMASK               (0x1cU)

#define RP_PMC0_BITMASK                (0x0fU)
#define RP_PMC1_BITMASK                (0xccU)
#define RP_PMC12_BITMASK               (0x01U)
#define RP_PMC14_BITMASK               (0x80U)

#define RP_ADPC_BITMASK                (0x0fU)		// Congirable ports are P20-27, P150-156

#define RP_MCU_INT_INTP0               (0x00U)
#define RP_MCU_INT_INTP1               (0x01U)
#define RP_MCU_INT_INTP2               (0x02U)
#define RP_MCU_INT_INTP3               (0x03U)
#define RP_MCU_INT_INTP4               (0x04U)
#define RP_MCU_INT_INTP5               (0x05U)
#define RP_MCU_INT_INTP6               (0x06U)
#define RP_MCU_INT_INTP7               (0x07U)
#define RP_MCU_INT_INTP8               (0x08U)
#define RP_MCU_INT_INTP9               (0x09U)
#define RP_MCU_INT_INTP10              (0x0aU)
#define RP_MCU_INT_INTP11              (0x0bU)


/** @defgroup GPIO_Exported_Types GPIO Exported Types
  * @{
  */
/** 
  * @brief   GPIO Init structure definition  
  */
typedef struct
{
  uint32_t Pin;       /*!< Specifies the GPIO pins to be configured.
                           This parameter can be any value of @ref GPIO_pins */

  uint32_t Mode;      /*!< Specifies the operating mode for the selected pins.
                           This parameter can be a value of @ref GPIO_mode */

  uint32_t Pull;      /*!< Specifies the Pull-up or Pull-Down activation for the selected pins.
                           This parameter can be a value of @ref GPIO_pull */

  uint32_t Speed;     /*!< Specifies the speed for the selected pins.
                           This parameter can be a value of @ref GPIO_speed */

  uint32_t Alternate;  /*!< Peripheral to be connected to the selected pins 
                            This parameter can be a value of @ref GPIOEx_Alternate_function_selection */
}GPIO_InitTypeDef;


/*!
 * Board GPIO pin names
 */
typedef enum
{
    MCU_PINS,
    IOE_PINS,

    // Not connected
    NC = (int16_t)0xFFFF
}PinNames;

/*!
 * Operation Mode for the GPIO
 */
typedef enum
{
    PIN_INPUT = 0,
    PIN_OUTPUT,
    PIN_ALTERNATE_FCT,
    PIN_ANALOGIC
}PinModes;

/*!
 * Add a pull-up, a pull-down or nothing on the GPIO line
 */
typedef enum
{
    PIN_NO_PULL = 0,
    PIN_PULL_UP,
}PinTypes;

/*!
 * Define the GPIO as Push-pull type or Open Drain
 */
typedef enum
{
    PIN_PUSH_PULL = 0,	// Schmitt input
    PIN_OPEN_DRAIN,	// (pseudo) n-ch open drain output
    PIN_TTL		// TTL input
}PinConfigs;

/*!
 * Define the GPIO IRQ on a rising, falling or both edges
 */
typedef enum
{
    NO_IRQ = 0,
    IRQ_RISING_EDGE,
    IRQ_FALLING_EDGE,
    IRQ_RISING_FALLING_EDGE
}IrqModes;

/*!
 * Define the IRQ priority on the GPIO
 */
typedef enum
{
    IRQ_VERY_LOW_PRIORITY = 0,
    IRQ_LOW_PRIORITY,
    IRQ_MEDIUM_PRIORITY,
    IRQ_HIGH_PRIORITY,
    IRQ_VERY_HIGH_PRIORITY
}IrqPriorities;

/*!
 * Structure for the GPIO
 */
typedef struct
{
    PinNames  pin;
    PinTypes  pull;
    void        *port;
    uint16_t    pinIndex;
    uint16_t    portIndex;
    void* Context;
}Gpio_t;


/*!
 * GPIO IRQ handler function prototype
 */
typedef void( GpioIrqHandler )( void* context );



/*!
 * \brief Equivalent to GpioInit()
 */
void RpMcuGpioMcuInit(  Gpio_t *obj, PinNames pin, PinModes mode, PinConfigs config, PinTypes type
                        , unsigned value  );

static inline
void GpioMcuInit( Gpio_t *obj, PinNames pin, PinModes mode
                            , PinConfigs config, PinTypes type
                            , unsigned value )
{
    RpMcuGpioMcuInit(obj, pin, mode, config, type, value);
}

/*!
 * \brief Equivalent to GpioWrite()
 */
void GpioMcuWrite( Gpio_t *obj, unsigned value );

/*!
 * \brief Equivalent to GpioToggle()
 */
void GpioMcuToggle( Gpio_t *obj  );

/*!
 * \brief Configures port interrupts
 */
void RpMcuIntpInit( void );

/*!
 * \brief Initializes the given GPIO object
 *
 * \param [IN] obj    Pointer to the GPIO object
 * \param [IN] pin    Pin name ( please look in pinName-board.h file )
 * \param [IN] mode   Pin mode [PIN_INPUT, PIN_OUTPUT,
 *                              PIN_ALTERNATE_FCT, PIN_ANALOGIC]
 * \param [IN] config Pin config [PIN_PUSH_PULL, PIN_OPEN_DRAIN]
 * \param [IN] type   Pin type [PIN_NO_PULL, PIN_PULL_UP, PIN_PULL_DOWN]
 * \param [IN] value  Default output value at initialization
 */
void GpioInit( Gpio_t *obj, PinNames pin, PinModes mode, PinConfigs config, PinTypes type, unsigned value );

/*!
 * \brief Sets a user defined object pointer
 *
 * \param [IN] context User defined data object pointer to pass back
 *                     on IRQ handler callback
 */

static inline
void GpioMcuSetContext( Gpio_t *obj, void* context ){
    obj->Context = context;
}

/*!
 * \brief GPIO IRQ Initialization
 *
 * \param [IN] obj         Pointer to the GPIO object
 * \param [IN] irqMode     IRQ mode [NO_IRQ, IRQ_RISING_EDGE,
 *                                   IRQ_FALLING_EDGE, IRQ_RISING_FALLING_EDGE]
 * \param [IN] irqPriority IRQ priority [IRQ_VERY_LOW_PRIORITY, IRQ_LOW_PRIORITY
 *                                       IRQ_MEDIUM_PRIORITY, IRQ_HIGH_PRIORITY
 *                                       IRQ_VERY_HIGH_PRIORITY]
 * \param [IN] irqHandler  Callback function pointer
 */
void GpioSetInterrupt( Gpio_t *obj, IrqModes irqMode, IrqPriorities irqPriority, GpioIrqHandler *irqHandler );

/*!
 * \brief Removes the interrupt from the object
 *
 * \param [IN] obj Pointer to the GPIO object
 */
void GpioRemoveInterrupt( Gpio_t *obj );

/*!
 * \brief Writes the given value to the GPIO output
 *
 * \param [IN] obj   Pointer to the GPIO object
 * \param [IN] value New GPIO output value
 */
void GpioWrite( Gpio_t *obj, unsigned value );

/*!
 * \brief Toggle the value to the GPIO output
 *
 * \param [IN] obj   Pointer to the GPIO object
 */
void GpioToggle( Gpio_t *obj );

/*!
 * \brief Reads the current GPIO input value
 *
 * \param [IN] obj Pointer to the GPIO object
 * \retval value   Current GPIO input value
 */
unsigned GpioRead( Gpio_t *obj );

#endif //#ifndef __GPIO_H__
