Rind vor 8 Jahren
Commit
a5d790ff36

BIN
build/Toolchain/arm/libgfatimer.so.1.0.0


BIN
build/Toolchain/arm/libgfatimerd.so.1.0.0


+ 62 - 0
build/Toolchain/gfatimer.h

@@ -0,0 +1,62 @@
+// gfatimer.h :
+//
+
+#if !defined(AGD_GFATIMER_H__60DC793C_D443_45EB_AD2F_D947862C2060__INCLUDED_)
+#define AGD_GFATIMER_H__60DC793C_D443_45EB_AD2F_D947862C2060__INCLUDED_
+
+#ifdef __cplusplus
+extern "C" {
+#endif	//	__cplusplus
+
+/////////////////////////////////////////////////////////////////////////////
+// gfatimer.h - Declarations:
+
+typedef enum GfaTimerResolution
+{
+	GTR_Invalid,
+	GTR_10ms,
+	GTR_25ms,
+	GTR_50ms
+}GfaTimerResolution;
+
+/////////////////////////////////////////////////////////////////////////////
+
+typedef enum GfaTimerClockPulse
+{
+	GTCP_250ms,
+	GTCP_500ms,
+	GTCP_750ms,
+	GTCP_1000ms,
+	GTCP_1500ms,
+	GTCP_2000ms,
+	GTCP_5000ms,
+	GTCP_10000ms
+}GfaTimerClockPulse;
+
+/////////////////////////////////////////////////////////////////////////////
+// initialization (if GfaTimerRelease is not called explicitly, clean up will
+// be done internally, if the process exits gracefully)
+
+int				GfaTimerInit(int nTimerCount, GfaTimerResolution res);
+void			GfaTimerRelease(void);
+
+/////////////////////////////////////////////////////////////////////////////
+// mondial legacy timer API
+
+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); // val in milliseconds
+
+/////////////////////////////////////////////////////////////////////////////
+// test clock pulse (see GfaTimerClockPulse enumeration for possible values)
+
+int				cp_test(GfaTimerClockPulse cp);
+
+/////////////////////////////////////////////////////////////////////////////
+#ifdef __cplusplus
+}
+#endif	//	__cplusplus
+#endif	//	!defined(AGD_GFATIMER_H__60DC793C_D443_45EB_AD2F_D947862C2060__INCLUDED_)

+ 52 - 0
build/Toolchain/install.sh

