/**
**************************************************************************
* @file rs_message.h
* @brief Заголовочный файл для модуля реализации протоколов по RS/UART.
**************************************************************************
* @defgroup RS_TOOLS
* @brief 		Всякое для работы по UART/RS
**************************************************************************
@details
**************************************************************************
Для настройки RS/UART под нужный протокол, необходимо:
  - Определить структуру сообщения RS_MsgTypeDef и 
  дефайны RX_FIRST_PART_SIZE и MSG_SIZE_MAX.
  - Подключить этот файл в раздел rs_message.h.
	- Определить функции для обработки сообщения: RS_Parse_Message(), 
  RS_Collect_Message(), RS_Response(), RS_Define_Size_of_RX_Message()
	- Добавить UART/TIM Handler в Хендлер используемых UART/TIM.
 
Так же данный модуль использует счетчики 
**************************************************************************
@verbatim
Визуальное описание. Форматирование сохраняется как в коде.
@endverbatim
*************************************************************************/
#ifndef __RS_LIB_H_
#define __RS_LIB_H_

#include "modbus.h" 

#include "crc_algs.h"


/////////////////////////////////////////////////////////////////////
////////////////////////////---DEFINES---////////////////////////////
/* Check that all defines required by RS are defined */
#ifndef MSG_SIZE_MAX
#error Define MSG_SIZE_MAX (Maximum size of message). This is necessary to create buffer for UART.
#endif

#ifndef RX_FIRST_PART_SIZE
#error Define RX_FIRST_PART_SIZE (Size of first part of message). This is necessary to receive the first part of the message, from which determine the size of the remaining part of the message.
#endif


/* Clear message-uart buffer */
#define RS_Clear_Buff(_buff_)				for(int i=0; i<MSG_SIZE_MAX;i++)	_buff_[i] = NULL

/* Set/Reset flags */
#define RS_Set_Free(_hRS_)					_hRS_->f.RS_Busy = 0
#define RS_Set_Busy(_hRS_)					_hRS_->f.RS_Busy = 1

#define RS_Set_RX_Flags(_hRS_)			    _hRS_->f.RX_Busy = 1; _hRS_->f.RX_Done = 0; _hRS_->f.RX_Half = 0
#define RS_Set_RX_Active_Flags(_hRS_)   _hRS_->f.RX_Ongoing = 1


#define RS_Set_TX_Flags(_hRS_)			    _hRS_->f.TX_Busy = 1; _hRS_->f.TX_Done = 0

#define RS_Reset_RX_Active_Flags(_hRS_) _hRS_->f.RX_Ongoing = 0
#define RS_Reset_RX_Flags(_hRS_)		    RS_Reset_RX_Active_Flags(_hRS_); _hRS_->f.RX_Busy = 0; _hRS_->f.RX_Done = 0; _hRS_->f.RX_Half = 0
#define RS_Reset_TX_Flags(_hRS_)		    _hRS_->f.TX_Busy = 0; _hRS_->f.TX_Done = 0

#define RS_Set_RX_End_Flag(_hRS_)		_hRS_->f.RX_Done = 1;
#define RS_Set_TX_End_Flag(_hRS_)		_hRS_->f.TX_Done = 1

#define RS_Set_RX_End(_hRS_)				RS_Reset_RX_Flags(_hRS_); RS_Set_RX_End_Flag(_hRS_)
#define RS_Set_TX_End(_hRS_)				RS_Reset_TX_Flags(_hRS_); RS_Set_TX_End_Flag(_hRS_)

/* Clear all RS stuff */
#define RS_Clear_All(_hRS_) 				RS_Clear_Buff(_hRS_->pBufferPtr);	RS_Reset_RX_Flags(_hRS_);	RS_Reset_TX_Flags(_hRS_);

//#define MB_Is_RX_Busy(_hRS_)				((_hRS_->huart->gState&HAL_USART_STATE_BUSY_RX) == HAL_USART_STATE_BUSY_RX)
//#define MB_Is_TX_Busy(_hRS_)				((_hRS_->huart->gState&HAL_USART_STATE_BUSY_RX) == HAL_USART_STATE_BUSY_TX)
#define RS_Is_RX_Busy(_hRS_)				(_hRS_->f.RX_Busy == 1)
#define RS_Is_TX_Busy(_hRS_)				(_hRS_->f.TX_Busy == 1)


