Tom Doyle / Timer64
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Timer64.cpp Source File

Timer64.cpp

00001  /*
00002  * Licensed under the Apache License, Version 2.0 (the "License");
00003  * you may not use this file except in compliance with the License.
00004  * You may obtain a copy of the License at
00005  *
00006  *     http://www.apache.org/licenses/LICENSE-2.0
00007  *
00008  * Unless required by applicable law or agreed to in writing, software
00009  * distributed under the License is distributed on an "AS IS" BASIS,
00010  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00011  * See the License for the specific language governing permissions and
00012  * limitations under the License.
00013  */
00014  
00015 #include "Timer64.h"
00016 #include "ticker_api.h"
00017 #include "us_ticker_api.h"
00018 
00019 Timer64::Timer64() :
00020     _timerInitialized(false),
00021     _timerRunning(false), 
00022     _tickerStartTimeUsec(0u), 
00023     _totalTimeUsec(0llu), 
00024     _ticker_data(get_us_ticker_data()),
00025     _rollOverCheckTimer(NULL),
00026     _rollOverCheckTimerPeriodInMsec(TIMER64_DEFAULT_ROLLOVER_CHECK_IN_MSECS),
00027     _sem(NULL)
00028 {
00029     ;
00030 }
00031 
00032 Timer64::~Timer64()
00033 {
00034     release();
00035 }
00036 
00037 int Timer64::init(uint32_t rolloverCheckTimeInMsec)
00038 {
00039     if (_timerInitialized)
00040     {
00041         return(TIMER64_WARNING_ALREADY_INITIALIZED);
00042     }
00043     
00044     if (rolloverCheckTimeInMsec < TIMER64_MIN_ROLLOVER_CHECK_IN_MSECS)
00045     {
00046         rolloverCheckTimeInMsec = TIMER64_MIN_ROLLOVER_CHECK_IN_MSECS;
00047     }
00048     else if (rolloverCheckTimeInMsec > TIMER64_MAX_ROLLOVER_CHECK_IN_MSECS)
00049     {
00050         rolloverCheckTimeInMsec = TIMER64_MAX_ROLLOVER_CHECK_IN_MSECS;
00051     }
00052 
00053     _timerRunning = false; 
00054     _tickerStartTimeUsec = 0u; 
00055     _totalTimeUsec = 0llu; 
00056     _rollOverCheckTimerPeriodInMsec = rolloverCheckTimeInMsec;
00057     _rollOverCheckTimer = new RtosTimer(_rollOverCheck, osTimerPeriodic, this);
00058     _sem = new Semaphore(1);
00059     _timerInitialized = true;
00060     
00061     return(TIMER64_OK);
00062 }
00063 
00064 int Timer64::release(void)
00065 {
00066     if (!_timerInitialized)
00067     {
00068         return(TIMER64_WARNING_ALREADY_RELEASED);
00069     }
00070     
00071     if (_timerRunning)
00072     {
00073         stop();
00074     }
00075     
00076     _tickerStartTimeUsec = 0u; 
00077     _totalTimeUsec = 0llu; 
00078     _timerInitialized = false;
00079     _rollOverCheckTimer->stop();
00080     delete _rollOverCheckTimer;
00081     _rollOverCheckTimer = NULL;
00082     delete _sem;
00083     _sem = NULL;
00084     
00085     return(TIMER64_OK);
00086 }
00087 
00088 int Timer64::start(void)
00089 {
00090     int status = TIMER64_OK;
00091 
00092     _sem->wait();
00093     {
00094         if (!_timerInitialized)
00095         {
00096             status = TIMER64_ERROR_NOT_INITIALIZED;
00097         }
00098         else if (_timerRunning)
00099         {
00100             status = TIMER64_WARNING_ALREADY_RUNNING;
00101         }
00102         else
00103         {
00104             _tickerStartTimeUsec = ticker_read(_ticker_data);
00105             _timerRunning = true;
00106             _rollOverCheckTimer->start(_rollOverCheckTimerPeriodInMsec);
00107         }
00108     }
00109     _sem->release();
00110     
00111     return(status);
00112 }
00113 
00114 int Timer64::stop(void)
00115 {
00116     int status = TIMER64_OK;
00117 
00118     _sem->wait();
00119     {
00120         if (!_timerInitialized)
00121         {
00122             status = TIMER64_ERROR_NOT_INITIALIZED;
00123         }
00124         else if (!_timerRunning)
00125         {
00126             status = TIMER64_WARNING_ALREADY_STOPPED;
00127         }
00128         else
00129         {
00130             _read_us(this);
00131             _timerRunning = false;
00132             _rollOverCheckTimer->stop();
00133         }
00134     }
00135     _sem->release();
00136     
00137     return(status);
00138 }
00139 
00140 int Timer64::reset(void)
00141 {
00142     int status = TIMER64_OK;
00143 
00144     _sem->wait();
00145     {
00146         if (!_timerInitialized)
00147         {
00148             status = TIMER64_ERROR_NOT_INITIALIZED;
00149         }
00150         else
00151         {
00152             if (_timerRunning)
00153             {
00154                 _tickerStartTimeUsec = ticker_read(_ticker_data);
00155                 _rollOverCheckTimer->start(_rollOverCheckTimerPeriodInMsec);
00156             }
00157             
00158             _totalTimeUsec = 0llu;
00159         }
00160     }
00161     _sem->release();
00162     
00163     return(status);
00164 }
00165 
00166 int Timer64::read_us(uint64_t* timeInUsec)
00167 {
00168     int status = TIMER64_OK;
00169 
00170     _sem->wait();
00171     {
00172         if (!_timerInitialized)
00173         {
00174             status = TIMER64_ERROR_NOT_INITIALIZED;
00175         }
00176         else if (timeInUsec == NULL)
00177         {
00178             status = TIMER64_ERROR_NULL_POINTER;
00179         }
00180         else
00181         {
00182             if (_timerRunning)
00183             {
00184                 *timeInUsec = _read_us(this);
00185             }
00186             else
00187             {
00188                 *timeInUsec = _totalTimeUsec;
00189             }
00190         }
00191     }
00192     _sem->release();
00193     
00194     return(status);
00195 }
00196 
00197 int Timer64::read_ms(uint64_t* timeInMsec)
00198 {
00199     int status = TIMER64_OK;
00200 
00201     _sem->wait();
00202     {
00203         if (!_timerInitialized)
00204         {
00205             status = TIMER64_ERROR_NOT_INITIALIZED;
00206         }
00207         else if (timeInMsec == NULL)
00208         {
00209             status = TIMER64_ERROR_NULL_POINTER;
00210         }
00211         else
00212         {
00213             if (_timerRunning)
00214             {
00215                 *timeInMsec = _read_us(this)/1000LU;
00216             }
00217             else
00218             {
00219                 *timeInMsec = _totalTimeUsec/1000LU;
00220             }
00221         }
00222     }
00223     _sem->release();
00224     
00225     return(status);
00226 }
00227 
00228 int Timer64::read(double* timeInSec)
00229 {
00230     int status = TIMER64_OK;
00231 
00232     _sem->wait();
00233     {
00234         if (!_timerInitialized)
00235         {
00236             status = TIMER64_ERROR_NOT_INITIALIZED;
00237         }
00238         else if (timeInSec == NULL)
00239         {
00240             status = TIMER64_ERROR_NULL_POINTER;
00241         }
00242         else
00243         {
00244             if (_timerRunning)
00245             {
00246                 *timeInSec = (double)_read_us(this)/1000000.0L;
00247             }
00248             else
00249             {
00250                 *timeInSec = (double)_totalTimeUsec/1000000.0L;
00251             }
00252         }
00253     }
00254     _sem->release();
00255     
00256     return(status);
00257 }
00258 
00259 int Timer64::isRunning(bool* running)
00260 {
00261     int status = TIMER64_OK;
00262 
00263     _sem->wait();
00264     {
00265         if (!_timerInitialized)
00266         {
00267             status = TIMER64_ERROR_NOT_INITIALIZED;
00268         }
00269         else
00270         {
00271             *running = _timerRunning;
00272         }
00273     }
00274     _sem->release();
00275     
00276     return(status);
00277 }
00278 
00279 void Timer64::_rollOverCheck(void const* args)
00280 {
00281     Timer64* timer = (Timer64*)args;
00282     timer->_read_us(timer);
00283     return;
00284 }
00285 
00286 uint64_t Timer64::_read_us(void const* args)
00287 {
00288     Timer64* timer = (Timer64*)args;
00289     timestamp_t ticker_current_timeUsec = ticker_read(timer->_ticker_data);
00290     
00291     // check for ticker time rollover
00292     
00293     if (ticker_current_timeUsec >= timer->_tickerStartTimeUsec)
00294     {
00295         timer->_totalTimeUsec += (uint64_t)(ticker_current_timeUsec - timer->_tickerStartTimeUsec);
00296     }
00297     else
00298     {
00299         // rollover!
00300         timer->_totalTimeUsec += (uint64_t)(4294967296U - timer->_tickerStartTimeUsec) + (uint64_t)ticker_current_timeUsec;
00301         
00302     }
00303     
00304     timer->_rollOverCheckTimer->start(timer->_rollOverCheckTimerPeriodInMsec);
00305     timer->_tickerStartTimeUsec = ticker_current_timeUsec;
00306     return(timer->_totalTimeUsec);
00307 }
00308