@@ -0,0 +1,52 @@
+#!/bin/bash
+set -e
+set -o pipefail
+
+REMPWD="root"
+REMUSR="root@192.168.0.125"
+
+
+TOOLCHAIN_SYSROOT="/opt/GfA/T_C49xL448RT_Qt57x/usr/arm-buildroot-linux-gnueabihf/sysroot"
+LIBBASENAMEREL="gfatimer"
+LIBBASENAMEDBG="gfatimerd"
+LIBDBGx86_64SRC="x86_64/lib$LIBBASENAMEDBG.so.1.0.0"
+LIBRELx86_64SRC="x86_64/lib$LIBBASENAMEREL.so.1.0.0"
+LIBDBGARMSRC="arm/lib$LIBBASENAMEDBG.so.1.0.0"
+LIBRELARMSRC="arm/lib$LIBBASENAMEREL.so.1.0.0"
+INCSRC="$LIBBASENAMEREL.h"
+
+LIBDBGx86_64DST="/usr/lib/"
+LIBRELx86_64DST="/usr/lib/"
+INCDSTx86_64DST="/usr/include/"
+
+LIBDBGARMDST_LOC="$TOOLCHAIN_SYSROOT/usr/lib/"
+LIBRELARMDST_LOC="$TOOLCHAIN_SYSROOT/usr/lib/"
+INCDSTARM_LOC="$TOOLCHAIN_SYSROOT/usr/include/"
+
+sudo cp $LIBDBGx86_64SRC $LIBDBGx86_64DST
+sudo cp $LIBRELx86_64SRC $LIBRELx86_64DST
+sudo cp $INCSRC $INCDSTx86_64DST
+
+sudo ln -sfnr /usr/lib/lib$LIBBASENAMEDBG.so.1.0.0 /usr/lib/lib$LIBBASENAMEDBG.so.1
+sudo ln -sfnr /usr/lib/lib$LIBBASENAMEDBG.so.1 /usr/lib/lib$LIBBASENAMEDBG.so
+sudo ln -sfnr /usr/lib/lib$LIBBASENAMEREL.so.1.0.0 /usr/lib/lib$LIBBASENAMEREL.so.1
+sudo ln -sfnr /usr/lib/lib$LIBBASENAMEREL.so.1 /usr/lib/lib$LIBBASENAMEREL.so
+
+cp $LIBDBGARMSRC $LIBDBGARMDST_LOC
+cp $LIBRELARMSRC $LIBRELARMDST_LOC
+cp $INCSRC $INCDSTARM_LOC
+
+ln -sfnr $TOOLCHAIN_SYSROOT/usr/lib/lib$LIBBASENAMEDBG.so.1.0.0 $TOOLCHAIN_SYSROOT/usr/lib/lib$LIBBASENAMEDBG.so.1
+ln -sfnr $TOOLCHAIN_SYSROOT/usr/lib/lib$LIBBASENAMEDBG.so.1 $TOOLCHAIN_SYSROOT/usr/lib/lib$LIBBASENAMEDBG.so
+ln -sfnr $TOOLCHAIN_SYSROOT/usr/lib/lib$LIBBASENAMEREL.so.1.0.0 $TOOLCHAIN_SYSROOT/usr/lib/lib$LIBBASENAMEREL.so.1
+ln -sfnr $TOOLCHAIN_SYSROOT/usr/lib/lib$LIBBASENAMEREL.so.1 $TOOLCHAIN_SYSROOT/usr/lib/lib$LIBBASENAMEREL.so
+
+pscp -pw $REMPWD $LIBDBGARMSRC $REMUSR:/usr/lib/ > /dev/null
+pscp -pw $REMPWD $LIBRELARMSRC $REMUSR:/usr/lib/ > /dev/null
+
+plink -batch -t -pw $REMPWD $REMUSR ln -sfn /usr/lib/lib$LIBBASENAMEDBG.so.1.0.0 /usr/lib/lib$LIBBASENAMEDBG.so.1
+plink -batch -t -pw $REMPWD $REMUSR ln -sfn /usr/lib/lib$LIBBASENAMEDBG.so.1 /usr/lib/lib$LIBBASENAMEDBG.so
+plink -batch -t -pw $REMPWD $REMUSR ln -sfn /usr/lib/lib$LIBBASENAMEREL.so.1.0.0 /usr/lib/lib$LIBBASENAMEREL.so.1
+plink -batch -t -pw $REMPWD $REMUSR ln -sfn /usr/lib/lib$LIBBASENAMEREL.so.1 /usr/lib/lib$LIBBASENAMEREL.so
+
+echo Done.

BIN
build/Toolchain/x86_64/libgfatimer.so.1.0.0


BIN
build/Toolchain/x86_64/libgfatimerd.so.1.0.0


+ 17 - 0
build/arm/builddbg.sh

