#ifndef _GW3323_GPIO_H
#define _GW3323_GPIO_H

#include "include.h"

//---------- GPIO pin definition ----------//
#define GPIO_PIN_0                  ((uint8_t)0x01)
#define GPIO_PIN_1                  ((uint8_t)0x02)
#define GPIO_PIN_2                  ((uint8_t)0x04)
#define GPIO_PIN_3                  ((uint8_t)0x08)
#define GPIO_PIN_4                  ((uint8_t)0x10)
#define GPIO_PIN_5                  ((uint8_t)0x20)
#define GPIO_PIN_6                  ((uint8_t)0x40)
#define GPIO_PIN_7                  ((uint8_t)0x80)

//---------- Mapping definition ----------//
//bit[15:12]:    FUNCMCONx REG address offset
//bit[11:4] :    INNER offset in register
//bit[3:0]  :    which gpio mapping selected
#define FUNCMCONx_MASK_REG          ((uint16_t)0xf000)
#define FUNCMCONx_MASK_INNER        ((uint16_t)0x0ff0)
#define FUNCMCONx_MASK_MAPPING      ((uint16_t)0x000f)

#define UT1RXMAP_PA6                ((uint16_t)0x01c1)
#define UT1RXMAP_PA3                ((uint16_t)0x01c2)
#define UT1RXMAP_TX_PIN             ((uint16_t)0x01c3)
#define UT1RXMAP_CLEAR              ((uint16_t)0x01cf)

#define UT1TXMAP_PA7                ((uint16_t)0x0181)
#define UT1TXMAP_PA4                ((uint16_t)0x0182)
#define UT1TXMAP_CLEAR              ((uint16_t)0x018f)

#define HSUTRXMAP_PA7               ((uint16_t)0x0141)
#define HSUTRXMAP_PB2               ((uint16_t)0x0142)
#define HSUTRXMAP_PB3               ((uint16_t)0x0143)
#define HSUTRXMAP_PE7               ((uint16_t)0x0144)
#define HSUTRXMAP_PB1               ((uint16_t)0x0147)
#define HSUTRXMAP_PB4               ((uint16_t)0x0148)
#define HSUTRXMAP_PE6               ((uint16_t)0x0149)
#define HSUTRXMAP_CLEAR             ((uint16_t)0x014f)

#define HSUTTXMAP_PA7               ((uint16_t)0x0101)
#define HSUTTXMAP_PB2               ((uint16_t)0x0102)
#define HSUTTXMAP_PB3               ((uint16_t)0x0103)
#define HSUTTXMAP_PE7               ((uint16_t)0x0104)
#define HSUTTXMAP_PB1               ((uint16_t)0x0107)
#define HSUTTXMAP_PB4               ((uint16_t)0x0108)
#define HSUTTXMAP_PE6               ((uint16_t)0x0109)
#define HSUTTXMAP_CLEAR             ((uint16_t)0x010f)

#define UT0RXMAP_PA6                ((uint16_t)0x00c1)
#define UT0RXMAP_PB1                ((uint16_t)0x00c2)
#define UT0RXMAP_PB4                ((uint16_t)0x00c3)
#define UT0RXMAP_PE6                ((uint16_t)0x00c4)
#define UT0RXMAP_TX_PIN             ((uint16_t)0x00c7)
#define UT0RXMAP_CLEAR              ((uint16_t)0x00cf)

#define UT0TXMAP_PA7                ((uint16_t)0x0081)
#define UT0TXMAP_PB2                ((uint16_t)0x0082)
#define UT0TXMAP_PB3                ((uint16_t)0x0083)
#define UT0TXMAP_PE7                ((uint16_t)0x0084)
#define UT0TXMAP_PE0                ((uint16_t)0x0085)
#define UT0TXMAP_PF1                ((uint16_t)0x0086)
#define UT0TXMAP_PF5                ((uint16_t)0x0087)
#define UT0TXMAP_CLEAR              ((uint16_t)0x008f)

