#include "uart.h"
#include "gpio.h"
//faire GPIO

void (* pFncUART) (uint8_t data); /* d�claration d�un pointeur de fonction */

void MyUART_Init_Periph (void (* ptrFonction)(uint8_t))
{
	pFncUART = ptrFonction; /* affectation du pointeur */
}

int MyUART_setClockBit(MyUART_Struct_Typedef * UARTStructPtr)
{
	if (UARTStructPtr->UART == USART1)
	{
		RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
		USART1->BRR = 72000000/(UARTStructPtr->BaudRate);	//Calculating the baudrate depending on the clock frequency
		return 0;
	}
	else if (UARTStructPtr->UART == USART2)
	{
		RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
		USART2->BRR = 36000000/(UARTStructPtr->BaudRate);
		return 0;
	}
	else if (UARTStructPtr->UART == USART3)
	{
		RCC->APB1ENR |= RCC_APB1ENR_USART3EN;
		USART3->BRR = 36000000/(UARTStructPtr->BaudRate);
		return 0;
	}
	else {
		return 1;
	}
}

uint8_t MyUART_GetInterruptNum(USART_TypeDef * UART)
{
	if(UART == USART1)
	{
		return USART1_IRQn;
	}
	else if(UART == USART2)
	{
		return USART2_IRQn;
	}
	else if(UART == USART3)
	{
		return USART3_IRQn;
	}
	else{
		return 0;
	}
}

void MyUART_ActiveIT(USART_TypeDef * UART, uint8_t Prio)
{
	uint32_t IRQNumber = MyUART_GetInterruptNum(UART);
	UART->CR1 |= (USART_CR1_RXNEIE); 				//Interruption active pour la reception UNIQUEMENT
	NVIC->IP[IRQNumber] |= (Prio << 0x4);			//Prio de l'interruption (p.197 manuel reference RM0008 pour ADC1_IRQn)
	NVIC->ISER[1] |= (0x1<<(IRQNumber-32));				//Active l'interruption au niveau NVIC  (p.119 manuel programming pour ISER[1])
}

void MyUART_Init(MyUART_Struct_Typedef * UARTStructPtr){
	MyUART_setClockBit(UARTStructPtr);	//Clock enable and setting the baud.
	UARTStructPtr->UART->CR1 = 0x00;   // Clear ALL
	UARTStructPtr->UART->CR1 |= USART_CR1_UE;
	UARTStructPtr->UART->CR1 |= ((UARTStructPtr->length)<<12);	//Setting the Length of the data transmitted

	UARTStructPtr->UART->CR1 &= ~(0x3<<9);		//reset CR1 9-10 bits, Parity Selection
	if(UARTStructPtr->parity != parityNone)		//if parity is enabled
	{
		UARTStructPtr->UART->CR1 |= (UARTStructPtr->parity<<9);	//depending on the parity changing the 9th bit, and set 10th bit to 1
	}

	UARTStructPtr->UART->CR2 &= ~(0x3<<12);		//reset CR2 13-12  bits, Stop bits
	if(UARTStructPtr->stop != stopBit1)				//if stop bits > 1
	{
		UARTStructPtr->UART->CR2 |= (UARTStructPtr->stop<<12);	//depending on the stop changing the 12th and 13th bit.
	}
	//TxD Enable, RxD Enable, USART Global Enable
	UARTStructPtr->UART->CR1 |= (USART_CR1_TE | USART_CR1_RE);
	MyUART_ActiveIT(UARTStructPtr->UART,3);
}

void MyUART_InitGPIO(MyUART_Struct_Typedef * UARTStructPtr)
{
	MyGPIO_Struct_TypeDef rxd,txd;
	if(UARTStructPtr->UART == USART1)
	{
		rxd = (MyGPIO_Struct_TypeDef){GPIOA,10,In_Floating};
		txd = (MyGPIO_Struct_TypeDef){GPIOA,9,AltOut_Ppull};
	}
	else if(UARTStructPtr->UART == USART2) {
		rxd = (MyGPIO_Struct_TypeDef){GPIOA,3,In_Floating};
		txd = (MyGPIO_Struct_TypeDef){GPIOA,2,AltOut_Ppull};
	}
	else if(UARTStructPtr->UART == USART3) {
		rxd = (MyGPIO_Struct_TypeDef){GPIOB,11,In_PullUp};
		txd = (MyGPIO_Struct_TypeDef){GPIOB,10,AltOut_Ppull};
	}
	else {
		return;
	}
	MyGPIO_Init(&rxd);
	MyGPIO_Init(&txd);
}

int MyUART_SendArray(MyUART_Struct_Typedef *UART, uint8_t * data, int dataLength)
{
	int i;
	for(i=0; i<dataLength; i++)
	{
		UART->UART->DR = data[i];
		while (!(UART->UART->SR & USART_SR_TXE));
	}
	return 0;
}

void MyUART_Send(MyUART_Struct_Typedef *UART, uint8_t data)
{
  UART->UART->DR = data;
	//du DR au Registre de Transmission, on attend que le shift register ai récupéré le DR
  while (!(UART->UART->SR & USART_SR_TXE));
}

uint8_t MyUART_Receive(MyUART_Struct_Typedef *UART)
{
	while (!(UART->UART->SR & USART_SR_RXNE));  // Si RXNE est mis à 1, alors on vient de recevoir une donnée !
	uint8_t data = UART->UART->DR;  // Read the data. 
	UART->UART->SR &= ~USART_SR_RXNE;	//flag to 0
	return data;
}

void USART1_IRQHandler(void)
{
	if((USART1->SR & USART_SR_RXNE) == USART_SR_RXNE)	//verify the flag
	{
		if (pFncUART != 0)
		(*pFncUART) (USART1->DR); /* appel indirect de la fonction */
		USART1->SR &= ~USART_SR_RXNE;	//flag to 0
	}
}

void USART2_IRQHandler(void)
{
	if((USART2->SR & USART_SR_RXNE) == USART_SR_RXNE) //verify the flag
	{
		if (pFncUART != 0)
		(*pFncUART) (USART2->DR); /* appel indirect de la fonction */
		USART2->SR &= ~USART_SR_RXNE;	//flag to 0
	}
}

void USART3_IRQHandler(void)
{
  // Check if receive data register not empty
  if((USART3->SR & USART_SR_RXNE) == USART_SR_RXNE) //verify the flag
  {
		if (pFncUART != 0)
		(*pFncUART) (USART3->DR); /* appel indirect de la fonction */
		USART2->SR &= ~USART_SR_RXNE;	//flag to 0
  }
}

/* exemple utilisation fonction :
	
	UART1.UART = USART1; // choix UART (USART1, USART2, USART3)
	UART1.BaudRate = 9600; // Vitesse de communication MAX 118200
	UART1.Wlengh = Wlengh8; // longeur du mot (Wlengh8 ,Wlengh9)
	UART1.Wparity = parity_even; // parit� (parity_even, parity_odd, parity_none)
	UART1.Wstop = stop1b; // nombre bit de stop (stop1b, stop2b)
	MyUART_Init(&UART1); // initialisation
*/
