#include "sysbasetypes.h"
#include "c6727dsk.h"                                                                                                        
#include <stdio.h>                                                                                                           
#include <string.h>

#include <c6x.h>                                                                                                             


#include "tistdtypes.h"
#include "csl.h"
#include "csl_error.h"
#include "csl_types.h"
#include "csl_chip.h"
#include "csl_dmax.h"
#include "csl_mcasp.h"
#include "soc.h"
#include "csl_rti.h"
#include "csl_intc.h"


// RAM address to which Interrupt vector table is to be loacated 
// needs to be aligned to 0x400
#define DEST_ADDR   			 0x10001000


// timer setup variables 

// Load value to watchdog timer 
#define PRELOAD_VALUE            0x1FF

// Macros for functional clock value 
#define RTI_INPUT_CLOCK          32000000
#define DIVIDER_FOR_TEST         4
#define EFFECTIVE_CLOCK_FOR_TEST (RTI_INPUT_CLOCK/DIVIDER_FOR_TEST)
#define UP_COMP_INTERVAL         1
#define COMP_INTERVAL            10000             
         
// Test intervals used for tests  
#define UC_COMP_VALUE      		((UP_COMP_INTERVAL * EFFECTIVE_CLOCK_FOR_TEST)\
								/1000)
#define COMPARE0_VALUE      	(COMP_INTERVAL)
#define COMPARE1_VALUE      	(COMP_INTERVAL)
#define COMPARE2_VALUE      	(COMP_INTERVAL)
#define COMPARE3_VALUE      	(COMP_INTERVAL)
#define UPDATECOMPARE_VALUE     (UP_COMP_INTERVAL)




// McASP handles 
static CSL_McaspHandle          hMcasp;
static CSL_McaspObj             mcaspObj; 
static CSL_McaspHwSetup         mcaspHwCfg = CSL_MCASP_HWSETUP_DEFAULTS;
    
//DMAX handles 
static CSL_DmaxObj              dmaxEvent; 	// DMAX Event Object    
static CSL_DmaxHandle           hDmax;     	// DMAX Handle       
static CSL_DmaxHwSetup          dmaxHwSetup;   // DMAX Tx Hardware Setup 

// cpu interrupt event setup
static CSL_DmaxCpuintEventSetup cpuIntEventSetup;

// Status variable 
static CSL_Status                  status=CSL_SOK;

// Handle for the real time interrupt instance 
static CSL_RtiHandle    hRti;
static CSL_RtiObj      	rtiObj;
static CSL_RtiHwSetup   hwSetup= CSL_RTI_HWSETUP_DEFAULTS;
static CSL_RtiHwSetup   hwSetupRead;

// Handles for the INTC 
static CSL_IntcHandle           hIntc;
static CSL_IntcObj                   intcObj;    
static CSL_IntcEventEnableState      state;
static CSL_IntcEventHandlerRecord    isrRec;       
static CSL_IntcDispatcherContext     intcDispatcherContext;
static CSL_IntcContext               intcContext;


volatile int numInterrupts = 0;
volatile int intFlag = 0;
volatile Uint32 compInt0Event;


// interrupt routines
// since intc module has a dispatcher which is going to be used 
// the routine is defined without use of the interrupt keyword
void comp0Isr();
void myIsr();




