//----------------------------------------------------
/**
	\file		ctk/inc/lenze.h
	\ingroup	can
	\ingroup	all

	\brief		Ovladac menice LENZE
				<<< ALL >>>
	
	\author		ConTeK s.r.o., Pavel Bazika
	\version	01.01
	\date		05.09.2007

	\todo word write request bylo 0x27, ted vychazi 0x2b, coz je v souladu s datasheetem
*/
//----------------------------------------------------

#ifndef _LENZE_H_
#define _LENZE_H_

#include <canopentime.h>

//----------------------------------------------------
//!	Kanaly lenze komunikace

typedef enum _LNZ_CANCHNL_PARAM_DATA
{
	LNZ_PARAMCHNL_1,
	LNZ_PARAMCHNL_2
} LNZ_CANCHNL_PARAM_DATA;

typedef enum _LNZ_CANCHNL_PROCESS_DATA
{
	LNZ_PROCESSCHNL_1,
	LNZ_PROCESSCHNL_2,
	LNZ_PROCESSCHNL_3
} LNZ_CANCHNL_PROCESS_DATA;


//----------------------------------------------------
//!	Typ chyboveho kodu

typedef uint32_t LNZ_ERROR;

//----------------------------------------------------
//!	Konstanty chyb - konstanta je chybovemu callbacku predana v poli data

static const uint32_t LNZERR_CANOPEN_ERROR = 0;								// Chyba je indikovana ctkErrCodem, neni reportovana menicem, ale protokolem

static const uint32_t LNZERR_TOGGLE = 0x05030000;							// Toggle bit not changed
static const uint32_t LNZERR_SDO_EXPIRED = 0x05040000;						// SDO protocol expired
 static const uint32_t LNZERR_INVALID_COMMAND = 0x05040001;					// Invalid or unknown client/server command specifier
 static const uint32_t LNZERR_INVALID_BLOCKSIZE = 0x05040002;				// Invalid block size (only blockmode)
 static const uint32_t LNZERR_INVALID_PROCESS_NUMBER = 0x05040003;			// Invalid processing number (only blockmode)
 static const uint32_t LNZERR_CRC = 0x05040004;								// CRC error (only blockmode)
 static const uint32_t LNZERR_OOM = 0x05040005;								// Not enoughmemory
static const uint32_t LNZERR_ACCESS_DENIED = 0x06010000;					// Object access not supported
 static const uint32_t LNZERR_UNREADABLE = 0x06010001;						// Try to read writable object
 static const uint32_t LNZERR_UNWRITEABLE = 0x06010002;						// Try to write readable object
static const uint32_t LNZERR_OBJ_NOT_LISTED = 0x06020000;					// Object not listed in object directory	
static const uint32_t LNZERR_OBJ_NO_PDO = 0x06040041;						// Object not transferable to PDO
static const uint32_t LNZERR_PDO_OVERFLOW = 0x06040042;						// Number and length of objects to be transferred longer than PDO.
static const uint32_t LNZERR_PARAM_INCOMPATIBLE = 0x06040043;				// General parameter incompatibility
static const uint32_t LNZERR_CONTROLLER_INCOMPATIBLE = 0x06040047;			// General internal controller incompatibility
static const uint32_t LNZERR_HW = 0x06060000;								// Access denied because of hardware error
static const uint32_t LNZERR_INVALID_DATA_SIZE = 0x06070010;				// Inappropriate data type, service parameter length
 static const uint32_t LNZERR_INVALID_DATA_SIZE_HIGH = 0x06070012;			// Inappropriate data type, service parameter length exceeded
 static const uint32_t LNZERR_INVALID_DATA_SIZE_LOW = 0x06070013;			// Inappropriate data type, service parameters not long enough
static const uint32_t LNZERR_NO_SUBINDEX = 0x06090011;						// Subindex does not exist
static const uint32_t LNZERR_OOR = 0x06090030;								// Parameter value range exceeded
static const uint32_t LNZERR_PARAM_TOO_HIGH =	0x06090031;					// Parameter values too high
static const uint32_t LNZERR_PARAM_TOO_LOW = 0x06090032;					// Parameter values too low
static const uint32_t LNZERR_MAX_BELOW_MIN = 0x06090036;					// Maximumvalue falls belowminimumvalue
static const uint32_t LNZERR_GENERAL = 0x08000000;							// General error
 static const uint32_t LNZERR_DATA_TRANSFER_STORE = 0x08000020;				// Data cannot be transferred/stored for application.
  static const uint32_t LNZERR_DATA_TRANSFER_STORE_LOCAL = 0x08000021;		// Because of local control data cannot be transferred/stored for application.
  static const uint32_t LNZERR_DATA_TRANSFER_STORE_CONTROLLER = 0x08000022;	// Because of current controller status data cannot be transferred/stored for application.
  static const uint32_t LNZERR_OBJECTDIR_ERROR = 0x08000023;				// Dynamic generation of object directory not successful or no object
																			// directory available (e.g. object directory generated fromfile, generation
																			// not possible because of a file error).

