/*
 * ftu_node1.c
 *
 *  Created on: Oct 6, 2015
 *      Author: a0324020
 */


#include "fray.h"
#include "ftu.h"
#include "LED_Show.h"
#include "file_io.h"
#include "stdio.h"
#include "fray_node_config.h"
#include "sys_vim.h"

#ifdef PMU_CYCLE
#include "sys_pmu.h"
#endif

#if ((FrayNodeNumber == 2) && (FRAY_ENABLE_FTU == 1))

unsigned int g_ftuErrorFlag, g_ftuDataRCVED, g_ftuDataTXED;
unsigned int g_frayErrorFlag, g_frayDataRCVED, g_frayDataTXED;

#define MAX_MSG_LENGTH    16     //maximum TX/RX payload length + header length (4 words)
#define MAX_TXRX_BUFFER    8     //8 buffers are used
#define TX_PLC            16     //2-bytes; payload length: TX_PLC*2=32 bytes, eight 32-bit words

// buffer0, 2 for lot 3, 9; Payload is 16 (32 bytes)
// Check the received data at:
// Buffer0 at 0x00 (offset)
// Buffer1 at offset + MAX_MSG_LENGTH  * 4
// Buffer2 at offset + 2*MAX_MSG_LENGTH  * 4
// Buffer3 at offset + 3*MAX_MSG_LENGTH  * 4; ...
unsigned int FRAY_TX_Payload[36] = {0x00000000, 0x00000000, 0x00000000, 0x00000000, //buffer0 header
		                            0x23232323, 0x23232323, 0x23232323,	0x23232323, //buff0 payload
						        	0x55AAFF00,	0x00FFAA55,	0x00000000,	0xdeadbeef, //buff0 payload
									0x00000000, 0x00000000, 0x00000000, 0x00000000, //buffer1 header
	                                0x28282828, 0x28282828, 0x28282828,	0x28282828, //buff1 payload
								    0x55AAFF00,	0x00FFAA55,	0x00000000,	0xdeadbeef, //buff1 payload
									0x00000000, 0x00000000, 0x00000000, 0x00000000, //buffer2 header
									0x00000000, 0x00000000, 0x00000000, 0x00000000, //buff1 payload
									0x00000000, 0x00000000, 0x00000000, 0x00000000  //buff1 payload
							       };

unsigned int FRAY_SysMemory[MAX_TXRX_BUFFER * MAX_MSG_LENGTH];

#pragma DATA_ALIGN (FRAY_SysMemory, 64)

static void configure_node_header(FRAY_ST *Fray_Ptr);
static void triger_tx_static_data(FTU_ST *FTU_Ptr);
static void triger_tx_dynamic_data(FTU_ST *FTU_Ptr);
static void triger_receive_data(FRAY_ST *Fray_Ptr, FTU_ST *FTU_Ptr);

void FTU_Test(FRAY_ST *Fray_Ptr, FTU_ST *FTU_Ptr);

