/**
 * \file  timerCounter.c
 *
 * \brief Sample application for timer.
 */

/*
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ 
*
*  Redistribution and use in source and binary forms, with or without 
*  modification, are permitted provided that the following conditions 
*  are met:
*
*    Redistributions of source code must retain the above copyright 
*    notice, this list of conditions and the following disclaimer.
*
*    Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the 
*    documentation and/or other materials provided with the   
*    distribution.
*
*    Neither the name of Texas Instruments Incorporated nor the names of
*    its contributors may be used to endorse or promote products derived
*    from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma CODE_SECTION(GetTimer64bits,".AltProg");
#pragma CODE_SECTION(Time_sec,".AltProg");
#pragma CODE_SECTION(MarkTimeX,".AltProg");
#pragma CODE_SECTION(MarkTimeValueX,".AltProg");
#pragma CODE_SECTION(MarkTimeFloatValueX,".AltProg");

#include "KMotionDef.h"
#include "uart.h"
#include "hw_uart.h"
#include "interrupt.h"
#include "soc_C6748.h"
#include "hw_syscfg0_C6748.h"
#include "timer.h"
#include "lcdkC6748.h"
#include "uartStdio.h"
#include "hw_types.h"
#include "timerCounter.h"
#include "string.h"

#ifndef _TMS320C6X
#include "cpu.h"
#endif

/******************************************************************************
**                      INTERNAL MACRO DEFINITIONS
*******************************************************************************/
#define STR_LEN                        (13)
#define TimePeriod (456000000U/2*1U)
//#define TMR_PERIOD_LSB32               (0x07FFFFFF)
#define TMR_PERIOD_LSB32               TimePeriod
#define TMR_PERIOD_MSB32               (0x0)

/******************************************************************************
**                      INTERNAL FUNCTION PROTOTYPES
*******************************************************************************/

static void TimerSetUp64Bit(void);
double Time_sec(void);
void OnTimer(void);

/******************************************************************************
**                      INTERNAL VARIABLE DEFINITIONS
*******************************************************************************/

/******************************************************************************
**                          FUNCTION DEFINITIONS
*******************************************************************************/
void  SetupTimer(void)
{
    /* Set up the Timer2 & 3 peripheral */
    TimerSetUp64Bit();

    /* Set up the AINTC to generate Timer2 interrupts */
    TimerIntrSetUp();

    /* Start the timer. Characters from cntArr will be sent from the ISR */
    TimerEnable(SOC_TMR_2_REGS, TMR_TIMER12, TMR_ENABLE_CONT);

    /* Start the free running timer */
    TimerEnable(SOC_TMR_3_REGS, TMR_TIMER12, TMR_ENABLE_CONT);
}



unsigned long long GetTimer64bits(void)
{
    return TIMERLL0;
}


double Time_sec(void)
{
    unsigned long long x=TIMERLL0;
    unsigned int lsw = x & 0xffffffff;
    unsigned int msw = x >> 32;

    double result = msw * 4294967296.0 + lsw;
    result *= (1.0/CLOCKFREQ);

    return result;
}


/*
** Setup the timers for 64 bit mode
*/
static void TimerSetUp64Bit(void)
{
    /* Configuration of Timer */
    TimerConfigure(SOC_TMR_2_REGS, TMR_CFG_64BIT_CLK_INT);

    /* Set the 64 bit timer period */
    TimerPeriodSet(SOC_TMR_2_REGS, TMR_TIMER12, (unsigned int)(CLOCKFREQ * TIMEBASE + 0.5) );
    TimerPeriodSet(SOC_TMR_2_REGS, TMR_TIMER34, 0);

    /* Configuration of Timer 3 */
    TimerConfigure(SOC_TMR_3_REGS, TMR_CFG_64BIT_CLK_INT);

    /* Set the 64 bit timer period - count forever*/
    TimerPeriodSet(SOC_TMR_3_REGS, TMR_TIMER12, 0xffffffff);
    TimerPeriodSet(SOC_TMR_3_REGS, TMR_TIMER34, 0xffffffff);
}