#define SPI0MAP_G1                  ((uint16_t)0x0041)      // CLK:PG4  DO:PG5  DI:PG1  CS:PG2
#define SPI0MAP_G3                  ((uint16_t)0x0043)      // CLK:PB4  DO:PB3  DI:PE0
#define SPI0MAP_CLEAR               ((uint16_t)0x004f)

#define SD0_MAP_G1                  ((uint16_t)0x0001)      // CLK:PA6  CMD:PA5  DAT:PA7
#define SD0_MAP_G2                  ((uint16_t)0x0002)      // CLK:PB1  CMD:PB0  DAT:PB2
#define SD0_MAP_G3                  ((uint16_t)0x0003)      // CLK:PE6  CMD:PE5  DAT:PE7
#define SD0_MAP_G4                  ((uint16_t)0x0004)      // CLK:PA6  CMD:PA5  DAT:PB4
#define SD0_MAP_G5                  ((uint16_t)0x0005)      // CLK:PA6  CMD:PA5  DAT:PB3
#define SD0_MAP_G6                  ((uint16_t)0x0006)      // CLK:PA6  CMD:PB3  DAT:PB4
#define SD0_MAP_G7                  ((uint16_t)0x0007)      // CLK:PF4  CMD:PF5  DAT:PA7
#define SD0_MAP_CLEAR               ((uint16_t)0x000f)

#define SPI1_MAP_G1                 ((uint16_t)0x10c1)      // CLK:PA3  DO:PA4  DI:PA5
#define SPI1_MAP_G2                 ((uint16_t)0x10c2)      // CLK:PA6  DO:PA7  DI:PA5
#define SPI1_MAP_G3                 ((uint16_t)0x10c3)      // CLK:PB1  DO:PB2  DI:PB0
#define SPI1_MAP_G4                 ((uint16_t)0x10c4)      // CLK:PE6  DO:PE7  DI:PE5
#define SPI1_MAP_G5                 ((uint16_t)0x10c5)      // CLK:PF4  DO:PF5  DI:PF1
#define SPI1_MAP_CLEAR              ((uint16_t)0x10cf)

#define UT2RXMAP_PB1                ((uint16_t)0x1082)
#define UT2RXMAP_TX_PIN             ((uint16_t)0x1083)
#define UT2RXMAP_CLEAR              ((uint16_t)0x108f)

#define UT2TXMAP_PB2                ((uint16_t)0x1042)
#define UT2TXMAP_CLEAR              ((uint16_t)0x104f)

#define CLK_OUT_MAP_PA5             ((uint16_t)0x1001)
#define CLK_OUT_MAP_PA6             ((uint16_t)0x1002)
#define CLK_OUT_MAP_PB0             ((uint16_t)0x1003)
#define CLK_OUT_MAP_PB1             ((uint16_t)0x1004)
#define CLK_OUT_MAP_PE5             ((uint16_t)0x1005)
#define CLK_OUT_MAP_PE6             ((uint16_t)0x1006)
#define CLK_OUT_MAP_CLEAR           ((uint16_t)0x100f)

#define IICMAP_G1                   ((uint16_t)0x2181)      // DAT:PA7  CLK:PA6
#define IICMAP_G2                   ((uint16_t)0x2182)      // DAT:PA5  CLK:PA6
#define IICMAP_G3                   ((uint16_t)0x2183)      // DAT:PB2  CLK:PB1
#define IICMAP_G4                   ((uint16_t)0x2184)      // DAT:PB0  CLK:PB1
#define IICMAP_G5                   ((uint16_t)0x2185)      // DAT:PE7  CLK:PE6
#define IICMAP_G6                   ((uint16_t)0x2186)      // DAT:PE5  CLK:PE6
#define IICMAP_G7                   ((uint16_t)0x2187)      // DAT:PF5  CLK:PF4
#define IICMAP_G8                   ((uint16_t)0x2188)      // DAT:PB4  CLK:PB3
#define IICMAP_CLEAR                ((uint16_t)0x218f)