void FTU_Test(FRAY_ST *Fray_Ptr, FTU_ST *FTU_Ptr)
{
	register unsigned int i;

	for (i=0; i<(MAX_TXRX_BUFFER * MAX_MSG_LENGTH); i++)
	   FRAY_SysMemory[i] = 0;

    // buffer 0 is used for TX
	for (i=0; i<(TX_PLC/2+4); i++)
	{
	   FRAY_SysMemory[i] = FRAY_TX_Payload[i];
	}
    // buffer 3 is used for TX, +4 is for header
	for (i=0; i<(TX_PLC/2+4); i++)
	{
	   FRAY_SysMemory[3*MAX_MSG_LENGTH+i] = FRAY_TX_Payload[1*(TX_PLC/2 + 4)+i];
	}
    // buffer 5 is used for TX
	for (i=0; i<(TX_PLC/2 + 4); i++)
	{
	   FRAY_SysMemory[5*MAX_MSG_LENGTH+i] = FRAY_TX_Payload[2*(TX_PLC/2 + 4)+i];
	}

	//Configure the Flexray control registers, enable the interrupts
	Fray_testInit(Fray_Ptr);

	//define the buffer headers and write to FRAY Message RAM
	configure_node_header(Fray_Ptr);

	//Enable FTU, enable the Interrupts, and clear FTU TCR
	FTU_Init(FTU_Ptr, Fray_Ptr, ftuTCR);

	// configure TBA
	FTU_Ptr->TBA_UL = (unsigned int)&FRAY_SysMemory[0];

	// TU RAM Configuration
	// configure Buffer 0/2: System-Memory to Communication Controller
	// TX, Manual Transfer
	// set STXRH, transfer Payload only from SRAM to CC
	// Keep in mind that the offset is 32-bit aligned buffer address
	ftuTCR->FTUTCR_ST[0].TCR_UN.TCR_UL = 0x00044000;
	ftuTCR->FTUTCR_ST[2].TCR_UN.TCR_UL = 0x00044000 + MAX_MSG_LENGTH*2;

    // configure Buffer 1/3/4/5/7: Communication Controller to System-Memory
	// RX, Event Mode, payload only
	// Keep in mind that the offset is 32-bit aligned buffer address
	// Transfer Header and Payload from CC and SRAM
	ftuTCR->FTUTCR_ST[1].TCR_UN.TCR_UL = 0x00030000 + MAX_MSG_LENGTH*1;
	ftuTCR->FTUTCR_ST[3].TCR_UN.TCR_UL = 0x00030000 + MAX_MSG_LENGTH*3;
	ftuTCR->FTUTCR_ST[4].TCR_UN.TCR_UL = 0x00030000 + MAX_MSG_LENGTH*4;
	ftuTCR->FTUTCR_ST[5].TCR_UN.TCR_UL = 0x00030000 + MAX_MSG_LENGTH*5;
	ftuTCR->FTUTCR_ST[7].TCR_UN.TCR_UL = 0x00030000 + MAX_MSG_LENGTH*7;

	// Config Event Mode
	// enable Message Buffer 1/6/7 event for transfer to system memory
	if (TransferOnEventToSRAM == 1)
		FTU_Ptr->ETESMS1_UL = 0x00000000 | (0x1 << 1) | (0x1 << 3) | (0x1 << 4) | (0x1 << 5) | (0x1 << 7);

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

    // Change CC state from CONFIG state to READY state, Also define TXSY and TXST
    // A coldstart node has bits SUCC1.TXST and SUCC1.TXSY set to 1
	Fray_CC_READY(Fray_Ptr, 1, 1);

	// Enable Cold Start
	Fray_AllowColdStart(Fray_Ptr);

	// Change the CC state to RUN
	Fray_StartCommunication(Fray_Ptr);

	while(1){
	}
}