/*
** Set up the ARM Interrupt Controller for generating timer interrupt
*/
void TimerIntrSetUp(void)
{
    /* Map Timer interrupts to DSP maskable interrupt */
    IntEventMap(C674X_MASK_INT6, SYS_INT_T64P2_TINTALL);

    /* Enable DSP interrupt in DSPINTC */
    IntEnable(C674X_MASK_INT6);

    /* Enable DSP interrupts */
    IntGlobalEnable();

    /* Enable the timer interrupt */
    TimerIntEnable(SOC_TMR_2_REGS, TMR_INT_TMR12_NON_CAPT_MODE);
}




//#define DO_TIMING

//#ifdef DO_TIMING
double EventTimes[NEVENTS];
char *EventNames[NEVENTS];
int EventValue[NEVENTS];
int n_event=0;
int TimingOn=0;


void AddLog(char *s)
{
    UARTPuts(s,-1);
}

void LWIP_error(char *message, char * pcFilename, unsigned long ulLine)
{
    char str1[80];

    sprintf(str1,"%s File:%s  Line:%d\n",message, pcFilename,ulLine);
    AddLog(str1);
}

void FatalError(char *s)
{
    AddLog(s);
    AddLog("\n");
    MarkTimeC("Fatal Error");
    for (;;)//hang
    {
        if (UARTCharGetNB()=='P')
        {
            PrintTimes();
        }
    }
}

//#endif

void ClearTimes(void)
{
    n_event=0;
}
void MarkTimeX(char *s)
{
#ifdef DO_TIMING
    if (n_event >= NEVENTS) ClearTimes();

    EventTimes[n_event]=Time_sec();
    EventValue[n_event]=0;
    EventNames[n_event++]=s;
#endif
}

void MarkTimeValueX(char *s, int value)
{
#ifdef DO_TIMING
    if (n_event >= NEVENTS) ClearTimes();

    EventTimes[n_event]=Time_sec();
    EventValue[n_event]=value;
    EventNames[n_event++]=s;
#endif
}

void MarkTimeFloatValueX(char *s,float value)
{
#ifdef DO_TIMING
    if (n_event >= NEVENTS) ClearTimes();

    EventTimes[n_event]=Time_sec();
    EventValue[n_event]=0;
    EventNames[n_event++]=s;
#endif
}

#define MAXBEG 20

void PrintTimes(void)
{
#ifdef DO_TIMING
    int i,k,indent=0,beg,end,iBegStack=0;
    double dt;
    char EventStr[20];

    for (i=0; i<n_event; i++)
    {
        char str1[80],*s=EventNames[i];

        beg=end=FALSE;
        if (strncmp(s,"beg ",4)==0)
        {
            beg=TRUE;
            iBegStack++;
        }
        else if (strncmp(s,"end ",4)==0)
        {
            // search for beg
            int k;
            for (k=i-1; k>=0; k--)
            {
                if (strncmp(s+4,EventNames[k]+4,80)==0)
                {
                    // found
                    end=TRUE;
                    dt = EventTimes[i] - EventTimes[k];
                    iBegStack--;
                    break;
                }
            }
        }

        if (EventValue[i] != 0)
            sprintf(EventStr,"%9d",EventValue[i]);
        else
            sprintf(EventStr,"         ");

        if (i>0 && end)
        {
            sprintf(str1,"%12.1f %9.1f %9.1f %s   ",(EventTimes[i]-EventTimes[0])*1e6,
                (EventTimes[i]-EventTimes[i-1])*1e6,dt*1e6,EventStr);
        }
        else  if (i>0)
        {
            sprintf(str1,"%12.1f %9.1f           %s   ",(EventTimes[i]-EventTimes[0])*1e6,
                (EventTimes[i]-EventTimes[i-1])*1e6,EventStr);
        }
        else
        {
            sprintf(str1,"%12.1f %9.1f           %s   ", 0.0, 0.0,EventStr);
        }
        AddLog(str1);

        if (end) indent--;
        for (k=0; k<indent; k++) AddLog("   ");
        if (beg) indent++;

        AddLog(s);
        AddLog("\n");


    }
    n_event=0;
#endif
}


/***************************** End Of File ***********************************/
