/*******************************************************************
 *
 *    DESCRIPTION: FlexRay Drivers
 *
 *******************************************************************/ 

#include <fray.h>
#include <fray_ram.h>
#include"LED_Show.h"
#include "sys_vim.h"


void Fray_testInit(FRAY_ST *Fray_Ptr)
{
	// Configure FlexRay, basic parameters
	Fray_Init(Fray_Ptr);  //same for all nodes; GTU, PTRC, SUCC, det regs

	// Switch to READY state from CONFIGURE state
	// The communication controller can transit to the following states from READY:
	// • To CONFIG state by writing SUCC1.CMD(3-0) = 0001 (CONFIG command)
	// • To WAKEUP state by writing SUCC1.CMD(3-0) = 0011 (WAKEUP command)
	// • To STARTUP state by writing SUCC1.CMD(3-0) = 0100 (RUN command)
	// TXSY =1, TXST=1
	// This node is coldstarter and sync node
	//Fray_CC_READY(Fray_Ptr, 1, 1);

	// Initialize Interrupts
	Fray_Ptr->EIR_UN.EIR_UL       = 0xFFFFFFFF; // Clear Error Int.
	Fray_Ptr->SIR_UN.SIR_UL       = 0xFFFFFFFF; // Clear Status Int.
	Fray_Ptr->SILS_UN.SILS_UL     = 0x00000000; // all Status Int to cc_int0
	Fray_Ptr->SIER_UN.SIER_UL     = 0xFFFFFFFF; // disable all Status Ints
	Fray_Ptr->SIES_UN.SIES_UL     = 0x00000000
	                              | (0x01 << 2)  //Enable CYCSE Int
								  | (0x01 << 4)  //RX INT
								  | (0x01 << 15); //start of dynamic segment int
	Fray_Ptr->ILE_UN.ILE_UL       = 0x00000003; // enable eray_int0

}

/***********************************************************************
	Fray_Init

	The function shall internally store the configuration address to enable
	subsequent API calls to access the configuration.
***********************************************************************/