// Configure the headers for all the msg buffers used on this node
// You can put the headers to FRAY_TX_Payload[] and Transfer to MSG along with the payload
static void configure_node_header(FRAY_ST *Fray_Ptr)
{
	HEADER_ST Header;
	BC_ST BufCMD;
	HEADER_ST *Header_Ptr = &Header;
	BC_ST *BC_Ptr = &BufCMD;

	// Buffer config initialization
	Header_Ptr->mbi  = 1;   // message buffer interrupt
	Header_Ptr->txm  = 0;   // transmission mode - continuous mode
	Header_Ptr->ppit = 0;   // Payload Preamble Indicator
	Header_Ptr->cfg  = 0;   // message buffer configuration bit (0=RX, 1 = TX)
	Header_Ptr->chb  = 1;   // Ch B
	Header_Ptr->cha  = 1;   // Ch A
	Header_Ptr->cyc  = 0;   // Cycle Filtering Code (no cycle filtering)
	Header_Ptr->fid  = 0;   // Frame ID
	Header_Ptr->plc  = 0;   // Payload Length
	Header_Ptr->dp   = 0;   // Pointer to start of data in message RAM
	Header_Ptr->sfi  = 0;   // startup frame indicator
	Header_Ptr->syn  = 0;   // sync frame indicator

	BC_Ptr->ibrh = 0;  // input buffer number
	BC_Ptr->stxrh= 0;  // set transmission request
	BC_Ptr->ldsh = 0;  // load data section
	BC_Ptr->lhsh = 0;  // load header section
	BC_Ptr->ibsyh = 1; // check for input buffer busy shadow
	BC_Ptr->ibsys = 1; // check for input buffer busy host
	BC_Ptr->obrs = 0;  // output buffer number
	BC_Ptr->rdss = 0;  // read data section
	BC_Ptr->rhss = 0;  // read header section

	// Message buffers
    // Message buffer 0 or 1 is dedicated to hold the startup frame, the sync frame, or the designated single slot
    // frame as configured by SUCC1.TXST, SUCC1.TXSY, and SUCC1.TSM in the SUC Configuration register
    // 1. In this case it can be reconfigured in DEFAULT_CONFIG or CONFIG state only. This ensures that any
    // node transmits at most one startup / sync frame per communication cycle.

// Static Segement MSG
	// buffer #0   TX MSG
	Header_Ptr->fid  = 3;   // frame ID
	Header_Ptr->dp   = 0x90; // Pointer to start of data in message RAM
	Header_Ptr->cfg  = 1;    // TX frame
	Header_Ptr->syn  = 1;    // sync frame indicator
	Header_Ptr->sfi  = 1;    // startup frame indicator
	Header_Ptr->cha  = 1;    // Ch A
	Header_Ptr->chb  = 1;    // No transmission on Ch B
	Header_Ptr->plc  = 16;	 // 32 byte payload
	Header_Ptr->crc  = header_crc_calc(Header_Ptr);

	BC_Ptr->lhsh = 1;  // load header section
	BC_Ptr->ibrh = 0;  // input buffer number
	Fray_PrepareHeader(Fray_Ptr, Header_Ptr);
	Fray_Transmit(Fray_Ptr, BC_Ptr);          //transfer header and data to FRAY MSG RAM


	// Buffer #1, RX MSG
	Header_Ptr->fid  = 1;    // frame ID
	Header_Ptr->dp   = 0x80; // Pointer to start of data in message RAM
	Header_Ptr->cfg  = 0;    // RX frame
	Header_Ptr->cyc  = 0x14;  //every 16th cycle at 4/20/36/52 cycle
	Header_Ptr->syn  = 1;    // sync frame indicator
	Header_Ptr->sfi  = 0;    // startup frame indicator
	Header_Ptr->cha  = 1;    // Ch A
	Header_Ptr->chb  = 0;    // Ch B
	Header_Ptr->plc  = 16;	 // 16 byte payload
	Header_Ptr->crc  = 0;

	BC_Ptr->lhsh = 1;  // load header section
	BC_Ptr->ibrh = 1;  // input buffer numberinput buffer number:0x80, 0x85, 0x8A, 0x8F, 0x94, 0x99, 0x9E, 0xA3
	Fray_PrepareHeader(Fray_Ptr, Header_Ptr);
	Fray_Transmit(Fray_Ptr, BC_Ptr);          //transfer header and data to FRAY MSG RAM

	// Buffer #4, RX MSG
	Header_Ptr->fid  = 2;    // frame ID
	Header_Ptr->dp   = 0x88; // Pointer to start of data in message RAM
	Header_Ptr->cfg  = 0;    // RX frame
	Header_Ptr->cyc  = 0x19;  //every 16th cycle at 9/25/41/57 cycle
	Header_Ptr->syn  = 1;    // sync frame indicator
	Header_Ptr->sfi  = 0;    // startup frame indicator
	Header_Ptr->cha  = 1;    // Ch A
	Header_Ptr->chb  = 0;    // Ch B
	Header_Ptr->plc  = 16;
	Header_Ptr->crc  = 0;

	BC_Ptr->lhsh = 1;  // load header section
	BC_Ptr->ibrh = 4;  // input buffer numberinput buffer number:0x80, 0x85, 0x8A, 0x8F, 0x94, 0x99, 0x9E, 0xA3
	Fray_PrepareHeader(Fray_Ptr, Header_Ptr);
	Fray_Transmit(Fray_Ptr, BC_Ptr);          //transfer header and data to FRAY MSG RAM

	// Buffer #3, receive msg
	Header_Ptr->fid  = 5;    // frame ID
	Header_Ptr->dp   = 0xA0; // Pointer to start of data in message RAM
	Header_Ptr->cfg  = 0;    // RX frame
	Header_Ptr->cyc  = 0x23;  //every 32th cycle at 3/35 cycle
	Header_Ptr->syn  = 0;    // sync frame indicator
	Header_Ptr->sfi  = 0;    // startup frame indicator
	Header_Ptr->cha  = 1;    // Ch A
	Header_Ptr->chb  = 0;    // Ch B
	Header_Ptr->plc  = 16;
	Header_Ptr->crc  = 0;

	BC_Ptr->lhsh = 1;  // load header section
	BC_Ptr->ibrh = 3;  // input buffer number:0x80, 0x85, 0x8A, 0x8F, 0x94, 0x99, 0x9E, 0xA3
	Fray_PrepareHeader(Fray_Ptr, Header_Ptr);
	Fray_Transmit(Fray_Ptr, BC_Ptr);          //transfer header and data to FRAY MSG RAM

	// buffer #2   TX MSG
	Header_Ptr->fid  = 8;   // frame ID
	Header_Ptr->dp   = 0xB8; // Pointer to start of data in message RAM
	Header_Ptr->cfg  = 1;    // TX frame
	Header_Ptr->cyc  = 0x18;  //every 16th cycle at 8/24/40/56 cycle
	Header_Ptr->syn  = 0;    // sync frame indicator
	Header_Ptr->sfi  = 0;    // startup frame indicator
	Header_Ptr->cha  = 1;    // Ch A
	Header_Ptr->chb  = 0;    // No transmission on Ch B
	Header_Ptr->plc  = 16;	 // 32 byte payload
	Header_Ptr->crc  = header_crc_calc(Header_Ptr);

	BC_Ptr->lhsh = 1;  // load header section
	BC_Ptr->ibrh = 2;  // input buffer number
	Fray_PrepareHeader(Fray_Ptr, Header_Ptr);
	Fray_Transmit(Fray_Ptr, BC_Ptr);          //transfer header and data to FRAY MSG RAM

// Dynamic Segement MSG
	// buffer #5, RX MSG
	Header_Ptr->fid  = 9;     // frame ID
	Header_Ptr->dp   = 0x200; // Pointer to start of data in message RAM
	Header_Ptr->cfg  = 0;    // RX frame
	Header_Ptr->cyc  = 0;  //every 16th cycle at 8/24/40/56 cycle
	Header_Ptr->syn  = 0;    // sync frame indicator
	Header_Ptr->sfi  = 0;    // startup frame indicator
	Header_Ptr->cha  = 1;    // Ch A
	Header_Ptr->chb  = 0;    // No transmission on Ch B
	Header_Ptr->plc  = 16;
	Header_Ptr->crc  = 0;

	BC_Ptr->lhsh = 1;  // load header section
	BC_Ptr->ibrh = 5;  // input buffer number
	Fray_PrepareHeader(Fray_Ptr, Header_Ptr);
	Fray_Transmit(Fray_Ptr, BC_Ptr);          //transfer header and data to FRAY MSG RAM

	// buffer #7, RX MSG
	Header_Ptr->fid  = 16;     // frame ID
	Header_Ptr->dp   = 0x3C0; // Pointer to start of data in message RAM
	Header_Ptr->cfg  = 0;    // RX frame
	Header_Ptr->cyc  = 0;  //every 16th cycle at 8/24/40/56 cycle
	Header_Ptr->syn  = 0;    // sync frame indicator
	Header_Ptr->sfi  = 0;    // startup frame indicator
	Header_Ptr->cha  = 1;    // Ch A
	Header_Ptr->chb  = 0;    // No transmission on Ch B
	Header_Ptr->plc  = 16;
	Header_Ptr->crc  = 0;

	BC_Ptr->lhsh = 1;  // load header section
	BC_Ptr->ibrh = 7;  // input buffer number
	Fray_PrepareHeader(Fray_Ptr, Header_Ptr);
	Fray_Transmit(Fray_Ptr, BC_Ptr);          //transfer header and data to FRAY MSG RAM
}

