/********************************************************************************/
/* FILE NAME: main.c                            COPYRIGHT (c) Freescale 2010 	*/
/*                                                       All Rights Reserved 	*/
/*  																		 	*/
/*	MPC5668 Example Projects Suite												*/
/*	eDMA_SPI Example															*/
/*																				*/
/*	Revision History															*/
/*	Rev: 1.0		Author:	Steven McLaughlin			DATE: 08/10/2010		*/
/*																			 	*/
/* eDMA channel 0 used to take data from RAM Tx_buffer and place it in the 	 	*/
/* tranmit FIFO of DSPI_A as required. Channel 1 used to move received data  	*/
/* from DSPI_B receive FIFO to Rx_buffer in RAM                              	*/
/*                                                                           	*/
/* After transfers are complete, the receive bufer is tested to ensure			*/
/* success and an LED indicates this. Number of errors are stored in Errcount	*/
/********************************************************************************/

/***************************** Includes *****************************************/
#include "mpc5668.h"

/***************************** Global variables *********************************/
uint32_t Errcount, count; 				/* stores number of errors */
uint32_t RFOFCount, TFUFCount; 
vuint32_t Tx_buffer[10], Rx_buffer[10];

/****************************** Function Prototypes *****************************/
void PLLinit(void);                     /* PLL Initialisation */  
void eDMAinit(void);
void DSPIinit(void);

/********************************** Main ****************************************/
void main()
{
	int i;								/* local variables */
	Errcount = 0;						/* assigning values to globals */ 
	count = 0;							/* assigning values to globals */
	SIU.PCR[16].R=0x0200;				/* PB0 to output */
	
    for(i=0;i<10;i++)
	{
		Tx_buffer[i] = 0x00010000|i; 	/* use CS0, data = 0-9 */
		Rx_buffer[i] = 0;
	}
	
	PLLinit();							/* Init PLL to 66Mhz from an 40MHz XOSC */		
	eDMAinit();							/* setup the TCD registers */
	DSPIinit();							/* configure DSPI*/
	
	/* exercise the SPI */
    DSPI_A.MCR.B.HALT = 0x0;			/* exit HALT mode in master */
	DSPI_A.MCR.B.MDIS = 0x0;			/* enable module in master*/ 
	for(i=0;i<0xFFF;i++);     			/* delay to ensure master is fully active before slave */
	DSPI_B.MCR.B.HALT = 0x0;			/* exit HALT mode in slave */
	DSPI_B.MCR.B.MDIS = 0x0;			/* enable module in slave  */
	
	DMAMUX.CHCONFIG[0].R = 0x92;	 	/* setup DMA MUX */
    DMAMUX.CHCONFIG[1].R = 0x95;	 	/* setup DMA MUX */

	EDMA.SERQR.R = 0x00; 				/* enable hardware interrupt for channel 0 */
	EDMA.SERQR.R = 0x01; 				/* enable hardware interrupt for channel 1 */

	for(i=0;i<0xFFFF;i++);				/* pause to allow transfers to take place */
	
	for(i=0;i<10;i++)					/* test to ensure success */
	{
		if(Rx_buffer[i] == Tx_buffer[i])
			Errcount++;
	}

	if(Errcount==0)
	{
		while(1)						/* pass :) */
		{
			for (count=0; count<100000; count++);
			SIU.GPDO[16].R = 0x01;
			for (count=0; count<100000; count++);
			SIU.GPDO[16].R = 0x00;
		}
	}
	else
	{
		while(1);						/* fail :( */
	}		
} /* END of Main */

void PLLinit(void)
{
	int ERFD = 3;
	int EPREDIV = 9;
	int EMFD = 112;

	SIU.SYSCLK.B.SYSCLKSEL = 0x0;		/* Select IRC as CLK Source */ 

	/* Configure PLL CTRL Regs */ 
	FMPLL.ESYNCR1.B.CLKCFG = 0x7; 
	FMPLL.ESYNCR2.B.ERFD = ERFD+2;
	FMPLL.ESYNCR1.B.EPREDIV = EPREDIV;
	FMPLL.ESYNCR1.B.EMFD = EMFD;

	while(FMPLL.SYNSR.B.LOCK != 1);		/* Wait for PLL to lock */ 

	FMPLL.ESYNCR2.B.ERFD = ERFD;		/* Change pll up to final freq */
	SIU.SYSCLK.B.SYSCLKSEL = 0x2;		/* Switch from IRC to PLL */ 

	SIU.PCR[153].R = 0x060C; 			/* clkout - K9 */
	SIU.ECCR.B.ECDF = 0x1;     			/* CLKOUT = sys freq / 2. Set to 0 for sys freq. */
	SIU.ECCR.B.ECEN = 1; 				/* enable CLKOUT */
} /* End of PLLinit */