void Fray_Init(FRAY_ST *Fray_Ptr)
{
	// Wait for PBSY bit to clear - POC not busy
	while(((Fray_Ptr->SUCC1_UN.SUCC1_UL) & 0x00000080) != 0);

	// write SUCC1 configuration
    // [27:24]=0xF: CC and MTS are for both channel A and channel B
	// [23:20]=0x1: TSM=0, All slot mode; WUCS=0, send wakeup pattern on channel A
	//              PTA=1F, PTA=0x1F
	// [15:11]=0x1F: cold start attempts
	// TXSY[9]=1, TXST[8]=1
	Fray_Ptr->SUCC1_UN.SUCC1_UL = 0x0F1FF800 | CMD_CONFIG;

	// Check if POC has accepted last command
	if ((Fray_Ptr->SUCC1_UN.SUCC1_UL & 0xF) == 0x0) return 1;
	// Wait for PBSY bit to clear - POC not busy
	while ((Fray_Ptr->SUCC1_UN.SUCC1_UL & 0x00000080) != 0x0);

	//Write WRC register (message RAM Configuration register)
	//It defines the number of message buffers assigned to the static
	//segment, dynamic segment, and FIFO. The register can be written
	//during DEFAULT_CONFIG or CONFIG state only.
	// LCB[23:16]=0x10=16d: Last config buffer,# of msg buffer=0x16+1=17.  >=80h, no message buffer configured; The maximum number of message buffers is 128
	// FFB[15:8]= 64d: First buffer of FIFO; 64 buffers are assigned to FIFO.  >80h, No message buffer assigned to the FIFO
	// FDB[ 7:0]= 8d (0..3..7 static, 8..23 dyn., 0 fifo); First dynamic buffer, 0~(8-1) for static segment
	// #dynamic buffers = LCB - FFB - FDB = 16 - 8 = 8
	Fray_Ptr->MRC_UN.MRC_UL       = 0x00108108;

	//Configure PRT parameters
	// RWP[31:26]: 2, Repetition of transmission wakeup pattern. pWakeupPattern = 2h
	// RXW[24:16]: 0x4c=76d, Wakeup symbol receive window length(# of bit time). gdWakeupSymbolRxWindow = 76d,
	// BRP[15:14]: Baud rate prescaler. BRP = 0: 10 MBit/s (Sample Clock Period = 12.5ns; 1 µT = 25ns; Samples per µT = 2)
	// SPP[13:12]: Strobe Point Position, has to be 0x0 (flexray 2.1 spec)
	// CASM[10-4]: 43h, Collision avoidance symbol max (in bit times). CASM[6] == 1
	// TSST[3-0], gdTSSTransmitter = Ah; These bits configure the duration of the transmission start sequence (TSS) in terms of bit times
	// (1 bit time = 4uT = 100ns @ 10Mbps).
	// CASM[10-4], 43h,CASM[6] == 1
	Fray_Ptr->PRTC1_UN.PRTC1_UL   = 0x084C043A;

	// gdWakeupSymbolTxLow = 60d, gdWakeupSymbolTxIdle = 180d, gdWakeupSymbolRxLow = 18d, gdWakeupSymbolRxIdle = 18d
    // TXL[29:24], Wakeup symbol transmit low (in bit times). TXL=0x3C=60
	// TXI[23:16], Wakeup symbol transmit idle (in bit times).TXI=0xB4=180
	// RXL[13:8],  Wakeup symbol receive low (in bit times).  RXL=0x12=18
	// RXI[5:0],   Wakeup symbol receive idle (in bit times). RXI=0x12=18
	Fray_Ptr->PRTC2_UN.PRTC2_UL   = 0x3CB41212;

	//Static frame payload length
	// SLT[28:16], pLatestTransmit = 0d = 0h; Start of latest transmit (in minislots).
	// These bits configure the maximum minislot value allowed before inhibiting new frame transmissions in the
	// Dynamic Segment of the cycle. There is no transmission in dynamic segment if SLT(12-0) is set to zero.
	// SFDL[7:0], gPayloadLengthStatic = 9h; Static frame data length in double bytes. payload = 16*2 bytes
	Fray_Ptr->MHDC_UN.MHDC_UL     = 0x010D0010;

	//Init GTU
	// UT[19:0], pMicroPerCycle = 224000d = 36B00h; Microtick per communication cycle (in microticks).
	// so 1 communication cycle is 5.6ms (224000*25ns)
	Fray_Ptr->GTUC1_UN.GTUC1_UL   = 0x00036B00;

	//Flexray spec: Minimum of two sync nodes required for clock synchronization and startup
	// SNM[19:16], Sync node max (in frames). These bits configure the maximum number of frames within a
	//             cluster with sync frame indicator bit SYN set.
	//             gSyncodeMax = 8h;  Sync node max (2~15).
	// MPC[13:0],  Macrotick per cycle (in macroticks).
	//             gMacroPerCycle =  5600d = 15E0h
	// So, pdMacrotick = 40 microticks = 1uS. (640000/16000)
	Fray_Ptr->GTUC2_UN.GTUC2_UL   = 0x000815E0;

	// Macrotick and Microtick initial offset
	// MIOB[30:24], Macrotick initial offset channel B (in macroticks).
	// MIOA[22:16], gMacroInitialOffset = 6h, Macrotick initial offset channel A (in macroticks).
	// UIOB[15:8],  Microtick initial offset channel B (in microticks).
	// UIOA[7:0],   pMicroInitialOffset = 24d = 18h, Microtick initial offset channel A (in microticks).
	Fray_Ptr->GTUC3_UN.GTUC3_UL   = 0x06061818;

    // Correction Offset and NIT
	// OCS[29:16], gOffsetCorrectionStart - 1 = 9601d = 2581h, Offset correction start (in macroticks).
	// NIT[13:0],  gMacroPerCycle - gdNIT - 1 = 8601d = 2199h, Network idle time start (in macroticks).
	// For this FlexRay module the offset correction start is required to be GTUC4.OCS >= GTUC4.NIT + 1 = k+1
	// symbol window length=GTUC4.NIT-(static L+Dynamic L+dynamic offset-1)
	//                     =2787-(86*8+346*4+4-2-1)=714 macroticks
	// NIT length = m+1-k = GTUC2.MPC+1-k=5600+1-2787=2815 macroticks
	Fray_Ptr->GTUC4_UN.GTUC4_UL   =  0x0AE40AE3;

	// DEC[31:24], pDecodingCorrection = 51d = 33h, Decoding correction (in microticks).
	// CDD[20:16], pClusterDriftDamping = 1h, Cluster drift damping (in microticks).
	// DCA[7:0],   pDelayCompensation = 3h, Delay compensation channel A (in microticks).
	Fray_Ptr->GTUC5_UN.GTUC5_UL   = 0x33010303;

	// MOD[26:16], pdMaxDrift = 337d = 151h, Maximum oscillator drift (in microticks). Maximum drift offset between two nodes
	// ASR[10:0],pdAcceptedStartupRange = 129d = 81h, Accepted startup range (in microticks). Number of microticks
	Fray_Ptr->GTUC6_UN.GTUC6_UL   = 0x01510081;

	/*Static segments */
	// NSS[25:16], gNumberOfStaticSlots = 8d; the number of static slots in a cycle(2~1023)
	// SSL[9:0],   gdStaticSlot = 56h  = 86d (in macroticks); the duration of a static slot (4~661).
	// Static segment length = 86 * 8 = 688 macroticks
	Fray_Ptr->GTUC7_UN.GTUC7_UL   = 0x00080056;

	/*Dynamic segments */
	// NMS[28:16], gNumberOfMinislots = 15Ad = 346h; Number of minislots in the dynamic segment of a cycle.
	// MSL[5:0],   gdMinislot = 4h;  Minislot length (in macroticks).
	Fray_Ptr->GTUC8_UN.GTUC8_UL   = 0x015A0004;

    /* Action piont for Static, Dynamic and symbol window */
	// DSI[17:16]: gdDynamicSlotIdlePhase = 1; Dynamic slot idle phase (in minislots).
	// MAPO[12:8]: gdMinislotActionPointOffset = 2; Minislot action point offset (in macroticks).
	// APO[5:0]:   gdActionPointOffset = 4h; Action point offset (in macroticks)
	// dynamic segment offset is ActionPointOffset - MinislotActionPointOffset
	Fray_Ptr->GTUC9_UN.GTUC9_UL   = 0x00010204;

	/*Clock Synchronization */
	// MRC[26:16], pRateCorrectionOut = 337d = 151h, Maximum rate correction (in microticks).
	// MOC[13:0],  pOffsetCorrectionOut = 205d = CDh, Maximum offset correction (in microticks).
	Fray_Ptr->GTUC10_UN.GTUC10_UL = 0x015100CD;

	// pExternRateCorrection = 0, pExternOffsetCorrection = 0, no ext. clk. corr.
	Fray_Ptr->GTUC11_UN.GTUC11_UL = 0x00000000;

	// System Universal Control (SUC).	The SUC controls the following functions:
	// Configuration; Wakeup;  Startup;  Normal Operation;  Passive Operation;  Monitor Mode
	// gListenNoise = Fh, pdListenTimeout = 224674d = 36DA2h
	// LTN[27:24]: 0xF, Listen timeout noise. Configures the upper limit for the startup and wakeup listen timeout in the
	//                  presence of noise. Must be identical in all nodes of a cluster.
	// LT[20:0]: Listen timeout. Configures the upper limit of the startup and wakeup listen timeout.
	Fray_Ptr->SUCC2_UN.SUCC2_UL   = 0x0F036DA2;

	// WCF[7:4]: 0xF, Maximum without clock correction fatal. gMaxWithoutClockCorrectionFatal = Fh
	// WCP[3:0]: 0xF, Maximum without clock correction passive
	Fray_Ptr->SUCC3_UN.SUCC3_UL   = 0x000000FF;
}

