#include "periph_gpio.h"

#define GPIO_RES_TBL_VBAT_IDX_MIN   0
#define GPIO_RES_TBL_VBAT_IDX_MAX   15
#define GPIO_RES_TBL_VBAT_MIN       1800
#define GPIO_RES_TBL_VBAT_MAX       3300
// gnd
const uint16_t gpio_res_tbl_gnd[] = {
  1396,    482,    296,    220,
  1321,    457,    283,    209,
  1258,    438,    269,    201,
  1206,    421,    261,    194,
  1166,    406,    253,    188,
  1129,    396,    245,    184,
  1096,    385,    240,    180,
  1072,    378,    235,    177,
  1050,    371,    232,    175,
  1032,    366,    229,    173,
  1016,    360,    226,    171,
  1002,    356,    224,    170,
   990,    352,    222,    168,
   980,    349,    221,    167,
   971,    346,    219,    166,
   964,    344,    217,    165
};
// vdd
const uint16_t gpio_res_tbl_vdd[] = {
  1644,    562,    345,    252,
  1567,    537,    329,    241,
  1505,    515,    315,    231,
  1447,    493,    304,    223,
  1397,    478,    294,    215,
  1353,    463,    285,    209,
  1315,    448,    278,    203,
  1279,    436,    270,    197,
  1245,    426,    264,    192,
  1218,    417,    256,    188,
  1192,    408,    250,    185,
  1169,    400,    246,    181,
  1145,    390,    242,    178,
  1123,    383,    237,    174,
  1105,    376,    232,    170,
  1086,    371,    226,    165
};


/**
 *引脚功能选择配置
 * param: PinNum(#define GPIO_PIN_0---#define GPIO_PIN_23)
 */
void GPIO_FunctionConfig(uint8_t PinNum, uint8_t CfgVal)
{
    volatile uint32_t * pcfg = (volatile uint32_t *)OMW_GPIO_CFG_BASE_ADDR;

    uint32_t wof = (PinNum >> 2);
    uint32_t bof = (PinNum & 3);
    uint32_t msk = (0xFF << (8 * bof));
    uint32_t rv  = *(pcfg + wof);

    rv &= (~msk);
    rv |= (CfgVal << (8 * bof));

    *(pcfg + wof) = rv;
}

// 结构体初始化函数
void GPIO_StructInit(GPIO_InitTypeDef *GPIO_InitStruct){
    GPIO_InitStruct->GPIO_Pin = GPIO_PIN_NONE;
    GPIO_InitStruct->GPIO_Mode = GPIO_MODE_HIZ;
    GPIO_InitStruct->GPIO_AltFunc = GPIO_ATF_NONE;
    GPIO_InitStruct->GPIO_DriveStrength = GPIO_DRIVE_STRENGTH_0;
}

// GPIO初始化函数
void GPIO_Init(GPIO_InitTypeDef *GPIO_InitStruct)
{
    uint8_t i, func, func_mod, func_drv, func_atf;
    // mode parse
    if (GPIO_InitStruct->GPIO_Mode == GPIO_MODE_OUT_PP)
    {
        func_mod = 0;
        func_atf = 0;
        GPIO_ResetBits(GPIO_InitStruct->GPIO_Pin);
        GPIO_OutputCMD(GPIO_InitStruct->GPIO_Pin, ENABLE);
    }
    else
    {
        func_mod = GPIO_InitStruct->GPIO_Mode;
        func_atf = GPIO_InitStruct->GPIO_AltFunc;
        GPIO_OutputCMD(GPIO_InitStruct->GPIO_Pin, DISABLE);
    }
    func_drv = GPIO_InitStruct->GPIO_DriveStrength;
#ifdef OMW_CHIP_T1100
	func = GPIO_FunctionAsselbme(func_mod, func_atf ,0);
	if((GPIO_InitStruct->GPIO_Pin) <16)
	{
		*(volatile uint32_t *)(0x400100A0)|= ((GPIO_InitStruct->GPIO_Pin)<<func_drv);
		
	}
	else {
		*(volatile uint32_t *)(0x400100A4)|= ((GPIO_InitStruct->GPIO_Pin)<<func_drv);
	}
#else
    func = GPIO_FunctionAsselbme(func_mod, func_drv, func_atf);
#endif
    // gpio configuration
    for(i=0; i<24; i++)
    {
        if(((GPIO_InitStruct->GPIO_Pin) >> i) & 1)
        {
            GPIO_FunctionConfig(i, func);
        }
    }
}


/**
 * 重置GPIO引脚
 * param: (#define GPIO_PIN_0---#define GPIO_PIN_23)
 */
