/*!
 * \file    spi_common.c
 * \brief   common SPI defines
 *
 * This file defines the macros used to validate the SPI test cases.
 * And some common function prototypes and initializations.
 *
 * \version $Revision: 1.1 $
 * \author  Khushboo Gupta (b18246)
 */

#include "common.h"
#include "dma_common.h"

uint8 dma_xfr_done = 0;

/************************************************************************/
void dma_config(int COMMAND, struct dma_tcd *tcd_value) {
	int i=0, j=0;  //i: for channel_no; j: for loop_count
	uint32 data32;
	uint16 data16;
	uint32 *p,*q;

	switch (COMMAND) {	
	case CONFIG_BASIC_XFR : 
			i			= tcd_value -> channel_no;
			data16		= tcd_value -> testdata16;
			data32		= tcd_value -> testdata32;
			DMA_SAR(i) 	= tcd_value -> saddr;
			DMA_DAR(i) 	= tcd_value -> daddr;
			DMA_DSR_BCR(i)= tcd_value -> nbytes;
			DMA_DCR(i) 	= tcd_value -> ctrl;
			break;
	case SOFT_START:
			i = tcd_value -> channel_no;
			DMA_DCR(i) |= DMA_DCR_START_MASK;			
			break;
	case WAIT_FOR_XFR:
			i = tcd_value -> channel_no;
			while((!(DMA_DSR_BCR(i) & DMA_DSR_BCR_DONE_MASK)));// & (!(DMA_DSR_BCR_BES_MASK)));
			/* Clear all errors and interrupts by writing 1 to DONE */
			DMA_DSR_BCR(i) |= DMA_DSR_BCR_DONE_MASK; 
			print_str("\nTransfer Completed. ");
			break;
	case WAIT_FOR_INTR:
			i = tcd_value -> channel_no;
			while(!dma_xfr_done);
			dma_xfr_done = 0; //Clear flag
			print_str("\nTransfer Completed and Intr serviced. ");
			break;
	case MEM_FILL_BYTE_XFR:
			i = tcd_value -> channel_no;
			for(j=0; j<(tcd_value->nbytes); j++) {  
				*((uint8 *)(tcd_value->saddr +j)) = i+j+1;
				//print_str("\n Value written at src addr is = 0x%x", (*((uint16 *)(tcd_value->saddr +j))));
			}
			break;
	case MEM_FILL_WORD_XFR:
			i = tcd_value -> channel_no;
			//data16 = (uint16) tcd_value -> testdata16;
			for(j=0; j<(tcd_value->nbytes); j=j+2) {  
				*((uint16 *)(tcd_value->saddr +j)) = i+j+2;
				//print_str("\n Value written at src addr is = 0x%x", (*((uint16 *)(tcd_value->saddr +j))));
				//data16 = ~data16;
			}
			break;
	case MEM_FILL_LONGWORD_XFR:
			i = tcd_value -> channel_no;
			//data32 = tcd_value -> testdata32;
			for(j=0; j<(tcd_value->nbytes); j=j+4) {  
				*((uint32 *)(tcd_value->saddr +j)) = i+j+4;//data32;
				//print_str("\n Value written at src addr is = 0x%x",(*((uint8_t *)(tcd_value->saddr +j))));
				//data32 = ~data32;
			}
			break;
	case CHECK_PRIORITY:
			i = tcd_value -> channel_no;
			j = tcd_value -> link;
			while((!(DMA_DSR_BCR(j) & DMA_DSR_BCR_DONE_MASK)) || (!(DMA_DSR_BCR(i) & DMA_DSR_BCR_DONE_MASK)));
			if ((DMA_DSR_BCR(j) & DMA_DSR_BCR_DONE_MASK)) {
				print_str("\n transfer is complete for channel %x",j);
			}
			else
				print_str("\n transfer is complete for channel %x",i);

			/*while((!(DMA_DSR_BCR(i) & DMA_DSR_BCR_BSY_MASK) == DMA_DSR_BCR_BSY_MASK) ||
				  (!(DMA_DSR_BCR(j) & DMA_DSR_BCR_DONE_MASK) == DMA_DSR_BCR_DONE_MASK));
            print_str("\n transfer is complete for channel %x",j);
            print_str("\n and channel %x is preempted ",i);
        
			while((!(DMA_DSR_BCR(i) & DMA_DSR_BCR_DONE_MASK) == DMA_DSR_BCR_DONE_MASK) ||
				  (!(DMA_DSR_BCR(j) & DMA_DSR_BCR_BSY_MASK) == DMA_DSR_BCR_BSY_MASK));
            print_str("\n Both the channels have completed the transfer\n"); */
 			break;
	case MEM_CLR:
			i = tcd_value -> channel_no;
			for(j=0; j<(tcd_value->nbytes); j=j+4) {  
				*((uint32 *)(tcd_value->daddr +j)) = 0;
				//print_str("\n Value written at dest addr is = 0x%x",*((uint8_t *)(tcd_value->daddr +j)));
			}
			break;
	case MEM_CMP:
			i = tcd_value -> channel_no;
			p = (uint32 *)tcd_value -> saddr;
			q = (uint32 *)tcd_value -> daddr;
			print_str("\n Compare memory.");
			for(j=0; j<(tcd_value->nbytes)/4; j++) {
				//print_str("\n\n nbytes = 0x%x, dest_addr = 0x%x, src_addr = 0x%x, j = 0x%x", tcd_value->nbytes, q+j, p+j, j);
				if(*(p+j) != *(q+j)) {
					error("\n Data transfer failed.");
					print_str("\n source address = 0x%x", (uint32)(p+j));
					print_str("\t value = 0x%8x",*(p+j));
					print_str("\n dest address = 0x%x", (uint32)(q+j));
					print_str("\t value = 0x%8x",*(q+j));
					break;
				}
				else {
					print_str("\n Check for data coherence");
					/* Clear destination data */
					//*(q+j) = 0;
				}
				if(j >= ((tcd_value -> nbytes)/4))
					print_str("\n DMA transfer OK");
			}
			break;
	}
}