/***********************************************************************
	Fr_PrepareHeader
	The function Fr_PrepareLPdu shall perform the following tasks on FlexRay
	CC Fr_CtrIdx:
	1. Figure out the physical resource (e.g., a buffer) mapped to the processing of
	the FlexRay frame identified by Fr_LPduIdx.
	2. Configure the physical resource (a buffer) appropriate for Header_Ptr
	operation (SlotId, Cycle filter, payload length, header CRC, etc.) if the MCG
	uses the reconfiguration feature.
***********************************************************************/
void Fray_PrepareHeader(FRAY_ST *Fray_PST, HEADER_ST *Header_Ptr)
{
	int wrhs1;
	int wrhs2;
	wrhs1  = ((Header_Ptr->mbi) & 0x1)  <<29;
	wrhs1 |= (Header_Ptr->txm & 0x1)  << 28;
	wrhs1 |= (Header_Ptr->ppit & 0x1) << 27;
	wrhs1 |= (Header_Ptr->cfg & 0x1)  << 26;
	wrhs1 |= (Header_Ptr->chb & 0x1)  << 25;
	wrhs1 |= (Header_Ptr->cha & 0x1)  << 24;
	wrhs1 |= (Header_Ptr->cyc & 0x7F) << 16;
	wrhs1 |= (Header_Ptr->fid & 0x7FF);
	Fray_PST->WRHS1_UN.WRHS1_UL = wrhs1;

	wrhs2  = ((Header_Ptr->plc & 0x7F) << 16) | (Header_Ptr->crc & 0x7FF);
	Fray_PST->WRHS2_UN.WRHS2_UL = wrhs2;

	Fray_PST->WRHS3_UN.WRHS3_UL = (Header_Ptr->dp & 0x7FF);
}

