// $Id: linux_pfc.c,v 1.2 2011/07/08 21:50:30 lpoulsen Exp $
//
// Copyright (c) 2011 by Afar Communications Inc, Santa Barbara, CA 93117 USA
//
// Utility functions for low-overhead high precision short interval timers.
// A Linux re-implementation to be a drop-in replacement for afar_pcf.c
//
// $Log: linux_pfc.c,v $
// Revision 1.2  2011/07/08 21:50:30  lpoulsen
// Eliminate (almost all) use of debug_level, use debug_flags instead.
//
// Revision 1.1  2011/02/08 22:05:45  lpoulsen
// Short term timer.
//
//

#include <stdio.h>
#include <sys/time.h>  // defines struct timeval
#include <errno.h>
#include <stdlib.h>    // defines exit()
#include "afartype.h"

int     afar_pfc_freq = 0;
// Example values: 25,000,000 on my AMD64 desktop PC
//                  1,19?,??? on an old Windows 98 on Scott's bench
time_t  afar_pfc_base_sec;

void
afar_pfc_setup(void)
{
    struct timeval tv;
    int            nogood;

    afar_pfc_freq = 1000*1000;
    nogood = gettimeofday(&tv, NULL);
    if (nogood) {
        printf("afar_pfc_setup failed - errno = %d\n", errno);
        exit(EXIT_FAILURE);
    }
    afar_pfc_base_sec = tv.tv_sec;
}

uint32
afar_pfc_read(void)
{
    int            nogood;
    struct timeval tv;
    int            delta_seconds;
    uint32         usec_timer;

    nogood = gettimeofday(&tv, NULL);

    if (nogood)
    {
        printf("afar_pfc_read failed - errno = %d\n", errno);
        exit(EXIT_FAILURE);
    }
    delta_seconds = tv.tv_sec - afar_pfc_base_sec;
    usec_timer = (1000000*delta_seconds) + tv.tv_usec;
    return usec_timer;
}

uint32
afar_usec_delta(uint32 start, uint32 end)
{
    int32   delta = (end - start);
    double  MHz = afar_pfc_freq / 1000000.0;
    int     microsec = delta/MHz + 0.5;

    return  microsec;
}
