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


#include "c672xevmcfg.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"



// McASP handles
CSL_McaspHandle          hMcasp;
CSL_McaspObj             mcaspObj; 
CSL_McaspHwSetup         mcaspHwCfg = CSL_MCASP_HWSETUP_DEFAULTS;

    
//DMAX Handles 
CSL_DmaxObj              dmaxEvent; 	// DMAX Event Object    
CSL_DmaxHandle           hDmax;     	// DMAX Handle       
CSL_DmaxHwSetup          dmaxHwSetup;   // DMAX Tx Hardware Setup 

// cpu interrupt event setup
CSL_DmaxCpuintEventSetup cpuIntEventSetup;

// Status variable 
CSL_Status                  status = CSL_SOK;



volatile int numInterrupts = 0;
volatile int intFlag = 0;

int main()
{
	unsigned int mask = 0;

	// 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);

	// 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");
        status = CSL_ESYS_BADHANDLE;
        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 Initilization 
    status = CSL_dmaxInit (NULL);
    if (status != CSL_SOK) {
        printf ("\nTEST FAILED\nERROR:CSL_dmaxInit");
        return status;
    }  

    // 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");
        status = CSL_DMAX_BADHANDLE;
        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;
    }

	// this is how you should enable interrupts, in this case int13 
	// BIOS does not enable user interrupts by default even when configured in the .tcf file
	// BIOS only globally enables interrupts
	// see bios api users guide 
	mask = C62_disableIER();
	mask |= 0x2000;
	C62_enableIER(mask);

	LOG_printf(&LOG0, "end of main");

}


// this task 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 triggerTask()
{

	hMcasp->regs->PDCLR = 0x2;

	while(1)
	{
		hMcasp->regs->PDIN_PDSET = 0x2;

		TSK_sleep(100);

		hMcasp->regs->PDCLR = 0x2;

		TSK_sleep(100);
	}
}

// this task just logs the interrupts being received
void loggingTask()
{
  while(1)
  {
	// pend on the interrupt event semaphore and log the occurrence
    SEM_pendBinary(&SEM0, SYS_FOREVER);
    
    LOG_printf(&LOG0, "int #%d\n", numInterrupts);
  }
}

// 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 
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

	// note: SEM_post can be used without restrictions since the BIOS dispatcher is
	// being configured in the BIOS config file (.tcf).
	// Otherwise BIOS calls are forbidden unless isr is written in assembly
	// and HWI_enter / HWI_exit macros are used
	SEM_postBinary(&SEM0);
}




