/************************************************************************
*
*  SOURCE NAME: vcp2_interrupt.c
*
*************************************************************************
*
*  SOURCE FUNCTION: Header file for vcp2_interrupt.c
*
*
*  PROCEDURES IN THIS SOURCE FILE: Interrupt setup and handling
*  									functions for the VCP2
*
*

*********************************************************************/

#include <stdio.h>
#include <ti/csl/csl.h>
#include <ti/csl/csl_tsc.h>
#include <ti/csl/csl_types.h>
#include <ti/csl/csl_error.h>
#include <csl_intc.h>
#include <ti/csl/csl_edma3.h>
#include <ti/csl/csl_vcp2.h>
#include <ti/csl/csl_vcp2Aux.h>
#include <ti/csl/soc.h>
#include <ti/csl/csl_cpIntcAux.h>
#include <ti/csl/csl_device_interrupt.h>
#include <xdc/cfg/global.h>


/* BIOS includes */
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Semaphore.h>
#include <ti/sysbios/family/c64p/Hwi.h>
#include <ti/sysbios/family/c64p/EventCombiner.h>
#include <ti/sysbios/family/c66/tci66xx/CpIntc.h>

#include "val_util.h"
#include "vcp2_edma3.h"
#include "vcp2_testInit.h"

// Global variable declaration
CSL_IntcHandle              hIntcEdma;
CSL_IntcHandle              hIntcVcp;
CSL_IntcObj                 intcObjEdma;
CSL_IntcObj                 intcObjVcp;
CSL_CPINTC_Handle           hCpintc;
CSL_IntcEventHandlerRecord  eventHandler[2];
CSL_IntcGlobalEnableState   state;  //dummy var since not used to restore state later
CSL_Edma3CmdIntr            regionIntrQuerry;


CSL_CPINTCSystemInterrupt	sysIntr;

// External global variables

extern CSL_Edma3Handle hModule;
extern Semaphore_Handle SEM;

extern Uint32 decisions[4][1024];
extern VCP2_Params vcpParameters[20];

extern volatile Uint32 VcpError;
extern volatile Uint32 RxCount;

extern volatile Uint32 TxEdmaChannelBCount;
extern volatile Uint32 ChannelTXCount;
extern volatile Uint32 ChannelRXCount;

extern VCP2Handle hVcp2;
extern Uint32 coreNum1;

// Function declarations
interrupt void EDMA_ISR(void);
interrupt void VCP2_ISR(void);

