/************************************************************************/
/* Copyright 1993 - 1997 MBARI                                          */
/************************************************************************/
/* $Header: microtime.c,v 1.2 91/09/23 09:38:59 hebo Exp $              */
/* Summary  : Clock adjustment functions for MVME-162 CPU under vxWorks */
/* Filename : sysMicroClock.c                                           */
/* Author   : Bob Herlien (rah)                                         */
/* Project  : Tiburon ROV                                               */
/* $Revision: 1.2 $                                                     */
/* Created  : 02/28/91                                                  */
/************************************************************************/
/* Modification History:                                                */
/* $Log$
*/
/* 23nov93 rah, created for MVME-162                                    */
/************************************************************************/

#include <mbariTypes.h>                 /* MBARI standard types             */
#include <vxWorks.h>                    /* VxWorks includes                 */
#include <mv162.h>                      /* Hardware defns for MVME-162      */
#include <drv/multi/mcchip.h>           /* MCC chip definitions             */
#include <intLib.h>                     /* for intLock/intUnlock            */

#define DELTA   1000


/********************************/
/*      Module Local Data       */
/********************************/

MLocal Nat32    currentTick;            /* Current clock tick interval    */


/************************************************************************/
/* Function    : sysMicroClockInit                                      */
/* Purpose     : Init function for sysMicroClock                        */
/* Input       : Period of clock tick in microseconds                   */
/* Outputs     : None                                                   */
/************************************************************************/
        Void
sysMicroClockInit( Nat32 tickTime )
{
    currentTick = tickTime;

} /* sysMicroClockInit() */


/************************************************************************/
/* Function    : sysMicroClockAdj                                       */
/* Purpose     : Adjust the clock frequency of system ticker            */
/* Input       : Period of clock in microseconds                        */
/* Outputs     : None                                                   */
/* Comments    : Needed in support of adjtime(), which is in support    */
/*               of NTP.  For NTP, clock adjustments are small differences*/
/*               from the normal system clock rate.  In our case (MV-162),*/
/*               normal rate is 16.67 ms, and the adjustments are       */
/*               +/- 8 microseconds from that.                          */
/************************************************************************/
        Void
sysMicroClockAdj( Nat32 tickTime )
{
    Reg int     key;

    key = intLock();

    *MCC_TIMER1_CMP = tickTime;         /*Set up new compare value      */

/* Note that this routine gets called from the clock tick interrupt.    */
/* Therefore the current timer count should be low.  The following is   */
/* a sanity check, to ensure we're not going to set a compare value     */
/* below the current count, which would result in no tick for 71        */
/* minutes.  It should never happen, barring extreme interrupt latency  */
/* (> 15.6 ms).  But if it does, the result of the following is to      */
/* lose a small amount of clock time, rather than 71 minutes.           */
/* This check is the reason for the intLock/intUnlock.                  */

    if ( *MCC_TIMER1_CNT > (tickTime - DELTA) )
        *MCC_TIMER1_CNT = tickTime - DELTA;

    intUnlock(key);

    currentTick = tickTime;

} /* sysMicroClockAdj() */


/************************************************************************/
/* Function    : sysMicroClockGet                                       */
/* Purpose     : Return microseconds since last clock tick              */
/* Input       : None                                                   */
/* Outputs     : Microseconds since last clock tick                     */
/************************************************************************/
        Nat32
sysMicroClockGet( Void )
{
    Reg Nat32   cnt;

/* No intLock() needed, because the following is a single transfer      */

    cnt = *MCC_TIMER1_CNT;

    if ( cnt > currentTick )
        return( 0 );

    return( cnt );

} /* sysMicroClockGet() */


/************************************************************************/
/* Function    : sysMicroClockSet                                       */
/* Purpose     : Set the microtime counter                              */
/* Input       : Microseconds since last tick to set                    */
/* Outputs     : None                                                   */
/************************************************************************/
        Void
sysMicroClockSet( Nat32 microTime )
{
    Reg int     key;

    key = intLock();

    if ( microTime < (currentTick - DELTA) )
        *MCC_TIMER1_CNT = microTime;

    intUnlock(key);

} /* sysMicroClockSet() */