void eDMAinit(void)
{
	/* channel 0 used to move data from RAM to DSPI_A transfer buffer */
	EDMA.TCD[0].SADDR = (vuint32_t)Tx_buffer; /* source address of data */
	EDMA.TCD[0].SMOD = 0;				/* source address modulo disabled */
	EDMA.TCD[0].SSIZE = 0x2;			/* 32-bit source size */
	EDMA.TCD[0].DMOD = 0;				/* Destination address modulo disabled */
	EDMA.TCD[0].DSIZE = 0x2;			/* 32-bit destination size */
	EDMA.TCD[0].SOFF = 0x4;				/* source address offset = 4 (32 bit) */
	EDMA.TCD[0].NBYTES = 0x4;			/* transfer 4 bytes per channel activation */
	EDMA.TCD[0].SLAST = -40;			/* Restore Source address by -40 -> 10x32-bits */
	EDMA.TCD[0].DADDR = (vuint32_t)&DSPI_A.PUSHR.R;	/* destination address (DSPI_A.PUSHR) */
	EDMA.TCD[0].CITERE_LINK = 0;		/* disabled chanel2chanel linking */
	EDMA.TCD[0].CITER = 0xA;			/* current major iteration */
	EDMA.TCD[0].DOFF = 0;				/* destination address offset = 0 */
	EDMA.TCD[0].DLAST_SGA = 0;			/* restore destination address by 0 */
	EDMA.TCD[0].BITERE_LINK = 0;		/* disabled chanel2chanel linking */
	EDMA.TCD[0].BITER = 0xA;			/* starting major iteration count */
	EDMA.TCD[0].BWC = 0;				/* no bandwidth control */
	EDMA.TCD[0].MAJORLINKCH = 0;		/* disabled chanel2chanel linking */
	EDMA.TCD[0].DONE = 0;
	EDMA.TCD[0].ACTIVE = 0;
	EDMA.TCD[0].MAJORE_LINK = 0;
	EDMA.TCD[0].E_SG = 0;
	EDMA.TCD[0].D_REQ = 0;
	EDMA.TCD[0].INT_HALF = 0;
	EDMA.TCD[0].INT_MAJ = 0;
	EDMA.TCD[0].START = 0;

	/* channel 1 used to move data from DSPI_B receive buffer to RAM */
	EDMA.TCD[1].SADDR = (vuint32_t)&DSPI_B.POPR.R;		/* source address of data */
	EDMA.TCD[1].SMOD = 0;				/* source address modulo disabled */
	EDMA.TCD[1].SSIZE = 0x2;			/* 32-bit source size */
	EDMA.TCD[1].DMOD = 0;				/* Destination address modulo disabled*/
	EDMA.TCD[1].DSIZE = 0x2;			/* 32-bit destination size */
	EDMA.TCD[1].SOFF = 0;				/* source address offset = 0 */
	EDMA.TCD[1].NBYTES = 0x4;			/* transfer 4 bytes per channel activation */
	EDMA.TCD[1].SLAST = 0;				/* Restore Source address by 0 */
	EDMA.TCD[1].DADDR = (vuint32_t)Rx_buffer;		/* destination address (DSPI_A.PUSHR) */
	EDMA.TCD[1].CITERE_LINK = 0;		/* disabled chanel2chanel linking */
	EDMA.TCD[1].CITER = 0xA;			/* current major iteration*/
	EDMA.TCD[1].DOFF = 0x4;				/* destination address offset = 4 (32-bit) */
	EDMA.TCD[1].DLAST_SGA = -40;		/* restore destination address by -40  -> 10x32-bits */
	EDMA.TCD[1].BITERE_LINK = 0;		/* disabled chanel2chanel linking */
	EDMA.TCD[1].BITER = 0xA;			/* starting major iteration count */
	EDMA.TCD[1].BWC = 0;				/* no bandwidth control */
	EDMA.TCD[1].MAJORLINKCH = 0;		/* disabled chanel2chanel linking */ 
	EDMA.TCD[1].DONE = 0;				
	EDMA.TCD[1].ACTIVE = 0;
	EDMA.TCD[1].MAJORE_LINK = 0;
	EDMA.TCD[1].E_SG = 0;
	EDMA.TCD[1].D_REQ = 0;
	EDMA.TCD[1].INT_HALF = 0;
	EDMA.TCD[1].INT_MAJ = 0;
	EDMA.TCD[1].START = 0;	
}

