#include "config.h"

.section L1_code;

.global _main;

	
_main:
		
			R6 = 0;					// ISR Count

			//P4 always = data read/write address
			P4.H = 0x2030;
			P4.L = 0x0000;
		
			//P5 always = config read/write address
		
			P5.H = 0x2030;
			P5.L = 0xFFFE;
			

			call Init_PLL;
			call Init_ASYNC_Memory;
			call InitGPIO_interrupts;
	
			#ifndef HOST_READ
		
			call Fill_Master_Buffer;
		
			#endif
		
			call Config_MemDMA;

			// Read HOST_STATUS to check if ALLOW_CONFIG is set i.e. to if HOST is ready or not

			check_again:
			
			R0.L = W[P5];
			CC = Bittst (R0,7);	
		
			if !CC jump check_again;
		
			//If ALLOW_CONFIG is set to 1, call the function to fill HDMA config words
		
			call HDMA_Config;
			
	
			here: nop;			
			jump here;
		
		
_main.end:

/************************************************************************/


Init_PLL:
			//configure CCLK and SCLK to 500 and 100 MHz respectively.CLKIN is 25MHz
			[--SP] = RETS;
			
			CLI R0;
			
			P0.L = LO(PLL_CTL);
			P0.H = HI(PLL_CTL);
			R0.L = 0x2800;
			W[P0] = R0.L;
			ssync;
					
			IDLE;
			
			STI R0;
			
			P0.L = LO(PLL_DIV);
			P0.H = HI(PLL_DIV);
			R0.L = 0x5;
			W[P0] = R0.L;
			ssync;
		
			RETS = [SP++];
		
			
			RTS;

Init_PLL.end:						
			
/**************************************************************/

Init_ASYNC_Memory:


			[--SP] = RETS;
				
			P0.L = lo(EBIU_AMBCTL0);
			P0.H = hi(EBIU_AMBCTL0);
			R0.H = 0xFFC2;
			R0.L = 0xFFC2;
			[P0] = R0;
			ssync;
		
		
			P0.L = lo(EBIU_AMBCTL1);
			P0.H = hi(EBIU_AMBCTL1);
			R0.H = 0xFFC3;
			R0.L = 0xFFC2;
			[P0] = R0;
			ssync;
		
			
			P0.L = lo(EBIU_AMGCTL);
			P0.H = hi(EBIU_AMGCTL);			//enable all banks
			R0.L = 0x00FE;
			W[P0] = R0.L;
			ssync;
		
			RETS = [SP++];
		
			RTS;
		
Init_ASYNC_Memory.end:


/***********************************************************************/

InitGPIO_interrupts:

			[--SP] = RETS;

			P0.L = lo(PORTGIO_DIR);
			P0.H = hi(PORTGIO_DIR);
			R0.L = 0;
			W[P0] = R0.L;		//PG13 is used as Input
			ssync;
		
		
			P0.L = lo(PORTGIO_INEN);
			P0.H = hi(PORTGIO_INEN);
			R0.L = PG13;
			W[P0] = R0.L;		//Enable PG13
			ssync;
		
	
			P0.L = lo(PORTGIO_EDGE);
			P0.H = hi(PORTGIO_EDGE);
			R0.L = PG13;		
			W[P0] = R0.L;		
			ssync;
				
				
			P0.L = lo(PORTGIO_POLAR);
			P0.H = hi(PORTGIO_POLAR);		// Falling edge sensitive
			R0.L = PG13;				
			W[P0] = R0.L;		
			ssync;
		
			P0.L = lo(PORTGIO_MASKA);
			P0.H = hi(PORTGIO_MASKA);
			R0.L = PG13;
			W[P0] = R0.L;		
			ssync;
		
			// Map the vector table to the PG13_ISR address.
		
			P0.L = LO(EVT12);
			P0.H = HI(EVT12);
			R0.L = LO(PG13_ISR);		//Default IAR value for PORTG int A is 5
			R0.H = HI(PG13_ISR);
			[ P0 ] = R0;
			ssync;
	
				
			// Enable PORT G Interrupt A at SIC level
		
			P0.L = lo(SIC_IMASK);
			P0.H = hi(SIC_IMASK);
			R0 = 0;
			bitset(R0,27);
			[P0] = R0;		//Enable PORT G Interrupt A
			ssync;
		
			// Enable interrupts IVG12
		
			P0.L = LO(IMASK);
			P0.H = HI(IMASK);
			R0.H = 0; 
			R0.L = EVT_IVG12 ;
			[ P0 ] = R0;
			ssync;
			
				
			RETS = [SP++];
		
			RTS;
		
		
InitGPIO_interrupts.end:

/*************************************************************************************/


Fill_Master_Buffer:


			[--SP] = RETS;
			
			R0 =0;
			P0.L = LO(Master_Buffer);
			P0.H = HI(Master_Buffer);
			
			P1 = Transfer_Size;	// Array size
			
			Lsetup(start, end) LC0 = P1;
		
			R0.L = 0x1111;
			R1 = R0;
			
			start: 			
				
				W[P0++] = R0;
					
			end: R0 = R0 + R1;
			
			RETS = [SP++];
		
			RTS;
								
			
Fill_Master_Buffer.end:

/*********************************************************************/


