//----------------------------------------------------
/**
	\file		ctk/inc/memlog.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

	Knihovna obsahuje algoritmy pro ukladani udalosti do pameti.
	Udalosti lze ukladat jednak do dat v hlavicce, ktera je v ramci kontextu jedina
	a dale v rotujici casti, jejiz velikost se definuje pri vytvoreni uloziste.
*/
//----------------------------------------------------

#ifndef _MEMLOG_H_
#define _MEMLOG_H_

#include <ctktypes.h>
#include <stmachine.h>
#include <nvmem.h>


//----------------------------------------------------
/**
	\brief	Maska pro ziskavani velikosti polozky
*/
//----------------------------------------------------

static const uint32_t MEMLOG_ITEMSIZE_MASK = 0x00FFFFFF;


//----------------------------------------------------
/**
	\brief	Prikazy datalogu
*/
//----------------------------------------------------

typedef enum _MEMLOG_COMMAND
{
	LCMD_NONE = 0,			//!< Zadny prikaz neni vykonavan
	LCMD_CREATE,			//!< Vytovor novy datalog
	LCMD_LOAD,				//!< Nacti udaje o existujicim datalogu
	LCMD_READ_HEADER,		//!< Precti data pripojena k hlavicce
	LCMD_READ_ITEM,			//!< Precti danou polozku datalogu v historii
	LCMD_WRITE_HEADER,		//!< Zapise data pripojena k hlavicce
	LCMD_WRITE_ITEM			//!< Zapise novou polozku
} MEMLOG_COMMAND;


//----------------------------------------------------
/**
	\brief	Chybove stavy knihovny
*/
//----------------------------------------------------

typedef enum _MEMLOG_STATUS
{
	LSTS_SUCCESS = 0,		//!< Vse OK
	LSTS_ERROR,				//!< Doslo k chybe
	LSTS_NOITEM				//!< Pozadovana data nejsou v logu
} MEMLOG_STATUS;


//----------------------------------------------------
/**
	\brief	Hlavicka s informacemi o logu
*/
//----------------------------------------------------

typedef struct _MEMLOG_HEADER
{
	uint16_t	LogMagicNumber;	//!< Identifikator logu
	uint16_t	AppMagicNumber;	//!< Kontrolni cislo rozlisujici jednotlive logy - melo by zaviset na aplikaci a jejim logu
	uint32_t	HeadDataSize;	//!< Velikost dat ulozenych za hlavickou
	uint32_t	ItemCount;		//!< Pocet polozek rotujiciho logu
	uint32_t	ItemSize;		//!< Velikost polozky + priznak preteceni (nejvyssi byte obsahuje priznak poctu polozek (actcount ci itemcount = 1))
	uint32_t	ActItem;		//!< Index aktualni polozky k zapisu
} MEMLOG_HEADER;


//----------------------------------------------------
/**
	\brief	Callbacky pro odpoved na prikaz
*/
//----------------------------------------------------
struct _MEMLOG_CTX;

typedef void (*mlmDone_t) (struct _MEMLOG_CTX * ctx, MEMLOG_STATUS Status, void * UserData);


//----------------------------------------------------
/**
	\brief	Parametry jednotlivych prikazu
*/
//----------------------------------------------------

typedef union _MEMLOG_CMDDATA
{
	struct
	{
		uint16_t	AppMagicNumber;	//!< Magicke cislo aplikace
		uint32_t	HeadDataSize;	//!< Velikost dat hlavicky
		uint32_t	ItemSize;		//!< Velikost polozky
		uint32_t	ItemCount;		//!< Pocet polozek
	} Create;

	struct
	{
		uint16_t	AppMagicNumber;	//!< Ocekavane magicke cislo aplikace
	} Load;

	struct
	{
		void		* Buffer;		//!< Buffer pro nactena data
	} ReadHeader;

	struct
	{
		void 		* Buffer;		//!< Buffer pro nactena data
		uint32_t	Depth;			//!< Index ctene polozky
	} ReadItem;

	struct
	{
		const void		* Buffer;	//!< Buffer se zapisovanymi daty
	} WriteHeader;

	struct
	{
		const void		* Buffer;	//!< Buffer se zapisovanymi daty
	} WriteItem;

	mlmDone_t	cbDone;				//!< Callback volany po dokonceni
	void		*UserData;			//!< Uzivatelska data
} MEMLOG_CMDDATA;


//----------------------------------------------------
/**
	\brief	Struktura kontextu automatu
*/
//----------------------------------------------------

typedef struct _MEMLOG_CTX
{
	MEMLOG_STATUS		Status;			//!< Stav knihovny

	uint32_t			BaseAddr;		//!< Adresa pocatku hlavicky
	NVMEMDESC			* Mem;			//!< Pamet nad kterou se pracuje

	STMACHINE			Stm;			//!< Stav automatu

	MEMLOG_COMMAND		Cmd;			//!< Prikaz
	MEMLOG_CMDDATA		CmdData;		//!< Parametry prikazu

	MEMLOG_HEADER		Header;			//!< Obraz hlavicky v RAM

} MEMLOG_CTX;


//----------------------------------------------------
/**
	\brief	Zjisteni pripravenosti knihovny

	\param	_ctx	Kontext

	\return		TRUE, pokud je knihovna pripravena prijmout prikaz
*/
//----------------------------------------------------

static inline bool_t MemLogReady(MEMLOG_CTX * const _ctx)
{
	return stmFinished(&_ctx->Stm);
}


