// timer.h :
//

#if !defined(AGD_TIMER_H__039EAF1D_4D42_44F5_9CAD_437128DA1BA9__INCLUDED_)
#define AGD_TIMER_H__039EAF1D_4D42_44F5_9CAD_437128DA1BA9__INCLUDED_

#include <stdio.h>
#include <string.h>
#include "mutex.h"
#include "gfatimer.h"

/////////////////////////////////////////////////////////////////////////////
// timer.h - Declarations:

typedef struct _GFA_TIMER
{
    int tf;
    unsigned long tw;
    pfnTIMERCALLBACK pfnCallback;
    void *pContext;
    bool bCallScheduled;
}GFA_TIMER, *LPGFA_TIMER;
typedef const GFA_TIMER *LPCGFA_TIMER;

typedef struct _GFA_TIMER_PULSE_CALLBACK
{
    pfnPULSECALLBACK pfnCallback;
    void *pContext;
}GFA_TIMER_PULSE_CALLBACK, *LPGFA_TIMER_PULSE_CALLBACK;
typedef const GFA_TIMER_PULSE_CALLBACK *LPCGFA_TIMER_PULSE_CALLBACK;

/////////////////////////////////////////////////////////////////////////////

class CGfaTimer
{
public:
	CGfaTimer(void);
	~CGfaTimer(void);

	int Initialize(int nTimerCount, GfaTimerResolution res);
	void Release(void);
	void RegisterTimerCallback(int tnum, pfnTIMERCALLBACK pfnCallback, void *pContext);
	void RegisterClockPulseCallback(GfaTimerClockPulse cp, pfnPULSECALLBACK pfnCallback, void *pContext);

	int tf_test(int tnum);
	void tf_set(int tnum);
	void tf_clear(int tnum);
	void tf_store(int tnum, int fset);
	unsigned long tw_read(int tnum);
	void tw_set(int tnum, unsigned long val);

	int cp_test(GfaTimerClockPulse cp);

private:
	bool ValidateTimer(int tnum, const char *pszCaller);
	static void* LordOfTheTimers(void *pParam);
	static void AddTimeSpecs(const struct timespec &ts1, const struct timespec &ts2, struct timespec &tsResult);

private:
	LPGFA_TIMER m_pTimer;
	int m_nTimerCount;
	unsigned long m_nTimerIncrement;
	unsigned long long m_nClockCount;
	unsigned long m_nClockPulse;
	CLocalMutex m_mutex;
    pthread_t m_threadID;
    struct timespec m_timInterval;
    bool m_bProcessTimers;
    static const int m_nPulseFreq[];
    GFA_TIMER_PULSE_CALLBACK m_ClkPulseCallbackTable[GTCP_Last];
};

/////////////////////////////////////////////////////////////////////////////
#endif	//	!defined(AGD_TIMER_H__039EAF1D_4D42_44F5_9CAD_437128DA1BA9__INCLUDED_)