Config_MemDMA:


			[--SP] = RETS;
			
			
			#ifdef HOST_READ
	
			// From ASYNC Memory to Buffer
	
			P0.L = LO(MDMA_S0_START_ADDR);
			P0.H = HI(MDMA_S0_START_ADDR);
			R0.L = 0x0000;
			R0.H = 0x2030;
			[P0] = R0;
			ssync;
			
			P0.L = LO(MDMA_D0_START_ADDR);
			P0.H = HI(MDMA_D0_START_ADDR);
			R0.L = LO(Master_Buffer);
			R0.H = HI(Master_Buffer);
			[P0] = R0;
			ssync;
						
			#else
	
			//From Buffer to ASYNC Memory
	
			P0.L = LO(MDMA_S0_START_ADDR);
			P0.H = HI(MDMA_S0_START_ADDR);
			R0.L = LO(Master_Buffer);
			R0.H = HI(Master_Buffer);
			[P0] = R0;
			ssync;
			
			P0.L = LO(MDMA_D0_START_ADDR);
			P0.H = HI(MDMA_D0_START_ADDR);
			R0.L = 0x0000;
			R0.H = 0x2030;
			[P0] = R0;
			ssync;
			
			#endif
	
			//DMA Configuration for Source
			
			P0.L = LO(MDMA_S0_CONFIG);
			P0.H = HI(MDMA_S0_CONFIG);
			R0.L = WDSIZE_16;
			W[P0] = R0;
			ssync;
			
			
			P0.L = LO(MDMA_S0_X_COUNT);
			P0.H = HI(MDMA_S0_X_COUNT);
			R0.L = Transfer_Size;
			W[P0] = R0;
			ssync;
			
			P0.L = LO(MDMA_S0_X_MODIFY);
			P0.H = HI(MDMA_S0_X_MODIFY);
			R0.L = 2;
			W[P0] = R0;
			ssync;
			
			P0.L = LO(MDMA_S0_Y_COUNT);
			P0.H = HI(MDMA_S0_Y_COUNT);
			R0.L = 0;
			W[P0] = R0;
			ssync;
			
			P0.L = LO(MDMA_S0_Y_MODIFY);
			P0.H = HI(MDMA_S0_Y_MODIFY);
			R0.L = 0;
			W[P0] = R0;
			ssync;
			
			
			//DMA Configuration for Destination.
			
			P0.L = LO(MDMA_D0_CONFIG);
			P0.H = HI(MDMA_D0_CONFIG);
			R0.L = WDSIZE_16 | WNR;
			W[P0] = R0;
			ssync;
			
			
			P0.L = LO(MDMA_D0_X_COUNT);
			P0.H = HI(MDMA_D0_X_COUNT);
			R0.L = Transfer_Size;
			W[P0] = R0;
			ssync;
			
			P0.L = LO(MDMA_D0_X_MODIFY);
			P0.H = HI(MDMA_D0_X_MODIFY);
			R0.L = 2;
			W[P0] = R0;
			ssync;
			
			P0.L = LO(MDMA_D0_Y_COUNT);
			P0.H = HI(MDMA_D0_Y_COUNT);
			R0.L = 0;
			W[P0] = R0;
			ssync;
			
			P0.L = LO(MDMA_D0_Y_MODIFY);
			P0.H = HI(MDMA_D0_Y_MODIFY);
			R0.L = 0;
			W[P0] = R0;
			ssync;
			
			RTS;

Config_MemDMA.end:						
						
			
/*********************************************************************/

HDMA_Config:

	
			[--SP] = RETS;
		
		
			P0 = 7;
			
			
			P1.L = LO(HDMA_Config_Words);
			P1.H = HI(HDMA_Config_Words);
		
			LSETUP(Config_Start, Config_End) LC0 = P0;
		
			Config_Start: 	R0 = W[P1++];
							W[P5] = R0;
			Config_End:		ssync;

			
			//Wait until configuration is complete
		
			
		config_complete:

	
			R0.L = W[P5]; 				//Read HOST_STATUS Register
			CC = BITTST (R0, 0); 		//Check if DMA READY Bit is set
			if !CC jump config_complete; //If not, poll again
	
			RETS = [SP++];
		
			rts;
		
HDMA_Config.end:

/**********************************************************************/

PG13_ISR:


			// First acknowledge the interrupt
			
			R6+= 1;		//ISR Count;
						
			P0.L = lo(PORTGIO_CLEAR);
			P0.H = hi(PORTGIO_CLEAR);
			R1.L = PG13;
			W[P0] = R1.L;
			ssync;

			P0.L = LO(MDMA_S0_CONFIG);
			P0.H = HI(MDMA_S0_CONFIG);
			
			P1.L = LO(MDMA_D0_CONFIG);
			P1.H = HI(MDMA_D0_CONFIG);
			
			// This is required when HOSTDMA is in AUTO Buffer
			R0.L = W[P0];		
			R1.L = 0xFFFE;
			
			R0 = R0 & R1;
			W[P0] = R0;
			ssync;
			
					
			R0.L = W[P1];		
			R1.L = 0xFFFE;
			R0 = R0 & R1;
			W[P1] = R0;
			ssync;
			
			
			// Enable the DMA here. 			
			R0 = 0x0001;		
			
			R1.L = W[P0];
			R0 = R0 | R1;
			W[P0] = R0;
			ssync;
			
			R1.L = W[P1];
			R0 = R0 | R1;
			W[P1] = R0;
			ssync;
					
					
			RTI;
			

			
PG13_ISR.end:



/*********************************************************************/	


