#ifndef __INTERFACE_H
#define __INTERFACE_H

#include "includes.h"
#include "stm32f4xx_rcc.h"
#include <stm32f4xx.h>

typedef enum
{
    kI2C0 = 0,
    kI2C1,
    kI2C2,
    kADC0,
    kADC3,
    kSPI1,
    kUart1,
    kUart3,
    kCAN1,
    kCAN2,
    kEthernet_dm9161,
    kFSMC,
    kInput,
    kOutput,
    kPMU,
    kDMA1,
    kAM2303,
    //    kTIMER1,
    kInterfaceEnd,
} interface_type;

typedef enum
{
    RCC_APB1Periph,
    RCC_APB2Periph,
    RCC_AHB1Periph,
    RCC_AHB2Periph,
    RCC_AHB3Periph,
} enum_clock_type;

typedef struct
{
    interface_type  type;
    enum_clock_type RCC_AXBPeriph;
    uint32_t        AF_Clock;
} Gpio_Clock;

typedef enum
{
    kTFTLCD,
    kRunLed,
    kAd7606,
    kPRelayCtr,
    kNRelayCtr,
    kPreRelayCtr,
    kFanCtr,
    kOut1Ctr, // charger
    kOut2Ctr, // charger heat
    kExtWatchDog,
    kExtRelayLed,
    kExtFaultLed,
    kISOPRelayCtr,
    kISONRelayCtr,
    kSoftI2C3_SDA,
    kSoftI2C3_SCL,
    kSoftI2C4_SDA,
    kSoftI2C4_SCL,
    kOutputEnd,
} Output_Type;

typedef enum
{
    DM9K_INIT,
    NOR_FLASH_STATE,
    NAND_FLASH_STATE,
    kInputEnd,
    kKey,
} Input_type;

typedef struct
{
    GPIO_TypeDef *GPIOx;
    INT16U        GPIO_PinSource;
    INT8U         GPIO_AF;
} GPIO_AF_Info;

typedef struct
{
    interface_type    type;
    Output_Type       Out_Type;
    Input_type        In_Type;
    GPIO_TypeDef     *GPIOx;
    INT32U            GPIO_Pin;
    GPIOMode_TypeDef  GPIO_Mode;
    GPIO_AF_Info      AF_Info;
    GPIOOType_TypeDef GPIO_OType;
    GPIOSpeed_TypeDef GPIO_Speed;
    GPIOPuPd_TypeDef  GPIO_PuPd;
} Interface_struct;

// // soft I2C
// #define SI2C3_SDA_PIN GPIO_PIN_3
// #define SI2C3_SDA_PORT GPIOD
// #define SI2C3_SCL_PIN GPIO_PIN_2
// #define SI2C3_SCL_PORT GPIOD
// #define SI2C4_SDA_PIN GPIO_PIN_15
// #define SI2C4_SDA_PORT GPIOE
// #define SI2C4_SCL_PIN GPIO_PIN_14
// #define SI2C4_SCL_PORT GPIOE

// #define SI2C3_SDA_HIGH GPIO_SetBits(SI2C3_SDA_PORT, SI2C3_SDA_PIN)
// #define SI2C3_SDA_LOW GPIO_ResetBits(SI2C3_SDA_PORT, SI2C3_SDA_PIN)
// #define SI2C3_SCL_HIGH GPIO_SetBits(SI2C3_SCL_PORT, SI2C3_SCL_PIN)
// #define SI2C3_SCL_LOW GPIO_ResetBits(SI2C3_SCL_PORT, SI2C3_SCL_PIN)
// #define SI2C4_SDA_HIGH GPIO_SetBits(SI2C4_SDA_PORT, SI2C4_SDA_PIN)
// #define SI2C4_SDA_LOW GPIO_ResetBits(SI2C4_SDA_PORT, SI2C4_SDA_PIN)
// #define SI2C4_SCL_HIGH GPIO_SetBits(SI2C4_SCL_PORT, SI2C4_SCL_PIN)
// #define SI2C4_SCL_LOW GPIO_ResetBits(SI2C4_SCL_PORT, SI2C4_SCL_PIN)

// #define SI2C3_SDA_OUT gpio_mode_set(SI2C3_SDA_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, SI2C3_SDA_PIN)
// #define SI2C3_SDA_IN gpio_mode_set(SI2C3_SDA_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, SI2C3_SDA_PIN)
// #define SI2C3_SDA_READ gpio_input_bit_get(SI2C3_SDA_PORT, SI2C3_SDA_PIN)
// #define SI2C4_SDA_OUT gpio_mode_set(SI2C4_SDA_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, SI2C4_SDA_PIN)
// #define SI2C4_SDA_IN gpio_mode_set(SI2C4_SDA_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, SI2C4_SDA_PIN)
// #define SI2C4_SDA_READ gpio_input_bit_get(SI2C4_SDA_PORT, SI2C4_SDA_PIN)

