/*
* Copyright (c) 2023-2028, SpaceTouch Inc.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date          Author      Notes
* 2023-04-18    dongx       the first version
* 2023-06-05    weijiac     add gpio interrupt part
* 2023-07-24    weijiac     add spio part
*/

#ifndef _HAL_GPIO_H__
#define _HAL_GPIO_H__

#include <stdlib.h>
#include <stdbool.h>
#include "platform.h"
#include "hal_def.h"
#ifdef __cplusplus
extern "C" {
#endif



typedef enum
{
    GPIO0 = 0,
    GPIO1,
    GPIO2,
    GPIO3,
    GPIO4,
    GPIO5,
    GPIO6,
    GPIO7,
    GPIO8,
    GPIO9,
    GPIO10,
    GPIO11,
    GPIO12,
    GPIO13,
    GPIO14,
    GPIO15,
    GPIO16,
    GPIO17,
    GPIO18,
    GPIO19,
    GPIO20,
    GPIO21,
    GPIO22,
    GPIO23,
    GPIO24,
    GPIO25,
    GPIO26,
    GPIO27,
    GPIO28,
    GPIO29,
    GPIO30,
    GPIO31,
    GPIO32,
    GPIO33,
    GPIO34,
    GPIO35,
    GPIO36,
    GPIO37,
    GPIO38,
    GPIO39,
    GPIONUM,

    /* To aviod compile warnings. */
    GPIO_MAX = GPIO39
} gpio_pin_t;


/**************SPIO*********************/
typedef enum
{
    SPIO0 = 0,
    SPIO1,
    SPIO2,
    SPIO3,
    SPIO4,
    SPIO5,
    SPIONUM,
    SPIO_MAX = SPIO5
} spio_pin_t;

typedef enum
{
    GPIO_MUXSEL_GPIO = 0,
    GPIO_MUXSEL_FUNCTION1 = 1,
    GPIO_MUXSEL_FUNCTION2 = 2,
    GPIO_MUXSEL_FUNCTION3 = 3,
    GPIO_MUXSEL_FUNCTION4 = 4,
    GPIO_MUXSEL_FUNCTION5 = 5,
    GPIO_MUXSEL_FUNCTION6 = 6,
    GPIO_MUXSEL_FUNCTION7 = 7,
    GPIO_MUXSEL_FUNCTION8 = 8,
    GPIO_MUXSEL_FUNCTION9 = 9,
    GPIO_MUXSEL_FUNCTION10 = 10,
    GPIO_MUXSEL_FUNCTION11 = 11,
    GPIO_MUXSEL_FUNCTION12 = 12,
    GPIO_MUXSEL_FUNCTION13 = 13,
    GPIO_MUXSEL_FUNCTION14 = 14,
    GPIO_MUXSEL_DISABLED = 15,
} gpio_muxsel_t;


typedef enum
{
    GPIO_DRIVING_LEVEL0    = 0,        /**< Defines GPIO driving current as level0.  */
    GPIO_DRIVING_LEVEL1    = 1,        /**< Defines GPIO driving current as level1.  */
} gpio_driving_level_t;

typedef enum
{
    GPIO_PULL_DOWN_DISABLED    = 0,        /**< Defines GPIO pull up and pull down disable.  */
    GPIO_PULL_UP          = 1,             /**< Defines GPIO is pull up state.  */
    GPIO_PULL_DOWN            = 2,         /**< Defines GPIO is pull down state. */
} gpio_pull_status_t;

/** This enum defines the GPIO direction. */
typedef enum
{
    GPIO_DIRECTION_INPUT  = 0,              /**<  GPIO input direction. */
    GPIO_DIRECTION_OUTPUT = 1               /**<  GPIO output direction. */
} gpio_direction_t;

/** This enum defines the data type of GPIO. */
typedef enum
{
    GPIO_DATA_LOW  = 0,                     /**<  GPIO data low. */
    GPIO_DATA_HIGH = 1                      /**<  GPIO data high. */
} gpio_data_t;

/** This enum defines the invert type of GPIO. */
typedef enum
{
    GPIO_INPUT_INVERT = 0,
    GPIO_OUTPUT_INVERT = 1
} gpio_invert_mode_t;

/** this enum defines all gpio interrupt channel **/
typedef enum
{
    GPIO_IC0, GPIO_IC1, GPIO_IC2, GPIO_IC3, NUM_GPIO_IC
} gpio_interrupt_channel_t;

/** GPIO_IC trigger event **/
typedef enum
{
    NONE_EVENT,     /**<  interrupts do not respond to any form of input level mode */
    RISING_EDGE,    /**<  PIN_IRQ_MODE_RISING */
    FALLING_EDGE,   /**<  PIN_IRQ_MODE_FALLING */
    BOTH_EDGE,      /**<  PIN_IRQ_MODE_RISING_FALLING */
    HIGH_LEVEL,     /**<  PIN_IRQ_MODE_HIGH_LEVEL */
    LOW_LEVEL       /**<  PIN_IRQ_MODE_LOW_LEVEL*/
} gpio_interrupt_trigger_event_t;

typedef enum
{
    GPIO_ENABLE     = ENABLE,
    GPIO_DISABLE    = DISABLE,
} gpio_enable_t;

typedef enum
{
    GPIO_RSTN_PU            = DEV_GPIO_RSTN_PU_ENABLE,
    GPIO_RSTN_PU_DISABLE    = DEV_GPIO_RSTN_PU_DISABLE,
} gpio_rstn_pull_t;

typedef struct gpio_interrupt_config_type
{
    gpio_interrupt_channel_t ic;
    gpio_pin_t pin;
    gpio_interrupt_trigger_event_t event;
} gpio_interrupt_config_type_t;

typedef struct gpio_reset_config_type
{
    gpio_pin_t pin;
    gpio_rstn_pull_t reset_pull;
    gpio_enable_t   reset_enable;
} gpio_reset_config_type_t;

typedef void (*gpio_callback)(void *param);
typedef void (*spio_callback)(void *param);
typedef struct
{
    gpio_callback callback;
    void  *param;
} hal_gpio_callback_t;

typedef struct
{
    gpio_callback callback;
    void  *param;
} hal_spio_callback_t;

typedef enum
{
    SPIO_MUXSEL_SPIO = 0,
    SPIO_MUXSEL_FUNCTION1 = 1,
    SPIO_MUXSEL_FUNCTION2 = 2,
    SPIO_MUXSEL_FUNCTION15 = 14,
} spio_muxsel_t;

typedef enum
{
    SPIO_DATA_LOW  = 0,                     /**<  SPIO data low. */
    SPIO_DATA_HIGH = 1                      /**<  SPIO data high. */
} spio_data_t;

typedef enum
{
    SPIO_PULL_DOWN_DISABLED    = 0,        /**< Defines SPIO pull up and pull down disable.  */
    SPIO_PULL_UP          = 1,             /**< Defines SPIO is pull up state.  */
    SPIO_PULL_DOWN            = 2,         /**< Defines SPIO is pull down state. */
} spio_pull_status_t;

/** This enum defines the GPIO direction. */
typedef enum
{
    SPIO_DIRECTION_INPUT  = 0,              /**<  SPIO input direction. */
    SPIO_DIRECTION_OUTPUT = 1               /**<  SPIO output direction. */
} spio_direction_t;

/** This enum defines the data type of GPIO. */

typedef struct spio_interrupt_config_type
{
    spio_pin_t pin;
    gpio_interrupt_trigger_event_t event;
} spio_interrupt_config_type_t;

bool hal_spio_check_valid(spio_pin_t pin);
void hal_spio_get_data(spio_pin_t pin, spio_data_t *data);
void hal_spio_set_data(spio_pin_t pin, spio_data_t data);
void hal_spio_set_direction(spio_pin_t pin, spio_direction_t direction);
void hal_spio_get_direction(spio_pin_t pin, spio_direction_t *direction);
void hal_spio_set_pull(spio_pin_t pin, spio_pull_status_t pull);
void hal_spio_get_pull(spio_pin_t pin, spio_pull_status_t *pull);
void hal_spio_pinmux_set_function(spio_pin_t pin, spio_muxsel_t function_index);
void hal_spio_pinmux_get_function(spio_pin_t pin, spio_muxsel_t *function_index);
uint32_t spio_read_input_pin(spio_pin_t pin);
void hal_set_spio_interrupt_enable(void);
void hal_set_spio_interrupt_disable(void);

void hal_spio_interrput_config(spio_interrupt_config_type_t *spio_interrupt_struct,  void *callback, void *param);
void hal_spio_interrupt_set_event(gpio_interrupt_trigger_event_t event);
void hal_spio_interrupt_set_pin(spio_pin_t pin);
uint32_t hal_spio_interrupt_get_interrupt_status(void);
void hal_spio_interrupt_clear_interrupt_pending(void);
void hal_spio_interrupt_set_callback(void *callback, void *param);
void hal_spio_detach_irq(void);
void hal_spio_print_pinmux(void);
uint8_t hal_spio_read(spio_pin_t pin);


void hal_gpio_clear_interrupt_control(gpio_interrupt_channel_t icx);
bool hal_gpio_check_valid(gpio_pin_t pin);
void hal_gpio_get_data(gpio_pin_t pin, gpio_data_t *data);
uint8_t hal_gpio_read(gpio_pin_t pin);
void hal_gpio_set_data(gpio_pin_t pin, gpio_data_t data);
void hal_gpio_set_direction(gpio_pin_t pin, gpio_direction_t direction);
void hal_gpio_get_direction(gpio_pin_t pin, gpio_direction_t *direction);
void hal_gpio_set_pull(gpio_pin_t pin, gpio_pull_status_t pull);
void hal_gpio_get_pull(gpio_pin_t pin, gpio_pull_status_t *pull);
void hal_gpio_set_driving_level(gpio_pin_t pin, gpio_driving_level_t level);
void hal_gpio_get_driving_level(gpio_pin_t pin, gpio_driving_level_t *level);
void hal_gpio_pinmux_set_function(gpio_pin_t pin, gpio_muxsel_t function_index);
void hal_gpio_pinmux_get_function(gpio_pin_t pin, gpio_muxsel_t *function_index);

int hal_gpio_init(void);

void hal_set_gpio_interrupt_enable(gpio_interrupt_channel_t icx);
void hal_set_gpio_interrupt_disable(gpio_interrupt_channel_t icx);
int hal_gpio_find_free_interrupt_channel(void);
int hal_gpio_find_busy_interrupt_channel(void);
int hal_gpio_find_interrupt_channel_by_pin(gpio_pin_t pin);
void hal_gpio_interrupt_init(void);

void hal_gpio_interrput_config(gpio_interrupt_config_type_t *gpio_interrupt_struct);
void hal_gpio_interrupt_set_event(gpio_interrupt_channel_t icx, gpio_interrupt_trigger_event_t event);
void hal_gpio_interrupt_set_pin(gpio_pin_t pin, gpio_interrupt_channel_t icx);
uint32_t hal_gpio_interrupt_get_interrupt_status(gpio_interrupt_channel_t icx);
void hal_gpio_interrupt_clear_interrupt_pending(gpio_interrupt_channel_t icx);
void hal_gpio_interrupt_set_callback(gpio_interrupt_channel_t icx, void *callback, void *param);
void hal_gpio_output_toggle(gpio_pin_t pin);
void hal_gpio_reset_init(gpio_reset_config_type_t *gpio_reset_type);
void hal_gpio_set_reset_pullup(gpio_rstn_pull_t  gpio_rstn_pull);
void hal_gpio_reset_set_pin(gpio_pin_t pin);
void hal_set_gpio_reset_enable(void);
void hal_set_gpio_reset_disable(void);
void hal_gpio_clear_reset(void);
void hal_gpio_print_pinmux(void);
uint64_t hal_gpio_read_inputport(void);
HAL_StatusTypeDef hal_gpio_detach_irq(gpio_pin_t pin);
HAL_StatusTypeDef hal_gpio_irq_enable(gpio_pin_t pin, gpio_enable_t enable);

void gpio_eclk_init(uint32_t pin);
void gpio_toggle_pin(uint32_t pin);
void gpio_init_output(uint32_t pin,uint8_t val);
/*
int hal_gpio_irq_request(uint32_t irq, hal_irq_handler_t hdle, unsigned long flags, void *data);
int hal_gpio_irq_free(uint32_t irq);
*/

#ifdef __cplusplus
}
#endif
#endif
