
#ifndef RTE_GPIO_H__
#define RTE_GPIO_H__

#include "stdint.h"
#include "RTE_GPIO_BAT32A279.h"


/**@enum RTE_GPIO_Level_en_t
 * @brief GPIO端口的电平 \n
 */
#define   RTE_GPIO_LEVEL_LOW                (0x00U)   /**< 低电平 */
#define   RTE_GPIO_LEVEL_HIGH               (0x01U)   /**< 高电平 */

/**@enum RTE_GPIO_Dir_en_t
 * @brief GPIO端口的输入输出方向 \n
 */
#define   RTE_GPIO_DIR_IN                   (0x00U)   /**< 输入 */
#define   RTE_GPIO_DIR_OUT                  (0x80U)   /**< 输出 */

/*******************************************************************************
* GPIO 的输入工作模式定义
* =======================================================================
*  bit 8 | bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 
* -------+-------+-------+-------+-------+-------+-------+-------+-------
*   DIR  |   -   |   -   |   -   |  TYPE |   -   |   -   |  PULL UP/DN      
* =======================================================================
* - 其中DIR须为 RTE_GPIO_DIR_IN
*******************************************************************************/

/**@enum RTE_GPIO_Pull_en_t
 * @brief GPIO端口的上下拉 \n
 */
#define   RTE_GPIO_PULL_NONE                (0x00U)   /**< 无上/下拉 */
#define   RTE_GPIO_PULL_DOWN                (0x01U)   /**< 下拉      */
#define   RTE_GPIO_PULL_UP                  (0x02U)   /**< 上拉      */
#define   RTE_GPIO_PULL_BOTH                (0x03U)   /**< 上下拉同时存在(拉至1/2VCC),慎用 */

/**@enum RTE_GPIO_Input_Type_en_t
 * @brief GPIO端口的输入类型 \n
 */
#define   RTE_GPIO_INPUT_CMOS               (0x00U)   /**< COMS电平输入 */
#define   RTE_GPIO_INPUT_TTL                (0x10U)   /**< TTL电平输入  */

/*******************************************************************************
* GPIO 的输出工作模式定义
* =======================================================================
*  bit 8 | bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 
* -------+-------+-------+-------+-------+-------+-------+-------+-------
*   DIR  | Rsvd. | Rsvd. | Rsvd. |  TYPE |         SPEED         | LEVEL    
* =======================================================================
* - 其中DIR须为 RTE_GPIO_DIR_OUT
* - 其中LEVEL为输出电平 RTE_GPIO_LEVEL_LOW 或 RTE_GPIO_LEVEL_HIGH
*******************************************************************************/

/**@enum RTE_GPIO_Output_Type_en_t
 * @brief GPIO端口的输出类型 \n
 */
#define   RTE_GPIO_OUTPUT_PP                (0x00U)   /**< Push-Pull推挽输出  */
#define   RTE_GPIO_OUTPUT_OD                (0x10U)   /**< Open Drain开漏输出 */

/**@enum RTE_GPIO_Output_Speed_en_t
 * @brief GPIO端口的输出速度 \n
 */
#define   RTE_GPIO_SPEED_HIGH               (0x00U)   /**< 输出最高速度  */
#define   RTE_GPIO_SPEED_0                  (0x00U)   /**< 输出速度等级0 (最高) */
#define   RTE_GPIO_SPEED_1                  (0x02U)   /**< 输出速度等级1 */
#define   RTE_GPIO_SPEED_2                  (0x04U)   /**< 输出速度等级2 */
#define   RTE_GPIO_SPEED_3                  (0x06U)   /**< 输出速度等级3 */
#define   RTE_GPIO_SPEED_4                  (0x08U)   /**< 输出速度等级4 */
#define   RTE_GPIO_SPEED_5                  (0x0AU)   /**< 输出速度等级5 */
#define   RTE_GPIO_SPEED_6                  (0x0CU)   /**< 输出速度等级6 */
#define   RTE_GPIO_SPEED_7                  (0x0EU)   /**< 输出速度等级7 (最低) */
#define   RTE_GPIO_SPEED_LOW                (0x0EU)   /**< 输出最低速度  */