#define IR_MAP_PA5                  ((uint16_t)0x2141)
#define IR_MAP_PA6                  ((uint16_t)0x2142)
#define IR_MAP_PB0                  ((uint16_t)0x2143)
#define IR_MAP_PB1                  ((uint16_t)0x2144)
#define IR_MAP_PE0                  ((uint16_t)0x2145)
#define IR_MAP_PE5                  ((uint16_t)0x2146)
#define IR_MAP_PE6                  ((uint16_t)0x2147)
#define IR_MAP_PE7                  ((uint16_t)0x2148)
#define IR_MAP_PF1                  ((uint16_t)0x2149)
#define IR_MAP_CLEAR                ((uint16_t)0x214f)

#define TMR5MAP_G1                  ((uint16_t)0x2101)      // PWM0:PA5  PWM1:PA6  PWM2:PA7
#define TMR5MAP_G2                  ((uint16_t)0x2102)      // PWM0:PF4  PWM1:PF5
#define TMR5MAP_CLEAR               ((uint16_t)0x210f)

#define TMR4MAP_G1                  ((uint16_t)0x20c1)      // PWM0:PE5  PWM1:PE6  PWM2:PE7
#define TMR4MAP_G2                  ((uint16_t)0x20c2)      // PWM0:PF1  PWM1:PF2  PWM2:PF3
#define TMR4MAP_CLEAR               ((uint16_t)0x20cf)

#define TMR3MAP_G1                  ((uint16_t)0x2081)      // PWM0:PB0  PWM1:PB1  PWM2:PB2
#define TMR3MAP_G2                  ((uint16_t)0x2082)      // PWM0:PB3  PWM1:PB4  PWM2:PB5
#define TMR3MAP_G3                  ((uint16_t)0x2083)      // PWM0:PF0  PWM1:PA3  PWM2:PA4
#define TMR3MAP_G4                  ((uint16_t)0x2084)      // PWM0:PE0  PWM1:PE4
#define TMR3MAP_CLEAR               ((uint16_t)0x208f)

#define TMR3CPTMAP_PA5              ((uint16_t)0x2041)
#define TMR3CPTMAP_PA6              ((uint16_t)0x2042)
#define TMR3CPTMAP_PB0              ((uint16_t)0x2043)
#define TMR3CPTMAP_PB1              ((uint16_t)0x2044)
#define TMR3CPTMAP_PE0              ((uint16_t)0x2045)
#define TMR3CPTMAP_PE5              ((uint16_t)0x2046)
#define TMR3CPTMAP_PE6              ((uint16_t)0x2047)
#define TMR3CPTMAP_CLEAR            ((uint16_t)0x204f)

#define IISMAP_G1                   ((uint16_t)0x2001)      // DI:PA3  DO:PA7  BCLK:PA5  LRCLK:PA6  MCLK:PA4
#define IISMAP_G2                   ((uint16_t)0x2002)      // DI:PB2  DO:PE7  BCLK:PE5  LRCLK:PE6  MCLK:PB1
#define IISMAP_G3                   ((uint16_t)0x2003)      // DI:PB5  DO:PE7  BCLK:PB2  LRCLK:PE6  MCLK:PB1
#define IISMAP_CLEAR                ((uint16_t)0x200f)

//GPIO port type enumeration
typedef enum {
    GPIO_MODE_ANALOG  = 0x00,
    GPIO_MODE_DIGITAL = 0x01,
} GPIO_MODE_TYPEDEF;

//GPIO direction enumeration
typedef enum {
    GPIO_DIR_OUTPUT   = 0x00,
    GPIO_DIR_INPUT    = 0x01,
} GPIO_DIR_TYPEDEF;

//GPIO function mapping enable enumeration
typedef enum {
    GPIO_FEN_GPIO    = 0x00,
    GPIO_FEN_PER     = 0x01,
} GPIO_FEN_TYPEDEF;