/***********************************************************************
	Fray_INT_Disable
***********************************************************************/
void Fray_INT_Disable(FRAY_ST *Fray_Ptr)
{
	// Initialize Interrupts
	Fray_Ptr->EIR_UN.EIR_UL   = 0xFFFFFFFF;	// Clear Error Int.
	Fray_Ptr->SIR_UN.SIR_UL   = 0xFFFFFFFF;	// Clear Status Int.
	Fray_Ptr->SILS_UN.SILS_UL = 0x00000000;	// all Status Int. to eray_int0
	Fray_Ptr->SIER_UN.SIER_UL = 0xFFFFFFFF;	// Disable all Status Int.
	Fray_Ptr->ILE_UN.ILE_UL   = 0x00000000; // CC_int0 and CC_int1 are disabled
}

/***********************************************************************
	Fray_INT_Enable, 0x1: enable int0, 0x2=int1, 0x3=int0 and int1
***********************************************************************/
void Fray_INT_Enable(FRAY_ST *Fray_Ptr, unsigned int value)
{
	Fray_Ptr->ILE_UN.ILE_UL   = value; // CC_int0 and CC_int1
}

/***********************************************************************
	Fray_CC_Config

   CC is in default configuration mode after reset
   write SUCC1 configuration to enter the CONFIG State
***********************************************************************/
void Fray_CC_CONFIG(FRAY_ST *Fray_Ptr)
{
	// Wait for PBSY bit to clear - POC not busy
	while(((Fray_Ptr->SUCC1_UN.SUCC1_UL) & 0x00000080) != 0);

	// write SUCC1 configuration
    // [27:24]=0xF: CC and MTS are for both channel A and channel B
	// [23:20]=0x1: TSM=0, All slot mode; WUCS=0, send wakeup pattern on channel A
	//              PTA=1F, PTA=0x1F
	// [15:11]=0x1F: cold start attempts
	// TXSY[9]=1, TXST[8]=1
	Fray_Ptr->SUCC1_UN.SUCC1_UL = 0x0F1FF800 | CMD_CONFIG;
	// Check if POC has accepted last command
	if ((Fray_Ptr->SUCC1_UN.SUCC1_UL & 0xF) == 0x0) return 1;
	// Wait for PBSY bit to clear - POC not busy
	while ((Fray_Ptr->SUCC1_UN.SUCC1_UL & 0x00000080) != 0x0);
}

