

#include "ti/csl/csl_chip.h"
#include "ti/csl/csl_chipAux.h"
#include <ti/csl/src/intc/csl_intc.h>
#include <ti/csl/csl_ipc.h>
#include <ti/csl/csl_ipcAux.h>

#include <stdio.h>

CSL_IntcContext             intcContext;
CSL_IntcEventHandlerRecord  EventHandler[30];
CSL_IntcObj                 intcObj;
CSL_IntcHandle              hTest;
CSL_IntcGlobalEnableState   state;
CSL_IntcEventHandlerRecord  EventRecord;
CSL_IntcParam               vectId;


#pragma  DATA_SECTION(int_flag,".data");
int volatile int_flag = 0;


interrupt void intIsr()
{
	unsigned int index = 0;
	unsigned int srcId = 0;
	unsigned int retVal = 0;

	switch (DNUM)
	{
		case 0:
			index = 0;
			srcId = 1;
		    break;
		case 1:
			index = 1;
			srcId = 0;
			break;
		default:
			printf("incorrect core number\n");
			break;
	}

	retVal = CSL_IPC_isGEMInterruptSourceSet (index, srcId);
    if (retVal == 0)
    {
   		//Clear INTC interrupt
   		CSL_intcHwControl(hTest,CSL_INTC_CMD_EVTCLEAR, NULL);

    	int_flag = 0;		// Maybe continue waiting for the IPC/message
    }
   	else
   	{
   		/* This function clears the interrupt source IDs by setting the SRCCx bit of
   		 * the IPC Acknowledgment Register (IPCARx) and SRCSx bit of IPC Generation Register (IPCGRx)
   		 * corresponding to the CorePac index and Source ID specified. */
   		CSL_IPC_clearGEMInterruptSource (index, srcId);

   		//Clear INTC interrupt
   		CSL_intcHwControl(hTest,CSL_INTC_CMD_EVTCLEAR, NULL);

   		int_flag++;		// Do the needful processing.

   	}

	return ;
}


void IPC_Init (void)
{


	    /* INTC module initialization */
	    intcContext.eventhandlerRecord = EventHandler;
	    intcContext.numEvtEntries      = 10;
	    if (CSL_intcInit(&intcContext) != CSL_SOK)
	    {
	        printf("Error: CorePac-INTC initialization failed\n");
	        return;
	    }

	    /* Enable NMIs */
	    if (CSL_intcGlobalNmiEnable() != CSL_SOK)
	    {
	        printf("Error: CorePac-INTC global NMI enable failed\n");
	        return;
	    }

	    /* Enable global interrupts */
	    if (CSL_intcGlobalEnable(&state) != CSL_SOK)
	    {
	        printf ("Error: CorePac-INTC global enable failed\n");
	        return;
	    }

	    /* Open the INTC Module for Vector ID: 4 and Event ID: 91 (IPCn in C6678)*/
	    vectId = CSL_INTC_VECTID_4;
	    hTest = CSL_intcOpen (&intcObj, 90/*91*/, &vectId , NULL);
	    if (hTest == NULL)
	    {
	        printf("Error: CorePac-INTC Open failed\n");
	        return;
	    }

	    /* Register an call-back handler which is invoked when the event occurs. */
	    EventRecord.handler = &intIsr;
	    EventRecord.arg = 0;
	    if (CSL_intcPlugEventHandler(hTest,&EventRecord) != CSL_SOK)
	    {
	        printf("Error: CorePac-INTC Plug event handler failed\n");
	        return;
	    }

	    /* Enabling the events. */
	    if (CSL_intcHwControl(hTest,CSL_INTC_CMD_EVTENABLE, NULL) != CSL_SOK)
	    {
	        printf("Error: CorePac-INTC CSL_INTC_CMD_EVTENABLE command failed\n");
	        return;
	    }


}

void IPC_Trigger (void)
{
	unsigned int index = 0;
	unsigned int srcId = 0;

	switch (DNUM)
	{
		case 0:
			index = 1;
			srcId = 0;
			 /*This function sets the IPCG bit of the IPC Generation Register (IPCGRx)
			 * to create an inter-DSP pulse to the CorePac corresponding to the index
			 * specified here. This API also configures the source ID for this
			 * interrupt by setting the SRCSx bit of the IPCGRx register based on
			 * the source ID specified. */
			CSL_IPC_genGEMInterrupt(index,srcId);	//IPC generation from Core0 to Core1
			break;

		case 1:
			index = 0;
			srcId = 1;
			CSL_IPC_genGEMInterrupt(index,srcId);	//IPC generation from Core1 to Core0
			break;

		default:
			printf("incorrect core number\n");
			break;
	}
}

void main(void)
{
	unsigned int i=0;

	IPC_Init();
	//add some delay here to make sure both cores finish IPC_Init()
	for (i=0;i<20000;i++);

	IPC_Trigger();
	while (int_flag != 1) {};

	printf("IPC interrupt occurred on Core %d\n", DNUM);

	IPC_Trigger();
	while (int_flag != 2) {};

	printf("IPC interrupt occurred on Core %d, again.\n", DNUM);
	printf("end of test\n");

	return;
}
