/*
 * ftu.c
 *
 *  Created on: Sep 22, 2015
 *      Author: a0324020
 */

#include "ftu.h"
#include "fray.h"
#include "fray_node_config.h"
#include "sys_vim.h"

#if (FRAY_ENABLE_FTU == 1)

void FTU_Init(FTU_ST *FTU_Ptr, FRAY_ST *FRAY_Ptr, FTURAM_ST *TCR_Ptr)
{
    unsigned int i;
	//Clear CCTC, TTSM, ETESM. Disable Parity protection
    //Enable FTU
	FTU_Ptr->GCS_UN.GCS_UL = 0x00057033;

	//config the TBA and TCR
	FTU_Ptr->SAMP_UL = 0x08000000;
	FTU_Ptr->EAMP_UL = 0x08040000;

	for (i=0; i< 128; i++)
		TCR_Ptr->FTUTCR_ST[i].TCR_UN.TCR_UL = 0x00000000;

	//enable FTU transfer status interrupt line
	FTU_Ptr->GCS_UN.GCS_ST.SILE_B1 = 0x1;

	//enable FTU error interrupt line
	FTU_Ptr->GCS_UN.GCS_ST.EILE_B1 = 0x1;

	//enable all the transfer error interrupts
	FTU_Ptr->TEIRES_UN.TEIRES_UL = 0x773;

	//enable the interrupt in the FTU.
	// buffers (to CC) interrupt enabled, we only use 8 buffers
	FTU_Ptr->TCCIES1_UL = 0x0000FFFF;

	//buffers (to system memory) interrupt enabled
    FTU_Ptr->TSMIES1_UL = 0x0000FFFF;

	//Enable FTU
	FTU_Ptr->GCS_UN.GCS_UL |= 0x1;  //Enable FTU

    // RUN FTU
	//FTU_Ptr->GCR_UN.GCR_UL = 0x00000002; // RUN TU
}


/*--------------------------------------------------------------------------*/
/* TCR transfer initialization */
/* int TCR_Init(int channel, int header, int payload, int offset, int dir) */
/* */
/* int channel:FTU channel */
/* int header:  1: transfers header;    0: no header transfer */
/* int payload: 1: transfers payload;   0: no payload transfer */
/* int dir:     1: transfer to SM;      0: transfer to CC */
/* int offset: transfer start offset */
/* */
/* returns 0 */
/*--------------------------------------------------------------------------*/
int FTU_TCR_Init(FTURAM_ST *TCR_Ptr, int channel, int header, int payload, int offset, int dir)
{
	int value = 0;
	if (dir != 0) // if direction is other than to CC
	dir = 2; // direction will be SM
	value = value + (header << (15 + dir));
	value = value + (payload << (14 + dir));
	value = value + offset;
	TCR_Ptr->FTUTCR_ST[channel].TCR_UN.TCR_UL = value;
	return(0);
}

void FTU_Enable(FTU_ST *FTU_Ptr)
{
	FTU_Ptr->GCS_UN.GCS_UL |= 0x01;// enable FTU
}

void FTU_Disable(FTU_ST *FTU_Ptr)
{
	FTU_Ptr->GCR_UN.GCR_UL |= 0x01;// disable FTU
}

// Transfer to SM interrupt enable/Disable
// TSMIES registers
int FTU_TOSM_IntEnable(FTU_ST *FTU_Ptr, int TSMIE0_val, int TSMIE1_val, int TSMIE2_val, int TSMIE3_val)
{
	// transfer to SM
	FTU_Ptr->TSMIES1_UL = TSMIE0_val;
	FTU_Ptr->TSMIES2_UL = TSMIE1_val;
	FTU_Ptr->TSMIES3_UL = TSMIE2_val;
	FTU_Ptr->TSMIES4_UL = TSMIE3_val;
	return 0;
}

// Transfer to CC interrupt enable/Disable
// TCCIES registers
int FTU_TOCC_IntEnable(FTU_ST *FTU_Ptr, int TCCIE0_val, int TCCIE1_val, int TCCIE2_val, int TCCIE3_val)
{
	// transfer to CC
	FTU_Ptr->TCCIES1_UL = TCCIE0_val;
	FTU_Ptr->TCCIES2_UL = TCCIE1_val;
	FTU_Ptr->TCCIES3_UL = TCCIE2_val;
	FTU_Ptr->TCCIES4_UL = TCCIE3_val;
	return 0;
}

