// ****************************************************************************
// INCLUDE FILES: Header files of modules referenced by this module
// ****************************************************************************
#include <StopWatch.h>
#include <asf.h>
#include <string.h>


// ****************************************************************************
// PRIVATE TYPES: Private types used by this module only
// ****************************************************************************


// ****************************************************************************
// PRIVATE MACROS: Private #define directives used by this module only
// ****************************************************************************


// ****************************************************************************
// PRIVATE VARIABLES: Variables used by this module only (static)
// ****************************************************************************
#ifdef STOP_WATCH_ENABLED

static uint32_t swStartList[SW_ID_NUM];
static uint32_t swElapsedList[SW_ID_NUM];
static uint32_t swElapsedListMax[SW_ID_NUM];
static uint32_t swElapsedListMin[SW_ID_NUM];

#endif // STOP_WATCH_ENABLED

// ****************************************************************************
// PRIVATE FUNCTIONS PROTOTYPES: Functions used by this module only (static)
// ****************************************************************************


// ****************************************************************************
// PUBLIC VARIABLES: Public variables shared with other modules
// ****************************************************************************


// ****************************************************************************
// PRIVATE FUNCTIONS: Private functions used by this module only
// ****************************************************************************


// ****************************************************************************
// PUBLIC FUNCTIONS: Public functions shared with other modules
// ****************************************************************************
#ifdef STOP_WATCH_ENABLED

void SWInit(void)
{
    // TC common parameters
    pmc_enable_periph_clk(ID_TC1);
    tc_init(TC0, 1, TC_CMR_TCCLKS_TIMER_CLOCK4 | TC_CMR_WAVE);
    tc_start(TC0, 1);

    // Clear statistics
    memset( swElapsedListMin, 0xFF, sizeof(swElapsedListMin) );
    memset( swElapsedList, 0x00, sizeof(swElapsedList) );
    memset( swElapsedListMax, 0x00, sizeof(swElapsedListMax) );
}

void SWStart( StopWatchId_t stopWatchId )
{
    swStartList[stopWatchId] = tc_read_cv(TC0, 1); 
}

uint32_t SWElapsedTimeUs( StopWatchId_t stopWatchId)
{
    uint32_t currentTime = tc_read_cv(TC0, 1);
    uint32_t elapsedTime;
    
    // Elapse time is not exactly in microseconds, however in order to
    // avoid float multiplication correction is not applied
    
    if( currentTime < swStartList[stopWatchId] )
    {
        elapsedTime = (0xffff) - swStartList[stopWatchId] + currentTime;
    }
    else
    {
        elapsedTime = currentTime - swStartList[stopWatchId];  
    }

    swElapsedList[stopWatchId] = elapsedTime;
    
    if( elapsedTime > swElapsedListMax[stopWatchId] )
    {
        swElapsedListMax[stopWatchId] = elapsedTime;
    }
    
    if( elapsedTime < swElapsedListMin[stopWatchId] )
    {
        swElapsedListMin[stopWatchId] = elapsedTime;
    }

    return elapsedTime;
}

#endif // STOP_WATCH_ENABLED