//----------------------------------------------------
/**
	\file		ctk/inc/timeticks.h
	\ingroup	general
	\ingroup	all

	\brief		Funkce a definice pro praci s casovacem
				<<< ALL >>>

	\author		ConTeK s.r.o., Ing. Petr Cernin
	\version	01.01
	\date		12.01.2007
*/
//----------------------------------------------------

#ifndef _TIMETICKS_H_
#define _TIMETICKS_H_

#include <ctktypes.h>
#ifdef USE_FREERTOS
 #include <FreeRTOS.h>
 #include <freertos_task.h>
 #include <freertostick.h>
#endif
#include <hwmodel.h>

//-----------------------------------------------------
//!	Priznak inicializace TimeTicks

extern volatile bool_t flTimeTicksRunning;


//----------------------------------------------------
//!	\name	definice typu a citac tiku
//@{

typedef uint16_t	ticks_t;				//!< 16-bitovy citac tiku (milisekund)
typedef uint32_t	lticks_t;				//!< 32-bitovy citac tiku (milisekund)

//----------------------------------------------------
/**
	\brief	Typ funkce volane jako callback ticku
*/
//----------------------------------------------------

typedef void (* timetick_t) (void);


//-----------------------------------------------------
//!	\brief	Kontext timeticku

typedef struct _TIMETICK_CTX
{
	volatile lticks_t	TimerCnt;			//!< Citac tiku
	volatile ticks_t	AddTimerCnt;		//!< Hodnota pricitana k gTimerCnt v TimeTicku

#ifdef TTCK_REALTICK
	timetick_t			RealTick;			//!< callback volany pri kazdem ticku
	volatile bool_t		flRealTick;			//!< priznak provadeni real ticku
 #ifdef TTCK_REALTICK_MEASURE
	volatile hrctime_t	RealTickTime;		//!< Cas vykonavani RealTicku
	volatile hrctime_t	RealTickMaxTime;	//!< Cas vykonavani RealTicku
	hrccnt_t			RealTickCnt;		//!< Citac RealTicku
 #endif // TTCK_REALTICK_MEASURE
#endif // TTCK_REALTICK

#ifdef TTCK_HWTICK
	timetick_t			HWTick;				//!< Callback volany cca. 1 ms
	volatile bool_t		flHWTick;			//!< Priznak provadeni hw ticku
	volatile ticks_t	HWCounter;			//!< Preddelic hw ticku
	ticks_t				HWSpeed;			//!< Rychlost provadeni hwticku
 #ifdef USE_FREERTOS
	ticks_t				HWSpeedRaw;
	TaskHandle_t		HWTickHandle;
 #endif
 #ifdef TTCK_HWTICK_MEASURE
	volatile hrctime_t	HWTickTime;			//!< Cas vykonavani HWTicku
	volatile hrctime_t	HWTickMaxTime; 		//!< Cas vykonavani HWTicku
	hrccnt_t			HWTickCnt;			//!< Citac HWTicku
 #endif // TTCK_HWTICK_MEASURE
#endif // TTCK_HWTICK

#ifdef TTCK_FASTTICK
	timetick_t			FastTick;			//!< Callback volany cca. 1 ms
	volatile bool_t		flFastTick;			//!< Priznak provadeni fast ticku
	volatile ticks_t	FastCounter;		//!< Preddelic fast ticku
	ticks_t				FastSpeed;			//!< Rychlost provadeni fastticku
 #ifdef USE_FREERTOS
	ticks_t				FastSpeedRaw;
	TaskHandle_t		FastTickHandle;
 #endif
 #ifdef TTCK_FASTTICK_MEASURE
	volatile hrctime_t  FastTickTime;		//!< Cas vykonavani FastTicku
	volatile hrctime_t	FastTickMaxTime;	//!< Cas vykonavani FastTicku
	hrccnt_t			FastTickCnt;		//!< Citac FastTicku
 #endif // TTCK_FASTTICK_MEASURE
#endif // TTCK_FASTTICK

#ifdef TTCK_SLOWTICK
	timetick_t			SlowTick;			//!< Callback volany cca 10 ms
	volatile bool_t		flSlowTick;			//!< Priznak provadeni slow ticku
	volatile lticks_t	SlowCounter;		//!< Preddelic slow ticku
	lticks_t			SlowSpeed;			//!< Rychlost provadeni slowticku
 #ifdef USE_FREERTOS
	ticks_t				SlowSpeedRaw;
	TaskHandle_t		SlowTickHandle;
 #endif
 #ifdef TTCK_SLOWTICK_MEASURE
	volatile hrctime_t	SlowTickTime;		//!< Cas vykonavani SlowTicku
	volatile hrctime_t	SlowTickMaxTime;	//!< Cas vykonavani SlowTicku
	hrccnt_t			SlowTickCnt;		//!< Citac SlowTicku
 #endif // TTCK_SLOWTICK_MEASURE
#endif // TCK_SLOWTICK

#ifdef TTCK_MAINTICK
	timetick_t			MainTick;			//!< Callback volany nepretrzite v hlavni smycce
	volatile bool_t		flMainTerminate;	//!< Priznak ukoncujici main tick
 #ifdef TTCK_MAINTICK_MEASURE
	volatile hrctime_t	MainTickTime;		//!< Cas vykonavani MainTicku
	volatile hrctime_t	MainTickMaxTime;	//!< Cas vykonavani MainTicku
	hrccnt_t			MainTickCnt;		//!< Citac MainTicku
 #endif // TTCK_MAINTICK_MEASURE
#endif // TTCK_MAINTICK

} TIMETICK_CTX;