@@ -0,0 +1,17 @@
+#!/bin/bash
+set -e
+set -o pipefail
+
+SYSROOT="/opt/GfA/T_C49xL448RT_Qt57x/usr/arm-buildroot-linux-gnueabihf/sysroot"
+CC="/opt/GfA/T_C49xL448RT_Qt57x/usr/bin/arm-buildroot-linux-gnueabihf-c++"
+CCOPTS="-g -pthread -fPIC -Wall -Wno-unused -Wno-unused-label -Wformat -Wuninitialized -Wundef -Wcast-qual -Wwrite-strings -std=c++11 -fabi-version=2 -fno-omit-frame-pointer -D_DEBUG"
+
+LIBBASENAME="gfatimerd"
+LIBFILENAME="lib$LIBBASENAME.so.1.0.0"
+LINKNAME="lib$LIBBASENAME.so"
+
+$CC $CCOPTS -c ../../src/timer.cpp ../../src/gfatimer.cpp ../../../gfaipc/src/locmtx.cpp
+$CC -g -fPIC -shared -L. -Wl,-soname,$LIBFILENAME -o $LIBFILENAME timer.o gfatimer.o locmtx.o -lc -pthread
+rm -f *.o
+mv $LIBFILENAME ../Toolchain/arm
+

+ 17 - 0
build/arm/buildrel.sh

@@ -0,0 +1,17 @@
+#!/bin/bash
+set -e
+set -o pipefail
+
+SYSROOT="/opt/GfA/T_C49xL448RT_Qt57x/usr/arm-buildroot-linux-gnueabihf/sysroot"
+CC="/opt/GfA/T_C49xL448RT_Qt57x/usr/bin/arm-buildroot-linux-gnueabihf-c++"
+CCOPTS="-O3 -pthread -fPIC -Wall -Wno-unused -Wno-unused-label -Wformat -Wuninitialized -Wundef -Wcast-qual -Wwrite-strings -std=c++11 -fabi-version=2 -fno-omit-frame-pointer"
+
+LIBBASENAME="gfatimer"
+LIBFILENAME="lib$LIBBASENAME.so.1.0.0"
+LINKNAME="lib$LIBBASENAME.so"
+
+$CC $CCOPTS -c ../../src/timer.cpp ../../src/gfatimer.cpp ../../../gfaipc/src/locmtx.cpp
+$CC -O3 -fPIC -shared -L. -Wl,-soname,$LIBFILENAME -o $LIBFILENAME timer.o gfatimer.o locmtx.o -lc -pthread
+rm -f *.o
+mv $LIBFILENAME ../Toolchain/arm
+

+ 15 - 0
build/build.sh

@@ -0,0 +1,15 @@
+#!/bin/bash
+set -e
+set -o pipefail
+
+cd x86_64
+./builddbg.sh
+./buildrel.sh
+
+cd ../arm
+./builddbg.sh
+./buildrel.sh
+
+cd ..
+cp "../src/gfatimer.h" "Toolchain/"
+echo done

+ 15 - 0
build/x86_64/builddbg.sh

@@ -0,0 +1,15 @@
+#!/bin/bash
+set -e
+set -o pipefail
+
+CC=c++
+CCOPTS="-g -pthread -fPIC -Wall -Wno-unused -Wno-unused-label -Wformat -Wuninitialized -Wundef -Wcast-qual -Wwrite-strings -std=c++11 -fabi-version=2 -fno-omit-frame-pointer -D_DEBUG"
+
+LIBBASENAME="gfatimerd"
+LIBFILENAME="lib$LIBBASENAME.so.1.0.0"
+LINKNAME="lib$LIBBASENAME.so"
+
+$CC $CCOPTS -c ../../src/timer.cpp ../../src/gfatimer.cpp ../../../gfaipc/src/locmtx.cpp
+$CC -g -fPIC -shared -L. -Wl,-soname,$LIBFILENAME -o $LIBFILENAME timer.o gfatimer.o locmtx.o -lc -pthread
+rm -f *.o
+mv $LIBFILENAME ../Toolchain/x86_64

+ 16 - 0
build/x86_64/buildrel.sh

