/*
 * Modbus_serial.c
 *
 *  Created on: 8. 3. 2020
 *      Author: Ondrej Vitoslavsky
 */

#include "main.h"
#include "Modbus.h"
#include "Modbus_RTU.h"
#include "Modbus_periph.h"

UART_HandleTypeDef huart2;

void Modbus_Serial_Init(uint32_t BaudRate, uint32_t Word_Length, uint32_t Parity )
{
  GPIO_InitTypeDef GPIO_InitStructure;

  //Enable UART clock
  __HAL_RCC_USART2_CLK_ENABLE();
  //Enable GPIOD clock
  __HAL_RCC_GPIOD_CLK_ENABLE();

  //Configure USART Tx and Rx as alternate function
  GPIO_InitStructure.Pin=MODBUS_TX_PIN_PLC|MODBUS_RX_PIN_PLC;
  GPIO_InitStructure.Mode=GPIO_MODE_AF_PP;
  GPIO_InitStructure.Pull=GPIO_PULLUP;
  GPIO_InitStructure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStructure.Alternate=GPIO_AF7_USART2;
  HAL_GPIO_Init(MODBUS_TX_GPIO_PORT_PLC,&GPIO_InitStructure);

  //USART configuration
  huart2.Instance = MODBUS_USART_PLC;
  huart2.Init.BaudRate = BaudRate;
  huart2.Init.WordLength = Word_Length;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = Parity;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;

  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }

  //Enable the USARTx Interrupt
  HAL_NVIC_SetPriority(MODBUS_IRQn_PLC, 1, 0);
  HAL_NVIC_EnableIRQ(MODBUS_IRQn_PLC);


  __HAL_UART_DISABLE_IT(&huart2, UART_IT_RXNE);
  __HAL_UART_DISABLE_IT(&huart2, UART_IT_TXE);

  //Enable USART
  __HAL_UART_ENABLE(&huart2);
}


void Modbus_Serial_Enable( uint8_t Rx_Enable, uint8_t Tx_Enable )
{
	if(Rx_Enable)
    {
		//wait until all data are transmitted (transmit flag is 0)
		while(!__HAL_UART_GET_FLAG(&huart2,UART_FLAG_TC));
		MODBUS_RS422_RECEIVE_MODE();
		//safety delay for DE pin to come down
    	Delay_us(2);
		__HAL_UART_ENABLE_IT(&huart2, UART_IT_RXNE);
    }
    else
    {
    	MODBUS_RS422_SEND_MODE();
    	//safety delay for DE pin to come up
    	Delay_us(2);
    	__HAL_UART_DISABLE_IT(&huart2, UART_IT_RXNE);
    }

    if(Tx_Enable)
    {
		__HAL_UART_ENABLE_IT(&huart2, UART_IT_TXE);
    }
    else
    {

		__HAL_UART_DISABLE_IT(&huart2, UART_IT_TXE);
    }

}


void Modbus_Put_Byte( uint8_t Byte )
{
	//non-blocking mode
	huart2.Instance->DR=(Byte&(uint16_t)0x01FF);
}

void Modbus_Get_Byte(uint8_t* Byte)
{
	HAL_UART_Receive(&huart2,Byte,1,HAL_MAX_DELAY);
	__HAL_UART_CLEAR_FLAG(&huart2,UART_FLAG_RXNE);
}


void USART2_IRQHandler(void)
{
	if(__HAL_UART_GET_IT_SOURCE(&huart2,UART_IT_RXNE)||
			__HAL_UART_GET_IT_SOURCE(&huart2,UART_IT_TXE))
	{
		Modbus_RTU_FSM();
	}
}