extern TIMETICK_CTX gTimeTickCtx;			//!< Kontext timeticku

//----------------------------------------------------
//!	\name	Pocet tiku za sekundu
//@{

extern const ticks_t 		TICKS_PER_SEC;
extern const lticks_t		LTICKS_PER_SEC;
//@}*/

//-----------------------------------------------------
/**
	\brief		Funkce volana v casovem preruseni
				obsluhuje volani real, fast a slow ticku

	\param		hodnota, ktera se pricte k gTimerCnt

	\note		predpoklada se, ze je pri volani zakazane nebo povolene preruseni !!!
*/
//-----------------------------------------------------

void TimeTick(void);


//----------------------------------------------------
/**
	\brief	Funkce zaregistruje predanou funkci jako real tick

	\param	tick	Ukazatel na callback funkci
*/
//----------------------------------------------------

#ifdef TTCK_REALTICK

void RegisterRealTick(timetick_t tick);

//----------------------------------------------------
/**
	\brief	Funkce zrusi volani real ticku

	\return	Ukazatel na ukoncenou funkci fast ticku
*/
//----------------------------------------------------

timetick_t ClearRealTick(void);

#endif // TTCK_REALTICK


//----------------------------------------------------
/**
	\brief	Funkce zaregistruje predanou funkci jako hw tick

	\param	tick	Ukazatel na callback funkci
*/
//----------------------------------------------------

#ifdef TTCK_HWTICK
void RegisterHWTick(timetick_t _tick);


//----------------------------------------------------
/**
	\brief	Funkce zrusi volani hw ticku

	\return	Ukazatel na ukoncenou funkci hw ticku
*/
//----------------------------------------------------

timetick_t ClearHWTick(void);

#endif // TTCK_HWTICK

//----------------------------------------------------
/**
	\brief	Funkce zaregistruje predanou funkci jako fast tick

	\param	tick	Ukazatel na callback funkci
*/
//----------------------------------------------------

#ifdef TTCK_FASTTICK

void RegisterFastTick(timetick_t _tick);


//----------------------------------------------------
/**
	\brief	Funkce zrusi volani fast ticku

	\return	Ukazatel na ukoncenou funkci fast ticku
*/
//----------------------------------------------------

timetick_t ClearFastTick(void);

#endif // TTCK_FASTTICK

//----------------------------------------------------
/**
	\brief	Funkce zaregistruje predanou funkci jako slow tick

	\param	tick	Ukazatel na callback funkci
*/
//----------------------------------------------------

#ifdef TTCK_SLOWTICK

void RegisterSlowTick(timetick_t tick);


//----------------------------------------------------
/**
	\brief	Funkce zrusi volani slow ticku

	\return	Ukazatel na ukoncenou funkci fast ticku
*/
//----------------------------------------------------

timetick_t ClearSlowTick(void);

#endif //TTCK_SLOWTICK

#ifdef TTCK_MAINTICK

//----------------------------------------------------
/**
	\brief	Funkce zaregistruje predanou funkci jako Main tick

	\param	tick	Ukazatel na callback funkci
*/
//----------------------------------------------------

void RegisterMain(timetick_t _tick);


//----------------------------------------------------
/**
	\brief	Funkce zrusi volani main ticku

	\return	Ukazatel na ukoncenou funkci fast ticku
*/
//----------------------------------------------------

timetick_t ClearMain(void);

#endif // TTCK_MAINTICK

#ifdef TTCK_HWTICK

//----------------------------------------------------
/**
	\brief	Funkce nastavi rychlost hw ticku

	\param	speed	Perioda volani v ms
*/
//----------------------------------------------------

void SetHWTickSpeed(const ticks_t _speed);

#endif // TTCK_HWTICK

#ifdef TTCK_FASTTICK

//----------------------------------------------------
/**
	\brief	Funkce nastavi rychlost fast ticku

	\param	speed	Perioda volani v ms
*/
//----------------------------------------------------

void SetFastTickSpeed(const ticks_t _speed);

#endif // TTCK_FASTTICK

#ifdef TTCK_SLOWTICK

//----------------------------------------------------
/**
	\brief	Funkce nastavi rychlost slow ticku

	\param	speed	Perioda volani v ms
*/
//----------------------------------------------------

void SetSlowTickSpeed(const lticks_t _speed);