// We TX data to MSG RAM at every cycle start. CC will transmit the data to FRAY BUS based on
// the filters defined in the header of the buffer
static void triger_tx_static_data(FTU_ST *FTU_Ptr)
{
	// transfer Message Buffer 0/2 to CC
	FTU_Ptr->TTCCS1_UL  = (0x1 << 0);
	FTU_Ptr->TTCCS1_UL  = (0x1 << 2);
}

// We TX data to MSG RAM at every cycle start. CC will transmit the data to FRAY BUS based on
// the filters defined in the header of the buffer
static void triger_tx_dynamic_data(FTU_ST *FTU_Ptr)
{
	//no dynamics data for transmission
}

// This function is used only when the Transfer on EVENT is disabled
// If ETESMS is enabled, the NDAT1 will be zero
static void triger_receive_data(FRAY_ST *Fray_Ptr, FTU_ST *FTU_Ptr)
{
	unsigned int ndat1;

	// IF FTU EVENt is enabled, ndat1 is always 0
	// Buffer is automatically transfered to system memory
	ndat1 = Fray_Ptr->NDAT1_UN.NDAT1_UL;

    if ( 0x2 == (ndat1 & 0x2)) //buffer 1 from Node 0, slot  1
    {
    	FTU_Ptr->TTSMS1_UL   = 0x02;
    }
    if ( (1 << 3) == (ndat1 & (1 << 3))) //buffer 3 from Node 0, slot  5
    {
    	FTU_Ptr->TTSMS1_UL   = (1<<3);
    }
    if ( (1 << 4) == (ndat1 & (1 << 4))) //buffer 4 from Node 1, slot  2
    {
    	FTU_Ptr->TTSMS1_UL   = (1<<4);
    }
    if ( (1 << 5) == (ndat1 & (1 << 5))) //buffer 5 from Node 0, slot  9
    {
    	FTU_Ptr->TTSMS1_UL   = (1<<5);
    }
    if ( (1 << 7) == (ndat1 & (1 << 7))) //buffer 7 from Node 01 slot  16
    {
    	FTU_Ptr->TTSMS1_UL   = (1<<7);
    }
}