/***********************************************************************
	Fray_CC_Ready
	
	Transition from Condifure state to Ready state
	After unlocking CONFIG state and writing SUCC1.CMD(3-0) = 0010 the communication controller
	enters READY state. From this state the communication controller can transit to WAKEUP
	state and perform a cluster wakeup or to STARTUP state to perform a coldstart or to
	integrate into a running cluster.
	TXSY=1: sync node
	TXST=1: coldstarter
***********************************************************************/
int Fray_CC_READY(FRAY_ST *Fray_Ptr, unsigned int TXSY, unsigned int TXST)
{
	unsigned int err=0;

	// write SUCC1 configuration
    // [27:24]=0xF: CC and MTS are for both channel A and channel B
	// [23:20]=0x1: TSM=0, All slot mode; WUCS=0, send wakeup pattern on channel A
	//              PTA=1F, PTA=0x1F
	// [15:11]=0x1F: cold start attempts
	// TXSY[9]=1, TXST[8]=1
	Fray_Ptr->SUCC1_UN.SUCC1_UL = 0x0F1FF800 | ((TXSY & 0x1) << 0x9) | ((TXST & 0x01) << 0x8) | CMD_CONFIG;
	// Check if POC has accepted last command
	if ((Fray_Ptr->SUCC1_UN.SUCC1_UL & 0xF) == 0x0) return 1;
	// Wait for PBSY bit to clear - POC not busy
	while ((Fray_Ptr->SUCC1_UN.SUCC1_UL & 0x00000080) != 0x0);

	// unlock CONFIG and enter READY state
	// To leave CONFIG state by writing to CMD(3-0) in the SUC configuration register 1
	// (commands READY; MONITOR_MODE; ATM; LOOP_BACK), the write operation has to be directly preceded by
	// two consecutive write accesses to the configuration lock key (unlock sequence).
	// If this write sequence is interrupted by other write accesses, the communication controller remains
	// in CONFIG state and the sequence has to be repeated.
	Fray_Ptr->LCK_UN.LCK_ST.clk_B8 = 0xCE;
	Fray_Ptr->LCK_UN.LCK_ST.clk_B8 = 0x31;

	// write SUCC1 configuration
	Fray_Ptr->SUCC1_UN.SUCC1_ST.cmd_B4 = CMD_READY;

	// Check if POC has accepted last command 
	if ((Fray_Ptr->SUCC1_UN.SUCC1_UL & 0xF) == 0x0) err = 1;

	// Wait for PBSY bit to clear - POC not busy
	while ((Fray_Ptr->SUCC1_UN.SUCC1_UL & 0x00000080) != 0x0);
	return err;
}


/***********************************************************************
	Fray_Transmit
***********************************************************************/

void Fray_Transmit(FRAY_ST *Fray_Ptr, BC_ST *BC_Ptr)
{
	// ensure nothing is pending
	while ((Fray_Ptr->IBCR_UN.IBCR_UL & 0x0008000) != 0);
	Fray_Ptr->IBCM_UN.IBCM_UL=((BC_Ptr->stxrh & 0x1) << 2) | ((BC_Ptr->ldsh & 0x1) << 1) | (BC_Ptr->lhsh & 0x1);
	Fray_Ptr->IBCR_UN.IBCR_UL=(BC_Ptr->ibrh & 0x3F);
	// optimization possible for future by not gating like below
	// wait for completion on host registers
	while ((BC_Ptr->ibsyh != 0) && ((Fray_Ptr->IBCR_UN.IBCR_UL & 0x00008000) != 0));
	// wait for completion on shadow registers
	while ((BC_Ptr->ibsys != 0) && ((Fray_Ptr->IBCR_UN.IBCR_UL & 0x80000000) != 0));
}


/***********************************************************************
	Fray_Receive
***********************************************************************/

void Fray_Receive(FRAY_ST *Fray_Ptr, BC_ST *BC_Ptr)
{
	// ensure no transfer in progress on shadow registers
	while (((Fray_Ptr->OBCR_UN.OBCR_UL) & 0x00008000) != 0);
	Fray_Ptr->OBCM_UN.OBCM_UL=(((BC_Ptr->rdss & 0x1) << 1) | (BC_Ptr->rhss & 0x1));
	Fray_Ptr->OBCR_UN.OBCR_UL=((1 << 9) | (BC_Ptr->obrs & 0x3F)); //req=1, view=0
	// wait for completion on shadow registers
	while (((Fray_Ptr->OBCR_UN.OBCR_UL) & 0x00008000) != 0);

//	Fray_Ptr->OBCM_UN.OBCM_UL=(((BC_Ptr->rdss & 0x1) << 1) | (BC_Ptr->rhss & 0x1));
	Fray_Ptr->OBCR_UN.OBCR_UL=((1 << 8) | (BC_Ptr->obrs & 0x3F)); //req=0, view=1
}

