#include "sr_gpio.h"
#include "sr_log.h"
#include "sr_osal.h"


// hezhou
#include "driver_gpio.h"
#include "platform_define.h"
#include "bsp_common.h"

static luat_gpio_alt_table_t gpio_alt[GPIO_ALT_MAX] = {
    {HAL_GPIO_17, 4},
    {HAL_GPIO_18, 4},
    {HAL_GPIO_19, 4},
    {HAL_GPIO_20, 4},
};

struct pin_irq_hdr pin_irq_hdr_table[] = {
    {0, 0}, // GPIO_0
    {0, 0}, // GPIO_1
    {0, 0}, // GPIO_2
    {0, 0}, // GPIO_3
    {0, 0}, // GPIO_4
    {0, 0}, // GPIO_5
    {0, 0}, // GPIO_6
    {0, 0}, // GPIO_7
    {0, 0}, // GPIO_8
    {0, 0}, // GPIO_9
    {0, 0}, // GPIO_0
    {0, 0}, // GPIO_11
    {0, 0}, // GPIO_12
    {0, 0}, // GPIO_13
    {0, 0}, // GPIO_14
    {0, 0}, // GPIO_15
    {0, 0}, // GPIO_16
    {0, 0}, // GPIO_17
    {0, 0}, // GPIO_18
    {0, 0}, // GPIO_19
    {0, 0}, // GPIO_20
#if defined TYPE_EC716S
#else
    {0, 0}, // GPIO_21
    {0, 0}, // GPIO_22
    {0, 0}, // GPIO_23
    {0, 0}, // GPIO_24
    {0, 0}, // GPIO_25
    {0, 0}, // GPIO_26
    {0, 0}, // GPIO_27
    {0, 0}, // GPIO_28
    {0, 0}, // GPIO_29
    {0, 0}, // GPIO_30
    {0, 0}, // GPIO_31
    {0, 0}, // GPIO_32
    {0, 0}, // GPIO_33
    {0, 0}, // GPIO_34
    {0, 0}, // GPIO_35
    {0, 0}, // GPIO_36
    {0, 0}, // GPIO_37
    {0, 0}, // GPIO_38
#endif
    {0, 0}, // 39 WAKEUP_0
    {0, 0}, // 40 WAKEUP_1
    {0, 0}, // 41 WAKEUP_2
    {0, 0}, // 42 WAKEUP_3
    {0, 0}, // 43 WAKEUP_4
    {0, 0}, // 44 WAKEUP_5
    {0, 0}, // 45 WAKEUP_CHARGE
    {0, 0}, // 46 WAKEUP_PWRKEY
};


static int _luat_gpio_irq_cb(int gpioId, void *args)
{
    BSP_LOG(DEBUG,"[BSP] gpio callback enter!\n");

    // 在合宙的GPIO中断回调中调用朝阳的回调
    SR_GPIO_IRQ_CB_T *callback = (SR_GPIO_IRQ_CB_T *)args;
    if ((callback) && (callback->args))
        BSP_LOG(DEBUG,"[BSP] args = %s\n", callback->args);
    BSP_LOG(DEBUG,"[BSP] func addr = %x\n", callback->func);
    if ((callback) && (callback->func))
        callback->func(callback->args);
}

/*
EC618平台，上下拉只对输出模式有效，输入模式只有默认上下拉或者取消上下拉，普通的GPIO配置为LUAT_GPIO_DEFAULT，表示完全关闭上下拉；AGPIO软件上不支持配置上下拉，即使配置了也无效，一直是硬件开机或者复位时的默认状态
*/
int BspGpioInit(int gpioId, SR_GPIO_CFG_T *gpioCfg)
{
    int ret = 0;
    luat_gpio_cfg_t cfg = {0};
    
    //参数有效性判断
    SR_ASSERT(IS_GPIO_ID(gpioId));
    SR_ASSERT((gpioCfg!=SR_NULL));
    SR_ASSERT(IS_GPIO_INIT_LVL(gpioCfg->initLvl));
    SR_ASSERT(IS_GPIO_MODE(gpioCfg->gpioMode));
    SR_ASSERT(IS_GPIO_PULL(gpioCfg->pull));
    SR_ASSERT(IS_GPIO_IRQ_MODE(gpioCfg->irqMode));

	
    cfg.mode = gpioCfg->gpioMode;
    cfg.pin = gpioId;
    cfg.pull = gpioCfg->pull;
    cfg.irq_type = gpioCfg->irqMode;
    cfg.irq_cb = _luat_gpio_irq_cb; // 合宙定义的回调函数格式
    cfg.irq_args = gpioCfg->irqCb;  // 朝阳的回调作为合宙回调的void*形参
    cfg.output_level = gpioCfg->initLvl;   //输出模式才有效

    for (uint8_t i = 0; i < GPIO_ALT_MAX; i++)
    {
        if (gpioId == gpio_alt[i].pin)
        {
            cfg.alt_fun = gpio_alt[i].alt;
            break;
        }
    }


    pin_irq_hdr_table[gpioId].irqMode = gpioCfg->irqMode;
    pin_irq_hdr_table[gpioId].irqCb = gpioCfg->irqCb;
	
    return luat_gpio_open(&cfg);  
}

int BspGpioDeinit(int gpioId)
{
    //参数有效性判断
    if (((uint32_t)gpioId) >= HAL_GPIO_QTY) return SR_INVALID;

    luat_gpio_close(gpioId);
    return 0;
}

int BspGpioRead(int gpioId)
{
    //参数有效性判断
    SR_ASSERT(IS_GPIO_ID(gpioId));

    return luat_gpio_get(gpioId);
}