/*******************************************************************************
 * RTE_GPIO_Init 函数和 RTE_GPIO_Config 函数的参数中的GPIO工作模式由多个字段组合而成
 * 
 * 当GPIO被配置成输入模式时，GPIO工作模式应当依照输入模式下定义的字段组合而成，例如：
 *  u8Mode = RTE_GPIO_DIR_IN | RTE_GPIO_PULL_UP | RTE_GPIO_INPUT_CMOS
 * 
 * 当GPIO被配置成输出模式时，GPIO工作模式应当依照输出模式下定义的字段组合而成，例如：
 *  u8Mode = RTE_GPIO_DIR_OUT | RTE_GPIO_OUTPUT_PP | RTE_GPIO_LEVEL_HIGH
 * 
*******************************************************************************/
/**@enum RTE_GPIO_Input_Type_en_t
 * @brief GPIO工作模式掩码 \n
 */
#define   RTE_GPIO_DIR_MASK                 (0x80U)   /**< 输入输出方向掩码 bit 7 */

#define   RTE_GPIO_PULL_MASK                (0x03U)   /**< 上/下拉掩码 bit 0 - bit 1 */
#define   RTE_GPIO_INPUT_TYPE_MASK          (0x10U)   /**< 输入类型掩码 bit 4 */

#define   RTE_GPIO_LEVEL_MASK               (0x01U)   /**< 输出电平掩码 bit 0  */
#define   RTE_GPIO_SPEED_MASK               (0x0EU)   /**< 输出速度掩码 bit 1 - bit 3  */
#define   RTE_GPIO_OUTPUT_TYPE_MASK         (0x10U)   /**< 输出类型掩码 bit 4  */

#define   RTE_GPIO_INT_EDGE_MODE_MASK       (0x04U)   /**< 边沿中断模式掩码 bit 2  */

/**@enum RTE_GPIO_Interrupt_Type_en_t
 * @brief GPIO端口的中断类型 \n
 */
typedef enum
{
    RTE_GPIO_INT_LOW_LEVEL    = 0x00U,      /**< 低电平中断 */
    RTE_GPIO_INT_HIGH_LEVEL   = 0x01U,      /**< 高电平中断 */
    RTE_GPIO_INT_FALLING_EDGE = 0x04U,      /**< 下降沿中断 */
    RTE_GPIO_INT_RISING_EDGE  = 0x05U,      /**< 上升沿中断 */
    RTE_GPIO_INT_DUAL_EDGE    = 0x06U,      /**< 双沿中断   */
}RTE_GPIO_Interrupt_Type_en_t;

/**@type RTE_GPIO_Int_Handler_Func_ptr_t
 * @brief GPIO端口的中断服务回调函数 \n
 * @param[in] u16Pin 发生中断的端口编号
 * @param[in] u8Level 发生中断时端口的电平, 0为低电平, 1为高电平
 */
typedef void (*RTE_GPIO_Int_Handler_Func_ptr_t) (uint16_t u16Pin, uint8_t u8Level);

/**@enum RTE_GPIO_Mode_en_t
 * @brief GPIO端口的工作模式 \n
 */
typedef enum
{
    RTE_GPIO_MODE_INPUT_CMOS     = 0x00U,   /**< CMOS电平悬空输入 */
    RTE_GPIO_MODE_INPUT_CMOS_PD  = 0x01U,   /**< CMOS电平下拉输入 */
    RTE_GPIO_MODE_INPUT_CMOS_PU  = 0x02U,   /**< CMOS电平上拉输入 */
    RTE_GPIO_MODE_INPUT_TTL      = 0x04U,   /**< TTL电平悬空输入  */
    RTE_GPIO_MODE_INPUT_TTL_PD   = 0x05U,   /**< TTL电平下拉输入  */
    RTE_GPIO_MODE_INPUT_TTL_PU   = 0x06U,   /**< TTL电平上拉输入  */
    
    RTE_GPIO_MODE_OUTPUT_PP_LOW  = 0x40U,   /**< 推挽输出低电平   */
    RTE_GPIO_MODE_OUTPUT_PP_HIGH = 0x41U,   /**< 推挽输出高电平   */
    RTE_GPIO_MODE_OUTPUT_OD_LOW  = 0x42U,   /**< 开漏输出低电平   */
    RTE_GPIO_MODE_OUTPUT_OD_HIGH = 0x43U,   /**< 开漏输出高电平   */
    
    RTE_GPIO_MODE_INVALID        = 0xFFU,   /**< 无效的GPIO模式   */
}RTE_GPIO_Mode_en_t;