//----------------------------------------------------
/**
	\brief	Zjisteni stavu knihovny

	\param	_ctx	Kontext

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

static inline MEMLOG_STATUS MemLogStatus(MEMLOG_CTX * const _ctx)
{
	return AtomRead(_ctx->Status);
}


//----------------------------------------------------
/**
	\brief	Zjisteni magickeho cisla aplikace

	\param	_ctx	Kontext

	\return		Nactene magicke cislo aplikace
*/
//----------------------------------------------------

static inline uint32_t MemLogGetAppMagicNumber(const MEMLOG_CTX * const _ctx)
{
	return _ctx->Header.AppMagicNumber;
}


//----------------------------------------------------
/**
	\brief	Funkce vraci velikost jedne polozky

	\return		Velikost polozky v bytech
*/
//----------------------------------------------------

static inline uint32_t MemLogGetItemSize(const MEMLOG_CTX * const _ctx)
{
	return _ctx->Header.ItemSize & MEMLOG_ITEMSIZE_MASK;
}


//----------------------------------------------------
/**
	\brief	Zjisti aktualni pocet polozek v logu

	\param	_ctx	Kontext

	\return		Pocet polozek
*/
//----------------------------------------------------

uint32_t MemLogGetItemCount(const MEMLOG_CTX * const _ctx);


//----------------------------------------------------
/**
	\brief	Prikaz k nacteni dat z hlavicky

	\param	_ctx		Kontext
	\param	_buffer		Buffer pro ulozeni dat
	\param	_cbDone		Callback volany po nacteni dat ci chybe
	\param	_userData	Data predana callbacku
*/
//----------------------------------------------------

void MemLogReadHeader(MEMLOG_CTX * const _ctx, void * const _buffer, mlmDone_t _cbDone, void * const _userData);


//----------------------------------------------------
/**
	\brief	Prikaz k nacteni vybrane polozky z historie

	\param	_ctx				Kontext
	\param	_buffer				Buffer pro nactena data
	\param	_historyDepth		Hloubka historie, 0 = posledni polozka, 1 = predposledni...
	\param	_cbDone				Callback volany po nacteni dat ci chybe
	\param	_userData			Data predana callbacku
*/
//----------------------------------------------------

void MemLogReadItem(MEMLOG_CTX * const _ctx, void * const _buffer, const uint32_t _historyDepth, mlmDone_t _cbDone, void * const _userData);


//----------------------------------------------------
/**
	\brief	Prikaz k zapisu dat do hlavicky

	\param	_ctx		Kontext
	\param	_buffer		Zapisovana data
	\param	_cbDone		Callback volany po zapisu dat ci chybe
	\param	_userData	Data predana callbacku
*/
//----------------------------------------------------

void MemLogWriteHeader(MEMLOG_CTX * const _ctx, const void * const _buffer, mlmDone_t _cbDone, void * const _userData);


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

	\param	_ctx		Kontext
	\param	_buffer		Data zapisovane polozky
	\param	_cbDone		Callback volany po zapisu dat ci chybe
	\param	_userData	Data predana callbacku
*/
//----------------------------------------------------

void MemLogWriteItem(MEMLOG_CTX * const _ctx, const void * const _buffer, mlmDone_t _cbDone, void * const _userData);


//----------------------------------------------------
/**
	\brief	Prikaz k nacteni hlavicky

	\param	_ctx				Kontext
	\param	_appMagicNumber		Ocekavane magicke cislo aplikace
	\param	_cbDone				Callback volany po nacteni dat ci chybe
	\param	_userData			Data predana callbacku
*/
//----------------------------------------------------

void MemLogLoad(MEMLOG_CTX * const _ctx, const uint16_t _appMagicNumber, mlmDone_t _cbDone, void * const _userData);


//----------------------------------------------------
/**
	\brief	Prikaz k vytvoreni struktury logu v pameti

	\param	_ctx			Kontext
	\param	_appMagicNumber	Magicke cislo ulozene aplikaci
	\param	_headDataSize	Velikost dat hlavicky
	\param	_itemCount		Pocet polozek v rotujici casti
	\param	_itemSize		Velikost jedno polozky
	\param	_cbDone			Callback volany po vytvoreni logu ci chybe
	\param	_userData		Data predana callbacku
*/
//----------------------------------------------------

void MemLogCreate(
		MEMLOG_CTX * const _ctx,
		const uint16_t _appMagicNumber,
		const uint32_t _headDataSize,
		const uint32_t _itemCount,
		const uint32_t _itemSize,
		mlmDone_t _cbDone,
		void * const _userData);


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

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

void MemLogTick(MEMLOG_CTX * const _ctx);


//----------------------------------------------------
/**
	\brief	Inicializace knihovny

	\param	_ctx		Prazdny kontext
	\param	_desc		Popisovac pameti, nad kterou se bude pracovat
	\param	_baseAddr	Pocatecni adresa logu

	\return		TRUE, pokud se inicializace zdarila
*/
//----------------------------------------------------

bool_t MemLogInitialize(MEMLOG_CTX * const _ctx, NVMEMDESC * const _desc, const uint32_t _baseAddr);


//----------------------------------------------------
/**
	\brief	Finalizace knihovny

	\param	_ctx		Kontext

	\return		TRUE, pokud se finalizace zdarila
*/
//----------------------------------------------------

bool_t MemLogFinalize(const MEMLOG_CTX * const _ctx);

#endif /* _MEMLOG_H_ */