int main()
{

	// This is EVM specific
	// you might have to remove this or reconfigure as for your system
	InitHPI();

	// This is EVM specific
	// you might have to remove this or reconfigure as for your system
	// First thing to do = Init the External memory interface                 
	InitEmif();

	// This is EVM specific
	// you might have to remove this or reconfigure as for your system
	InitGPIO();

	// This is EVM specific
	// you might have to remove this or reconfigure as for your system
	SetAddrToFlash();



	// initialize the CSL lib
	CSL_chipInit(NULL);

   	// relocating the Interrupt Vector Table at DEST_ADDR
	CSL_intcSetVectorPtr(DEST_ADDR);

	// McASP configuration section
	// first configure on the McASP the pin to be used as input for AMUTEIN0
	// in this case AXR0[7] is chosen for AMUTEIN0
	// equivalent to *CFGMCASP0 = 0x00000001; 
	CSL_chipWriteReg(CSL_CHIP_REG_CFGMCASP0, 0x1);
   
  
    // McASP CSL Module Initilization 
    status = CSL_mcaspInit (NULL);
    if (status != CSL_SOK) {
        printf ("\nTEST FAILED\nERROR:CSL_MCASP_0 init failed");
        return status;
    }

    // Open the McASP Instance 
    hMcasp = CSL_mcaspOpen (&mcaspObj, CSL_MCASP_0, NULL, &status);
    if ((hMcasp == NULL) || (status != CSL_SOK)) {
        printf ("\nTEST FAILED\nERROR:CSL_MCASP_0 open failed");
        return status;
    }
     
	//configure the pin on the McASP0 to be used as GPIO, not McASP
	// all pins as GPIO
	// equivalent to *MCASP0_PFUNC |= 0xFE00FFFF;
	mcaspHwCfg.glb.pfunc = 0xFE00FFFF;
    
	// configure the directions of the McASP0 pins
	// AXR0[7] needs to be setup as input pin
	// (is already configured since input is default - bit 7)
	// ARX0[1]  - bit 2 needs to be setup as output pin
	// (used to generate the interrupt pulse)
	// equivalent to *MCASP0_PDIR = 0x00000002;
    mcaspHwCfg.glb.pdir = 0x00000002;

	// configure the AMUTE pin not to be activated when AMUTEIN is active
	// Clear the INEN bit in the AMUTE register but should keep the rest of the settings
	// default is all disabled
	// equivalent to *MCASP0_AMUTE &= (~0x00000008);
	mcaspHwCfg.glb.amute = 0x00000000;

	status = CSL_mcaspHwSetup(hMcasp, &mcaspHwCfg);
	if (status != CSL_SOK) {
        printf ("\nTEST FAILED\nERROR:CSL_MCASP_hwSetup");
        return status;
    }

	// dMax configuration section
	// DMAX Initialization 
    status = CSL_dmaxInit (NULL);
    if (status != CSL_SOK) {
        printf ("\nTEST FAILED\nERROR:CSL_dmaxInit");
        return status;
    }  

    // use High Priority Event  26
    dmaxEvent.eventUid = CSL_DMAX_HIPRIORITY_EVENT26_UID;

    // High Priority Parameter entry (any)
	// If an event is used to generate a CPU interrupt, a transfer entry is not
	// required, and the event entry only needs to specify which interrupt
	// line should be used to trigger the CPU interrupt
    dmaxEvent.paramUid = CSL_DMAX_HIPRIORITY_PARAMETERENTRY_ANY;

    // Getting the DMAX Handle by calling CSL_dmaxOpen() 
    hDmax = CSL_dmaxOpen (&dmaxEvent, CSL_DMAX, NULL, &status);
    if (status != CSL_SOK || (hDmax == (CSL_DmaxHandle) CSL_DMAX_BADHANDLE)) {
        printf ("\nTEST FAILED\nERROR:CSL_dmaxOpen");
        return status;
    }
    
	// interrupt number
	cpuIntEventSetup.cpuInt = CSL_DMAX_EVENT26_INT_INT13; // interrupt 13

	// Interrupt Event Type 
	cpuIntEventSetup.etype = CSL_DMAX_EVENT26_ETYPE_CPUINT;

    // Rising Edge polarity 
    dmaxHwSetup.polarity = CSL_DMAX_POLARITY_RISING_EDGE;

    // High Event priority 
    dmaxHwSetup.priority = CSL_DMAX_EVENT_HI_PRIORITY;
    
    // storing the EventSetup address in the Handle eventsetup variable 
    dmaxHwSetup.eventSetup = (CSL_DmaxEventSetup *) & cpuIntEventSetup;

    status = CSL_dmaxHwSetup (hDmax, &dmaxHwSetup);
    if (status != CSL_SOK) {
        printf ("\nTEST FAILED\nERROR:CSL_dmaxHwSetup");
        return status;
    }

    // Event Enable 
    status = CSL_dmaxHwControl (hDmax, CSL_DMAX_CMD_EVENTENABLE, NULL);
    if (status != CSL_SOK) {
        printf ("\nTEST FAILED\nERROR:CSL_dmaxHwControl");
        return status;
    }


	// interrupt initialization
	memset (&intcContext, 0, sizeof(CSL_IntcContext));
    memset (&intcDispatcherContext, 0, sizeof(CSL_IntcDispatcherContext));
    
    // initialize intc module
    status = CSL_intcInit(&intcContext); 
    if (status != CSL_SOK) {
        printf ("INTC: init....failed\n");
		return status;
    }
    
	// init the dispatcher
    status = CSL_intcDispatcherInit(&intcDispatcherContext);
    if (status != CSL_SOK) {
        printf ("INTC: intc Dispatcher init....failed\n");
		return status;
    }
    
    // disabling Global Interrupt 
    status = CSL_intcGlobalDisable(&state);
    if (status != CSL_SOK) {
        printf ("INTC: intc Global Disable....failed\n");
    	return status;
    }
    
    // Install handler for Rti compare interrupt0 
    hIntc = CSL_intcOpen(&intcObj, CSL_INTC_EVENTID_RTI_INT_REQ0 , 
                        NULL, &status);
    if ((status != CSL_SOK) || (hIntc == NULL)) {
        printf ("INTC: intc open....failed\n");
        return status;
    }
    
    isrRec.handler = comp0Isr;
    isrRec.arg = (void *)0x0; 

	// plug the interrupt handler via intc dispatcher    
    CSL_intcPlugEventHandler(hIntc, &isrRec);    
    
    // Enable the cpu interrupt 4 for the timer
    status = CSL_intcEventEnable(CSL_INTC_EVENTID_RTI_INT_REQ0, &state);
    if (status != CSL_SOK) {
        printf ("INTC: intc event enable....failed\n");
        return status;
    }

    // get a handler for the dmax interrupts
    hIntc = CSL_intcOpen(&intcObj, CSL_INTC_EVENTID_DMAXEVTOUT6   , 
                        NULL, &status);
    if ((status != CSL_SOK) || (hIntc == NULL)) {
        printf ("INTC: intc open....failed\n");
        return status;
    }

    isrRec.handler = myIsr;
    isrRec.arg = (void *)0x0; 
    
	// plug the interrupt handler via intc dispatcher
    CSL_intcPlugEventHandler(hIntc, &isrRec);    

    
    // Enable the cpu interrupt 13 for the dMax 
    status = CSL_intcEventEnable(CSL_INTC_EVENTID_DMAXEVTOUT6, &state); 
    if (status != CSL_SOK) {
        printf ("INTC: intc event enable....failed\n");
        return status;
    }


    // Enabling non-maskable interrupt 
    status = CSL_intcEventEnable(CSL_INTC_EVENTID_NMI, &state); 
    if (status != CSL_SOK) {
        printf ("INTC: intc nmi event enable....failed\n");
        return status;;
    }
	
	// globally enable interrupts
	status = CSL_intcGlobalEnable(&state);
	if (status != CSL_SOK) {
        printf ("INTC: intc global enable....failed\n");
        return status;;
    }
    

	// rti initialization phase
    memset (&rtiObj, 0, sizeof(CSL_RtiObj));
    memset (&hwSetup, 0, sizeof(CSL_RtiHwSetup));
    memset (&hwSetupRead, 0, sizeof(CSL_RtiHwSetup));
    
    // Initalize the RTI csl module 
    status = CSL_rtiInit(NULL);
    if (status != CSL_SOK) {
        printf ("INTC: rti init....failed\n");
		return status;
    }
    
    
    // Open csl module 
    hRti = CSL_rtiOpen(&rtiObj, CSL_RTI, NULL, &status);
    if ((status != CSL_SOK) || (hRti == NULL)) {
        printf ("INTC: rti open....failed\n");
		return status;
    }
    
    
    // Setup hardware parameters 
    hwSetup.blk0ExtnCntl                    = CSL_RTI_CAPTURE_EVENT_SOURCE1;
    hwSetup.blk1ExtnCntl                    = CSL_RTI_CAPTURE_EVENT_SOURCE1;   
    hwSetup.compareUpCntrs.compareUpCntr0   = UC_COMP_VALUE;   
    hwSetup.compVal.comp0Val                = COMPARE0_VALUE;
    hwSetup.compVal.comp1Val                = COMPARE1_VALUE;
    hwSetup.compVal.comp2Val                = COMPARE2_VALUE;
    hwSetup.compVal.comp3Val                = COMPARE3_VALUE;
    hwSetup.updateCompVal.updateComp0Val    = UPDATECOMPARE_VALUE;
    hwSetup.updateCompVal.updateComp1Val    = UPDATECOMPARE_VALUE;
    hwSetup.updateCompVal.updateComp2Val    = UPDATECOMPARE_VALUE;
    hwSetup.updateCompVal.updateComp3Val    = UPDATECOMPARE_VALUE;   
    hwSetup.preLoadWatchdog                 = PRELOAD_VALUE;

	// Enable compIntr0 alone 
	hwSetup.intConfig.compIntr0En = TRUE;
	hwSetup.intConfig.compIntr1En = FALSE;
	hwSetup.intConfig.compIntr2En = FALSE;
	hwSetup.intConfig.compIntr3En = FALSE;

    // Stop Rti Block0 counters 
    status = CSL_rtiHwControl (hRti, CSL_RTI_CMD_STOP_BLOCK0, NULL);
    if (status != CSL_SOK) {
        printf ("INTC: rti stop blk cmd....failed\n");
		return status;
    }
    
    // Setup rti module 
    status = CSL_rtiHwSetup (hRti, &hwSetup);
    if (status != CSL_SOK) {
        printf ("INTC: rti hwsetup....failed\n");
		return status;    
	}
   
    // verify the hwsetup configuration 
/*
    status = CSL_rtiGetHwSetup(hRti, &hwSetupRead);
    if (status != CSL_SOK) {
        printf ("INTC: rti getHwsetup....failed\n");
		return status;
    }
  */  
    // Start Rti Block0 counters 
    status = CSL_rtiHwControl (hRti, CSL_RTI_CMD_START_BLOCK0, NULL);
    if (status != CSL_SOK) {
        printf ("INTC: rti start blk cmd....failed\n");
		return status;
    }

	// clear the mcasp pin status
	hMcasp->regs->PDCLR = 0x2;

	// wait for the interrupts
	while(1)
	{
		// this is released by the dmax interrupt routine
		while (compInt0Event != TRUE);        
		    
        printf ("int#%d\n",numInterrupts);
        compInt0Event = FALSE;
	}
}