void DSPIinit(void)
{
	/* setup DSPI_A as master */
	SIU.PCR[81].R = 0x60C;     		    /* Configure pad PF1 for primary func: TxDA, output, fastest slew rate */
	SIU.PCR[82].R = 0x500;      		/* Configure pad PF2 for primary func: RxDA, input  */
	SIU.PCR[84].R = 0x60C;      		/* Configure pad PF4 for primary func: TxDA, output (chip select 1) , fastest slew rate */
	SIU.PCR[83].R = 0x60C;      		/* Configure pad PF3 for primary func: TxDA, output (chip select 0) , fastest slew rate */
	SIU.PCR[80].R = 0x60C;      		/* Configure pad PF0 for primary func: TxDA, output (clock) , fastest slew rate */
	SIU.PCR[95].R = 0xA0C;				/* Configure pad PF15 for secondary func: TxDA, output (chip select 5) , fastest slew rate */
	SIU.PCR[96].R = 0xA0C;				/* Configure pad PG0 for secondary func: TxDA, output (chip select 4) , fastest slew rate */
	SIU.PCR[154].R = 0xE0C;				/* Configure pad PK10 for secondary func: TxDA, output (chip select 3) , fastest slew rate */
		
	/* setup DSPI_B as slave */
	SIU.PCR[85].R = 0x60C;      		/* Configure pad PF5 for primary func: TxDA, output, fastest slew rate */
	SIU.PCR[146].R = 0x900;      		/* Configure pad PK2 for primary func: RxDA, input  */
	SIU.PCR[87].R = 0x500;      		/* Configure pad PF7 for primary func: TxDA, input (chip select 0) */
	SIU.PCR[84].R = 0x50C;      		/* Configure pad PK0 for primary func: TxDA, input  (clock) */
	SIU.PCR[86].R = 0x500;      		/* Configure pad PF5 SIN_B */

	/* setup DSPI modules */
	DSPI_A.MCR.B.MSTR = 0x1;		  	/* select master mode */
	DSPI_A.MCR.B.DCONF = 0x00;		  	/* select SPI mode */
	DSPI_A.DSICR.B.DSICTAS = 0x000;
	DSPI_A.MCR.B.PCSIS0 = 1; 			/* set inactive CS0 state to high */
	DSPI_A.CTAR[0].R = 0x78000000;		/* frame size 16bits, speed: 16.67MHz */
	
	DSPI_B.MCR.B.MSTR = 0x0;		   	/* select slave mode */
	DSPI_B.MCR.B.DCONF = 0x00;		   	/* select SPI mode */
	DSPI_B.DSICR.B.DSICTAS = 0x001;
	DSPI_B.MCR.B.PCSIS0 = 1; 		  	/* set inactive CS0 state to high (required for slave module) */
	DSPI_B.CTAR[1].R = 0x78000000;		/* frame size 16bits*/
	
	/* setup eDMA "interrupts" */
	DSPI_A.RSER.B.TFFF_RE = 1; 			/* enable transmit fifo fill request interrupt */
	DSPI_A.RSER.B.TFFF_DIRS = 1;		/* DMA interrupt will be generated */
	DSPI_B.RSER.B.RFDF_RE = 1;			/* enable receiver not empty interrupt 	*/
	DSPI_B.RSER.B.RFDF_DIRS = 1;		/* DMA interrupt will be generated */
	
	DSPI_A.RSER.B.TCF_RE = 1; 			/* enable transmit fifo fill request interrupt */
	DSPI_A.RSER.B.EOQF_RE = 1; 			/* enable transmit fifo fill request interrupt */
	
	DSPI_B.RSER.B.TCF_RE = 1; 			/* enable transmit fifo fill request interrupt */
	DSPI_B.RSER.B.RFOF_RE = 1; 			/* enable transmit fifo fill request interrupt */
}