// uart
#define UART3_ENABLE_PORT GPIOB
#define UART3_ENABLE_PIN  GPIO_Pin_2
#define UART3_TX_ENABLE   GPIO_SetBits(UART3_ENABLE_PORT, UART3_ENABLE_PIN)
#define UART3_RX_ENABLE   GPIO_ResetBits(UART3_ENABLE_PORT, UART3_ENABLE_PIN)

// SPI
#define SPI1_CS_PORT GPIOF
#define SPI1_CS_PIN  GPIO_Pin_8
#define SPI1_CS_HIGH GPIO_SetBits(SPI2_CS_PORT, SPI2_CS_PIN)
#define SPI1_CS_LOW  GPIO_ResetBits(SPI2_CS_PORT, SPI2_CS_PIN)

// ethernet
#define ETH_RESET_PORT GPIOH
#define ETH_RESET_PIN  GPIO_Pin_6
// #define ETH_RXER_PORT GPIOG
// #define ETH_RXER_PIN GPIO_PIN_12
#define ETH_RESET_ON  GPIO_ResetBits(ETH_RESET_PORT, ETH_RESET_PIN)
#define ETH_RESET_OFF GPIO_SetBits(ETH_RESET_PORT, ETH_RESET_PIN)

// input
#define DM9K_RESET_PORT GPIOA
#define DM9K_RESET_PIN  GPIO_Pin_15
#define DM9K_RESET_ON   GPIO_ResetBits(DM9K_RESET_PORT, DM9K_RESET_PIN)
#define DM9K_RESET_OFF  GPIO_SetBits(DM9K_RESET_PORT, DM9K_RESET_PIN)

#define NOR_FLASH_STATE_PORT GPIOD
#define NOR_FLASH_STATE_PIN  GPIO_Pin_6
#define NOR_FLASH_STATE_ON   GPIO_ResetBits(NOR_FLASH_STATE_PORT, NOR_FLASH_STATE_PIN)
#define NOR_FLASH_STATE_OFF  GPIO_SetBits(NOR_FLASH_STATE_PORT, NOR_FLASH_STATE_PIN)

#define NAND_FLASH_STATE_PORT GPIOG
#define NAND_FLASH_STATE_PIN  GPIO_Pin_6
#define NAND_FLASH_STATE_ON   GPIO_ResetBits(NAND_FLASH_STATE_PORT, NAND_FLASH_STATE_PIN)
#define NAND_FLASH_STATE_OFF  GPIO_SetBits(NAND_FLASH_STATE_PORT, NAND_FLASH_STATE_PIN)

#define GPIO_PORT_K1 GPIOI
#define GPIO_PIN_K1  GPIO_Pin_8

#define GPIO_PORT_K2 GPIOC
#define GPIO_PIN_K2  GPIO_Pin_13

#define GPIO_PORT_K3 GPIOI
#define GPIO_PIN_K3  GPIO_Pin_11

#define GPIO_PORT_K4 GPIOH
#define GPIO_PIN_K4  GPIO_Pin_2

#define GPIO_PORT_K5 GPIOH
#define GPIO_PIN_K5  GPIO_Pin_3

#define GPIO_PORT_K6 GPIOF
#define GPIO_PIN_K6  GPIO_Pin_11

#define GPIO_PORT_K7 GPIOG
#define GPIO_PIN_K7  GPIO_Pin_7

#define GPIO_PORT_K8 GPIOH
#define GPIO_PIN_K8  GPIO_Pin_15

// output
#define LED0_RUN_PORT GPIOC
#define LED0_RUN_PIN  GPIO_Pin_2
#define LED1_RUN_PORT GPIOF
#define LED1_RUN_PIN  GPIO_Pin_7
#define LED2_RUN_PORT GPIOF
#define LED2_RUN_PIN  GPIO_Pin_8
#define LED3_RUN_PORT GPIOI
#define LED3_RUN_PIN  GPIO_Pin_10

