/*
 * Modbus.h
 *
 *  Created on: 8. 3. 2020
 *      Author: Ondrej Vitoslavsky
 */

#ifndef MODBUS_H_
#define MODBUS_H_

#include "main.h"
#include "Modbus_functions.h"


//common Modbus defines
#define MODBUS_SLAVE_ADRESS  0x02

//USART for MODBUS communication with PLC
#define MODBUS_USART_PLC			USART2
#define MODBUS_TX_PIN_PLC			GPIO_PIN_5
#define MODBUS_TX_GPIO_PORT_PLC		GPIOD
#define MODBUS_TX_AF_PLC			GPIO_AF7_USART2

#define MODBUS_RX_PIN_PLC			GPIO_PIN_6
#define MODBUS_RX_GPIO_PORT_PLC		GPIOD
#define MODBUS_RX_AF_PLC			GPIO_AF7_USART2

#define MODBUS_IRQn_PLC				USART2_IRQn

#define MODBUS_DE_PIN_PLC     		GPIO_PIN_7
#define MODBUS_DE_GPIO_PORT_PLC		GPIOD


#define MODBUS_RS422_RECEIVE_MODE()	HAL_GPIO_WritePin(MODBUS_DE_GPIO_PORT_PLC,MODBUS_DE_PIN_PLC,0);
#define MODBUS_RS422_SEND_MODE()	HAL_GPIO_WritePin(MODBUS_DE_GPIO_PORT_PLC,MODBUS_DE_PIN_PLC,1);

#define MODBUS_TIMER_35			TIM3
#define MODBUS_TIMER_35_IRQn	TIM3_IRQn

#define MODBUS_TIMER_15			TIM4
#define MODBUS_TIMER_15_IRQn	TIM4_IRQn


typedef enum
{
	EVENT_NONE,				//No event happened
	EVENT_FRAME_RECEIVED,	//Frame received
	EVENT_FRAME_SENT,		//Frame sent
	EVENT_T15_EXPIRED		//Timer 1.5 expired
} ModbusEvent;



/**
  * @brief  Initialize the Modbus protocol.
  * @note   This functions initializes the RTU Modbus protocol.
  * 		Receiver is still disabled and no frames are
  * 		processed until Modbus_Enable() has been called.
  * @param  SlaveAddress slave address from 1 to 247.
  * @retval None.
  */
void Modbus_Init(uint8_t SlaveAddress);


/**
  * @brief  Pooling loop of  Modbus protocol.
  * @note   Must be called periodically. If there is new received frame,
  * 		function processes that frame and transmits message to master.
  * @param  none.
  * @retval None.
  */
void Modbus_Poll(void);


/**
  * @brief  Reading Holding registers.
  * @note   Copies data from holding_Register_Buffer to frame.
  * @param  RegisterBuffer pointer to first byte of frame, where read data
  * 		should be copied.
  * @param  RegisterAddress address of register in holding_Register_Buffer
  * 		where reading should start.
  * @param  RegCount number of registers to be read.
  * @retval none.
  */
void Modbus_Holding_Register_Read(uint8_t* Frame,
		uint16_t RegisterAddress, uint16_t RegCount);


/**
  * @brief  Writing Holding registers.
  * @note   Copies data from frame to holding_Register_Buffer.
  * @param  RegisterBuffer pointer to first byte of frame, where write data
  * 		should be copied.
  * @param  RegisterAddress address of register in holding_Register_Buffer
  * 		where writing should start.
  * @param  RegCount number of registers to be write.
  * @retval none.
  */
void Modbus_Holding_Register_Write(uint8_t* Frame,
		uint16_t RegisterAddress, uint16_t RegCount);

/**
  * @brief  Converts float value to uint16_t.
  * @note   Converts float value to two uint16_t values and writes it to
  * 		holding_register_Buffer.
  * @param  number real number to convert.
  * @param  store pointer to holding_register_Buffer where float value
  * 		should be written.
  * @retval none
  */
void ModBus_Real_to_Uint(float number,volatile uint16_t *store);

/**
  * @brief  Converts uint16_t value to float.
  * @note   Converts two uint16_t values to float.
  * @param  store pointer to first uint16_t value in holding_register_Buffer
  * @retval converted float value.
  */
float ModBus_Uint_to_Real(volatile uint16_t *store);

/**
  * @brief  Calculate Thickness.
  * @note   Calculate Thickness from measured Voltage on Analog Input.
  * 		uses scale and offset values sent by Master.
  * @param  Voltage voltage on Analog Input.
  * @param  Settings structure containing all data sent by master
  * 		including scale and offset values.
  * @retval Calculated thickness
  */
float Calculate_Thickness(float Voltage, Settings_struct *Settings);

/**
  * @brief  Updates Settings structure.
  * @note   Call after Modbus Master writes new settings data
  *			to holding_register_Buffer.
  * @param  Settings structure containing all data sent by master.
  * @retval none
  */
void Settings_Update(Settings_struct *Settings);

/**
  * @brief  Sets Settings structure to service settings.
  * @note   Call in case of unplugged Modbus communication.
  * @param  Settings structure containing all data sent by master.
  * @retval none
  */
void Settings_Service(Settings_struct *Settings);

#endif /* MODBUS_H_ */
