//----------------------------------------------------
/**
	\file		ctk/inc/datalog.h
	\ingroup	other
	\ingroup	all

	\brief		Knihovna logovani informaci do pameti
				<<< ALL >>>

	\author		ConTeK s.r.o., Ing. Pavel Bazika
	\version	01.01
	\date		01.04.2009

	\note		Knihovna umoznuje cist a zapisovat zaznamy rotujicicho logu.
				Zapisy jsou razeny do fronty a jsou provadeny, pokud neni pozadavek
				na cteni. Jedna se o nadstavbu knihovny memlog.
	
	\todo		nejsou kometare
*/
//----------------------------------------------------

#ifndef _DATALOG_H_
#define _DATALOG_H_

#include <memlog.h>
#include <comm.h>

//----------------------------------------------------
/**
	\brief	Callbacky
*/
//----------------------------------------------------

struct _DATALOG_CTX;
struct _DATALOG_BUFDESC;

typedef void (*dlmInitError_t) (struct _DATALOG_CTX * const _ctx);
typedef void (*dlmReadDone_t) (const struct _DATALOG_CTX * const _ctx, const void * const _readData, const uint32_t _dataSize, void * const _userData);
typedef void (*dlmWriteDone_t) (const struct _DATALOG_CTX * const _ctx, const struct _DATALOG_BUFDESC * const _buffer, void * const _userData);


//----------------------------------------------------
/**
	\brief	Prikazy datalog automatu
*/
//----------------------------------------------------

typedef enum _DATALOG_CMD
{
	DCMD_NONE = 0,
	DCMD_INITLOAD,
	DCMD_READ
} DATALOG_CMD;


//----------------------------------------------------
/**
	\brief	Parametry prikazu datalogu
*/
//----------------------------------------------------

typedef union _DATALOG_CMDDATA
{
	struct
	{
		uint16_t		AppMagic;		//!< Magicke cislo aplikace
		dlmInitError_t	cbInitError;	//!< Callback v pripade chyby
	} InitLoad;

	struct
	{
		uint32_t		HistoryDepth;	//!< Pozadovana hloubka historie ctene polozky
		void			*Buffer;		//!< Buffer pro nactenou polozku
		dlmReadDone_t	cbReadDone;		//!< Callback volany po dokonceni nacteni ci chybe
		void			*UserData;		//!< Data predana callbacku
	} Read;

} DATALOG_CMDDATA;


//----------------------------------------------------
/**
	\brief	 Popisovac bufferu s daty k zalogovani
*/
//----------------------------------------------------

typedef struct _DATALOG_BUFDESC
{
	uint8_t			Status;			//!< Stav bufferu

	const void		*BufferData;	//!< Data k zapisu

	dlmWriteDone_t	cbDone;			//!< Callback volany po dokonceni zapisu ci chybe
	void			*UserData;		//!< Data predana callbacku

	struct _DATALOG_BUFDESC * next;	//!< Ukazatel na dalsi buffer ve fronte
} DATALOG_BUFDESC;


//----------------------------------------------------
/**
	\brief	 Kontext datalogu
*/
//----------------------------------------------------

typedef struct _DATALOG_CTX
{
	MEMLOG_CTX				Parent;			//!< Rodicovsky objekt

	volatile bool_t			flInitialized;	//!< Priznak inicializace, tzn. nacteni hlavicky

	STMACHINE				Stm;			//!< Kontext automatu
	volatile MEMLOG_STATUS	Status;			//!< Stav knihovny

	DATALOG_CMD				Command;		//!< Prikaz k vykonani
	DATALOG_CMDDATA			CmdData;		//!< Data souvisejici s prikazem

	DATALOG_BUFDESC			*FirstWrite;	//!< Ukazatel na prvni buffer ve fronte
	DATALOG_BUFDESC			*LastWrite;		//!< Ukazatel na posledni buffer ve fronte
	DATALOG_BUFDESC			*CurWrite;		//!< Ukazatel na aktualne zapisovany buffer (mimo frontu)

} DATALOG_CTX;