/*************************** ISR definitions *****************************/
interrupt void DMA0_ISR(void)
{
	dma_xfr_done++;
	if((DMA_DSR_BCR0 & DMA_DSR_BCR_CE_MASK) == DMA_DSR_BCR_CE_MASK)
	{
		print_str("\n\rConfiguration Error: Clear DONE");
		//Write DONE=1, to clear DMA interrupt and error bits.
		DMA_DSR_BCR0 = DMA_DSR_BCR_DONE_MASK;  
	} 
	else if((DMA_DSR_BCR0 & DMA_DSR_BCR_BES_MASK) == DMA_DSR_BCR_BES_MASK)
	{
		print_str("\n\rBus Error on Source: Clear DONE"); 
		//Write DONE=1, to clear DMA interrupt and error bits.
		DMA_DSR_BCR0 = DMA_DSR_BCR_DONE_MASK;  
	}
	else if((DMA_DSR_BCR0 & DMA_DSR_BCR_BED_MASK) == DMA_DSR_BCR_BED_MASK)
	{
		print_str("\n\rBus Error on Destination: Clear DONE"); 
		//Write DONE=1, to clear DMA interrupt and error bits.
		DMA_DSR_BCR0 = DMA_DSR_BCR_DONE_MASK;  
	}
	else if((DMA_DSR_BCR3 & DMA_DSR_BCR_DONE_MASK) == DMA_DSR_BCR_DONE_MASK)
	{
		print_str("\n\rClear Flag DONE.");
		//Write DONE=1, to clear DMA interrupt and error bits.
		DMA_DSR_BCR0 = DMA_DSR_BCR_DONE_MASK;  
 	}
	else
	{
		print_str("\n\rDONE is not set");
	}
   // To return from this ISR
   //asm (rte);  		
}

