//###########################################################################
// FILE:   cpu_usage.c
// TITLE:  Routines to determine the CPU utilization.
//###########################################################################
// $TI Release: F28M35x Support Library v201 $
// $Release Date: Fri Jun  7 10:51:13 CDT 2013 $
//###########################################################################

#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/sysctl.h"
#include "driverlib/timer.h"
#include "utils/cpu_usage.h"

//*****************************************************************************
//! \addtogroup cpu_usage_api
//! @{
//*****************************************************************************

//*****************************************************************************
// The peripheral identifier for the timer modules that could be used for
// tracking CPU utilization.
//*****************************************************************************
static unsigned long g_pulCPUUsageTimerPeriph[4] =
{
    SYSCTL_PERIPH_TIMER0, SYSCTL_PERIPH_TIMER1, SYSCTL_PERIPH_TIMER2,
    SYSCTL_PERIPH_TIMER3
};

//*****************************************************************************
// The base address of the timer modules that could be used for tracking CPU
// utilization.
//*****************************************************************************
static unsigned long g_pulCPUUsageTimerBase[4] =
{
    TIMER0_BASE, TIMER1_BASE, TIMER2_BASE, TIMER3_BASE
};

//*****************************************************************************
// The index of the timer module that will be used for tracking CPU
// utilization.
//*****************************************************************************
static unsigned long g_ulCPUUsageTimer;

//*****************************************************************************
// The number of processor clock ticks per timing period.
//*****************************************************************************
static unsigned long g_ulCPUUsageTicks;

//*****************************************************************************
// The value of timer two on the previous timing period.  This is used to
// determine the number of clock ticks counted by the timer during the timing
// period.
//*****************************************************************************
static unsigned long g_ulCPUUsagePrevious;

//*****************************************************************************
//! Updates the CPU usage for the new timing period.
//!
//! This function, when called at the end of a timing period, will update the
//! CPU usage.
//!
//! \return Returns the CPU usage percentage as a 16.16 fixed-point value.
//*****************************************************************************
unsigned long
CPUUsageTick(void)
{
    unsigned long ulValue, ulUsage;

    // Get the current value of the timer.
    ulValue = TimerValueGet(g_pulCPUUsageTimerBase[g_ulCPUUsageTimer],
                            TIMER_A);

    // Based on the number of clock ticks accumulated by the timer during the
    // previous timing period, compute the CPU usage as a 16.16 fixed-point
    // value.
    ulUsage = ((((g_ulCPUUsagePrevious - ulValue) * 6400) /
                g_ulCPUUsageTicks) * 1024);

    // Save the previous value of the timer.
    g_ulCPUUsagePrevious = ulValue;

    // Return the new CPU usage value.
    return(ulUsage);
}

//*****************************************************************************
//! Initializes the CPU usage measurement module.
//!
//! \param ulClockRate is the rate of the clock supplied to the timer module.
//! \param ulRate is the number of times per second that CPUUsageTick() is
//! called.
//! \param ulTimer is the index of the timer module to use.
//!
//! This function prepares the CPU usage measurement module for measuring the
//! CPU usage of the application.
//!
//! \return None.
//*****************************************************************************
void
CPUUsageInit(unsigned long ulClockRate, unsigned long ulRate,
             unsigned long ulTimer)
{
    // Check the arguments.
    ASSERT(ulClockRate > ulRate);
    ASSERT(ulTimer < 4);

    // Save the timer index.
    g_ulCPUUsageTimer = ulTimer;

    // Determine the number of system clocks per measurement period.
    g_ulCPUUsageTicks = ulClockRate / ulRate;

    // Set the previous value of the timer to the initial timer value.
    g_ulCPUUsagePrevious = 0xffffffff;

    // Enable peripheral clock gating.
    SysCtlPeripheralClockGating(true);

    // Enable the third timer while the processor is in run mode, but disable
    // it in sleep mode.  It will therefore count system clocks when the
    // processor is running but not when it is sleeping.
    SysCtlPeripheralEnable(g_pulCPUUsageTimerPeriph[ulTimer]);
    SysCtlPeripheralSleepDisable(g_pulCPUUsageTimerPeriph[ulTimer]);

    // Configure the third timer for 32-bit periodic operation.
    TimerConfigure(g_pulCPUUsageTimerBase[ulTimer], TIMER_CFG_32_BIT_PER);

    // Set the load value for the third timer to the maximum value.
    TimerLoadSet(g_pulCPUUsageTimerBase[ulTimer], TIMER_A, 0xffffffff);

    // Enable the third timer.  It will now count the number of system clocks
    // during which the processor is executing code.
    TimerEnable(g_pulCPUUsageTimerBase[ulTimer], TIMER_A);
}

//*****************************************************************************
// Close the Doxygen group.
//! @}
//*****************************************************************************