int BspGpioWrite(int gpioId, uint8_t value)
{
    //参数有效性判断
    SR_ASSERT(IS_GPIO_ID(gpioId));
    SR_ASSERT(IS_GPIO_LVL(value));

    uint8_t tmpLevel = 0;
    if (SR_GPIO_TOGGLE == value)
    {
        tmpLevel = luat_gpio_get(gpioId);
        value = !tmpLevel;
    }

    return luat_gpio_set(gpioId, value);
}

int BspGpioEnableIrq(int gpioId)
{
    int ret = 0;
    luat_gpio_cfg_t cfg = {0};

    //参数有效性判断
    if (((uint32_t)gpioId) >= HAL_GPIO_QTY) return SR_INVALID;

    cfg.irq_type = pin_irq_hdr_table[gpioId].irqMode;
    if(cfg.irq_type==LUAT_GPIO_RISING_IRQ)
        cfg.pull = LUAT_GPIO_PULLDOWN;
    else if(cfg.irq_type==LUAT_GPIO_FALLING_IRQ)
        cfg.pull = LUAT_GPIO_PULLUP;
    else
        cfg.pull = LUAT_GPIO_DEFAULT;

    cfg.mode = LUAT_GPIO_IRQ;
    cfg.pin = gpioId;
    cfg.irq_cb = _luat_gpio_irq_cb; // 合宙定义的回调函数格式
    cfg.irq_args = pin_irq_hdr_table[gpioId].irqCb;  // 朝阳的回调作为合宙回调的void*形参

    for (uint8_t i = 0; i < GPIO_ALT_MAX; i++)
    {
        if (gpioId == gpio_alt[i].pin)
        {
            cfg.alt_fun = gpio_alt[i].alt;
            break;
        }
    }

    return luat_gpio_open(&cfg);

#if   0
    uint8_t irqMode = 0;

    if (gpioId >= HAL_GPIO_MAX)
    {
        uint8_t IsRiseHigh = 0;
        uint8_t IsFallLow = 0;
        uint8_t Pullup = 0;
        uint8_t Pulldown = 0;

        switch (pin_irq_hdr_table[gpioId].irqMode)
        {
        case SR_GPIO_IRQ_RISING:
            IsRiseHigh = 1;
            break;
        case SR_GPIO_IRQ_FALLING:
            IsFallLow = 1;
            break;
        case SR_GPIO_IRQ_DOUBLE:
            IsRiseHigh = 1;
            IsFallLow = 1;
            break;
        }

        switch (pin_irq_hdr_table[gpioId].pull_mode)
        {
        case SR_GPIO_PU:
            Pullup = 1;
            break;
        case SR_GPIO_PD:
            Pulldown = 1;
            break;
        }
        GPIO_WakeupPadConfig(gpioId, 1, IsRiseHigh, IsFallLow, Pullup, Pulldown);

        if (HAL_WAKEUP_PWRKEY == gpioId)
        {
            pwrKeySetSWOn();
        }
        return 0;
    }

    switch (pin_irq_hdr_table[gpioId].irqMode)
    {
    case SR_GPIO_IRQ_RISING:
        irqMode = LUAT_GPIO_RISING_IRQ;
        break;
    case SR_GPIO_IRQ_FALLING:
        irqMode = LUAT_GPIO_FALLING_IRQ;
        break;
    case SR_GPIO_IRQ_DOUBLE:
        irqMode = LUAT_GPIO_BOTH_IRQ;
        break;

    default:
        break;
    }

    return luat_gpio_ctrl(gpioId, LUAT_GPIO_CMD_SET_IRQ_MODE, irqMode);
#endif

}

int BspGpioDisableIrq(int gpioId)
{
    //参数有效性判断
    if (((uint32_t)gpioId) >= HAL_GPIO_QTY) return SR_INVALID;
    
    luat_gpio_close(gpioId);
    return  0;
#if 0
    if (gpioId >= HAL_GPIO_MAX)
    {
        uint8_t Pullup = 0;
        uint8_t Pulldown = 0;
        switch (pin_irq_hdr_table[gpioId].pull_mode)
        {
        case SR_GPIO_PU:
            Pullup = 1;
            break;
        case SR_GPIO_PD:
            Pulldown = 1;
            break;
        }
        GPIO_WakeupPadConfig(gpioId, 0, 0, 0, Pullup, Pulldown);
        return 0;
    }

    GPIO_ExtiConfig(gpioId, 0, 0, 0);
    return 0;
#endif
}

int BspGpioSetCb(int gpioId, SR_GPIO_IRQ_MODE_E irqMode, SR_GPIO_IRQ_CB_T *gpioIrqCb)
{
    //参数有效性判断
    if (((uint32_t)gpioId) >= HAL_GPIO_QTY) return SR_INVALID;
    if(gpioIrqCb==SR_NULL) return SR_INVALID;
    if(!IS_GPIO_IRQ_MODE(irqMode)) return SR_INVALID;


    pin_irq_hdr_table[gpioId].irqMode = irqMode;
    pin_irq_hdr_table[gpioId].irqCb = gpioIrqCb;
	luat_gpio_set_irq_cb(gpioId, _luat_gpio_irq_cb, gpioIrqCb);
    return 0;
}
int BspGpioUnsetCb(int gpioId)
{
    //参数有效性判断
    if (((uint32_t)gpioId) >= HAL_GPIO_QTY) return SR_INVALID;

    pin_irq_hdr_table[gpioId].irqCb = SR_NULL;
    GPIO_ExtiSetCB(gpioId, SR_NULL, SR_NULL);
    return SR_OK;
}