void GPIO_DeInit(uint32_t GPIO_Pin)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    // set gpio HIZ
    GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin;
    GPIO_Init(&GPIO_InitStruct);
    // clear output
    GPIO_OutputCMD(GPIO_Pin, DISABLE);
    GPIO_ResetBits(GPIO_Pin);
    // clear interrupt
    GPIO_ITCMD(GPIO_Pin, DISABLE);
    GPIO_ITConfig(GPIO_Pin, GPIO_ITMODE_ALL, DISABLE);
    GPIO_ClearITPendingBit(GPIO_Pin);
    // clear filt
    GPIO_FiltConfig(GPIO_Pin, DISABLE);
}

/**
 *  读取引脚输入状态
 *  param: (#define GPIO_PIN_0---#define GPIO_PIN_23)
 */
uint8_t GPIO_ReadInputDataBit(uint32_t GPIO_Pin)
{
    uint8_t bitstatus = 0x00;
    if (((GPIO_INOUT->GPIO_I) & GPIO_Pin) != RESET)
        bitstatus = SET;
    else
        bitstatus = RESET;
    return bitstatus;
}


/**
 * 读取所有引脚的输入状态
 * 返回值：引脚的输入状态
 */

uint32_t GPIO_ReadInputData(void)
{
    return GPIO_INOUT->GPIO_I; // remove output pins ???
}


/**
 * 读取指定引脚的输出状态
 * 返回值：引脚的输出状态
 */
uint8_t GPIO_ReadOutputDataBit(uint32_t GPIO_Pin)
{
    uint8_t bitstatus;
    if (((GPIO_INOUT->GPIO_O) & GPIO_Pin) != RESET)
    {
        bitstatus = SET;
    }
    else
    {
        bitstatus = RESET;
    }
    return bitstatus;
}


/**
 * 读取所有引脚的输出状态
 * 返回值：引脚的输出状态
 */
uint32_t GPIO_ReadOutputData(void)
{
    return GPIO_INOUT->GPIO_O;
}


/**
 * 输出使能/失能函数
 * param:GPIO_Pin: (#define GPIO_PIN_0---#define GPIO_PIN_23)
 *       state : ENABLE/DISABLE
 */
void GPIO_OutputCMD(uint32_t GPIO_Pin, FunctionalState state)
{
    if(state != DISABLE)
    {
        GPIO_INOUT->GPIO_OE |= GPIO_Pin;
    }
    else
    {
        GPIO_INOUT->GPIO_OE &= ~GPIO_Pin;
    }
}

// 对应引脚输出bit位，置1
void GPIO_SetBits(uint32_t GPIO_Pin)
{
    GPIO_INOUT->GPIO_O_SET = GPIO_Pin;
}

// 对应引脚输出bit位，置0
void GPIO_ResetBits(uint32_t GPIO_Pin)
{
    GPIO_INOUT->GPIO_O_CLR = GPIO_Pin;
}

/**
 * 设置引脚为高电平
 * param: GPIO_Pin: (#define GPIO_PIN_0---#define GPIO_PIN_23)
 *        BitVal : LOW/HIGH
 */
void GPIO_WriteBit(uint32_t GPIO_Pin, lineStatus BitVal)
{
    if (BitVal != LOW)
    {
        GPIO_INOUT->GPIO_O |= GPIO_Pin;
    }
    else
    {
        GPIO_INOUT->GPIO_O &= ~GPIO_Pin;
    }
}

// 设置所有引脚电平
void GPIO_Write(uint32_t RegVal)
{
    GPIO_INOUT->GPIO_O = RegVal;
}


 /**
 * GPIO中断配置
 * param: GPIO_Pin: (#define GPIO_PIN_0---#define GPIO_PIN_23)
 *        GPIO_ITMode:  #define GPIO_ITMODE_NONE            0x00
 *                      #define GPIO_ITMODE_HIGH            0x01
 *                      #define GPIO_ITMODE_LOW             0x02
 *                      #define GPIO_ITMODE_RISE            0x04
 *                      #define GPIO_ITMODE_FALL            0x08
 *                      #define GPIO_ITMODE_ALL             0x0F
 *        NewState: ENABLE/DISABLE
 */
void GPIO_ITConfig(uint32_t GPIO_Pin, uint8_t GPIO_ITMode, FunctionalState NewState)
{
    if (NewState != DISABLE) // ENABLE
    {
        if ((GPIO_ITMode >> 0) & 1) // high
        {
            GPIO_INTR->GPIO_IT_HI |= GPIO_Pin;
        }
        if ((GPIO_ITMode >> 1) & 1) // low
        {
            GPIO_INTR->GPIO_IT_LO |= GPIO_Pin;
        }
        if ((GPIO_ITMode >> 2) & 1) // rise
        {
            GPIO_INTR->GPIO_IT_PEDGE |= GPIO_Pin;
        }
        if ((GPIO_ITMode >> 3) & 1) // fall
        {
            GPIO_INTR->GPIO_IT_NEDGE |= GPIO_Pin;
        }
    }
    else // DISABLE
    {
        if ((GPIO_ITMode >> 0) & 1) // high
        {
            GPIO_INTR->GPIO_IT_HI &= ~GPIO_Pin;
        }
        if ((GPIO_ITMode >> 1) & 1) // low
        {
            GPIO_INTR->GPIO_IT_LO &= ~GPIO_Pin;
        }
        if ((GPIO_ITMode >> 2) & 1) // rise
        {
            GPIO_INTR->GPIO_IT_PEDGE &= ~GPIO_Pin;
        }
        if ((GPIO_ITMode >> 3) & 1) // fall
        {
            GPIO_INTR->GPIO_IT_NEDGE &= ~GPIO_Pin;
        }
    }
}