#ifndef RS_EnableReceive
#define RS_EnableReceive()
#endif
#ifndef RS_EnableTransmit
#define RS_EnableTransmit()
#endif
////////////////////////////---DEFINES---////////////////////////////



/////////////////////////////////////////////////////////////////////
///////////////////////---STRUCTURES & ENUMS---//////////////////////
//------------------ENUMERATIONS--------------------
/** @brief Enums for respond CMD about RS status */
typedef enum		// RS_StatusTypeDef
{
	/* IN-CODE STATUS (start from 0x01, and goes up)*/
	/*0x01*/	RS_OK = 0x01,
	/*0x02*/	RS_ERR,	
	/*0x03*/	RS_ABORTED,	
	/*0x04*/	RS_BUSY,		
	/*0x05*/	RS_SKIP,	
	
	/*0x06*/	RS_COLLECT_MSG_ERR,
	/*0x07*/	RS_PARSE_MSG_ERR,
	
	// reserved values
//	/*0x00*/ 	RS_UNKNOWN_ERR = 				0x00, ///< reserved for case, if no one error founded (nothing changed response from zero)
}RS_StatusTypeDef;


/** @brief Enums for RS Modes */
typedef enum	// RS_ModeTypeDef
{
	SLAVE_ALWAYS_WAIT =				0x01,		///< Slave mode with infinity waiting
	SLAVE_TIMEOUT_WAIT = 			0x02,		///< Slave mode with waiting with timeout
//	MASTER = 									0x03,		///< Master mode
}RS_ModeTypeDef;

/** @brief Enums for RS UART Modes */
typedef enum	// RS_ITModeTypeDef
{
	BLCK_MODE = 		0x00,		///< Blocking mode
	IT_MODE = 			0x01,		///< Interrupt mode
}RS_ITModeTypeDef;

/** @brief Enums for Abort modes */
typedef enum	// RS_AbortTypeDef
{
	ABORT_TX = 			0x01,		///< Abort transmit
	ABORT_RX = 			0x02,		///< Abort receive
	ABORT_RX_TX =		0x03,		///< Abort receive and transmit
	ABORT_RS = 			0x04,		///< Abort uart and reset RS structure
}RS_AbortTypeDef;

/** @brief Enums for RX Size modes */
typedef enum	// RS_RXSizeTypeDef
{
	RS_RX_Size_Const = 			0x01,		///< size of receiving message is constant
	RS_RX_Size_NotConst = 	0x02,		///< size of receiving message isnt constant
}RS_RXSizeTypeDef;


//-----------STRUCTURE FOR HANDLE RS------------
/** @brief Struct for flags RS */
typedef struct
{
	unsigned 									RX_Half:1;						///< flag: 0 - receiving msg before ByteCnt, 	0 - receiving msg after ByteCnt
	
	unsigned 									RS_Busy:1;						///< flag: 1 - RS is busy, 0 - RS isnt busy		
	unsigned 									RX_Ongoing:1;				  ///< flag: 1 - receiving data right now, 	0 - waiting for receiving data
  
	unsigned 									RX_Busy:1;						///< flag: 1 - receiving is active, 	0 - receiving isnt active
	unsigned 									TX_Busy:1;						///< flag: 1 - transmiting is active, 0 - transmiting isnt active				
	
	unsigned 									RX_Done:1;						///< flag: 1 - receiving is done, 	0 - receiving isnt done	
	unsigned 									TX_Done:1;						///< flag: 1 - transmiting is done, 0 - transmiting isnt done	
		
	// setted by user
	unsigned 									MessageHandled:1;		  ///< flag: 1 - RS command is handled, 				0 - RS command isnt handled yet
	unsigned 									EchoResponse:1;			  ///< flag: 1 - response with received msg,		0 - response with own msg
	unsigned 									DeferredResponse:1;	  ///< flag: 1 - response not in interrupt, 		0 - response in interrupt
	unsigned 									ReInit_UART:1;				///< flag: 1 - need to reinitialize uart, 		0 - nothing	
}RS_FlagsTypeDef;



/** 
	* @brief 	Handle for RS communication.
	* @note 	Prefixes: h - handle, s - settings, f - flag
	*/