//----------------------------------------------------
//!	Stav automatu ovladace

typedef enum _LENZE_STATE
{
	LS_START = 0,
	LS_INIT,
	LS_PREOP,
	LS_WAITOPER,
	LS_OPER,
	LS_ERROR,
	LS_SETPARAMETER_WAITSEND,
	LS_SETPARAMETER_WAITTIME
} LENZE_STATE;


//----------------------------------------------------
//!	Forward deklarace kontextu

struct _LENZEINV_CTX;


//----------------------------------------------------
//!	\brief	Metody objektu
//@{

typedef void (*lmParamWriteRs_t) (const struct _LENZEINV_CTX * _ctx, uint8_t _paramSet, uint16_t _code, uint8_t _subCode);
typedef void (*lmParamReadRs_t) (const struct _LENZEINV_CTX * _ctx, uint8_t _paramSet, uint16_t _code, uint8_t _subCode, const void * _data, uint8_t _size);
typedef void (*lmErrorRs_t) (const struct _LENZEINV_CTX * _ctx, CANOPEN_SDO_ERROR _ctkErrCode, LNZ_ERROR _errCode, uint8_t _paramSet, uint16_t _code, uint8_t _subCode, const void * _data, uint8_t _size);
typedef void (*lmRecvProcessData_t) (const struct _LENZEINV_CTX * _ctx, const void * _data, uint8_t _size);
//@}


//----------------------------------------------------
//!	\brief	Kontext objektu

typedef struct _LENZEINV_CTX
{
	CANOPEN_CTX			Parent;			//!< Automat CANOpen
	cdmCANDeviceTick	ParentTick;		//!< Puvodni tik predka
	
	STMACHINE		Stm;				//!< Automat sledujici stav menice
	uint8_t			NodeID;				//!< Identifikator ovladaneho menice
	
	CANOPEN_STATE	RqState;			//!< Pozadovany stav menice
	
	uint16_t		IDProcessOut;	//!< Kanal pro vystup process dat
	uint16_t		IDProcessIn;	//!< Kanal pro vstup process dat
	uint16_t		IDParamOut;		//!< Kanal pro vystup parameter dat
	uint16_t		IDParamIn;		//!< Kanal pro vstup parameter dat
	
	volatile bool_t flRunning;		//!< Priznak inicializovane knihovny
	
	// callbacky
	lmParamWriteRs_t	cbParamWriteRs;		//!< Callback volany pri prijmu odpovedi na zapis parameter dat
	lmParamReadRs_t		cbParamReadRs;		//!< Callback volany pri prijmu odpovedi na cteni parameter dat
	lmErrorRs_t			cbErrorRs;			//!< Callback volany pri chybe
	lmRecvProcessData_t	cbRecvProcessData;	//!< Callback volany pri prijmu process dat
	
} LENZEINV_CTX;


//----------------------------------------------------
/**
	\brief	Funkce zjistuje, zda je Lenze ovladac pripraven vysilat

	\param	_ctx		Kontext

	\return	TRUE, pokud je ovladac pripraven k vysilani
*/
//----------------------------------------------------

bool_t LenzeInvSendReady(LENZEINV_CTX * const _ctx);


//----------------------------------------------------
/**
	\brief	Metoda meni stav ovladaneho menice

	\param	_ctx			Kontext
	\param	_remoteState	Pozadovany stav
*/
//----------------------------------------------------

void LenzeInvChangeState(LENZEINV_CTX * const _ctx, const CANOPEN_STATE _remoteState);


//----------------------------------------------------
/**
	\brief	Odeslani jendorazovych process dat

	\param	_ctx	Kontext
	\param	_data	Zprava	
	\param	_size	Delka zpravy
*/
//----------------------------------------------------

void LenzeInvSendProcessData(LENZEINV_CTX * const _ctx, const void * const _data, const uint8_t _size);


//----------------------------------------------------
/**
	\brief	Vysle pozdavek na zapis parametru

	\param	_ctx		Kontext
	\param	_paramSet	Sada parametru
	\param	_code		Kod parametru
	\param	_subCode	Subkod parametru
	\param	_data		Zapisovana data
	\param	_size		Delka zapisovanych dat (max 4)
*/
//-----------------------------------------------------

