//----------------------------------------------------
/**
	\file		ctk/inc/modbusL2.h
	\ingroup	serial
	\ingroup	all

	\brief		Implementace protokolu SerialModbus (v1.02)
				<<< ALL >>>
	
	\author		ConTeK s.r.o., Bc. Jakub Kastner
	\version	01.02
	\date		28.12.2015
*/
//----------------------------------------------------

#ifndef _SerialModbus_H_
#define _SerialModbus_H_

#include <ctktypes.h>
#include <comm.h>
#include <stmachine.h>
#include <appsets.h>


//----------------------------------------------------
//defines
#define MODBUS_MAX_MSG_LENGHT		( 256 )
#define MODBUS_MAX_DATA_LENGHT		( 252 )
#define MODBUS_BROADCAST_ADDRESS	( 0 )

//----------------------------------------------------
//Timings [ms]
#ifdef MSVC

#define	INTER_FRAME_DELAY		(100) //!< NO SENSE

#define	MIN_TIME_INTER_FRAME_DELAY	(3000)
#define	MIN_TIME_MAX_INTER_CHAR_DELAY	(3000)

#else

#define	INTER_FRAME_DELAY		(3.5) //!< MINIMALNE 3.5 ZNAKU
#define	MAX_INTER_CHAR_DELAY		(1.5) //!< MAXIMALNE 1.5 ZNAKU

#define	MIN_TIME_INTER_FRAME_DELAY	(1.75)
#define	MIN_TIME_MAX_INTER_CHAR_DELAY	(0.75)
#endif

//----------------------------------------------------
//! Stavy automatu komunikace
typedef enum _MODBUS_STATE{
	ST_MODBUS_IDLE = STM_FIRST_USER_STATE,
	ST_MODBUS_CHECKING_REQUEST,
	ST_MODBUS_PROCESSING_REQUIED_ACTION,
//	ST_MODBUS_FORMATING_NORMAL_REPLY,
//	ST_MODBUS_FORMATING_ERROR_REPLY
	ST_MODBUS_REPLY
} MODBUS_STATE;

typedef enum _MB_STATE_CMD{
	ST_do_idle,
	ST_do_checking,
	ST_do_error
} MB_STATE_CMD;

//----------------------------------------------------
//!	Stavy automatu pro vysilani
typedef enum _MODBUS_RT_STATE
{
	ST_MODBUS_T_IDLE = STM_FIRST_USER_STATE,
	ST_MODBUS_T_RECEPTION_CONTROL_WAITING,
	ST_MODBUS_T_EMISSION,
} MODBUS_RT_STATE;


//----------------------------------------------------
/**
	\brief	Forward deklarace kontextu
*/
//----------------------------------------------------
struct _MODBUS_CTX;
struct _MODBUS_MSG;

//----------------------------------------------------
//Metody komunikace


//! Tick komunikcai automatu komunikace
typedef void (*cmSendCtrl_t) (const struct _COMMDESC * const _cmm, const bool_t _enable);

typedef void (*cmMBTick_t) ( struct _MODBUS_CTX * _ctx );

typedef uint8_t (*cmMBSendMSG_t) ( struct _MODBUS_CTX * const _ctx,  struct _MODBUS_MSG * _msg);

typedef uint8_t (*cmMBRecMSG_t) ( struct _MODBUS_CTX * const _ctx,  uint8_t * const _msg, uint8_t _len);

typedef bool_t (*cbMBProcesMSG_t) ( struct _MODBUS_CTX * const _ctx,  struct _MODBUS_MSG * const _msg );

//----------------------------------------------------
//! Struktura Zpravy 
typedef struct _MODBUS_MSG{
	uint8_t		Addr;		//!< adresa
	uint8_t		Function;	//!< Target function

	//data
	uint8_t		Data[MODBUS_MAX_DATA_LENGHT];		//!< Data bytes

	//check sum
	uint16_t	CRC;			//!< Check sum
	uint8_t		DataSize;
} MODBUS_MSG;


typedef struct _MODBUS_BUFF
{
	BUFDESC		Desc;
	uint8_t		Msg[MODBUS_MAX_MSG_LENGHT];
} MODBUS_BUFF;


//----------------------------------------------------
//! Struktura kontextu automatu vysilace a prijimace
typedef struct _MODBUS_RT_CTX
{
	STMACHINE	Stm;			//!< Kontext automatu
	uint16_t	CharNum;		//!< Cislo aktualne odeslaneho/prijateho bytu dat
	uint16_t	CRC;			//!< Check Sum

	ticks_t		T15;		//!< promenna pro ukladani timeoutu min ( vysilani )
	ticks_t		T35;		//!< promenna pro ukladani timeoutu max ( vysilani / prijem )

	MODBUS_BUFF	*	Actual;
} MODBUS_RT_CTX;


//----------------------------------------------------
//! Struktura kontextu automatu komunikace

typedef struct _MODBUS_CTX
{
	COMMDESC *			Cmm;		//!< ukazatel na komunikaci nizsi vrstvy {vuart}
	STMACHINE			Stm;		//!< Stavovy automat 
	MB_STATE_CMD		Cmd;

	MODBUS_RT_CTX		RTCtx;		//!< Automat vysilace/prijmace

	cmSend_t			Send;		//!< ukazatel na Send linkove vrstvy
	cmRecv_t			Recv;		//!< ukazatel na Recv linkove vrstvy

	MODBUS_MSG	 	SND_BUFF;		//!< Vysilaci buffer ve fronte
	MODBUS_MSG  	REC_MSG;		//!< Prijmaci buffer ve fronte

	cmRecvMsgEnd_t	CmmRecvMsgEnd;		//!< CallBack po prijeti zpravy

	cmMBTick_t		Tick;		//!< Tick stavovym automatem 
	cmMBSendMSG_t	SendMsg;	//!< Callback pro odeslani zpravy
	cmMBRecMSG_t	RecMsg;		//!< Callback po prijeti zpravy
	cbMBProcesMSG_t ProcesMsg;	//!< Callback pro zpacovani zpravy

	uint16_t	CPT1;		//!< Counter 1
	uint16_t	CPT2;		//!< Counter 2
	uint16_t	CPT3;		//!< Counter 3
	uint16_t	CPT4;		//!< Counter 4
	uint16_t	CPT5;		//!< Counter 5
	uint16_t	CPT6;		//!< Counter 6
	uint16_t	CPT7;		//!< Counter 7
	uint16_t	CPT8;		//!< Counter 8

	uint8_t		Address;		//!< Adresa zarizeni

	bool_t		RecievedMSG;	//!<

	ticks_t		endOfRecieveTime;	//!< po uplynuti casu muzeme vysilat odpoved
	ticks_t		endOfSendingTime;	//!< timer pro udrzeni casu

} MODBUS_CTX;


//----------------------------------------------------
/**
	\brief	Funkce pro inicializaci komunikacniho automatu 

	\param	_ctx		Struktura kontextu automatu komunikace
	\param	_cmm		Adresa knihovny fyzicke vrstvy
*/
//----------------------------------------------------

bool_t MBInitialize( MODBUS_CTX * const _ctx, COMMDESC * const _cmm );


//----------------------------------------------------
/**
	\brief	Funkce pro ukonceni komunikacniho automatu 

	\param	_ctx		Struktura kontextu automatu komunikace
*/
//----------------------------------------------------

void MBFinalize( MODBUS_CTX * const _ctx );

#endif // _MODBUS_H_


















