TimeStampCounter.cpp

Go to the documentation of this file.
00001 // Copyright CERN 2012 - Developed in collaboration with GSI
00002 /*
00003  *  Piece of code adapted for the FESA Framework.
00004  *  Original version references:
00005  *
00006  *  Portable Agile C++ Classes (PACC)
00007  *  Copyright (C) 2004 by Marc Parizeau
00008  *  http://manitou.gel.ulaval.ca/~parizeau/PACC
00009  *
00010  *  This library is free software; you can redistribute it and/or
00011  *  modify it under the terms of the GNU Lesser General Public
00012  *  License as published by the Free Software Foundation; either
00013  *  version 2.1 of the License, or (at your option) any later version.
00014  *
00015  *  This library is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  *  Lesser General Public License for more details.
00019  *
00020  *  You should have received a copy of the GNU Lesser General Public
00021  *  License along with this library; if not, write to the Free Software
00022  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  *
00024  *  Contact:
00025  *  Laboratoire de Vision et Systemes Numeriques
00026  *  Departement de genie electrique et de genie informatique
00027  *  Universite Laval, Quebec, Canada, G1K 7P4
00028  *  http://vision.gel.ulaval.ca
00029  *
00030  */
00031 #include <iostream>
00032 #include <fesa-core/Diagnostic/TimeStampCounter.h>
00033 
00034 namespace fesa
00035 {
00036 
00037     double TsCounter::mPeriod = 0;
00038 
00039     void TsCounter::calibrateCountPeriod(uint32_t inDelay/*ms*/, uint32_t inTimes)
00040     {
00041 
00042         if (mHardware)
00043         {
00044 #if defined (__GNUG__) && (defined (__i386__) || defined (__PPC__))
00045             double lPeriod = 0;
00046             // calibrate by matching the time-stamps with the micro-seconds of gettimeofday
00047             for (uint32_t i = 0; i < inTimes; ++i)
00048             {
00049                 timeval lStartTime, lTime;
00050                 ::gettimeofday(&lStartTime, 0);
00051                 uint64_t lStartCount = getCount();
00052 
00053                 struct timespec theDelay, time_left_before_wakeup;
00054                 int32_t sec = inDelay / 1000; // number of seconds since delay is expressed in ms
00055                 int32_t nsec = 0;
00056                 if ((nsec = inDelay % 1000)) // check remainder
00057                     nsec *= (int32_t) 1E6; // convert remainder into ns
00058                 theDelay.tv_sec = sec;
00059                 theDelay.tv_nsec = nsec;
00060                 nanosleep(&theDelay, &time_left_before_wakeup);
00061                 ::gettimeofday(&lTime, 0);
00062                 uint64_t lCount = getCount() - lStartCount;
00063                 lTime.tv_sec -= lStartTime.tv_sec;
00064                 lTime.tv_usec -= lStartTime.tv_usec;
00065                 // dismiss the first run of the loop
00066                 if (i != 0)
00067                     lPeriod += (lTime.tv_sec + lTime.tv_usec * 0.000001) / lCount;
00068             }
00069             mPeriod = lPeriod / (inTimes - 1);
00070 #else
00071             // use the microseconds of gettimeofday
00072             mPeriod = 0.000001;
00073 #endif
00074         }
00075         else
00076         {
00077             // use the microseconds of gettimeofday
00078             mPeriod = 0.000001;
00079         }
00080     }
00081 
00082     uint64_t TsCounter::getCount(void) const
00083     {
00084         uint64_t lCount = 0;
00085 
00086         if (mHardware)
00087         {
00088 #if defined (__GNUG__) && defined (__i386__)
00089             __asm__ volatile("rdtsc" : "=A" (lCount));
00090 #else
00091 #if defined (__GNUG__) && defined (__PPC__)
00092             register uint32_t lLow;
00093             register uint32_t lHigh1;
00094             register uint32_t lHigh2;
00095             do
00096             {
00097                 // make sure that high bits have not changed
00098                 __asm__ volatile ( "mftbu %0" : "=r" (lHigh1) );
00099                 __asm__ volatile ( "mftb  %0" : "=r" (lLow) );
00100                 __asm__ volatile ( "mftbu %0" : "=r" (lHigh2) );
00101             }while(lHigh1 != lHigh2);
00102             // transfer to lCount
00103             uint32_t *lPtr = (uint32_t*) &lCount;
00104             *lPtr++ = lHigh1; *lPtr = lLow;
00105 #else
00106             timeval lCurrent;
00107             ::gettimeofday(&lCurrent, 0);
00108             lCount = (uint64_t)lCurrent.tv_sec*1000000 + lCurrent.tv_usec;
00109 #endif
00110 #endif
00111         }
00112         else
00113         {
00114             timeval lCurrent;
00115             ::gettimeofday(&lCurrent, 0);
00116             lCount = (uint64_t) lCurrent.tv_sec * 1000000 + lCurrent.tv_usec;
00117         }
00118 
00119         return lCount;
00120     }
00121 }

Generated on 18 Jan 2013 for Fesa by  doxygen 1.6.1