//-------------------------------------------------------------
// Setup_Interrupt() - Performs setup for GEM INTC and CP_INTC
//-------------------------------------------------------------
void Setup_Interrupt()
{
    //---------------------------------
    // Setup GEM internal INTC
    //---------------------------------
	// printf("Star of Setup_Interrupt \n");
    // Declare variables
    /* Routing Iqn2 exception event thru INTC0 */


	  if(coreNum1 <= 3)
	  {
		hCpintc = CSL_CPINTC_open(0); // handle for INTC0
        CSL_CPINTC_disableAllHostInterrupt(hCpintc);
        CSL_CPINTC_setNestingMode(hCpintc, CPINTC_NO_NESTING);
        CSL_CPINTC_mapSystemIntrToChannel (hCpintc, CSL_CIC0_I2C_1_INT , 8); // assuming core0
        CSL_CPINTC_clearSysInterrupt (hCpintc, CSL_CIC0_I2C_1_INT );
        CSL_CPINTC_enableSysInterrupt (hCpintc, CSL_CIC0_I2C_1_INT );
	  }
	  else
	  {
		hCpintc = CSL_CPINTC_open(1); // handle for INTC0
		CSL_CPINTC_disableAllHostInterrupt(hCpintc);
		CSL_CPINTC_setNestingMode(hCpintc, CPINTC_NO_NESTING);
		CSL_CPINTC_mapSystemIntrToChannel (hCpintc, CSL_CIC1_I2C_1_INT , 8); // assuming core0
		CSL_CPINTC_clearSysInterrupt (hCpintc, CSL_CIC1_I2C_1_INT );
		CSL_CPINTC_enableSysInterrupt (hCpintc, CSL_CIC1_I2C_1_INT );
	  }
        Hwi_Params hwi1Params, hwi2Params;
        Hwi_disable();

        Hwi_disableInterrupt(CSL_INTC_VECTID_6);
        Hwi_disableInterrupt(CSL_INTC_VECTID_5);

        Hwi_Params_init(&hwi1Params);
        hwi1Params.enableInt = FALSE;
        hwi1Params.eventId =   CSL_C66X_COREPAC_CIC_OUT8_PLUS_16_MUL_N ;

		Hwi_Params_init(&hwi2Params);
		hwi2Params.enableInt = FALSE;
		hwi2Params.eventId =   CSL_C66X_COREPAC_CIC_OUT9_PLUS_16_MUL_N ;


        Hwi_create (CSL_INTC_VECTID_6, (ti_sysbios_interfaces_IHwi_FuncPtr) EDMA_ISR, &hwi1Params, NULL);
        Hwi_create (CSL_INTC_VECTID_5, (ti_sysbios_interfaces_IHwi_FuncPtr) VCP2_ISR, &hwi2Params, NULL);

        Hwi_clearInterrupt (CSL_INTC_VECTID_6);
        Hwi_clearInterrupt (CSL_INTC_VECTID_5);


#if 0

    CSL_IntcParam vectId1;
    CSL_IntcParam vectId2;
    CSL_IntcGlobalEnableState state;
    CSL_IntcContext intContext; 

    // Setup the global Interrupt
    intContext.numEvtEntries = 2;
    intContext.eventhandlerRecord = eventHandler; 

    CSL_intcInit(&intContext);

    // Enable NMIs
    CSL_intcGlobalNmiEnable();


    // Enable Global Interrupts
    CSL_intcGlobalEnable(&state);

    // Select interrupt vector IDs to use on DSP core
    vectId1 = CSL_INTC_VECTID_9;
    vectId2 = CSL_INTC_VECTID_10;

    // Map GEM input interrupt used for EDMA completion to vectId1  
    hIntcEdma = CSL_intcOpen(&intcObjEdma,
    		CSL_C66X_COREPAC_CIC_OUT8_PLUS_16_MUL_N,
            &vectId1,
            NULL);

    // Map GEM input interrupt used for VCP error to vectId2  
    hIntcVcp = CSL_intcOpen(&intcObjVcp,
    		CSL_C66X_COREPAC_CIC_OUT9_PLUS_16_MUL_N,
            &vectId2,
            NULL);

    // Hook the ISR's
    CSL_intcHookIsr(vectId1,&EDMA_ISR);
    CSL_intcHookIsr(vectId2,&VCP2_ISR);

    // Clear any pending interrupts
    CSL_intcHwControl(hIntcEdma,CSL_INTC_CMD_EVTCLEAR,NULL);
    CSL_intcHwControl(hIntcVcp,CSL_INTC_CMD_EVTCLEAR,NULL);

    // Enable the event and interrupt
     CSL_intcHwControl(hIntcEdma,CSL_INTC_CMD_EVTENABLE,NULL);
     CSL_intcHwControl(hIntcVcp,CSL_INTC_CMD_EVTENABLE,NULL);

#endif
    //----------------------------------------------------------
    // Setup CP_INTC
    //----------------------------------------------------------
    if(coreNum1 <= 3)
    {
    // Open a handle to CP_INTC instance 0
    hCpintc = CSL_CPINTC_open(CSL_CIC_0);
    if (hCpintc == 0)
		{
			printf ("Error: Unable to open CPINT instance 0\n");
			return;
		}
    }
    else
    {
    	hCpintc = CSL_CPINTC_open(CSL_CIC_1);
    	if (hCpintc == 0)
    	{
        printf ("Error: Unable to open CPINT instance 0\n");
        return;       
    	}
    }

    // Map EDMA completion and VCP error system interrupts to proper output interrupts (channels) and enable
    if (coreNum1 == 0) {
        CSL_CPINTC_mapSystemIntrToChannel (hCpintc, CSL_CIC1_EDMACC_3_TC_0_INT, (16 * coreNum1) + 8);
        CSL_CPINTC_mapSystemIntrToChannel (hCpintc, CSL_CIC1_VCP_0_INT0,          (16 * coreNum1) + 9);
        CSL_CPINTC_enableSysInterrupt (hCpintc, CSL_CIC1_EDMACC_3_TC_0_INT);
        CSL_CPINTC_enableSysInterrupt (hCpintc, CSL_CIC1_VCP_0_INT0);
    } else if (coreNum1 == 1) {
        CSL_CPINTC_mapSystemIntrToChannel (hCpintc, CSL_CIC1_EDMACC_3_TC_1_INT, (16 * coreNum1) + 8);
        CSL_CPINTC_mapSystemIntrToChannel (hCpintc, CSL_CIC1_VCP_0_INT1,          (16 * coreNum1) + 9);
        CSL_CPINTC_enableSysInterrupt (hCpintc, CSL_CIC1_EDMACC_3_TC_1_INT);
        CSL_CPINTC_enableSysInterrupt (hCpintc, CSL_CIC1_VCP_0_INT1);
    } else if (coreNum1 == 2) {
        CSL_CPINTC_mapSystemIntrToChannel (hCpintc, CSL_CIC1_EDMACC_3_TC_2_INT, (16 * coreNum1) + 8);
        CSL_CPINTC_mapSystemIntrToChannel (hCpintc, CSL_CIC1_VCP_0_INT2,          (16 * coreNum1) + 9);
        CSL_CPINTC_enableSysInterrupt (hCpintc, CSL_CIC1_EDMACC_3_TC_2_INT);
        CSL_CPINTC_enableSysInterrupt (hCpintc, CSL_CIC1_VCP_0_INT2);
    } else if(coreNum1 == 3) {
        CSL_CPINTC_mapSystemIntrToChannel (hCpintc, CSL_CIC1_EDMACC_3_TC_3_INT, (16 * coreNum1) + 8);
        CSL_CPINTC_mapSystemIntrToChannel (hCpintc, CSL_CIC1_VCP_0_INT3,          (16 * coreNum1) + 9);
        CSL_CPINTC_enableSysInterrupt (hCpintc, CSL_CIC1_EDMACC_3_TC_3_INT);
        CSL_CPINTC_enableSysInterrupt (hCpintc, CSL_CIC1_VCP_0_INT3);
    }else if (coreNum1 == 4) {
	   CSL_CPINTC_mapSystemIntrToChannel (hCpintc, CSL_CIC1_EDMACC_3_TC_4_INT, (16 * (coreNum1-4)) + 8);
	   CSL_CPINTC_mapSystemIntrToChannel (hCpintc, CSL_CIC1_VCP_1_INT0,          (16 * (coreNum1-4)) + 9);
	   CSL_CPINTC_enableSysInterrupt (hCpintc, CSL_CIC1_EDMACC_3_TC_4_INT);
	   CSL_CPINTC_enableSysInterrupt (hCpintc, CSL_CIC1_VCP_1_INT0 );
    } else if (coreNum1 == 5) {
	   CSL_CPINTC_mapSystemIntrToChannel (hCpintc, CSL_CIC1_EDMACC_3_TC_5_INT, (16 * (coreNum1-4)) + 8);
	   CSL_CPINTC_mapSystemIntrToChannel (hCpintc, CSL_CIC1_VCP_1_INT1,          (16 * (coreNum1-4)) + 9);
	   CSL_CPINTC_enableSysInterrupt (hCpintc, CSL_CIC1_EDMACC_3_TC_5_INT);
	   CSL_CPINTC_enableSysInterrupt (hCpintc, CSL_CIC1_VCP_1_INT1);
    } else if (coreNum1 == 6) {
	   CSL_CPINTC_mapSystemIntrToChannel (hCpintc, CSL_CIC1_EDMACC_3_TC_6_INT, (16 * (coreNum1-4)) + 8);
	   CSL_CPINTC_mapSystemIntrToChannel (hCpintc, CSL_CIC1_VCP_1_INT2,          (16 * (coreNum1-4)) + 9);
	   CSL_CPINTC_enableSysInterrupt (hCpintc, CSL_CIC1_EDMACC_3_TC_6_INT);
	   CSL_CPINTC_enableSysInterrupt (hCpintc, CSL_CIC1_VCP_1_INT2);
    } else { // coreNum11 == 3
	   CSL_CPINTC_mapSystemIntrToChannel (hCpintc, CSL_CIC1_EDMACC_3_TC_7_INT, (16 * (coreNum1-4)) + 8);
	   CSL_CPINTC_mapSystemIntrToChannel (hCpintc, CSL_CIC1_VCP_1_INT3,          (16 * (coreNum1-4)) + 9);
	   CSL_CPINTC_enableSysInterrupt (hCpintc, CSL_CIC1_EDMACC_3_TC_7_INT);
	   CSL_CPINTC_enableSysInterrupt (hCpintc, CSL_CIC1_VCP_1_INT3);
    }
    /*
    // Clear pending system interrupts
    if (CSL_CPINTC_isInterruptPending(hCpintc) == TRUE)
    {
    // Get the source of the interrupt
    sysIntr = CSL_CPINTC_getPendingInterrupt(hCpintc);

    // Clear the interrupt
    CSL_CPINTC_clearSysInterrupt(hCpintc, sysIntr);
    }*/


    if(coreNum1 <= 3)
    {

    	// Enable output (host) interrupts to GEM
    	CSL_CPINTC_enableHostInterrupt (hCpintc, (16 * coreNum1) + 8);
    	CSL_CPINTC_enableHostInterrupt (hCpintc, (16 * coreNum1) + 9);
    	// Enable global host interrupt enable
    	CSL_CPINTC_enableAllHostInterrupt(hCpintc);

    }
    else
    {
		CSL_CPINTC_enableHostInterrupt (hCpintc, (16 * (coreNum1 -4)) + 8);
		CSL_CPINTC_enableHostInterrupt (hCpintc, (16 * (coreNum1 - 4)) + 9);
		// Enable global host interrupt enable
		CSL_CPINTC_enableAllHostInterrupt(hCpintc);

   	 }

    Hwi_enableInterrupt (CSL_INTC_VECTID_6);
	Hwi_enableInterrupt (CSL_INTC_VECTID_5);

	Hwi_enable ();
}