// Trigger the Transfer to System Memory
// TTSMS registers
int FTU_TOSM_Trigger(FTU_ST *FTU_Ptr, int TTSM0_val, int TTSM1_val, int TTSM2_val, int TTSM3_val)
{
	// transfer to buffer
	FTU_Ptr->TTSMS1_UL = TTSM0_val;
	FTU_Ptr->TTSMS2_UL = TTSM1_val;
	FTU_Ptr->TTSMS3_UL = TTSM2_val;
	FTU_Ptr->TTSMS4_UL = TTSM3_val;
	return 0;
}

// Trigger the Transfer to Communication Controller
// TTCCS registers
int FTU_TOCC_Trigger(FTU_ST *FTU_Ptr, int TTCC0_val, int TTCC1_val, int TTCC2_val, int TTCC3_val)
{
	// transfer to buffer
	FTU_Ptr->TTCCS1_UL = TTCC0_val;
	FTU_Ptr->TTCCS2_UL = TTCC1_val;
	FTU_Ptr->TTCCS3_UL = TTCC2_val;
	FTU_Ptr->TTCCS4_UL = TTCC3_val;
	return 0;
}

//Enable/Disable Transfer on Event to System Memory
int FTU_Event_ETESMS(FTU_ST *FTU_Ptr, int ETESM0_val, int ETESM1_val, int ETESM2_val, int ETESM3_val)
{
	// transfer to SM
	FTU_Ptr->ETESMS1_UL = ETESM0_val;
	FTU_Ptr->ETESMS2_UL = ETESM1_val;
	FTU_Ptr->ETESMS3_UL = ETESM2_val;
	FTU_Ptr->ETESMS4_UL = ETESM3_val;
	return 0;
}

void FTU_Transfer_INT_Enable(FTU_ST *FTU_Ptr)
{
	FTU_Ptr->GCS_UN.GCS_UL |= (0x01 << 5);   // enable int0
}

void FTU_Error_INT_Enable(FTU_ST *FTU_Ptr)
{
	FTU_Ptr->GCS_UN.GCS_UL |= (0x01 << 4);   // enable int1
}

/*--------------------------------------------------------------*/
/* Clear Event to System Memory register*/
/* void FTU_ETESM_clear() */
/*--------------------------------------------------------------*/
void FTU_ETESM_Clear(FTU_ST *FTU_Ptr)
{
	FTU_Ptr->GCS_UN.GCS_UL = 1<<14;
	FTU_Ptr->GCR_UN.GCR_UL = 1<<14;
}
/*---------------------------------------------------------------*/
/* Clear Trigger Transfer to Communication Controller register */
/* void FTU_TTCC_clear() */
/*---------------------------------------------------------------*/
void FTU_TTCC_Clear(FTU_ST *FTU_Ptr)
{
	FTU_Ptr->GCS_UN.GCS_UL = 1<<13;
	FTU_Ptr->GCR_UN.GCR_UL = 1<<13;
}
/*---------------------------------------------------------------*/
/* Clear Trigger Transfer to System Memory register */
/* void FTU_TTSM_clear() */
/*---------------------------------------------------------------*/
void FTU_TTSM_Clear(FTU_ST *FTU_Ptr)
{
	FTU_Ptr->GCS_UN.GCS_UL = 1<<12;
	FTU_Ptr->GCR_UN.GCR_UL = 1<<12;
}


/** @fn void frayLowLevelInterrupt(void)
*   @brief FRAY Level 1 Interrupt Handler
*/
#pragma CODE_STATE(ftuTransferInterrupt, 32)
#pragma INTERRUPT(ftuTransferInterrupt, IRQ)

void ftuTransferInterrupt(void)
{
	unsigned int i, j, k;
	j = ftuREG->TCCO1_UL;
	k = ftuREG->TSMO1_UL;
	i = ftuREG->TOFF_UN.TOFF_UL;
	ftuStatusChangeNotification(ftuREG, i);
}

/** @fn void frayLowLevelInterrupt(void)
*   @brief FRAY Level 1 Interrupt Handler
*/
#pragma CODE_STATE(ftuErrorInterrupt, 32)
#pragma INTERRUPT(ftuErrorInterrupt, IRQ)
void ftuErrorInterrupt(void)
{
	ftuErrorNotification(ftuREG, 0);
}

#else

#pragma CODE_STATE(ftuTransferInterrupt, 32)
#pragma INTERRUPT(ftuTransferInterrupt, IR)

void ftuTransferInterrupt(void)
{
}

/** @fn void frayLowLevelInterrupt(void)
*   @brief FRAY Level 1 Interrupt Handler
*/
#pragma CODE_STATE(ftuErrorInterrupt, 32)
#pragma INTERRUPT(ftuErrorInterrupt, IRQ)
void ftuErrorInterrupt(void)
{
}
#endif