@@ -0,0 +1,16 @@
+#!/bin/bash
+set -e
+set -o pipefail
+
+CC=c++
+CCOPTS="-O3 -pthread -fPIC -Wall -Wno-unused -Wno-unused-label -Wformat -Wuninitialized -Wundef -Wcast-qual -Wwrite-strings -std=c++11 -fabi-version=2 -fno-omit-frame-pointer"
+
+LIBBASENAME="gfatimer"
+LIBFILENAME="lib$LIBBASENAME.so.1.0.0"
+LINKNAME="lib$LIBBASENAME.so"
+
+$CC $CCOPTS -c ../../src/timer.cpp ../../src/gfatimer.cpp ../../../gfaipc/src/locmtx.cpp
+$CC -O3 -fPIC -shared -L. -Wl,-soname,$LIBFILENAME -o $LIBFILENAME timer.o gfatimer.o locmtx.o -lc -pthread
+rm -f *.o
+mv $LIBFILENAME ../Toolchain/x86_64
+

+ 10 - 0
demo/arm/builddbg.sh

@@ -0,0 +1,10 @@
+#!/bin/bash
+set -e
+set -o pipefail
+
+CC="/opt/GfA/T_C49xL448RT_Qt57x/usr/bin/arm-buildroot-linux-gnueabihf-gcc"
+CCOPTS="-g -fPIC -Wall -Wno-unused -Wno-unused-label -Wformat -Wuninitialized -Wundef -Wcast-qual -Wwrite-strings -fabi-version=2 -fno-omit-frame-pointer -D_DEBUG -lc -pthread -lgfatimerd"
+
+$CC $CCOPTS ../main.c -o demod
+
+echo done

+ 10 - 0
demo/arm/buildrel.sh

@@ -0,0 +1,10 @@
+#!/bin/bash
+set -e
+set -o pipefail
+
+CC="/opt/GfA/T_C49xL448RT_Qt57x/usr/bin/arm-buildroot-linux-gnueabihf-gcc"
+CCOPTS="-O3 -fPIC -Wall -Wno-unused -Wno-unused-label -Wformat -Wuninitialized -Wundef -Wcast-qual -Wwrite-strings -fabi-version=2 -fno-omit-frame-pointer -lc -pthread -lgfatimer"
+
+$CC $CCOPTS ../main.c -o demo
+
+echo done

BIN
demo/arm/demo


BIN
demo/arm/demod


+ 79 - 0
demo/main.c

@@ -0,0 +1,79 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gfatimer.h>
+
+#define _NANOSECS_PER_SEC					1000000000
+
+static long long _TimeSpecDiffNs(const struct timespec *pts1, const struct timespec *pts2)
+{
+	long long ns1 = (long long)pts1->tv_sec * _NANOSECS_PER_SEC + pts1->tv_nsec;
+	long long ns2 = (long long)pts2->tv_sec * _NANOSECS_PER_SEC + pts2->tv_nsec;
+	return ns2 - ns1;
+}
+
+int main(int argc, char **argv)
+{
+	long long elps1, elps2;
+	int tnum1 = 3, tnum2 = 14, nPulse, nOldPulse = 0;
+	unsigned long tw1 = 1, tw2 = 1;
+	struct timespec tsRes, tsStart, tsEnd1, tsEnd2;
+	memset(&tsEnd1, 0, sizeof(tsEnd1));
+	memset(&tsEnd2, 0, sizeof(tsEnd2));
+
+	if(!GfaTimerInit(32, GTR_25ms))
+	{
+		printf("GfaTimerInit failed!\n");
+		return 1;
+	}
+
+	tf_set(tnum1);
+	tf_set(tnum2);
+	tw_set(tnum1, 15000);
+	tw_set(tnum2, 10000);
+
+	clock_gettime(CLOCK_MONOTONIC, &tsStart);
+
+	do
+	{
+		nPulse = cp_test(GTCP_750ms);
+
+		if(nOldPulse != nPulse)
+		{
+			nOldPulse = nPulse;
+			printf("Pulse 750ms %d\n", nPulse);
+		}
+
+		if(tw1)
+		{
+			if(!(tw1 = tw_read(tnum1)))
+			{
+				clock_gettime(CLOCK_MONOTONIC, &tsEnd1);
+				printf("T%d expired.\n", tnum1);
+			}
+		}
+
+		if(tw2)
+		{
+			if(!(tw2 = tw_read(tnum2)))
+			{
+				clock_gettime(CLOCK_MONOTONIC, &tsEnd2);
+				printf("T%d expired.\n", tnum2);
+			}
+		}
+
+		usleep(25000);
+//		printf("T%d: %3lu, T%d: %3lu\n", tnum1, tw1, tnum2, tw2);
+	}
+	while(tw1 || tw2);
+
+	elps1 = _TimeSpecDiffNs(&tsStart, &tsEnd1);
+	elps2 = _TimeSpecDiffNs(&tsStart, &tsEnd2);
+
+	printf("\nT%d effective: %lld ms.\n", tnum1, elps1 / 1000000);
+	printf("T%d effective: %lld ms.\n", tnum2, elps2 / 1000000);
+
+	return 0;
+}