/***********************************************************************
	Fr_AllowColdStart

	To Reset the coldstart inhibit flag CCSV.CSI by writing SUCC1.CMD[3:0]=1001

	CCSV.CSI indicates that the node is disabled from cold starting.
	The flag is set whenever the POC enters READY state. The flag has to be
	reset under control of the host by the controller host interface command
	ALLOW_COLDSTART (CMD(3-0) = 1001).
***********************************************************************/

int Fray_AllowColdStart(FRAY_ST *Fray_Ptr)
{
	unsigned int err=0;

	(Fray_Ptr->SUCC1_UN.SUCC1_UL = CMD_ALLOW_COLDSTART);

	// Check if POC has accepted last command 
	if ((Fray_Ptr->SUCC1_UN.SUCC1_UL & 0xF) == 0x0) err = 1;

	// Wait for PBSY bit to clear - POC not busy
	while ((Fray_Ptr->SUCC1_UN.SUCC1_UL & 0x00000080) != 0x0);
	return err;
}


/***********************************************************************
	Fr_StartCommunication
***********************************************************************/

int Fray_StartCommunication(FRAY_ST *Fray_Ptr)
{
	unsigned int err=0;

	// T10: Transition from StartUp state to Normal Active State
	// write SUCC1 configuration
	(Fray_Ptr->SUCC1_UN.SUCC1_UL = CMD_RUN);

	// Check if POC has accepted last command 
	if ((Fray_Ptr->SUCC1_UN.SUCC1_UL & 0xF) == 0x0) err = 1;
	return err;
}

/***********************************************************************
	header_crc_calc
	This function calculates the header CRC.
***********************************************************************/

int header_crc_calc(HEADER_ST *Header_Ptr)
{
  unsigned int header;

  int CrcInit = 0x1A;
  int length  = 20;
  int CrcNext;
  unsigned long CrcPoly  = 0x385;
  unsigned long CrcReg_X = CrcInit;
  unsigned long header_temp, reg_temp;

  header  = ((Header_Ptr->syn & 0x1)   << 19) | ((Header_Ptr->sfi & 0x1) << 18);
  header |= ((Header_Ptr->ppit & 0x1)  << 21) | ((Header_Ptr->nfi & 0x1) << 20);
  header |= ((Header_Ptr->fid & 0x7FF) <<  7) |  (Header_Ptr->plc & 0x7F);
  
  header   <<= 11;
  CrcReg_X <<= 21;
  CrcPoly  <<= 21;

  while(length--) {
    header    <<= 1;
    header_temp = header & 0x80000000;
    reg_temp    = CrcReg_X & 0x80000000;

    if(header_temp ^ reg_temp){  // Step 1
      CrcNext = 1;
    } else {	
      CrcNext = 0;
    }
		
    CrcReg_X <<= 1;              // Step 2
	
    if(CrcNext) {
      CrcReg_X ^= CrcPoly;       // Step 3
    }	
  }
	
  CrcReg_X >>= 21;

  return CrcReg_X;
}


/***********************************************************************
	Fr_TestMode, it is only used to double check if the RAM content is
	what I wrote into
***********************************************************************/
unsigned int Fray_TestMode(FRAY_ST *Fray_PST, unsigned int SSEL)
{
	// write SUCC1 configuration
	Fray_PST->SUCC1_UN.SUCC1_UL = 0x0F1FFB00 | CMD_READY;
	Fray_PST->SUCC1_UN.SUCC1_UL = 0x0F1FFB00 | CMD_CONFIG;
	// Check if POC has accepted last command
	if ((Fray_PST->SUCC1_UN.SUCC1_UL & 0xF) == 0x0) return 1;
	// Wait for PBSY bit to clear - POC not busy
	while ((Fray_PST->SUCC1_UN.SUCC1_UL & 0x00000080) != 0x0);

	// unlock CONFIG and enter READY state
	Fray_PST->LCK_UN.LCK_ST.tmk_B8=0x75;
	Fray_PST->LCK_UN.LCK_ST.tmk_B8=0x8A;
	Fray_PST->TEST1_UN.TEST1_ST.wrten_B1 = 1;

	//test1.TMC[5:4]: Test mode control, 1 is RAM test mode, 0 is normal operation mode
	//test2.SSEL[6:4]: segement select, total 8 8KB segments
	//test2.RS[2:0]: RAM select; 6 is Message RAM
	//Message RAM is mapped to 0xFFF7_ cc00 to 0xFFF7_CFFF
	//FRAM CC offset: 0xFFF7C800; Input/output buffer: offset + 0x400
	Fray_PST->TEST1_UN.TEST1_ST.tmc_B2 = 0x1;
	Fray_PST->TEST2_UN.TEST2_ST.rs_B3 = 0x6;
	Fray_PST->TEST2_UN.TEST2_ST.ssel_B3 = SSEL; //0: 0x0~0x3FF; 1: 0x400~7FF, ...
	return 0;
}