#define LCD_PWM_PORT  GPIOF
#define LCD_PWM_PIN   GPIO_Pin_6
#define LCD_BUSY_PORT GPIOD
#define LCD_BUSY_PIN  GPIO_Pin_3
// #define LED2_RUN_PORT GPIOF
// #define LED2_RUN_PIN  GPIO_Pin_8
// #define LED3_RUN_PORT GPIOI
// #define LED3_RUN_PIN  GPIO_Pin_10
/*	配置几个控制用的GPIO
    PH9/DCMI_D0/AD7606_OS0			---> AD7606_OS0		OS2:OS0 选择数字滤波参数
    PH10/DCMI_D1/AD7606_OS1         ---> AD7606_OS1
    PH11/DCMI_D2/AD7606_OS2         ---> AD7606_OS2
    PH12/DCMI_D3/AD7606_CONVST      ---> AD7606_CONVST	启动ADC转换
    PH14/DCMI_D4/AD7606_RAGE        ---> AD7606_RAGE	输入模拟电压量程，正负5V或正负10V
    PI4/DCMI_D5/AD7606_RESET        ---> AD7606_RESET	复位

    PI6/DCMI_D6/AD7606_BUSY			---> AD7606_BUSY    转换结束的信号
*/
#define AD7606_OS0_PORT    GPIOH
#define AD7606_OS0_PIN     GPIO_Pin_9
#define AD7606_OS1_PORT    GPIOH
#define AD7606_OS1_PIN     GPIO_Pin_10
#define AD7606_OS2_PORT    GPIOH
#define AD7606_OS2_PIN     GPIO_Pin_11
#define AD7606_CONVST_PORT GPIOH
#define AD7606_CONVST_PIN  GPIO_Pin_12
#define AD7606_RAGE_PORT   GPIOH
#define AD7606_RAGE_PIN    GPIO_Pin_14
#define AD7606_RESET_PORT  GPIOI
#define AD7606_RESET_PIN   GPIO_Pin_4
#define AD7606_BUSY_PORT   GPIOI
#define AD7606_BUSY_PIN    GPIO_Pin_6

#define AM2303_PORT GPIOB
#define AM2303_PIN  GPIO_Pin_1

// #define PRelayCtr_PORT GPIOD
// #define PRelayCtr_PIN GPIO_PIN_6
// #define NRelayCtr_PORT GPIOD
// #define NRelayCtr_PIN GPIO_PIN_5
// #define PreRelayCtr_PORT GPIOG
// #define PreRelayCtr_PIN GPIO_PIN_9
// #define Fan_PORT GPIOG
// #define Fan_PIN GPIO_PIN_10
// #define OUT1CTR_PORT GPIOD
// #define OUT1CTR_PIN GPIO_PIN_7
// #define OUT2CTR_PORT GPIOE
// #define OUT2CTR_PIN GPIO_PIN_1
// #define EXTWATCHDOG_PORT GPIOC
// #define EXTWATCHDOG_PIN GPIO_PIN_3
// #define ExtRelayLed_PORT GPIOD
// #define ExtRelayLed_PIN GPIO_PIN_11
// #define ExtFaultLed_PORT GPIOD
// #define ExtFaultLed_PIN GPIO_PIN_10
// #define ISOPRelayCtr_PORT GPIOF
// #define ISOPRelayCtr_PIN GPIO_PIN_14
// #define ISONRelayCtr_PORT GPIOF
// #define ISONRelayCtr_PIN GPIO_PIN_15

// // input
// #define LDetect1_PORT GPIOD
// #define LDetect1_PIN GPIO_PIN_13

// output operation
#define LED0_RUN_ON     GPIO_SetBits(LED0_RUN_PORT, LED0_RUN_PIN)
#define LED0_RUN_OFF    GPIO_ResetBits(LED0_RUN_PORT, LED0_RUN_PIN)
#define LED0_RUN_TOGGLE GPIO_ToggleBits(LED0_RUN_PORT, LED0_RUN_PIN)
#define LED1_RUN_ON     GPIO_SetBits(LED1_RUN_PORT, LED1_RUN_PIN)
#define LED1_RUN_OFF    GPIO_ResetBits(LED1_RUN_PORT, LED1_RUN_PIN)
#define LED1_RUN_TOGGLE GPIO_ToggleBits(LED1_RUN_PORT, LED1_RUN_PIN)
#define LED2_RUN_ON     GPIO_SetBits(LED2_RUN_PORT, LED2_RUN_PIN)
#define LED2_RUN_OFF    GPIO_ResetBits(LED2_RUN_PORT, LED2_RUN_PIN)
#define LED2_RUN_TOGGLE GPIO_ToggleBits(LED2_RUN_PORT, LED2_RUN_PIN)

// TFTLCD
#define LCD_PWM_HIGH GPIO_SetBits(LCD_PWM_PORT, LCD_PWM_PIN)
#define LCD_PWM_LOW  GPIO_ResetBits(LCD_PWM_PORT, LCD_PWM_PIN)