#endif // TTCK_SLOWTICK

#ifdef TTCK_MAINTICK

//-----------------------------------------------------
/**
	\brief	Funkce ukoncujici provadeni main ticku
*/
//-----------------------------------------------------

void TerminateMain(void);

//-----------------------------------------------------
/**
	\brief	Funkce zahajujici provadeni main ticku

	\note	funkce je blokujici, opakovane vola main tick,
			ukonceni je volanim TerminateMainTick,
			ukonceni je po ukonceni pruchodu main ticku
*/
//-----------------------------------------------------

 void ExecuteMain(void);

#endif // TTCK_MAINTICK

//-----------------------------------------------------
/**
	\brief		Funkce vraci aktualni hodnotu 16-bitoveho citace tiku

	\return		nizsich 16-bitu globalni promenne gTmrCounter

	\note		Funkce zakazuje preruseni na dobu cteni z
				promenne gTmrCounter
*/
//-----------------------------------------------------

ticks_t tmTicks(void);


//-----------------------------------------------------
/**
	\brief		Funkce vraci aktualni hodnotu 32-bitoveho citace tiku

	\return		Funkce vraci hodnotu globalni promenne gTmrCounter

	\note		Funkce zakazuje preruseni na dobu cteni z
				promenne gTmrCounter
*/
//-----------------------------------------------------

lticks_t ltmTicks(void);


//-----------------------------------------------------
/**	\name	Makra pro testovani casovych intervalu
			tmXXX porovnavaji 16-bitove citace
			ltmXXX porovnavaji 32-bitove citace
*/
//@{

//! Vraci nenulovou hodnotu pokud a < b
static inline bool_t tmLT(ticks_t _a, ticks_t _b)
{
	ticks_t diff = _a - _b;
	return ((int16_t)diff < 0);
}

//! Vraci nenulovou hodnotu pokud a <= b
static inline bool_t tmLE(ticks_t _a, ticks_t _b)
{
	ticks_t diff = _a - _b;
	return ((int16_t)diff <= 0);
}

//! Vraci nenulovou hodnotu pokud a > b
static inline bool_t tmGT(ticks_t _a, ticks_t _b)
{
	ticks_t diff = _a - _b;
	return ((int16_t)diff > 0);
}

//! Vraci nenulovou hodnotu pokud a >= b
static inline bool_t tmGE(ticks_t _a, ticks_t _b)
{
	ticks_t diff = _a - _b;
	return ((int16_t)diff >= 0);
}

//! Vraci nenulovou hodnotu pokud a < b
static inline bool_t ltmLT(lticks_t _a, lticks_t _b)
{
	lticks_t diff = _a - _b;
	return ((int32_t)diff < 0);
}

//! Vraci nenulovou hodnotu pokud a <= b
static inline bool_t ltmLE(lticks_t _a, lticks_t _b)
{
	lticks_t diff = _a - _b;
	return ((int32_t)diff <= 0);
}

//! Vraci nenulovou hodnotu pokud a > b
static inline bool_t ltmGT(lticks_t _a, lticks_t _b)
{
	lticks_t diff = _a - _b;
	return ((int32_t)diff > 0);
}

//! Vraci nenulovou hodnotu pokud a >= b
static inline bool_t ltmGE(lticks_t _a, lticks_t _b)
{
	lticks_t diff = _a - _b;
	return ((int32_t)diff >= 0);
}
//@}

//! Vraci aktualni hodnotu 16bitoveho citace tiku zvysenou o hodnotu parametru delta
static inline ticks_t tmTimeout(const ticks_t _delta)
{
	return (tmTicks() + _delta);
}

//! Vraci aktualni hodnotu 32bitoveho citace tiku zvysenou o hodnotu parametru delta
static inline lticks_t ltmTimeout(const lticks_t _delta)
{
	return (ltmTicks() + _delta);
}

//! Testuje, zda casovac prekrocil udany cas
static inline bool_t tmElapsed(const ticks_t _tm)
{
	ticks_t curtime = tmTicks();
	return tmGE(curtime, _tm);
}

//! Testuje, zda 32bitovy casovac prekrocil udany cas
static inline bool_t ltmElapsed(const lticks_t _tm)
{
	lticks_t curtime = ltmTicks();
	return ltmGE(curtime, _tm);
}

//! Vraci pocet uplynulych tiku
static inline ticks_t tmDuration(const ticks_t _time)
{
	return (tmTicks() - _time);
}

//! Vraci pocet uplynulych 32bitovych tiku
static inline lticks_t ltmDuration(const lticks_t _time)
{
	return (ltmTicks() - _time);
}

//-----------------------------------------------------
/**
	\brief	Funkce inicializujici TimeTicks
*/
//-----------------------------------------------------

bool_t TimeTicksInitialize(void);


//-----------------------------------------------------
/**
	\brief	Funkce ukoncujici TimeTicks
*/
//-----------------------------------------------------

void TimeTicksFinalize(void);

#endif // _TIMETICKS_H_