+ 7 - 0
demo/x86_64/builddbg.sh

@@ -0,0 +1,7 @@
+#!/bin/bash
+set -e
+set -o pipefail
+
+gcc -g ../main.c -o demod -pthread -lgfatimerd -D_DEBUG
+
+echo done

+ 7 - 0
demo/x86_64/buildrel.sh

@@ -0,0 +1,7 @@
+#!/bin/bash
+set -e
+set -o pipefail
+
+gcc -O3 ../main.c -o demo -pthread -lgfatimer
+
+echo done

BIN
demo/x86_64/demo


BIN
demo/x86_64/demod


+ 49 - 0
src/gfatimer.cpp

@@ -0,0 +1,49 @@
+#include "gfatimer.h"
+#include "timer.h"
+
+static CGfaTimer g_gfaTimer;
+
+int GfaTimerInit(int nTimerCount, GfaTimerResolution res)
+{
+	return g_gfaTimer.Initialize(nTimerCount, res);
+}
+
+void GfaTimerRelease(void)
+{
+	g_gfaTimer.Release();
+}
+
+int tf_test(int tnum)
+{
+	return g_gfaTimer.tf_test(tnum);
+}
+
+void tf_set(int tnum)
+{
+	g_gfaTimer.tf_set(tnum);
+}
+
+void tf_clear(int tnum)
+{
+	g_gfaTimer.tf_clear(tnum);
+}
+
+void tf_store(int tnum, int fset)
+{
+	g_gfaTimer.tf_store(tnum, fset);
+}
+
+unsigned long tw_read(int tnum)
+{
+	return g_gfaTimer.tw_read(tnum);
+}
+
+void tw_set(int tnum, unsigned long val)
+{
+	g_gfaTimer.tw_set(tnum, val);
+}
+
+int cp_test(GfaTimerClockPulse cp)
+{
+	return g_gfaTimer.cp_test(cp);
+}

+ 62 - 0
src/gfatimer.h

@@ -0,0 +1,62 @@
+// gfatimer.h :
+//
+
+#if !defined(AGD_GFATIMER_H__60DC793C_D443_45EB_AD2F_D947862C2060__INCLUDED_)
+#define AGD_GFATIMER_H__60DC793C_D443_45EB_AD2F_D947862C2060__INCLUDED_
+
+#ifdef __cplusplus
+extern "C" {
+#endif	//	__cplusplus
+
+/////////////////////////////////////////////////////////////////////////////
+// gfatimer.h - Declarations:
+
+typedef enum GfaTimerResolution
+{
+	GTR_Invalid,
+	GTR_10ms,
+	GTR_25ms,
+	GTR_50ms
+}GfaTimerResolution;
+
+/////////////////////////////////////////////////////////////////////////////
+
+typedef enum GfaTimerClockPulse
+{
+	GTCP_250ms,
+	GTCP_500ms,
+	GTCP_750ms,
+	GTCP_1000ms,
+	GTCP_1500ms,
+	GTCP_2000ms,
+	GTCP_5000ms,
+	GTCP_10000ms
+}GfaTimerClockPulse;
+
+/////////////////////////////////////////////////////////////////////////////
+// initialization (if GfaTimerRelease is not called explicitly, clean up will
+// be done internally, if the process exits gracefully)
+
+int				GfaTimerInit(int nTimerCount, GfaTimerResolution res);
+void			GfaTimerRelease(void);
+
+/////////////////////////////////////////////////////////////////////////////
+// mondial legacy timer API
+
+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); // val in milliseconds
+
+/////////////////////////////////////////////////////////////////////////////
+// test clock pulse (see GfaTimerClockPulse enumeration for possible values)
+
+int				cp_test(GfaTimerClockPulse cp);
+
+/////////////////////////////////////////////////////////////////////////////
+#ifdef __cplusplus
+}
+#endif	//	__cplusplus
+#endif	//	!defined(AGD_GFATIMER_H__60DC793C_D443_45EB_AD2F_D947862C2060__INCLUDED_)

