
#include "driver.h"
#include <linux/types.h>
#include <stdio.h>
#include <string.h>
#include "com_gpio.h"
#include "hal_interface_api.h"
#include "linux/fcntl.h"
#include <stdint.h>
#include "stm32f429xx.h"
#include "stm32_hal_legacy.h"

#define DEV_NAME	"/dev/gpio"

/* Demon
	// Set PD_2 output  
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.Pin = GPIO_PIN_12;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;

	stm32_gpio_init(GPIOD, &GPIO_InitStruct);
	stm32_gpio_write(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);

	// Set PI_8 input 
	GPIO_InitStruct.Pin = GPIO_PIN_8;
	GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
	stm32_gpio_init(GPIOI, &GPIO_InitStruct);

	//Set PD_2 low
	stm32_gpio_write(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET);
	//Get PI_8 value
	printf("PI_8: %d\n", stm32_gpio_read(GPIOI, GPIO_PIN_8));
*/

void  stm32_gpio_init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init)
{
	int fd;
	int ret;
	gpio_t gpio_arg;
	fd = open(DEV_NAME, O_RDWR);
	if(fd == -1)
	{
		printf("Open %s failed!\n", DEV_NAME);
	}

	gpio_arg.GPIOx = GPIOx;
	gpio_arg.GPIO_pin = GPIO_Init->Pin;
	memcpy(&gpio_arg.GPIO_Init, GPIO_Init, sizeof(GPIO_InitTypeDef));
	ret = ioctl(fd, GPIO_INIT, &gpio_arg);
	if(ret == -1)
	{
		printf("Init gpio failed!\n");
	}

	close(fd);
}

void stm32_gpio_write(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
{
	if(PinState != GPIO_PIN_RESET)
	{
	GPIOx->BSRR = GPIO_Pin;
	}
	else
	{
	GPIOx->BSRR = (uint32_t)GPIO_Pin << 16U;
	}
	// int fd;
	// int ret;
	// gpio_t gpio_arg;
	// fd = open(DEV_NAME, O_RDWR);
	// if(fd == -1)
	// {
	// 	printf("Open %s failed!\n", DEV_NAME);
	// }

	// gpio_arg.GPIOx = GPIOx;
	// gpio_arg.GPIO_pin = GPIO_Pin;
	// gpio_arg.Data	= PinState;
	// ret = ioctl(fd, GPIO_WRITE_PIN, &gpio_arg);
	// if(ret == -1)
	// {
	// 	printf("Write gpio failed!\n");
	// }

	// close(fd);
}

GPIO_PinState stm32_gpio_read(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
	GPIO_PinState bitstatus;

	/* Check the parameters */
	//assert_param(IS_GPIO_PIN(GPIO_Pin));

	if((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET)
	{
		bitstatus = GPIO_PIN_SET;
	}
	else
	{
		bitstatus = GPIO_PIN_RESET;
	}
	return bitstatus;
	// int fd;
	// int ret;
	// gpio_t gpio_arg;
	// fd = open(DEV_NAME, O_RDWR);
	// if(fd == -1)
	// {
	// 	printf("Open %s failed!\n", DEV_NAME);
	// }

	// gpio_arg.GPIOx = GPIOx;
	// gpio_arg.GPIO_pin = GPIO_Pin;
	// ret = ioctl(fd, GPIO_READ_PIN, &gpio_arg);
	// if(ret == -1)
	// {
	// 	printf("Write gpio failed!\n");
	// }
	// close(fd);

	// return gpio_arg.Data;
}

//direct = 0: input
//direct = 1: output
int stm32_gpio_direct(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, uint8_t direct)
{
	uint32_t temp;
	uint32_t ioposition;
	uint32_t iocurrent;
	uint32_t position;
	/* Configure the port pins */
  	for(position = 0U; position < 16; position++)
  	{
    	/* Get the IO position */
    	ioposition = 0x01U << position;
    	/* Get the current IO position */
    	iocurrent = (uint32_t)(GPIO_Pin) & ioposition;

	    if(iocurrent == ioposition)
	    {
			temp = GPIOx->MODER;
	      	temp &= ~(GPIO_MODER_MODER0 << (position * 2U));
	      	temp |= (direct << (position * 2U));
	      	GPIOx->MODER = temp;
	    }
    }
	// int fd;
	// int ret;
	// gpio_t gpio_arg;
	// if((direct != 0) && (direct != 1))
	// {
	// 	printf("Invalid direct! %d\n", direct);
	// 	return -1;
	// }
	// fd = open(DEV_NAME, O_RDWR);
	// if(fd == -1)
	// {
	// 	printf("Open %s failed!\n", DEV_NAME);
	// }

	// gpio_arg.GPIOx = GPIOx;
	// gpio_arg.GPIO_pin = GPIO_Pin;
	// gpio_arg.Direct = direct;
	// ret = ioctl(fd, GPIO_SET_DIR, &gpio_arg);
	// if(ret == -1)
	// {
	// 	printf("Set gpio direct failed!\n");
	// }
	// close(fd);

}