/***************************************************************************/
/*  Description: CPA Timer.lib.                                            */
/*                                                                         */
/*  Author: F. Jentey.                                                     */
/*  Last Update : 04/03/97                                                 */
/*                14/04/97 Change prototype using TMR_fn_xxxx              */
/*                16/04/97 Include CPA_std.h                               */
/*           MT   30/04/98 Take PSX account								   */
/*						   Translate functions into Timer.cxx specific file*/
/***************************************************************************/
 
 
#include "CPA_std.h"
 
#ifdef PSX
	#include "PSX.h"
#endif /* PSX */
 
/* CPA errors */
#include "ERM.h"
#define __DeclareGlobalVariableErrTmr_h__
#include "TMR/errTmr.h"
#undef __DeclareGlobalVariableErrTmr_h__
 
#include "TMR/Timer.h"
#include "Specif/TimerPrv.h"
 
 
  
/*
  To store the frequency of each timer type. If a type of timer isn't
  available, the corresponding entry is null. It's the case for event timer
  fro the medium and high frequency.
*/
u_long      a3_ulTimerFrequency[3];
u_long      a3_ulEventFrequency[3];
 
 
/* Info variables */
tdstTimer   a_stTimerTab[C_uwTimerMaxCount];
short       wTimerCount = 0;
short       TimerLibOk = 0;   /* Equals to the actual number of user */
short       TMR_g_wErmOK = 0; 
 
 
 
 
/************************************************/
/*       Private functions                      */
/************************************************/
 
/*
  Add, Sub stTimerCount value
  stOp1 is always greater than stOp2
*/
void fn_vAddTimerValues(stTimerCount* stOp1, stTimerCount* stOp2)
{
    u_long ulTmpValue;
 
    ulTmpValue = stOp1->m_ulLowPart + stOp2->m_ulLowPart;
    if ( ulTmpValue < stOp1->m_ulLowPart )
        stOp1->m_ulHighPart++;
    stOp1->m_ulLowPart = ulTmpValue;
 
    stOp1->m_ulHighPart += stOp2->m_ulHighPart;
}
void fn_vSubTimerValues(stTimerCount* stOp1, stTimerCount* stOp2)
{
    if ( stOp1->m_ulHighPart == stOp2->m_ulHighPart )
    {
        stOp1->m_ulLowPart -= stOp2->m_ulLowPart;
        stOp1->m_ulHighPart = 0;
    }
    else
    {
        if ( stOp1->m_ulLowPart >= stOp2->m_ulLowPart )
            stOp1->m_ulLowPart -= stOp2->m_ulLowPart;
        else
        {
            stOp1->m_ulLowPart += 0xffffffff - stOp2->m_ulLowPart + 1;
            stOp1->m_ulHighPart--;
        }
        stOp1->m_ulHighPart -= stOp2->m_ulHighPart;
    }
}
 
 
 
/************************************************/
/*       Public functions                       */
/************************************************/
 
/*
  short __stdcall TMR_fn_wInitLibrary( void )
  and
  short __stdcall TMR_fn_wExitLibrary( void )
  translated into the Timer.cxx specific file
*/
 
#include "Specif\Timer.cxx"
 
