///////////////////////////////////////////////////////////////////////////////
#include <vxworks.h>
#include <taskLib.h>
#include <limits.h>
#include <stdio.h>
#include <ticklib.h>
#include <semLib.h>
#include <tasklib.h>


#define ZERO_LOAD_IDLE_COUNTER 377993 /* Measured with 0 load on TFE CPU */
unsigned int maxIdleCount;

unsigned int innerIDLE;
unsigned int middleIDLE;
unsigned int outerIDLE;

unsigned int lastInnerIDLE;
unsigned int lastMiddleIDLE;
unsigned int lastOuterIDLE;

SEM_ID CPUIdleSemId;

int glblCPUIdleDebug=0;

extern "C" void CPUIdleTime(void)
{
    while (1)
    {
        while (innerIDLE <= UINT_MAX)
        {
            taskLock();
            innerIDLE++;
            taskUnlock();
        }
    }
}

//
//
// function clearIdleCounters(void)
//          resets the idle counters
//          to zero.
//
extern "C" void clearIdleCounters(void)
{
 STATUS status = semTake( CPUIdleSemId, sysClkRateGet() );

 lastInnerIDLE=innerIDLE;
 innerIDLE=0;
 lastMiddleIDLE=middleIDLE;
 middleIDLE=0;
 lastOuterIDLE=outerIDLE;
 outerIDLE=0;

 status = semGive( CPUIdleSemId );
}

//
//
// function displayIdleCounters(void)
//          prints out the current idle counters
//
extern "C" void displayIdleCounters(void)
{
    if (glblCPUIdleDebug==1)
        printf("The counters are: %d inner, %d middle, %d outer \n\n",innerIDLE, middleIDLE,outerIDLE);
}

//
//
// function displayIdleCounters(void)
//          prints out the current idle counters
//

extern "C" void measureCPUIdleTime(void)
{
    while (1)
    {
        clearIdleCounters();
        taskDelay(sysClkRateGet());
    }
}

//
//
// function startCPUIdleMonitor(void)
//
//

extern "C" void startCPUIdleMonitor(void)
{
    int tid;

    clearIdleCounters();

    maxIdleCount=ZERO_LOAD_IDLE_COUNTER;

    CPUIdleSemId = semBCreate( SEM_Q_PRIORITY, SEM_FULL );

    if ((tid = taskSpawn ("tMonCPUIdle", 255, 0, 10000, (FUNCPTR)CPUIdleTime,
            0,0,0,0,0,0,0,0,0,0)) == ERROR)
    {
        printf("Task creation error CPU IDLE Monitor Task 0x%x", errno);
    }

    if ((tid = taskSpawn ("tCPUIdlCapt", 1, 0, 10000, (FUNCPTR)measureCPUIdleTime,
            0,0,0,0,0,0,0,0,0,0)) == ERROR)
    {
        printf("Task creation error measure CPU Idle Time Task 0x%x", errno);
    }
    taskDelay(sysClkRateGet()+10);
    maxIdleCount=lastInnerIDLE;

    taskDelay(sysClkRateGet()+10);
    if (lastInnerIDLE > maxIdleCount)
        maxIdleCount=lastInnerIDLE;

    taskDelay(sysClkRateGet()+10);
    if (lastInnerIDLE > maxIdleCount)
        maxIdleCount=lastInnerIDLE;

    taskDelay(sysClkRateGet()+10);
    if (lastInnerIDLE > maxIdleCount)
        maxIdleCount=lastInnerIDLE;
}

extern "C" float getCPUIdlefloat(void)
{
    float idlePercent=0;

    STATUS status = semTake( CPUIdleSemId, sysClkRateGet() );
    idlePercent = (float)( ((float)lastInnerIDLE / (float)maxIdleCount)*(float)100);
    status = semGive( CPUIdleSemId );

    if (idlePercent > 100.0)
    {
        maxIdleCount +=1;
        idlePercent=100.0;
    }

    printf("The current CPU IDLE is %5.1f%\n",idlePercent);
    return (idlePercent);
}

//
// getCPUIdleInt(void) returns CPU Idle Percent in tenths of a percent
//                     e.g 50% returns 500
//
extern "C" int getCPUIdleInt(void)
{

    int idlePercent=0;

    STATUS status = semTake( CPUIdleSemId, sysClkRateGet() );
    idlePercent = ((lastInnerIDLE *1000) / maxIdleCount);
    status = semGive( CPUIdleSemId );

    if (idlePercent > 1000)
    {
        maxIdleCount +=1;
        idlePercent=1000;

    }

    printf("The current CPU IDLE is %d\n",idlePercent/10);
    return (idlePercent);
}
//