/**@struct RTE_GPIO_Config_st_t
 * @brief GPIO端口的配置结构 \n
 */
typedef struct
{
    uint16_t u16PinNum;           /**< GPIO端口编号(RTE_GPIO_PORTxx_PINyy) */
    uint16_t u16PinMode;          /**< GPIO工作模式 */
}RTE_GPIO_Config_st_t;

/******************************************************************************
* GPIO控制函数
******************************************************************************/
extern void     RTE_GPIO_Init(void);
extern void     RTE_GPIO_DeInit(void);

extern int32_t  RTE_GPIO_Config(uint16_t u16Pin, uint8_t u8Mode);
extern int32_t  RTE_GPIO_Bulk_Config(RTE_GPIO_Config_st_t *pstGPIOPinList, uint32_t u32Num);

extern int32_t  RTE_GPIO_Set_Level(uint16_t u16Pin, uint8_t u8Level);
extern uint8_t  RTE_GPIO_Get_Level(uint16_t u16Pin);

extern int32_t  RTE_GPIO_Set_Port(uint8_t u8Port, uint32_t u32Value);
extern uint32_t RTE_GPIO_Get_Port(uint8_t u8Port);

/*******************************************************************************
 * GPIO中断函数
 * 
 * GPIO所有的中断操作都是基于中断描述符的
 * 由于不同芯片的GPIO结构存在差异, GPIO中断描述符在芯片各自的GPIO头文件中定义
 * GPIO中断描述符中的参数必须使用RTE_GPIO_Interrupt_Register设置, 禁止直接修改
 * 
 * 使用GPIO中断的步骤:
 * 1. 使用RTE_GPIO_IRQ_Desc_st_t声明中断描述符, 生命周期为长期有效(全局/静态变量)
 *    每一个中断需要有唯一的中断描述符, 需要使用多少中断, 就声明多少个描述符
 * 2. 初始化GPIO
 * 3. 使用RTE_GPIO_Config将中断引脚配置为输入
 * 4. 使用RTE_GPIO_Interrupt_Register将中断引脚注册到其对应的中断描述符
 * 5. 使用RTE_GPIO_Interrupt_Enable使能中断
 * 6. 在中断系统中开启对应的外设中断
 * 7. 使用中断功能, 可以通过RTE_GPIO_Get_Interrupt_Flag获取中断标志, 也可以直接使用
 *    注册的中断回调函数
 * 8. 在不需要使用GPIO中断时，可能通过RTE_GPIO_Interrupt_Disable将其禁用
*******************************************************************************/
extern int32_t  RTE_GPIO_Interrupt_Register(RTE_GPIO_IRQ_Desc_st_t *pstIRQDesc,
                                            uint16_t u16Pin, 
                                            RTE_GPIO_Interrupt_Type_en_t enType,
                                            RTE_GPIO_Int_Handler_Func_ptr_t pfnHandler);

extern int32_t  RTE_GPIO_Interrupt_Enable(RTE_GPIO_IRQ_Desc_st_t *pstIRQDesc);
extern int32_t  RTE_GPIO_Interrupt_Disable(RTE_GPIO_IRQ_Desc_st_t *pstIRQDesc);

extern int32_t  RTE_GPIO_Get_Interrupt_Flag(RTE_GPIO_IRQ_Desc_st_t *pstIRQDesc);
extern int32_t  RTE_GPIO_Clear_Interrupt_Flag(RTE_GPIO_IRQ_Desc_st_t *pstIRQDesc);

#endif /* RTE_GPIO_H__ */