typedef struct	// RS_HandleTypeDef
{		
	/* MESSAGE */
	uint8_t										ID;										///< ID of RS "channel"
	RS_MsgTypeDef 						*pMessagePtr;					///< pointer to message struct
	uint8_t 									*pBufferPtr;					///< pointer to message buffer
	uint32_t									RS_Message_Size;			///< size of whole message, not only data
	
	/* HANDLERS and SETTINGS */
	UART_HandleTypeDef 				*huart;								///< handler for used uart
	TIM_HandleTypeDef 				*htim;								///< handler for used tim
	RS_ModeTypeDef						sRS_Mode;							///< setting: slave or master @ref RS_ModeTypeDef
	RS_ITModeTypeDef					sRS_IT_Mode;					///< setting: 1 - IT mode, 	0 - Blocking mode 
	uint16_t 									sRS_Timeout;					///< setting: timeout in ms
	RS_RXSizeTypeDef					sRS_RX_Size_Mode;			///< setting: 1 - not const, 0 - const 
	
	/* FLAGS */		
	RS_FlagsTypeDef           f;                    ///< These flags for controling receive/transmit
  
	/* RS STATUS */
	RS_StatusTypeDef 					RS_STATUS;						///< RS status
}RS_HandleTypeDef;
extern RS_HandleTypeDef hmodbus1;


///////////////////////---STRUCTURES & ENUMS---//////////////////////


/////////////////////////////////////////////////////////////////////
///////////////////////////---FUNCTIONS---///////////////////////////
//----------------FUNCTIONS FOR PROCESSING MESSAGE-------------------
/*--------------------Defined by users purposes--------------------*/
/* Respond accord to received message */
RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg);

/* Collect message in buffer to transmit it */
RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff);

/* Parse message from buffer to process it */
RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff);

/* Define size of RX Message that need to be received */
RS_StatusTypeDef RS_Define_Size_of_RX_Message(RS_HandleTypeDef *hRS, uint32_t *rx_data_size);


//-------------------------GENERAL FUNCTIONS-------------------------
/*-----------------Should be called from main code-----------------*/
/* Start receive IT */
RS_StatusTypeDef RS_Receive_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg);

/* Start transmit IT */
RS_StatusTypeDef RS_Transmit_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg);

/* Initialize UART and handle RS stucture */
#ifdef INCLUDE_GENERAL_PERIPH_LIBS
RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, UART_SettingsTypeDef *suart, TIM_SettingsTypeDef *stim, uint8_t *pRS_BufferPtr);
#else
RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, UART_HandleTypeDef *huart, TIM_HandleTypeDef *htim, uint8_t *pRS_BufferPtr);
#endif
/* ReInitialize UART and RS receive */
#ifdef INCLUDE_GENERAL_PERIPH_LIBS
HAL_StatusTypeDef RS_ReInit_UART(RS_HandleTypeDef *hRS, UART_SettingsTypeDef *suart);
#else
HAL_StatusTypeDef RS_ReInit_UART(RS_HandleTypeDef *hRS, UART_HandleTypeDef *suart);
#endif
/* Abort RS/UART */
RS_StatusTypeDef RS_Abort(RS_HandleTypeDef *hRS, RS_AbortTypeDef AbortMode);
//-------------------------GENERAL FUNCTIONS-------------------------


//-------------------------------------------------------------------
//--------------------CALLBACK/HANDLER FUNCTIONS---------------------
/* Handle for starting receive */
RS_StatusTypeDef RS_Handle_Receive_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg);
/* Handle for starting transmit */
RS_StatusTypeDef RS_Handle_Transmit_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg);
/* UART RX Callback: define behaviour after receiving parts of message */
RS_StatusTypeDef RS_UART_RxCpltCallback(RS_HandleTypeDef *hRS);
/* UART TX Callback: define behaviour after transmiting message */
RS_StatusTypeDef RS_UART_TxCpltCallback(RS_HandleTypeDef *hRS);
/* Handler for UART */
void RS_UART_Handler(RS_HandleTypeDef *hRS);
/* Handler for TIM */
void RS_TIM_Handler(RS_HandleTypeDef *hRS);
//--------------------CALLBACK/HANDLER FUNCTIONS---------------------
///////////////////////////---FUNCTIONS---///////////////////////////


#ifndef printf_rs_err
#define printf_rs_err(...)
#endif

#ifndef printf_rs
#define printf_rs(...)
#endif
#endif // __RS_LIB_H_