// GPIO引脚中断使能函数
void GPIO_ITCMD(uint32_t GPIO_Pin, FunctionalState NewState)
{
    if(NewState != DISABLE)
    {
        GPIO_INTR->GPIO_IE |= GPIO_Pin;
    }
    else
    {
        GPIO_INTR->GPIO_IE &= ~GPIO_Pin;
    }
}


// 判断GPIO指定引脚中断状态
uint32_t GPIO_GetITStatus(uint32_t GPIO_Pin)
{
    if ((GPIO_INTR->GPIO_MIS & GPIO_Pin) != 0)
    {
        return SET;
    }
    else
    {
        return RESET;
    }
}

// 清除GPIO中断标志位
void GPIO_ClearITPendingBit(uint32_t GPIO_Pin)
{
    GPIO_INTR->GPIO_IS = GPIO_Pin;
}


/**
 * 滤波窗口大小配置
 * param: FiltWinSize取值0~15
 */
void GPIO_FiltWindowConfig(uint8_t FiltWinSize)
{
    GPIO_INOUT->GPIO_FILT_CTRL &= 0x0000ffff; // clear 19:16
    GPIO_INOUT->GPIO_FILT_CTRL |= (FiltWinSize << 16); // set 19:16
}


// GPIO引脚的滤波配置
void GPIO_FiltConfig(uint32_t GPIO_Pin, FunctionalState NewState)
{
    // group 0, gpio[7:0]
    if (GPIO_Pin & (0xff << 0))
    {
        if (NewState != DISABLE)
        {
            GPIO_INOUT->GPIO_FILT_CTRL |= 0x0101;
        }
        else
        {
            GPIO_INOUT->GPIO_FILT_CTRL &= (~0x0101);
        }
    }
    // group 1, gpio[15:8]
    if (GPIO_Pin & (0xff << 8))
    {
        if (NewState != DISABLE)
        {
            GPIO_INOUT->GPIO_FILT_CTRL |= 0x0202;
        }
        else
        {
            GPIO_INOUT->GPIO_FILT_CTRL &= (~0x0202);
        }
    }
    // group 3, gpio[23:16]
    if (GPIO_Pin & (0xff << 16))
    {
        if (NewState != DISABLE)
        {
            GPIO_INOUT->GPIO_FILT_CTRL |= 0x0404;
        }
        else
        {
            GPIO_INOUT->GPIO_FILT_CTRL &= (~0x0404);
        }
    }
}

// Description: Get GPIO resistance
// Return value: GPIO resistance, unit: ohm
// DriveStrength: GPIO drive strength
// Vbat: battery voltage, unit: mV
// isToGND: 1: to GND, 0: to VDD
uint16_t GPIO_GetIORes(uint8_t DriveStrength, uint16_t Vbat, uint8_t isToGND)
{
    uint16_t *tbl;
    uint16_t vbat_idx;
    uint16_t res, res_base, res_diff;
    // table select
    if(isToGND)
    {
        tbl = (uint16_t *)gpio_res_tbl_gnd;
    }
    else
    {
        tbl = (uint16_t *)gpio_res_tbl_vdd;
    }
    // vbat index
    if(Vbat > GPIO_RES_TBL_VBAT_MAX)
    {
        vbat_idx = GPIO_RES_TBL_VBAT_IDX_MAX;
    }
    else if(Vbat < GPIO_RES_TBL_VBAT_MIN)
    {
        vbat_idx = GPIO_RES_TBL_VBAT_IDX_MIN;
    }
    else
    {
        vbat_idx = (Vbat - GPIO_RES_TBL_VBAT_MIN)/100;
    }
    DriveStrength &= 3;
    // get two adjacent elements
    res_base = tbl[vbat_idx*4 + DriveStrength];
    if(Vbat >= GPIO_RES_TBL_VBAT_MAX)
    {
        res = res_base;
        return ((res + 5)/10);
    }
    res_diff = res_base - tbl[(vbat_idx+1)*4 + DriveStrength];
    res = res_base - (res_diff * (Vbat%100) / 100);
    // return
    return ((res + 5)/10);
}

