#include "pin_io.h"

/* 配置 */
#include "config/board_config.h"
#include "config/app_config.h"
#include "config/app_log.h"

#if defined(CONFIG_CAP_LED_STRIP)
#include "led_strip/config/led_strip_config.h"
#endif

/* SDK */
#include "driver/gpio.h"

/* 通用模块 */
#include "button/button.h"

#include "os/os.h"

#define CONFIG_SYS_LOG_LEVEL SYS_LOG_LEVEL_INF
#define SYS_LOG_DOMAIN "PIN"
#include "sys_log.h"

/**
 * @brief IO 基本操作：配置为通用输入
 *
 * @param pin 0..n
 */
void pin_cfg_input(const cfg_board_pin_io_t *pin)
{
    if (GPIO_USED(pin->pin) == false)
    {
        SYS_LOG_WRN("pin %d not used", pin->pin);
        return;
    }

    gpio_config_t io_conf;
    io_conf.mode = GPIO_MODE_INPUT;
    io_conf.pull_up_en = (pin->en_lev == 0 ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE);
    io_conf.pull_down_en = (pin->en_lev ? GPIO_PULLDOWN_ENABLE : GPIO_PULLDOWN_DISABLE);
    io_conf.pin_bit_mask = 1ULL << pin->pin;
    io_conf.intr_type = GPIO_INTR_DISABLE;
    gpio_config(&io_conf);
}

/**
 * @brief IO 基本操作：获取当前输入电平是否为有效的电平
 *
 * @param pin 0..n
 * @retval true 对应预设为有效的电平
 * @retval false 对应预设为非有效的电平
 */
bool pin_get_valid(const cfg_board_pin_io_t *pin)
{
    if (GPIO_USED(pin->pin) == false)
    {
        SYS_LOG_WRN("pin %d not used", pin->pin);
        return false;
    }

    return gpio_get_level(pin->pin) ^ !pin->en_lev;
}

/**
 * @brief IO 基本操作：配置为通用输出
 *
 * @param pin 0..n
 */
void pin_cfg_output(const cfg_board_pin_io_t *pin)
{
    if (GPIO_USED(pin->pin) == false)
    {
        SYS_LOG_WRN("pin %d not used", pin->pin);
        return;
    }

    gpio_config_t io_conf;
    io_conf.mode = GPIO_MODE_INPUT_OUTPUT;
    io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
    io_conf.pull_down_en = GPIO_PULLDOWN_ENABLE;
    io_conf.pin_bit_mask = 1ULL << pin->pin;
    io_conf.intr_type = GPIO_INTR_DISABLE;
    gpio_config(&io_conf);
}

/**
 * @brief IO 基本操作：设置使输出是否为有效的电平
 *
 * @param pin 0..n
 * @param en false: 使输出为对应预设为非有效的电平； true: 使输出为对应预设为有效的电平
 */
void pin_set_valid(const cfg_board_pin_io_t *pin, bool en)
{
    if (GPIO_USED(pin->pin) == false)
    {
        SYS_LOG_WRN("pin %d not used", pin->pin);
        return;
    }

    gpio_set_level((gpio_num_t)pin->pin, !pin->en_lev ^ !!en);
}