void LenzeInvSetParameter(LENZEINV_CTX * const _ctx, const uint8_t _paramSet, const uint16_t _code, 
						  const uint8_t _subCode, const void * const _data, const uint8_t _size);


//----------------------------------------------------
/**
	\brief	Vysle pozdavek na zapis float parametru ve formatu FIX32

	\param	_ctx		Kontext
	\param	_paramSet	Sada parametru
	\param	_code		Kod parametru
	\param	_subCode	Subkod parametru
	\param	_data		Zapisovana data, budou vynasobena 10000 - pro formatovani
*/
//-----------------------------------------------------

static inline void LenzeInvSetFIX32FloatParameter(LENZEINV_CTX * const _ctx, const uint8_t _paramSet, const uint16_t _code, 
							  const uint8_t _subCode, const float_t _data)
{
	uint32_t data = (uint32_t)(_data * 10000.0f);
	LenzeInvSetParameter(_ctx, _paramSet, _code, _subCode, &data, 4);
}


//----------------------------------------------------
/**
	\brief	Vysle pozdavek na zapis celociselneho parametru

	\param	_ctx		Kontext
	\param	_paramSet	Sada parametru
	\param	_code		Kod parametru
	\param	_subCode	Subkod parametru
	\param	_data		Zapisovana data, budou vynasobena 10000 - pro formatovani
*/
//-----------------------------------------------------

static inline void LenzeInvSetFIX32UIntParameter(LENZEINV_CTX * const _ctx, const uint8_t _paramSet, const uint16_t _code, 
						  const uint8_t _subCode, const uint32_t _data)
{
	uint32_t data = _data * 10000U;
	LenzeInvSetParameter(_ctx, _paramSet, _code, _subCode, &data, 4);
}


//----------------------------------------------------
/**
	\brief	Vysle pozdavek na zapis parametru ve formatu U32

	\param	_ctx		Kontext
	\param	_paramSet	Sada parametru
	\param	_code		Kod parametru
	\param	_subCode	Subkod parametru
	\param	_data		Zapisovana data
*/
//-----------------------------------------------------

static inline void LenzeInvSetU32Parameter(LENZEINV_CTX * const _ctx, const uint8_t _paramSet, const uint16_t _code, 
						  const uint8_t _subCode, const uint32_t _data)
{
	LenzeInvSetParameter(_ctx, _paramSet, _code, _subCode, &_data, 4);
}


//----------------------------------------------------
/**
	\brief	Vysle pozdavek na zapis parametru ve formatu U16

	\param	_ctx		Kontext
	\param	_paramSet	Sada parametru
	\param	_code		Kod parametru
	\param	_subCode	Subkod parametru
	\param	_data		Zapisovana data
*/
//-----------------------------------------------------

static inline void LenzeInvSetU16Parameter(LENZEINV_CTX * const _ctx, const uint8_t _paramSet, const uint16_t _code, 
						  const uint8_t _subCode, const uint16_t _data)
{
	LenzeInvSetParameter(_ctx, _paramSet, _code, _subCode, &_data, 2);
}


//----------------------------------------------------
/**
	\brief	Vysle pozadavek na cteni parametru

	\param	_ctx		Kontext
	\param	_paramSet	Sada parametru
	\param	_code		Kod parametru
	\param	_subCode	Subkod parametru
*/
//----------------------------------------------------

void LenzeInvGetParameter(LENZEINV_CTX * const _ctx, const uint8_t _paramSet, const uint16_t _code, const uint8_t _subCode);


//----------------------------------------------------
/**
	\brief	Inicializace objektu

	\param	_ctx			Kontext
	\param	_cmm			Pridruzeny komunikacni objekt
	\param	_nodeID			CANOpen ID ovladaneho menice
	\param	_paramChannel	Pozadovany kanal pro parameter data
	\param	_processChannel	Pozadovany kanal pro process data
	\param	_priority		Priorita v ramci seznamu zarizeni

	\return	TRUE, pokud inicializace probehla uspesne
*/
//----------------------------------------------------

bool_t LenzeInvInitialize(LENZEINV_CTX * const _ctx, CANCOMMDESC * _cmm, const uint8_t _nodeID, const LNZ_CANCHNL_PARAM_DATA _paramChannel, 
						  const LNZ_CANCHNL_PROCESS_DATA _processChannel, const uint8_t _priority);


//----------------------------------------------------
/**
	\brief	Ukonceni objektu

	\param	_ctx			Kontext

	\return	TRUE, pokud ukonceni probeho uspesne
*/
//----------------------------------------------------

bool_t LenzeInvFinalize(LENZEINV_CTX * const _ctx);

#endif // _LENZE_H_