interrupt void DMA1_ISR(void)
{
	dma_xfr_done++;
	if((DMA_DSR_BCR1 & DMA_DSR_BCR_CE_MASK) == DMA_DSR_BCR_CE_MASK)
	{
		print_str("\n\rConfiguration Error: Clear DONE");
		//Write DONE=1, to clear DMA interrupt and error bits.
		DMA_DSR_BCR1 = DMA_DSR_BCR_DONE_MASK;  
	} 
	else if((DMA_DSR_BCR1 & DMA_DSR_BCR_BES_MASK) == DMA_DSR_BCR_BES_MASK)
	{
		print_str("\n\rBus Error on Source: Clear DONE"); 
		//Write DONE=1, to clear DMA interrupt and error bits.
		DMA_DSR_BCR1 = DMA_DSR_BCR_DONE_MASK;  
	}
	else if((DMA_DSR_BCR1 & DMA_DSR_BCR_BED_MASK) == DMA_DSR_BCR_BED_MASK)
	{
		print_str("\n\rBus Error on Destination: Clear DONE"); 
		//Write DONE=1, to clear DMA interrupt and error bits.
		DMA_DSR_BCR1 = DMA_DSR_BCR_DONE_MASK;  
	}
	else if((DMA_DSR_BCR3 & DMA_DSR_BCR_DONE_MASK) == DMA_DSR_BCR_DONE_MASK)
	{
		print_str("\n\rClear Flag DONE.");
		//Write DONE=1, to clear DMA interrupt and error bits.
		DMA_DSR_BCR1 = DMA_DSR_BCR_DONE_MASK;  
 	}
	else
	{
		print_str("\n\rDONE is not set");
	}
   // To return from this ISR
   //asm (rte);  		
}

interrupt void DMA2_ISR(void)
{
	dma_xfr_done++;
	if((DMA_DSR_BCR2 & DMA_DSR_BCR_CE_MASK) == DMA_DSR_BCR_CE_MASK)
	{
		print_str("\n\rConfiguration Error: Clear DONE");
		//Write DONE=1, to clear DMA interrupt and error bits.
		DMA_DSR_BCR2 = DMA_DSR_BCR_DONE_MASK;  
	} 
	else if((DMA_DSR_BCR2 & DMA_DSR_BCR_BES_MASK) == DMA_DSR_BCR_BES_MASK)
	{
		print_str("\n\rBus Error on Source: Clear DONE"); 
		//Write DONE=1, to clear DMA interrupt and error bits.
		DMA_DSR_BCR2 = DMA_DSR_BCR_DONE_MASK;  
	}
	else if((DMA_DSR_BCR2 & DMA_DSR_BCR_BED_MASK) == DMA_DSR_BCR_BED_MASK)
	{
		print_str("\n\rBus Error on Destination: Clear DONE"); 
		//Write DONE=1, to clear DMA interrupt and error bits.
		DMA_DSR_BCR2 = DMA_DSR_BCR_DONE_MASK;  
	}
	else if((DMA_DSR_BCR3 & DMA_DSR_BCR_DONE_MASK) == DMA_DSR_BCR_DONE_MASK)
	{
		print_str("\n\rClear Flag DONE.");
		//Write DONE=1, to clear DMA interrupt and error bits.
		DMA_DSR_BCR2 = DMA_DSR_BCR_DONE_MASK;  
 	}
	else
	{
		print_str("\n\rDONE is not set");
	}
   // To return from this ISR
   //asm (rte);  		
}

interrupt void DMA3_ISR(void)
{
	dma_xfr_done++;
	if((DMA_DSR_BCR3 & DMA_DSR_BCR_CE_MASK) == DMA_DSR_BCR_CE_MASK)
	{
		print_str("\n\rConfiguration Error: Clear DONE");
		//Write DONE=1, to clear DMA interrupt and error bits.
		DMA_DSR_BCR3 = DMA_DSR_BCR_DONE_MASK;  
	} 
	else if((DMA_DSR_BCR3 & DMA_DSR_BCR_BES_MASK) == DMA_DSR_BCR_BES_MASK)
	{
		print_str("\n\rBus Error on Source: Clear DONE"); 
		//Write DONE=1, to clear DMA interrupt and error bits.
		DMA_DSR_BCR3 = DMA_DSR_BCR_DONE_MASK;  
	}
	else if((DMA_DSR_BCR3 & DMA_DSR_BCR_BED_MASK) == DMA_DSR_BCR_BED_MASK)
	{
		print_str("\n\rBus Error on Destination: Clear DONE"); 
		//Write DONE=1, to clear DMA interrupt and error bits.
		DMA_DSR_BCR3 = DMA_DSR_BCR_DONE_MASK;  
	}
	else if((DMA_DSR_BCR3 & DMA_DSR_BCR_DONE_MASK) == DMA_DSR_BCR_DONE_MASK)
	{
		print_str("\n\rClear Flag DONE.");
		//Write DONE=1, to clear DMA interrupt and error bits.
		DMA_DSR_BCR3 = DMA_DSR_BCR_DONE_MASK;  
 	}
	else
	{
		print_str("\n\rDONE is not set");
	}
   // To return from this ISR
   //asm (rte);  		
}
