64 bit Timer Class.

Timer64.cpp

Committer:
tedoyle
Date:
2016-03-26
Revision:
0:1e0e79e82839
Child:
1:497fba179833

File content as of revision 0:1e0e79e82839:

 /*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
#include "Timer64.h"
#include "ticker_api.h"
#include "us_ticker_api.h"

Timer64::Timer64() :
    _timerInitialized(false),
    _timerRunning(false), 
    _tickerStartTimeUsec(0L), 
    _totalTimeUsec(0L), 
    _ticker_data(get_us_ticker_data()),
    _rollOverCheckTimer(NULL),
    _rollOverCheckTimerPeriodInMsec(TIMER64_15MINUTE_ROLLOVER_CHECK_IN_MSECS)
{
    reset();
}

Timer64::Timer64(const ticker_data_t *data) : 
    _timerInitialized(false),
    _timerRunning(false), 
    _tickerStartTimeUsec(0L), 
    _totalTimeUsec(0L), 
    _ticker_data(data),
    _rollOverCheckTimer(NULL),
    _rollOverCheckTimerPeriodInMsec(TIMER64_15MINUTE_ROLLOVER_CHECK_IN_MSECS)
{
    reset();
}

int Timer64::init(uint32_t rolloverCheckTimeInMsec)
{
    if (_timerInitialized)
    {
        return(TIMER64_WARNING_ALREADY_INITIALIZED);
    }
    
    if (rolloverCheckTimeInMsec < TIMER64_MIN_ROLLOVER_CHECK_IN_MSECS)
    {
        rolloverCheckTimeInMsec = TIMER64_MIN_ROLLOVER_CHECK_IN_MSECS;
    }
    else if (rolloverCheckTimeInMsec > TIMER64_MAX_ROLLOVER_CHECK_IN_MSECS)
    {
        rolloverCheckTimeInMsec = TIMER64_MAX_ROLLOVER_CHECK_IN_MSECS;
    }

    _timerRunning = false; 
    _tickerStartTimeUsec = 0L; 
    _totalTimeUsec = 0L; 
    _rollOverCheckTimerPeriodInMsec = rolloverCheckTimeInMsec;
    _rollOverCheckTimer = new RtosTimer(_rollOverCheck, osTimerPeriodic, this);
    _timerInitialized = true;
    
    return(TIMER64_OK);
}

int Timer64::release(void)
{
    if (!_timerInitialized)
    {
        return(TIMER64_ERROR_NOT_INITIALIZED);
    }
    
    if (_timerRunning)
    {
        stop();
    }
    
    _tickerStartTimeUsec = 0L; 
    _totalTimeUsec = 0L; 
    _timerInitialized = false;
    _rollOverCheckTimer->stop();
    delete _rollOverCheckTimer;
    _rollOverCheckTimer = NULL;
    
    return(TIMER64_OK);
}
int Timer64::start(void)
{
    if (!_timerInitialized)
    {
        return(TIMER64_ERROR_NOT_INITIALIZED);
    }
    
    if (!_timerRunning)
    {
        _tickerStartTimeUsec = ticker_read(_ticker_data);
        _timerRunning = true;
        _rollOverCheckTimer->start(_rollOverCheckTimerPeriodInMsec);
    }
    else
    {
        return(TIMER64_WARNING_ALREADY_RUNNING);
    }
    
    return(TIMER64_OK);
}

int Timer64::stop(void)
{
    if (!_timerInitialized)
    {
        return(TIMER64_ERROR_NOT_INITIALIZED);
    }
    
    if (_timerRunning)
    {
        _timerRunning = false;
        _rollOverCheckTimer->stop();
    }
    else
    {
        return(TIMER64_WARNING_ALREADY_STOPPED);
    }
    
    return(TIMER64_OK);
}

int Timer64::reset(void)
{
    if (!_timerInitialized)
    {
        return(TIMER64_ERROR_NOT_INITIALIZED);
    }
    
    if (_timerRunning)
    {
        _tickerStartTimeUsec = ticker_read(_ticker_data);
        _rollOverCheckTimer->start(_rollOverCheckTimerPeriodInMsec);
    }
    
    _totalTimeUsec = 0L;
    return(TIMER64_OK);
}

uint64_t Timer64::read_us(int* status)
{
    if (!_timerInitialized)
    {
        if (status)
        {
            *status = TIMER64_ERROR_NOT_INITIALIZED;
        }
        
        return(0L);
    }
    
    if (_timerRunning)
    {
        timestamp_t ticker_current_timeUsec = ticker_read(_ticker_data);
        
        // check for ticker time rollover
        
        if (ticker_current_timeUsec >= _tickerStartTimeUsec)
        {
            _totalTimeUsec += (uint64_t)(ticker_current_timeUsec - _tickerStartTimeUsec);
        }
        else
        {
            // rollover!
            _totalTimeUsec += (4294967296L - ((uint64_t)_tickerStartTimeUsec)) + (uint64_t)ticker_current_timeUsec;
            
        }
        
        _tickerStartTimeUsec = ticker_current_timeUsec;
    }    

    return(_totalTimeUsec);
}

uint64_t Timer64::read_ms(int* status)
{
    return(read_us(status) / 1000L);
}

double Timer64::read(int* status)
{
    return((double)read_us(status) / 1000000.0L);
}

#ifdef MBED_OPERATORS
Timer64::operator double()
{
    return read();
}

Timer64::operator uint64_t()
{
    return read_us();
}

Timer64::operator uint32_t()
{
    return read_us();
}
#endif

void Timer64::_rollOverCheck(void const* args)
{
    Timer64* timer = (Timer64*)args;
    timer->read_us();
    return;
}