//GPIO output current enumeration
typedef enum {
    GPIO_DRV_8MA     = 0x00,
    GPIO_DRV_32MA    = 0x01,
} GPIO_DRV_TYPEDEF;

//GPIO input pull resistance enumeration
typedef enum {
    GPIO_PUPD_UP     = 0x00, //10KΩ
    GPIO_PUPD_PD     = 0x01, //10KΩ
    GPIO_PUPD_PU200K = 0x02,
    GPIO_PUPD_PD200K = 0x03,
    GPIO_PUPD_PU300  = 0x04,
    GPIO_PUPD_PD300  = 0x05,
    GPIO_IN_FLOATING = 0x06,
} GPIO_PUPD_TYPEDEF;

//GPIO init structure
typedef struct{
  uint8_t            gpio_pin;
  GPIO_MODE_TYPEDEF  gpio_mode;
  GPIO_DIR_TYPEDEF   gpio_dir;
  GPIO_FEN_TYPEDEF   gpio_fen;
  GPIO_DRV_TYPEDEF   gpio_drv;
  GPIO_PUPD_TYPEDEF  gpio_pupd;
} gpio_init_typedef;

//GPIO 的外部中断表

//Pin selection
typedef enum {
    gpioa7 = 0x00,
    gpiob1,
    gpiob2,
    gpiob3, //尽量不使用PB3，此端口为下载调试口
    gpiob4,
    gpiob5,
    gpio_external_interrupt,      //外部中断为其它引脚时选它
} GPIO_TYPEDEF;

typedef enum{
  exti_trigger_rising = 0x00,   //上升沿
  exti_trigger_falling = 0x01   //下降沿
}Exti_Trigger;

// Other pin selection
typedef enum {
    null   = 0x00,
    gpioa3 = 0x08,
    gpioa4 = 0x10,
    gpioa5 = 0x20,
    gpioa6 = 0x40,
    gpiob0 = 0x100,
    gpioe0 = 0x2000,
    gpioe4 = 0x20000,
    gpioe5 = 0x40000,
    gpioe6 = 0x80000,
    gpioe7 = 0x100000,
    gpiof0 = 0x200000,
    gpiof1 = 0x400000,
    gpiof2 = 0x800000,
    gpiof3 = 0x1000000,
    gpiof4 = 0x2000000,
    gpiof5 = 0x4000000
} GPIO_Other_TYPEDEF;
typedef struct {
    GPIO_TYPEDEF        gpio_exti_line;
    Exti_Trigger        extitrigger;
    GPIO_Other_TYPEDEF  gpio_other_exti_line
} gpio_interrupt_typedef;

//---------- Function used to set or R/W GPIO ----------//
void gpio_init(gpio_typedef* gpiox, gpio_init_typedef* gpio_init_struct);
void gpio_set_bits(gpio_typedef* gpiox, uint8_t gpio_pin);
void gpio_reset_bits(gpio_typedef* gpiox, uint8_t gpio_pin);
void gpio_writebit(gpio_typedef* gpiox, uint8_t gpio_pin, FLAG_STATE BitVal);
void gpio_write_data(gpio_typedef *gpiox, uint8_t port_val);
void gpio_toggle_bits(gpio_typedef *gpiox, uint8_t gpio_pin);
uint8_t gpio_read_data(gpio_typedef* gpiox);
uint8_t gpio_read_bit(gpio_typedef* gpiox, uint8_t gpio_pin);
void gpio_func_mapping(uint16_t gpio_mapping);

void gpio_pic_config_reset(void);
void gpio_pic_config(gpio_interrupt_typedef* gpio_init_struct, isr_t isr, int pr, FUNCTIONAL_STATE state);
FLAG_STATE gpio_get_flag(u32 exti_line);
void gpio_clear_flag(u32 exti_line);

#endif  // _GW3323_GPIO_H