/*************************************************************************\
 *                    EDMA ISR
 \*************************************************************************/
interrupt void EDMA_ISR(void)
{

//	printf("Start of the EDMA_ISR \n");

    CSL_CPINTC_clearSysInterrupt(hCpintc, CSL_CIC1_EDMACC_3_TC_0_INT+coreNum1);
    CSL_intcHwControl(hIntcEdma,CSL_INTC_CMD_EVTCLEAR,NULL);

    regionIntrQuerry.region = coreNum1; // CSL_EDMA3_REGION_1;
    regionIntrQuerry.intrh = 0xffffffff;
    regionIntrQuerry.intr =0xffffffff;

    /* Read EDMA IPR */
    CSL_edma3GetHwStatus(hModule,CSL_EDMA3_QUERY_INTRPEND,&regionIntrQuerry); 
    /* Clear EDMA IPR */
    CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_INTRPEND_CLEAR,&regionIntrQuerry);


    VAL_TRACE(0xAAAA0000);
    do
    {
        /* Sample Timer Value after O/P Parameter Transfer is over */
        if(regionIntrQuerry.intr & (1 << VCP2_RCV_OPPARAM_TCC(coreNum1)))
        {

            ChannelRXCount++;
            VAL_TRACE(0xA0000003);
        }

        /* Sample Timer Value after I/P Parameter configuration is over */

        if(regionIntrQuerry.intr & (1 << VCP2_XMT_IPCONFIG_TCC(coreNum1)))
        {
            /* Populate the Time for Input Parameter XMT completion of Channel"i"*/
             VAL_TRACE(0xA0000004);
        }

        /* Start VCP BM Transfer */
        if(regionIntrQuerry.intrh & (1 << VCP2_XMT_TCC(coreNum1)-0x20))
        {

			ChannelTXCount++;
			VAL_TRACE(ChannelTXCount);
			VAL_TRACE(0xA0000005);
        }

        /* Start VCP Read for decisions */
        if(regionIntrQuerry.intr & (1 << VCP2_RCV_TCC(coreNum1)-0x20))
        {
            /* Populate the Time for RCV completion of Channel "i" */
            VAL_TRACE(0xA0000007);
            VAL_TRACE(ChannelRXCount);   

        }

        CSL_edma3GetHwStatus(hModule,CSL_EDMA3_QUERY_INTRPEND,&regionIntrQuerry); 
        CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_INTRPEND_CLEAR,&regionIntrQuerry);
   }while ((regionIntrQuerry.intr !=0)  & (regionIntrQuerry.intrh !=0));

    /* Set Interrupt EVAL */
 /*     regionIntrQuerry.region = coreNum1;
     CSL_edma3HwControl(hModule, CSL_EDMA3_CMD_INTR_EVAL,&regionIntrQuerry.region); */

   // Hwi_clearInterrupt (CSL_INTC_VECTID_6);
    CSL_CPINTC_clearSysInterrupt(hCpintc, sysIntr);