/***********************************************************************
	Fray_NormalMode, it is only used to double check if the RAM content is
	what I wrote into
***********************************************************************/
unsigned int Fray_NormalMode(FRAY_ST *Fray_PST)
{
	// write SUCC1 configuration
	Fray_PST->SUCC1_UN.SUCC1_UL = 0x0F1FFB00 | CMD_READY;
	Fray_PST->SUCC1_UN.SUCC1_UL = 0x0F1FFB00 | CMD_CONFIG;
	// Check if POC has accepted last command
	if ((Fray_PST->SUCC1_UN.SUCC1_UL & 0xF) == 0x0) return 1;
	// Wait for PBSY bit to clear - POC not busy
	while ((Fray_PST->SUCC1_UN.SUCC1_UL & 0x00000080) != 0x0);

	// unlock CONFIG and enter READY state
	Fray_PST->LCK_UN.LCK_ST.tmk_B8=0x75;
	Fray_PST->LCK_UN.LCK_ST.tmk_B8=0x8A;
	Fray_PST->TEST1_UN.TEST1_ST.wrten_B1 = 1;

	//test1.TMC[5:4]: Test mode control, 1 is RAM test mode, 0 is normal operation mode
	//test2.SSEL[6:4]: segement select, total 8 8KB segments
	//test2.RS[2:0]: RAM select; 6 is Message RAM
	//Message RAM is mapped to 0xFFF7_ cc00 to 0xFFF7_CFFF
	//FRAM CC offset: 0xFFF7C800; Input/output buffer: offset + 0x400
	Fray_PST->TEST1_UN.TEST1_ST.tmc_B2 = 0x0;
//	Fray_PST->TEST2_UN.TEST2_ST.rs_B3 = 0x6;
//	Fray_PST->TEST2_UN.TEST2_ST.ssel_B3 = SSEL; //0: 0x0~0x3FF; 1: 0x400~7FF, ...
	return 0;
}


/** @fn void frayHighLevelInterrupt(void)
*   @brief FRAY Level 0 Interrupt Handler
*/
#pragma CODE_STATE(frayHighLevelInterrupt, 32)
#pragma INTERRUPT(frayHighLevelInterrupt, IRQ)

void frayHighLevelInterrupt(void)
{
    unsigned int e_value;
    unsigned int s_value;

    e_value = frayREG1->EIR_UN.EIR_UL;
    s_value = frayREG1->SIR_UN.SIR_UL;


    frayREG1->EIR_UN.EIR_UL = e_value;
    frayREG1->SIR_UN.SIR_UL = s_value;

    if ( 0 != e_value )
    {
       frayErrorNotification(frayREG1, e_value);
    }

    //0x8014: SDS(15th bit), RXI (4th), CYCS (2th bit)
    if ( 0x8014 == (e_value & 0x8014))
    {
       frayStatusChangeNotification(frayREG1, s_value);
    }
 }

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

void frayLowLevelInterrupt(void)
{
    unsigned int e_value = frayREG1->EIR_UN.EIR_UL;
    unsigned int s_value = frayREG1->SIR_UN.SIR_UL;

/* USER CODE BEGIN (41) */
/* USER CODE END */

    if (e_value != 0x0)
    {
       frayErrorNotification(frayREG1, e_value);
    }

    if ( 0x8014 == (e_value & 0x8014))
    {
       frayStatusChangeNotification(frayREG1, s_value & (1 << 2));
    }
}