+ 305 - 0
src/timer.cpp

@@ -0,0 +1,305 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+
+#include <time.h>
+#include <errno.h>
+#include "timer.h"
+
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef _DEBUG
+#define _VALIDATE_TIMER_RET(tnum, ret)		if(!ValidateTimer(tnum, __FUNCTION__)) return (ret)
+#define _VALIDATE_TIMER_VOID(tnum)			if(!ValidateTimer(tnum, __FUNCTION__)) return
+#define TRACE								printf
+#else	//	_DEBUG
+#define _VALIDATE_TIMER_RET(tnum, ret)
+#define _VALIDATE_TIMER_VOID(tnum)
+#define TRACE(...)
+#endif	//	_DEBUG
+
+#define _GFA_DEFAULT_TIMER_COUNT			32
+#define _GFA_MAX_TIMER_COUNT				256
+#define _COUNTOF(a)							(sizeof(a) / sizeof(*a))
+#define _INVALID_THREAD_ID					0
+#define _NANOSECS_PER_SEC					1000000000
+
+/////////////////////////////////////////////////////////////////////////////
+
+const int CGfaTimer::m_nPulseFreq[] = {250, 500, 750, 1000, 1500, 2000, 5000, 10000};
+
+/////////////////////////////////////////////////////////////////////////////
+
+CGfaTimer::CGfaTimer(void) : m_pTimer(NULL), m_nTimerCount(0), m_nTimerIncrement(0), m_nClockCount(0), m_nClockPulse(0), m_threadID(_INVALID_THREAD_ID), m_bProcessTimers(false)
+{
+	memset(&m_timInterval, 0, sizeof(m_timInterval));
+
+	if(!m_mutex.Create())
+	{
+		TRACE("CGfaTimer::CGfaTimer: failed to create mutex!\n");
+		throw -1;
+	}
+}
+
+CGfaTimer::~CGfaTimer(void)
+{
+	Release();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+int CGfaTimer::Initialize(int nTimerCount, GfaTimerResolution res)
+{
+	if(!m_pTimer)
+	{
+		if(nTimerCount == 0)
+			nTimerCount = _GFA_DEFAULT_TIMER_COUNT;
+		else if(nTimerCount < 0)
+		{
+			TRACE("CGfaTimer::Initialize: invalid timer count: %d!\n", nTimerCount);
+			return 0;
+		}
+		else if(nTimerCount > _GFA_MAX_TIMER_COUNT)
+			nTimerCount = _GFA_MAX_TIMER_COUNT;
+
+		switch(res)
+		{
+		case GTR_10ms:
+			m_timInterval.tv_sec	= 0;
+			m_timInterval.tv_nsec	= 10000000;
+			m_nTimerIncrement		= 10;
+			break;
+		case GTR_25ms:
+			m_timInterval.tv_sec	= 0;
+			m_timInterval.tv_nsec	= 25000000;
+			m_nTimerIncrement		= 25;
+			break;
+		case GTR_50ms:
+			m_timInterval.tv_sec	= 0;
+			m_timInterval.tv_nsec	= 50000000;
+			m_nTimerIncrement		= 50;
+			break;
+		default:
+			TRACE("CGfaTimer::Initialize: invalid timer resolution: %d!\n", (int)res);
+			return 0;
+		}
+
+		m_pTimer = new GFA_TIMER[nTimerCount];
+		memset(m_pTimer, 0, sizeof(GFA_TIMER) * nTimerCount);
+		m_nTimerCount = nTimerCount;
+		m_bProcessTimers = true;
+
+		if(::pthread_create(&m_threadID, NULL, &CGfaTimer::LordOfTheTimers, reinterpret_cast<void*>(this)))
+		{
+			TRACE("CGfaTimer::Initialize: Failed to create timer thread!\n");
+			Release();
+		}
+
+		TRACE("CGfaTimer::Initialize: Success!\n");
+	}
+	else
+	{
+		TRACE("CGfaTimer::Initialize: Already initialized!\n");
+	}
+
+	return m_nTimerCount;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CGfaTimer::Release(void)
+{
+	if(m_pTimer)
+	{
+		if(m_threadID != _INVALID_THREAD_ID)
+		{
+			m_bProcessTimers = false;
+			::pthread_join(m_threadID, NULL);
+			m_threadID = _INVALID_THREAD_ID;
+		}
+
+		m_nTimerCount = m_nTimerIncrement = m_nClockCount = m_nClockPulse = 0;
+		delete [] m_pTimer;
+		m_pTimer = NULL;
+		TRACE("CGfaTimer::Release: Timer released.\n");
+	}
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+bool CGfaTimer::ValidateTimer(int tnum, const char *pszCaller)
+{
+	if(!m_pTimer)
+	{
+		TRACE("%s: Timer not initialized!\n", pszCaller);
+		return false;
+	}
+
+	if((tnum < 0) || (tnum >= m_nTimerCount))
+	{
+		TRACE("%s: Invalid Timer number: %d\n", pszCaller, tnum);
+		return false;
+	}
+
+	return true;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+int CGfaTimer::tf_test(int tnum)
+{
+	_VALIDATE_TIMER_RET(tnum, 0);
+	m_mutex.Lock();
+    int nRet = m_pTimer[tnum].tf;
+	m_mutex.Unlock();
+	return nRet;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CGfaTimer::tf_set(int tnum)
+{
+	_VALIDATE_TIMER_VOID(tnum);
+	m_mutex.Lock();
+	m_pTimer[tnum].tf = 1;
+	m_mutex.Unlock();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CGfaTimer::tf_clear(int tnum)
+{
+	_VALIDATE_TIMER_VOID(tnum);
+	m_mutex.Lock();
+	m_pTimer[tnum].tf = 0;
+	m_mutex.Unlock();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CGfaTimer::tf_store(int tnum, int fset)
+{
+	_VALIDATE_TIMER_VOID(tnum);
+	if(fset)
+	{
+		m_mutex.Lock();
+		m_pTimer[tnum].tf = 1;
+		m_mutex.Unlock();
+	}
+	else
+	{
+		m_mutex.Lock();
+		m_pTimer[tnum].tf = 0;
+		m_mutex.Unlock();
+	}
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+unsigned long CGfaTimer::tw_read(int tnum)
+{
+	_VALIDATE_TIMER_RET(tnum, 0);
+	m_mutex.Lock();
+    unsigned long nRet = m_pTimer[tnum].tw;
+	m_mutex.Unlock();
+	return nRet;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CGfaTimer::tw_set(int tnum, unsigned long val)
+{
+	_VALIDATE_TIMER_VOID(tnum);
+	m_mutex.Lock();
+    m_pTimer[tnum].tw = val;
+	m_mutex.Unlock();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+int CGfaTimer::cp_test(GfaTimerClockPulse cp)
+{
+	if(cp >= GTCP_250ms && cp <= GTCP_10000ms)
+	{
+		return !!(m_nClockPulse & (0x00000001 << cp));
+	}
+
+	TRACE("CGfaTimer::cp_test: Invalid clock pulse: %d.\n", (int)cp);
+	return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CGfaTimer::AddTimeSpecs(const struct timespec &ts1, const struct timespec &ts2, struct timespec &tsResult)
+{
+	long ns = ts1.tv_nsec + ts2.tv_nsec;
+	tsResult.tv_sec = ts1.tv_sec + ts2.tv_sec + (time_t)ns / _NANOSECS_PER_SEC;
+	tsResult.tv_nsec = ns % _NANOSECS_PER_SEC;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+
+void* CGfaTimer::LordOfTheTimers(void *pParam)
+{
+	int nRet;
+	struct timespec tsDueTime;
+	CGfaTimer* pSelf = reinterpret_cast<CGfaTimer*>(pParam);
+	TRACE("CGfaTimer::LordOfTheTimers: thread enter.\n");
+
+	::clock_gettime(CLOCK_MONOTONIC, &tsDueTime);
+
+	do
+	{
+		for(int i = 0; i < pSelf->m_nTimerCount; i++)
+		{
+			GFA_TIMER &rt = pSelf->m_pTimer[i];
+
+			pSelf->m_mutex.Lock();
+            if(rt.tf)
+            {
+                if(rt.tw >= pSelf->m_nTimerIncrement)
+                	rt.tw -= pSelf->m_nTimerIncrement;
+                else if(rt.tw)
+                	rt.tw = 0;
+            }
+            else
+            {
+                rt.tw = 0;
+            }
+			pSelf->m_mutex.Unlock();
+		}
+
+		pSelf->m_nClockCount += pSelf->m_nTimerIncrement;
+
+		if(!(pSelf->m_nClockCount % CGfaTimer::m_nPulseFreq[0]))
+		{
+			unsigned long nPulseMask = 1;
+			pSelf->m_nClockPulse ^= nPulseMask;
+
+			for(size_t i = 1; i < _COUNTOF(CGfaTimer::m_nPulseFreq); i++)
+			{
+				nPulseMask <<= 1;
+
+				if(!(pSelf->m_nClockCount % CGfaTimer::m_nPulseFreq[i]))
+				{
+					pSelf->m_nClockPulse ^= nPulseMask;
+				}
+			}
+		}
+
+		CGfaTimer::AddTimeSpecs(tsDueTime, pSelf->m_timInterval, tsDueTime);
+
+		if((nRet = ::clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &tsDueTime, NULL)))
+		{
+			while(nRet && (errno == EINTR))
+			{
+				errno = 0;
+				nRet = ::clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &tsDueTime, NULL);
+			}
+		}
+	}
+	while(pSelf->m_bProcessTimers);
+
+	TRACE("CGfaTimer::LordOfTheTimers: thread exit.\n");
+	return NULL;
+}

+ 62 - 0
src/timer.h

@@ -0,0 +1,62 @@
+// 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 "../../gfaipc/src/mutex.h"
+#include "gfatimer.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// timer.h - Declarations:
+
+typedef struct _GFA_TIMER
+{
+//    unsigned long tv;
+    unsigned long tw;
+    int tf;
+}GFA_TIMER, *LPGFA_TIMER;
+typedef const GFA_TIMER *LPCGFA_TIMER;
+
+/////////////////////////////////////////////////////////////////////////////
+
+class CGfaTimer
+{
+public:
+	CGfaTimer(void);
+	~CGfaTimer(void);
+
+	int Initialize(int nTimerCount, GfaTimerResolution res);
+	void Release(void);
+
+	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[];
+};
+
+/////////////////////////////////////////////////////////////////////////////
+#endif	//	!defined(AGD_TIMER_H__039EAF1D_4D42_44F5_9CAD_437128DA1BA9__INCLUDED_)