#if 1

    CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_DMAREGION_DISABLE,&regionIntrQuerry);
    CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_INTRPEND_CLEAR,&regionIntrQuerry);
    CSL_edma3HwControl(hModule, CSL_EDMA3_CMD_INTR_DISABLE, &regionIntrQuerry);
#endif

  //  Semaphore_post(SEM_VCP2Complete);
}


/*************************************************************************\
 *                    VCP2 ISR
 \*************************************************************************/
interrupt void VCP2_ISR(void)
{

    CSL_CPINTC_clearSysInterrupt(hCpintc, /*CSL_CIC0_VCP_0_INT0 */CSL_CIC1_VCP_0_INT0+coreNum1);
    CSL_intcHwControl(hIntcVcp,CSL_INTC_CMD_EVTCLEAR,NULL);
    VAL_TRACE(0xAAAA1100);

    // Read the Status Register
    VAL_TRACE(hVcp2->cfgregs->VCPSTAT0);
    VAL_TRACE(hVcp2->cfgregs->VCPSTAT1);

    // Read the VCP2 Error Register and set the status accordingly
    VAL_TRACE(hVcp2->cfgregs->VCPERR);
    hVcp2->cfgregs->VCPERR = 0;

    // Increment VCP error counter
    VAL_TRACE(0xAAAA11FF);
    VcpError++;

}


/******************************************************************************\
 * End of vcp2_interrupt.c
\******************************************************************************/