// this routine is called in response on the dMax interrupt to the cpu
// if using the dispatcher you will need to NOT use the interrupt keyword 
volatile int dmaxIntFlag = 0;
void myIsr()
{
	numInterrupts++;
  
	// check the source of the dMax interrupt
	// you need to verify in the McASP register which flags are being raised
	
	// event 26 MCASP0ERR is due to either AMUTEIN0 - McASP0 TX INT - McASP0 RX 
	// check RSTAX / XSTAT depending on RINTCTL / XINTCTL as needed

	// in this case the check is not done due to the simple example
	// McASP0 error ints are not enabled

	// release the cpu from waiting for the interrupt
	compInt0Event = TRUE;
}



volatile int flag=0;

// this isr triggers the external McASP pin configured as GPIO to generate a pulse
// note that pulse must be at least 2 dMax clock cycles to be recognized
void comp0Isr ()
{
    Bool          intEvent;
    CSL_Status    status;
    
    // Read the interrupt flag register 
    status = CSL_rtiGetHwStatus (hRti, CSL_RTI_QUERY_INT0_STATUS, &intEvent);

	// every odd interrupt generate a falling edge
	// first and every even interrupt generate a rising edge
	if(0 == flag)
	{
		hMcasp->regs->PDIN_PDSET = 0x2; 
		flag = 1;
	}
	else
	{
		hMcasp->regs->PDCLR = 0x2; 
		flag = 0;

	}      
	
    // Clear the interrupt 
    status = CSL_rtiHwControl (hRti, CSL_RTI_CMD_CLEAR_INT0, &intEvent);
}