#define AM2303_DO_HIGH GPIO_SetBits(AM2303_PORT, AM2303_PIN)
#define AM2303_DO_LOW  GPIO_ResetBits(AM2303_PORT, AM2303_PIN)
#define AM2303_TOGGLE  GPIO_ToggleBits(AM2303_PORT, AM2303_PIN)

// IO方向设置
#define AM2303_IO_IN                     \
    {                                    \
        GPIOB->MODER &= ~(3 << (1 * 2)); \
        GPIOB->MODER |= 0 << (1 * 2);    \
    }
#define AM2303_IO_OUT                    \
    {                                    \
        GPIOB->MODER &= ~(3 << (1 * 2)); \
        GPIOB->MODER |= 1 << (1 * 2);    \
    }
#define DQ_IS_LOW() ((AM2303_PORT->IDR & AM2303_PIN) == 0)
// #define LED3_RUN_ON     GPIO_SetBits(LED3_RUN_PORT, LED3_RUN_PIN)
// #define LED3_RUN_OFF    GPIO_ResetBits(LED3_RUN_PORT, LED3_RUN_PIN)
// #define LED3_RUN_TOGGLE GPIO_ToggleBits(LED3_RUN_PORT, LED3_RUN_PIN)
// #define PRelayCtr_ON GPIO_SetBits(PRelayCtr_PORT, PRelayCtr_PIN)
// #define PRelayCtr_OFF GPIO_ResetBits(PRelayCtr_PORT, PRelayCtr_PIN)
// #define NRelayCtr_ON GPIO_SetBits(NRelayCtr_PORT, NRelayCtr_PIN)
// #define NRelayCtr_OFF GPIO_ResetBits(NRelayCtr_PORT, NRelayCtr_PIN)
// #define PreRelayCtr_ON GPIO_SetBits(PreRelayCtr_PORT, PreRelayCtr_PIN)
// #define PreRelayCtr_OFF GPIO_ResetBits(PreRelayCtr_PORT, PreRelayCtr_PIN)
// #define FAN_ON GPIO_SetBits(Fan_PORT, Fan_PIN)
// #define FAN_OFF GPIO_ResetBits(Fan_PORT, Fan_PIN)
// #define OUT1CTR_ON GPIO_SetBits(OUT1CTR_PORT, OUT1CTR_PIN)
// #define OUT1CTR_OFF GPIO_ResetBits(OUT1CTR_PORT, OUT1CTR_PIN)
// #define OUT2CTR_ON GPIO_SetBits(OUT2CTR_PORT, OUT2CTR_PIN)
// #define OUT2CTR_OFF GPIO_ResetBits(OUT2CTR_PORT, OUT2CTR_PIN)
// #define FEED_DOG_ON GPIO_SetBits(EXTWATCHDOG_PORT, EXTWATCHDOG_PIN)
// #define FEED_DOG_OFF GPIO_ResetBits(EXTWATCHDOG_PORT, EXTWATCHDOG_PIN)
// #define FEED_DOG_TOGGLE GPIO_WriteBit(EXTWATCHDOG_PORT, EXTWATCHDOG_PIN, (FlagStatus)(1 - (gpio_output_bit_get(EXTWATCHDOG_PORT, EXTWATCHDOG_PIN))))
// #define ExtRelayLed_ON GPIO_SetBits(ExtRelayLed_PORT, ExtRelayLed_PIN)
// #define ExtRelayLed_OFF GPIO_ResetBits(ExtRelayLed_PORT, ExtRelayLed_PIN)
// #define ExtFaultLed_ON GPIO_SetBits(ExtFaultLed_PORT, ExtFaultLed_PIN)
// #define ExtFaultLed_OFF GPIO_ResetBits(ExtFaultLed_PORT, ExtFaultLed_PIN)
// #define ISOPRelay_ON GPIO_SetBits(ISOPRelayCtr_PORT, ISOPRelayCtr_PIN)
// #define ISOPRelay_OFF GPIO_ResetBits(ISOPRelayCtr_PORT, ISOPRelayCtr_PIN)
// #define ISONRelay_ON GPIO_SetBits(ISONRelayCtr_PORT, ISONRelayCtr_PIN)
// #define ISONRelay_OFF GPIO_ResetBits(ISONRelayCtr_PORT, ISONRelayCtr_PIN)

// // input result
// #define L_IN1_IS_LOW (gpio_input_bit_get(LDetect1_PORT, LDetect1_PIN) == RESET)

void interface_init(void);
void gpio_clock_init(void);
#endif
