/******************************************************************************
 * @file      drv_gpio.c
 * @brief     初始化gpio接口配置
 * @version    V1
 * @copyright    
 ******************************************************************************/
 
#include "drv_gpio.h"
#include "drv_clk.h"
#include "kit_data.h"
#include "kit_debug.h"

typedef struct
{
    uint16_t        pin_cnt;
    const GpioArray *array; 
}GpioItem;


static GpioItem gpio_item;
static kit_ret_e gpio_set_pin_mode(uint32_t io, GpioMode mode);
GPIO_TypeDef * stm32_gpio[kGpioPort_End] = {GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG};


GpioStatus drv_gpio_get_pin_status(uint16_t idx)
{
    uint32_t   tmp, pin_bit, port;
    GpioStatus res = kGpioStatus_Err;
    
    KIT_ASSERT_PARAM(idx < gpio_item.pin_cnt);

    if(idx < gpio_item.pin_cnt)
    {
        tmp = gpio_item.array[idx].io;
        port = GPIO_GET_PORT(tmp);
        pin_bit = GPIO_GET_PIN_BIT(tmp);
        
        res = (GpioStatus)((stm32_gpio[port]->IDR & pin_bit) != 0);
    }
    
    return res;
}

kit_ret_e drv_gpio_set_pin_mode(uint8_t io_idx, GpioMode mode)
{
	return gpio_set_pin_mode(gpio_item.array[io_idx].io, mode);
}

kit_ret_e drv_gpio_set_pin_status(uint16_t idx, GpioStatus status)
{
    uint32_t  tmp, pin_bit, port;
    kit_ret_e res;
    //KIT_ASSERT_PARAM((idx < gpio_item.pin_cnt) && (gpio_item.array[idx].mode == kGpioMode_Output_PP));
    
    if(idx < gpio_item.pin_cnt)    
    {
		tmp = gpio_item.array[idx].io;
		port = GPIO_GET_PORT(tmp);
		pin_bit = GPIO_GET_PIN_BIT(tmp);
        if (status == kGpioStatus_High)
		{
			stm32_gpio[port]->BSRRL |= pin_bit;
		}
		else
		{
			stm32_gpio[port]->BSRRH |= pin_bit;
		}
        
        res = kKit_Ret_Ok;
    }
    else
    {
        res = kKit_Ret_ParamErr;
    }

    return res;
}

uint32_t drv_gpio_get_actual_io(uint16_t idx)
{
    uint32_t io;
    
    KIT_ASSERT_PARAM(idx < gpio_item.pin_cnt);
    
    if(idx < gpio_item.pin_cnt)
    {
        io = gpio_item.array[idx].io;
    } 
    else
    {
        io = 0xFFFFFFFF;
    }
    
    return io;    
}

typedef enum
{ 
  GPIO_Mode_IN   = 0x00, /*!< GPIO Input Mode */
  GPIO_Mode_OUT  = 0x01, /*!< GPIO Output Mode */
  GPIO_Mode_AF   = 0x02, /*!< GPIO Alternate function Mode */
  GPIO_Mode_AN   = 0x03  /*!< GPIO Analog Mode */
}GPIOMode_TypeDef;

const uint8_t gpio_mode_value[kGpioMode_End] = {GPIO_Mode_IN, GPIO_Mode_OUT, GPIO_Mode_AF, GPIO_Mode_AN};
static kit_ret_e gpio_set_pin_mode(uint32_t io, GpioMode mode)
 {
    uint8_t  pin, port;
    kit_ret_e res;

    pin = GPIO_GET_PIN(io);
    port =  GPIO_GET_PORT(io);
	
    KIT_ASSERT_PARAM((port < kGpioPort_End) && (mode < kGpioMode_End));
	
    if((port < kGpioPort_End) && (mode < kGpioMode_End))
    {
		//端口模式 0输入 1通用输出 2复用功能  3模拟模式
        stm32_gpio[port]->MODER &=  ~(0x03 << (pin << 1));
		stm32_gpio[port]->MODER |= (uint32_t)gpio_mode_value[mode] << (pin << 1);
        //输出模式 0输出推挽(复位默认值) 1输出开漏
		//速度 50MHz
		stm32_gpio[port]->OSPEEDR |= (uint32_t)0x02 << (pin << 1);
		//上下拉 无
		stm32_gpio[port]->PUPDR &= ~((uint32_t)0x03 << (pin << 1));
//        stm32_gpio[port]->PUPDR |= ((uint32_t)0x02 << (pin << 1));
//		if(mode == kGpioMode_Comm_Rx)
//		{
//			stm32_gpio[port]->PUPDR |= ((uint32_t)0x01 << (pin << 1));
//		}
        
        res = kKit_Ret_Ok;
    }
    else
    {
        res = kKit_Ret_ParamErr;
    }

    return res;
}

kit_ret_e drv_gpio_init(const GpioArray *array, uint16_t cnt)
{
    uint16_t  pin_bit;
    uint32_t  i, port, tmp;
    kit_ret_e res;
    
    KIT_ASSERT_PARAM((array != NULL) && (cnt > 0));
    
    
    if((array != NULL) && (cnt > 0))
    {       
        //打开IO口时钟
        RCC->AHB1ENR |= (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD  | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOF  | RCC_AHB1Periph_GPIOG);
        
        for(i = 0; i < cnt; i++)
        {           
            tmp = array[i].io;    
            port =  GPIO_GET_PORT(tmp);
            KIT_ASSERT_PARAM(port < kGpioPort_End);
            pin_bit = GPIO_GET_PIN_BIT(tmp);           
            KIT_ASSERT_PARAM(array[i].mode < kGpioMode_End);
            gpio_set_pin_mode(tmp, array[i].mode);
            
            if(array[i].mode == kGpioMode_Output_PP)  
            {
                if (array[i].init_st == kGpioStatus_High)
				{
					stm32_gpio[port]->BSRRL |= pin_bit;
				}
                else
				{
					stm32_gpio[port]->BSRRH |= pin_bit;
				}
            }
        } 
        gpio_item.array = array;
        gpio_item.pin_cnt = cnt;
        
        res = kKit_Ret_Ok;
    }
    else
    {
        res = kKit_Ret_ParamErr;
    }
    
    KIT_ASSERT_RES(0, res);
    return res;
}

void drv_gpio_set_af(uint8_t port, uint8_t pin, uint8_t af)
{
	stm32_gpio[port]->AFR[pin >> 3] |= (uint32_t)af << ((pin % 8) << 2);
	
//	stm32_gpio[port]->AFR[pin>>3]&=~(0X0F<<((pin&0X07)*4));
//	stm32_gpio[port]->AFR[pin>>3]|=(u32)af<<((pin&0X07)*4);
}