/*
  This fonction create a timer and return an handle to this timer.
  The parameter wTimerType define the resolution of the timer and must
  set to one of the C_wTimerType Flag.
*/
short __stdcall TMR_fn_wCreateTimer( short wTimerType )
{
    short   i;
 
    if ( TimerLibOk == 0 )
    {
        Erm_M_UpdateLastError(Tmr, C_ucErmDefaultChannel, E_uwTmrLibraryNotInitialized, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    if ( wTimerCount == C_uwTimerMaxCount )
    {
        Erm_M_UpdateLastError(Tmr, C_ucErmDefaultChannel, E_uwTmrMaxTimerCountReached, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    if ( wTimerType > C_wTimerFrequencyHigh )
    {
        Erm_M_UpdateLastError(Tmr, C_ucErmDefaultChannel, E_uwTmrInvalidType, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    if ( a3_ulTimerFrequency[wTimerType] == 0 )
    {
        Erm_M_UpdateLastError(Tmr, C_ucErmDefaultChannel, E_uwTmrTypeNotAvailable, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
 
    for ( i = 0 ; i < C_uwTimerMaxCount ; i++ )
        if ( a_stTimerTab[i].m_wTimerState == C_wTimerUnused ) break;
    if ( i == C_uwTimerMaxCount )
    {
        Erm_M_UpdateLastError(Tmr, C_ucErmDefaultChannel, E_uwTmrMaxTimerCountReached, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
 
    a_stTimerTab[i].m_wTimerType = wTimerType;
    a_stTimerTab[i].m_wTimerState = C_wTimerReady;
    wTimerCount++;
 
    return (i);
}
 
 
/*
  Start a timer.
*/
short __stdcall TMR_fn_wStartTimer( short wTimerHandle )
{
    short          wTimerType;
    stTimerCount   stValue;
 
    if ( TimerLibOk == 0 )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrLibraryNotInitialized, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    if ( wTimerHandle >= C_uwTimerMaxCount )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrInvalidHandle, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    if ( a_stTimerTab[wTimerHandle].m_wTimerState == C_wTimerUnused )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrInvalidHandle, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    if ( a_stTimerTab[wTimerHandle].m_wTimerType > C_wTimerFrequencyHigh )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrInvalidForEventTimer, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    /*if ( (a_stTimerTab[wTimerHandle].m_wTimerState != C_wTimerReady) &&
        (a_stTimerTab[wTimerHandle].m_wTimerState != C_wTimerPaused)   )
    {
        ulTimerErrorCode = C_ErrTimerNotReady;
        return (C_wTimerError);
    }*/
 
    wTimerType = a_stTimerTab[wTimerHandle].m_wTimerType;
    fn_vTimerGetCounter(wTimerType,&stValue);
 
    a_stTimerTab[wTimerHandle].m_stTimerCount_InitValue.m_ulLowPart = stValue.m_ulLowPart;
    a_stTimerTab[wTimerHandle].m_stTimerCount_InitValue.m_ulHighPart = stValue.m_ulHighPart;
 
    if ( a_stTimerTab[wTimerHandle].m_wTimerState != C_wTimerPaused )
    {
        a_stTimerTab[wTimerHandle].m_stTimerCount_TotalValue.m_ulLowPart = 0;
        a_stTimerTab[wTimerHandle].m_stTimerCount_TotalValue.m_ulHighPart = 0;
    }
 
    a_stTimerTab[wTimerHandle].m_wTimerState = C_wTimerRunning;
 
    return (0);
}
 
 
/*
  Stop a Timer.
*/
short __stdcall TMR_fn_wStopTimer( short wTimerHandle )
{
    short          wTimerType;
    stTimerCount   stValue;
 
    if ( TimerLibOk == 0 )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrLibraryNotInitialized, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    if ( wTimerHandle >= C_uwTimerMaxCount )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrInvalidHandle, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    if ( a_stTimerTab[wTimerHandle].m_wTimerState == C_wTimerUnused )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrInvalidHandle, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    if ( a_stTimerTab[wTimerHandle].m_wTimerType > C_wTimerFrequencyHigh )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrInvalidForEventTimer, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    /*if (a_stTimerTab[wTimerHandle].m_wTimerState < C_wTimerRunning )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrStartTimerFirst, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }*/
 
    wTimerType = a_stTimerTab[wTimerHandle].m_wTimerType;
 
    if ( a_stTimerTab[wTimerHandle].m_wTimerState == C_wTimerRunning )
    {
        fn_vTimerGetCounter(wTimerType,&stValue);
        a_stTimerTab[wTimerHandle].m_stTimerCount_LastValue.m_ulLowPart = stValue.m_ulLowPart;
        a_stTimerTab[wTimerHandle].m_stTimerCount_LastValue.m_ulHighPart = stValue.m_ulHighPart;
    }
 
    if ( a_stTimerTab[wTimerHandle].m_wTimerState == C_wTimerPaused )
    {
        a_stTimerTab[wTimerHandle].m_stTimerCount_LastValue.m_ulLowPart = 
          a_stTimerTab[wTimerHandle].m_stTimerCount_TotalValue.m_ulLowPart;
        a_stTimerTab[wTimerHandle].m_stTimerCount_LastValue.m_ulHighPart = 
          a_stTimerTab[wTimerHandle].m_stTimerCount_TotalValue.m_ulHighPart;
 
        a_stTimerTab[wTimerHandle].m_stTimerCount_TotalValue.m_ulLowPart = 0;
        a_stTimerTab[wTimerHandle].m_stTimerCount_TotalValue.m_ulHighPart = 0;
        a_stTimerTab[wTimerHandle].m_stTimerCount_InitValue.m_ulLowPart = 0;
        a_stTimerTab[wTimerHandle].m_stTimerCount_InitValue.m_ulHighPart = 0;
    }
 
    a_stTimerTab[wTimerHandle].m_wTimerState = C_wTimerStop;
 
    return (0);
}
 
 
/*
  Pause a Timer.
*/
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
short __stdcall TMR_fn_wPauseTimer( short wTimerHandle )
{
    short           wTimerType;
    stTimerCount    stValue, stTempCount;
 
    if ( TimerLibOk == 0 )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrLibraryNotInitialized, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    if ( wTimerHandle >= C_uwTimerMaxCount )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrInvalidHandle, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    if ( a_stTimerTab[wTimerHandle].m_wTimerState == C_wTimerUnused )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrInvalidHandle, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    if ( a_stTimerTab[wTimerHandle].m_wTimerType > C_wTimerFrequencyHigh )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrInvalidForEventTimer, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    /*
    if (a_stTimerTab[wTimerHandle].m_wTimerState < C_wTimerRunning )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrStartTimerFirst, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }*/
 
    wTimerType = a_stTimerTab[wTimerHandle].m_wTimerType;
 
    /* If the timer is running, Add the elapsed time to the total count */
    if ( a_stTimerTab[wTimerHandle].m_wTimerState == C_wTimerRunning )
    {
        fn_vTimerGetCounter(wTimerType,&stTempCount);
 
        stValue.m_ulLowPart = a_stTimerTab[wTimerHandle].m_stTimerCount_InitValue.m_ulLowPart;
        stValue.m_ulHighPart = a_stTimerTab[wTimerHandle].m_stTimerCount_InitValue.m_ulHighPart;
        fn_vSubTimerValues(&stTempCount,&stValue);
 
        stValue.m_ulLowPart = a_stTimerTab[wTimerHandle].m_stTimerCount_TotalValue.m_ulLowPart;
        stValue.m_ulHighPart = a_stTimerTab[wTimerHandle].m_stTimerCount_TotalValue.m_ulHighPart;
        fn_vAddTimerValues(&stTempCount,&stValue);
        a_stTimerTab[wTimerHandle].m_stTimerCount_TotalValue.m_ulLowPart = stTempCount.m_ulLowPart;
        a_stTimerTab[wTimerHandle].m_stTimerCount_TotalValue.m_ulHighPart = stTempCount.m_ulHighPart;
    }
 
    a_stTimerTab[wTimerHandle].m_wTimerState = C_wTimerPaused;
 
    return (0);
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
 
/*
  Set timer current value. The timer is paused
*/
short __stdcall TMR_fn_wSetTimerValue( short wTimerHandle, stTimerCount *p_stValue )
{
    short           wTimerType;
 
    if ( TimerLibOk == 0 )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrLibraryNotInitialized, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    if ( wTimerHandle >= C_uwTimerMaxCount )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrInvalidHandle, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    if ( a_stTimerTab[wTimerHandle].m_wTimerType > C_wTimerFrequencyHigh )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrInvalidForEventTimer, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
 
    wTimerType = a_stTimerTab[wTimerHandle].m_wTimerType;
 
    a_stTimerTab[wTimerHandle].m_stTimerCount_TotalValue.m_ulLowPart = p_stValue->m_ulLowPart;
    a_stTimerTab[wTimerHandle].m_stTimerCount_TotalValue.m_ulHighPart = p_stValue->m_ulHighPart;
 
    a_stTimerTab[wTimerHandle].m_wTimerState = C_wTimerPaused;
 
    return (0);
}
 
 
/*
  Return the timer count tdsTimerCount structure pointed by p_tdsTimerCount.
*/
short __stdcall TMR_fn_wReadTimer( short wTimerHandle, stTimerCount *p_stTimerCount)
{
    short           wTimerState;
    stTimerCount    stValue;
 
/*    p_stTimerCount->m_ulLowPart = 0;
    p_stTimerCount->m_ulHighPart = 0;
*/
    if ( TimerLibOk == 0 )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrLibraryNotInitialized, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    if ( wTimerHandle >= C_uwTimerMaxCount )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrInvalidHandle, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    if ( a_stTimerTab[wTimerHandle].m_wTimerState == C_wTimerUnused )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrInvalidHandle, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    if ( a_stTimerTab[wTimerHandle].m_wTimerType > C_wTimerFrequencyHigh )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrInvalidForEventTimer, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    /*
    if ( a_stTimerTab[wTimerHandle].m_wTimerState < C_wTimerRunning )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrStartTimerFirst, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }*/
 
    wTimerState = a_stTimerTab[wTimerHandle].m_wTimerState;
 
    switch ( wTimerState )
    {
 
    /* If the timer is running */
    case C_wTimerRunning:
        fn_vTimerGetCounter(a_stTimerTab[wTimerHandle].m_wTimerType,p_stTimerCount);
        stValue.m_ulLowPart = a_stTimerTab[wTimerHandle].m_stTimerCount_InitValue.m_ulLowPart;
        stValue.m_ulHighPart = a_stTimerTab[wTimerHandle].m_stTimerCount_InitValue.m_ulHighPart;
        fn_vSubTimerValues(p_stTimerCount,&stValue);
        break;
 
    /* If the timer is stoped */
    case C_wTimerStop:
        p_stTimerCount->m_ulLowPart = a_stTimerTab[wTimerHandle].m_stTimerCount_LastValue.m_ulLowPart;
        p_stTimerCount->m_ulHighPart = a_stTimerTab[wTimerHandle].m_stTimerCount_LastValue.m_ulHighPart;
        stValue.m_ulLowPart = a_stTimerTab[wTimerHandle].m_stTimerCount_InitValue.m_ulLowPart;
        stValue.m_ulHighPart = a_stTimerTab[wTimerHandle].m_stTimerCount_InitValue.m_ulHighPart;
        fn_vSubTimerValues(p_stTimerCount,&stValue);
        break;
 
    /* If the timer is  paused or ready */
    case C_wTimerReady:
    case C_wTimerPaused:
        p_stTimerCount->m_ulHighPart = 0;
        p_stTimerCount->m_ulLowPart = 0;
        break;
    }
 
    /* Add the total count */
    stValue.m_ulLowPart = a_stTimerTab[wTimerHandle].m_stTimerCount_TotalValue.m_ulLowPart;
    stValue.m_ulHighPart = a_stTimerTab[wTimerHandle].m_stTimerCount_TotalValue.m_ulHighPart;
    fn_vAddTimerValues(p_stTimerCount,&stValue);
    
    return (0);
}
 
 
/*
  Reset a timer.
*/
short __stdcall TMR_fn_wResetTimer( short wTimerHandle )
{
    if ( TimerLibOk == 0 )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrLibraryNotInitialized, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    if ( wTimerHandle >= C_uwTimerMaxCount )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrInvalidHandle, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    if ( a_stTimerTab[wTimerHandle].m_wTimerState == C_wTimerUnused )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrInvalidHandle, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    if ( a_stTimerTab[wTimerHandle].m_wTimerType > C_wTimerFrequencyHigh )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrInvalidForEventTimer, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
 
    a_stTimerTab[wTimerHandle].m_wTimerState = C_wTimerReady;
 
    a_stTimerTab[wTimerHandle].m_stTimerCount_InitValue.m_ulLowPart = 0;
    a_stTimerTab[wTimerHandle].m_stTimerCount_InitValue.m_ulHighPart = 0;
    a_stTimerTab[wTimerHandle].m_stTimerCount_LastValue.m_ulLowPart = 0;
    a_stTimerTab[wTimerHandle].m_stTimerCount_LastValue.m_ulHighPart = 0;
    a_stTimerTab[wTimerHandle].m_stTimerCount_TotalValue.m_ulLowPart = 0;
    a_stTimerTab[wTimerHandle].m_stTimerCount_TotalValue.m_ulHighPart = 0;
 
    return (0);
}
 
 
/*
  Destroy a timer.
*/
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
short __stdcall TMR_fn_wDestroyTimer( short wTimerHandle )
{
    if ( TimerLibOk == 0 )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrLibraryNotInitialized, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    if ( (wTimerHandle >= C_uwTimerMaxCount) ||
         (a_stTimerTab[wTimerHandle].m_wTimerState == C_wTimerUnused) )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrInvalidHandle, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
 
    a_stTimerTab[wTimerHandle].m_wTimerState = C_wTimerUnused;
 
    /* If the timer is an event timer, destroy the event*/
    if ( a_stTimerTab[wTimerHandle].m_wTimerType > C_wTimerFrequencyHigh )
    {
        fn_wTimerDestroyEvent( a_stTimerTab[wTimerHandle].m_ulEventId );
        a_stTimerTab[wTimerHandle].m_ulEventId = 0;
        a_stTimerTab[wTimerHandle].m_p_fn_vEventCallback = NULL;
    }
 
    wTimerCount--;
 
    return (0);
}
 
 
/*
  This function fills the p_ulFrequency with the frequency of the
  specified timer type.
*/
short __stdcall TMR_fn_wGetTimerFrequency( short wTimerHandle , u_long *p_ulFrequency )
{
    short wTimerType;
 
    if ( TimerLibOk == 0 )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrLibraryNotInitialized, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    if ( a_stTimerTab[wTimerHandle].m_wTimerState == C_wTimerUnused )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrInvalidHandle, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    if ( a_stTimerTab[wTimerHandle].m_wTimerState == C_wTimerUnused )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrInvalidHandle, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
 
    wTimerType = a_stTimerTab[wTimerHandle].m_wTimerType;
    if ( wTimerType <= C_wTimerFrequencyHigh )
        *p_ulFrequency = a3_ulTimerFrequency[wTimerType];
    else
        *p_ulFrequency = a3_ulEventFrequency[wTimerType - C_wTimerEvent];
    return (0);
}
 
 
/*
  This function wait  The time unit is system dependant but should be
  1000 ticks per second.
*/
short __stdcall TMR_fn_wWait( u_long ulTimeToWait )
{
 
    if ( TimerLibOk == 0 )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrLibraryNotInitialized, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    fn_vTimerWait(ulTimeToWait);
 
    return (0);
}
 
 
/*
  Return the number of ticks pre second for the fn_wTimerDelay function
*/
short __stdcall TMR_fn_wGetWaitTickPerSecond(u_long *p_ulDelayFrequency)
{
    if ( TimerLibOk == 0 )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrLibraryNotInitialized, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    *p_ulDelayFrequency = fn_ulTimerWaitTicksPerSecond();
    return (0);
}
 
 
/*
  This function create a callback timer. Parameters are the timer ncy,
  a pointer to the callback function (returning void) and the timer type.
  ulPeriod defines the interval between two call of the callback function.
  The C_wTimerFrequencyLow is the only timer type available for event timer.
*/
short __stdcall TMR_fn_wCreateEvent(
                                 u_long ulPeriod ,
                                 td_p_fn_vTimerEventCallback p_fn_vEventCallback ,
                                 short wTimerType ,
                                 u_long ulTimerEventType
                                ) 
{
    short  wCreateEventResult;
    u_long ulEventId;
    int    i;
 
    if ( TimerLibOk == 0 )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrLibraryNotInitialized, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    if ( wTimerType > C_wTimerFrequencyLow )
    {
        Erm_M_UpdateLastError(Tmr, C_ucErmDefaultChannel, E_uwTmrTypeNotAvailable, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    for ( i = 0 ; i < C_uwTimerMaxCount ; i++ )
        if ( (a_stTimerTab[i].m_wTimerState == C_wTimerUnused) || (i>=C_uwTimerMaxCount) ) break;
    if ( i == C_uwTimerMaxCount )
    {
        Erm_M_UpdateLastError(Tmr, C_ucErmDefaultChannel, E_uwTmrMaxTimerCountReached, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
 
    a_stTimerTab[i].m_wTimerType = wTimerType + C_wTimerEvent;
    a_stTimerTab[i].m_wTimerState = C_wTimerReady;
 
    wCreateEventResult = fn_wTimerNewEvent(
                                           ulPeriod,
                                           a3_ulEventFrequency[wTimerType],
                                           p_fn_vEventCallback,
                                           ulTimerEventType,
                                           &ulEventId
                                          );
    if ( wCreateEventResult == C_wTimerError )
    {
        a_stTimerTab[i].m_wTimerState = C_wTimerUnused;
        Erm_M_UpdateLastError(Tmr, C_ucErmDefaultChannel, E_uwTmrCreateEventFailed, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
    a_stTimerTab[i].m_ulEventId = ulEventId;
    a_stTimerTab[i].m_p_fn_vEventCallback = p_fn_vEventCallback;
 
    wTimerCount++;
 
    return (i);
}
 
 
/*
  This function return vertical refresh rate in Hz * 100.
*/
u_long __stdcall TMR_fn_ulMonitorFrequency( void )
{
    u_long ulFrequency;
 
    if ( TimerLibOk == 0 )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrLibraryNotInitialized, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
 
    ulFrequency = fn_ulTimerVerticalRefreshRate(a3_ulTimerFrequency[C_wTimerFrequencyHigh]);
 
    return (ulFrequency);
}
 
/*
  This function return the length of a frame. The units length is the tick
  of a C_wTimerFrequencyHigh timer type (so the return value is the number CPU cycle)
*/
u_long __stdcall TMR_fn_ulFrameCycleNumber( void )
{
    u_long ulFrequency;
 
    if ( TimerLibOk == 0 )
    {
        Erm_M_UpdateLastError (Tmr, C_ucErmDefaultChannel, E_uwTmrLibraryNotInitialized, C_lErmNoDebugData, C_ucErmOpenInfoWindow, C_ucAllowStopForDebug, NULL);
        return (C_wTimerError);
    }
 
    ulFrequency = fn_ulTimerFrameLength();
    
    return (ulFrequency);
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