#pragma WEAK(ftuErrorNotification)
void ftuErrorNotification(FTU_ST *FTU_Ptr, unsigned int notification)
{
   register int eFlag;

   eFlag = FTU_Ptr->TEIR_UN.TEIR_UL;

   if(0x01 == (eFlag & 0x01)){
	   //FAC error
    	g_ftuErrorFlag = 1;
        gio_LED_Blinky(3);
   }
   if(0x02 == (eFlag & 0x02)){
	   //TNR error
	   g_ftuErrorFlag = 1;
       gio_LED_Blinky(3);
   }
   if(0x0 != (eFlag & 0x070)){
	   //WSTAT error
	   g_ftuErrorFlag = 1;
       gio_LED_Blinky(3);
   }
   if(0x0 != (eFlag & 0x700)){
	   //RSTAT error
	   g_ftuErrorFlag = 1;
       gio_LED_Blinky(3);
   }
   if(0x10000 == (eFlag & 0x10000)){
	   //Parity error
       gio_LED_Blinky(3);
	   g_ftuErrorFlag = 1;
   }
   if(0x20000 == (eFlag & 0x20000)){
	   //MPV error
	   g_ftuErrorFlag = 1;
       gio_LED_Blinky(3);
   }
}


#pragma WEAK(ftuStatusChangeNotification)
void ftuStatusChangeNotification(FTU_ST *Fray_Ptr, unsigned int notification)
{
#define BUF1_RX    0x002
#define BUF3_RX    0x004
#define BUF4_RX    0x005
#define BUF5_RX    0x006
#define BUF7_RX    0x008

#define BUF0_TX    0x101
#define BUF2_TX    0x103

	register int vect;

	vect= notification;
    if( 0 != (vect & (BUF1_RX | BUF3_RX | BUF4_RX | BUF5_RX | BUF7_RX)))
    {
    	g_ftuDataRCVED = 1;       //RX
		if (frayREG1->MTCCV_UN.MTCCV_ST.ccv_B6 == 0x20)
 			  gio_LED_Blinky(7);
	}
}

#pragma WEAK(frayErrorNotification)
void frayErrorNotification(FRAY_ST *Fray_PST, unsigned int notification)
{
	 gio_LED_Blinky(3);
}

#pragma WEAK(frayStatusChangeNotification)
void frayStatusChangeNotification(FRAY_ST *Fray_Ptr, unsigned int notification)
{
	if (notification == ( 0x1 << 2))   //CYCS
	{
		triger_tx_static_data(ftuREG);
		if (Fray_Ptr->MTCCV_UN.MTCCV_ST.ccv_B6 == 0x10)
 			  gio_LED_Blinky(0);

	}
	//Only when RXI Fray INT is defined, and the Transfer On Event is disabled
	if ((notification == (1 << 4)) && (TransferOnEventToSRAM == 0))   //RXI
	{
        triger_receive_data(Fray_Ptr, ftuREG);   //used if transfer on FTU EVEN is disabled
	}
	if (notification == ( 0x1 << 15))   //SDS
	{
		triger_tx_dynamic_data(ftuREG);
		if (Fray_Ptr->MTCCV_UN.MTCCV_ST.ccv_B6 == 0x10)
 			  gio_LED_Blinky(1);

	}
}

#endif