//----------------------------------------------------
/**
	\brief	 Zjisti, zda datalog prijima prikazy

	\param	_ctx		Kontext

	\return		TRUE, pokud je mozno zadat prikaz ke cteni ci zapisu
*/
//----------------------------------------------------

static inline bool_t DataLogReady(const DATALOG_CTX * const _ctx)
{
	return (_ctx->Command == DCMD_NONE);
}


//----------------------------------------------------
/**
	\brief	 Zjisti, zda je buffer datalogu pripraven

	\param	_desc		Popisovac bufferu

	\return		TRUE, pokud je buffer pripraven
*/
//----------------------------------------------------

static inline bool_t DataLogBufReady(const DATALOG_BUFDESC * const _desc)
{
	return (_desc->Status & STS_BUFREADY) ? FALSE : TRUE;
}


//----------------------------------------------------
/**
	\brief	 Navrati stav knihovny

	\param	_ctx		Kontext

	\return		Kod stavu knihovny
*/
//----------------------------------------------------

static inline MEMLOG_STATUS DataLogStatus(const DATALOG_CTX * const _ctx)
{
	return _ctx->Status;
}


//----------------------------------------------------
/**
	\brief	 Prikaz k inicializaci knihovny

	\param	_ctx			Kontext
	\param	_appMagic		Ocekavane magicke cislo aplikace
	\param	_cbInitError	Callback volany v pripade neuspesne inicializace
*/
//----------------------------------------------------

void DataLogInitLoad(DATALOG_CTX * const _ctx, const uint16_t _appMagic, dlmInitError_t _cbInitError);


//----------------------------------------------------
/**
	\brief	 Prikaz k nacteni polozky z logu

	\param	_ctx		Kontext
	\param	_depth		Index polozky v historii, 0 = posledni, 1 = preposledni atd.
	\param	_buffer		Buffer pro ulozeni nactene polozky
	\param	_cbReadDone	Callback volany po dokonceni cteni polozky
	\param	_userData	Data predana callbacku
*/
//----------------------------------------------------

void DataLogReadItem(DATALOG_CTX * const _ctx, const uint32_t _depth, void * const _buffer, dlmReadDone_t _cbReadDone, void * const _userData);


//----------------------------------------------------
/**
	\brief	 Prikaz k zapisu zaznamu do logu

	\param	_ctx			Kontext
	\param	_buffer			Buffer pro zapisovana data
	\param	_data			Zapisovana data (nejsou nikam kopirovana, musi byt v platnosti do konce zapisu)
	\param	_cbWriteDone	Callback volany po dokonceni zapisu
	\param	_userData		Data predana callbacku
*/
//----------------------------------------------------

void DataLogWrite(DATALOG_CTX * const _ctx, DATALOG_BUFDESC * const _buffer, const void * const _data, dlmWriteDone_t _cbWriteDone, void * const _userData);


//----------------------------------------------------
/**
	\brief	 Tik knihovny

	\param	_ctx			Kontext
*/
//----------------------------------------------------

void DataLogTick(DATALOG_CTX * const _ctx);


//----------------------------------------------------
/**
	\brief	 Prikaz k inicializaci knihovny

	\param	_ctx			Kontext
	\param	_desc			Pamet, se kterou se bude pracovat
	\param	_baseAddr		Adresa, na ktere bude ulozen zacatek logu
*/
//----------------------------------------------------

bool_t DataLogInitialize(DATALOG_CTX * const _ctx, NVMEMDESC * const _desc, const uint32_t _baseAddr);


//----------------------------------------------------
/**
	\brief	 Prikaz k finalizaci knihovny

	\param	_ctx			Kontext
*/
//----------------------------------------------------

bool_t DataLogFinalize(const DATALOG_CTX * const _ctx);

#endif // _DATALOG_H_
