/******************************************************************************
*
* CAEN SpA - Front End Division
* Via Vetraia, 11 - 55049 - Viareggio ITALY
* +390594388398 - www.caen.it
*
***************************************************************************//**
* \note TERMS OF USE:
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation. This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. The user relies on the
* software, documentation and results solely at his own risk.
******************************************************************************/

#ifndef _FERSCFG_H
#define _FERSCFG_H				// Protect against multiple inclusion

// _Thread_local is C11 with thread support
#if (__STDC_VERSION__ >= 201112L) && !defined(__STDC_NO_THREADS__)
#define THREAD_LOCAL				_Thread_local
#elif defined(_WIN32)
#define THREAD_LOCAL				__declspec(thread)
#elif defined(__GNUC__)
#define THREAD_LOCAL				__thread
#else
#error unsupported compiler
#endif

#define ARRAY_SIZE(x)				(sizeof(x)/sizeof((x)[0]))

#include "FERSlib.h"
#include "FERS_MultiPlatform.h"
#include "FERS_Registers_520X.h"
#include "FERS_Registers_5215.h"

/*!
* @cond EXCLUDE
*/
// ***************************************************************************
// Variables
// ***************************************************************************
extern int BoardConnected[FERSLIB_MAX_NBRD]; // = { 0 };			// Board connection status
extern int NumBoardConnected; // = 0;								// Number of boards connected
extern float CLK_PERIOD[FERSLIB_MAX_NBRD];
extern FERS_BoardInfo_t* FERS_BoardInfo[FERSLIB_MAX_NBRD];	// pointers to the board info structs 
extern uint16_t MaxEnergyRange;
extern float TDL_FiberDelayAdjust[FERSLIB_MAX_NCNC][FERSLIB_MAX_NTDL][FERSLIB_MAX_NNODES];
/*! 
* @endcond
*/

//****************************************************************************
// struct that contains the configuration parameters (HW and SW)
//****************************************************************************
/*!
* @ingroup FERSlib_CStructs
* @brief FERS configuration parameters structure (lib + board)
* @{
*/
typedef struct Config_t {

	// Board mutex
	mutex_t bmutex;

	// System info 
	//char ConnPath[200];					// IP address of the board. Set by FERSlib_open
	int handle;

	// -------------------------------------------------------------
	// Raw data parameters
	// -------------------------------------------------------------
	uint8_t OF_RawData;									//!< Enable saving raw data output files
	uint8_t OF_LimitedSize;								//!< Enable limited size on raw data output files
	float MaxSizeDataOutputFile;						//!< Maximum size writable for raw data output files in bytes. Minimum size allowed 1 MB
	char OF_RawDataPath[200];							//!< Raw data files saving path
	
	// -------------------------------------------------------------
	// Settings for the acquisition modes and I/O masks
	// -------------------------------------------------------------
	int AcquisitionMode;								//!< Acquisition mode (Spectroscopy, Timing, Counting, etc...). Options are board dependent.
	int StartRunMode;									//!< Start Mode (this is a HW setting that defines how to start/stop the acquisition in the boards)
	int StopRunMode;									//!< Stop Mode (for now, stop is always controlled by SW, but in the future it might be implemented in HW)
	uint32_t TestMode;									//!< Run with fixed data patterns generated by the FPGA

	uint32_t TriggerMask;								//!< Bunch Trigger mask
	uint32_t T0_outMask;								//!< T0-OUT mask
	uint32_t T1_outMask;								//!< T1-OUT mask
	uint32_t Tref_Mask;									//!< Tref mask											
	uint32_t Veto_Mask;									//!< Veto mask
	uint32_t Validation_Mask;							//!< Validation mask
	uint32_t Validation_Mode;							//!< Validation Mode: 0=disabled, 1=positive (accept), 2=negative (reject)
	uint32_t Counting_Mode;								//!< Counting Mode (Singles, Paired_AND)
	uint32_t TrgIdMode;									//!< Trigger ID: 0 = trigger counter, 1 = validation counter
	uint32_t EnableServiceEvents; 						//!< Enable service events
	uint32_t EnableCntZeroSuppr;						//!< Enable zero suppression in Counting Mode 
	uint32_t Dis_tdl; 									//!< Enable the TDL switching off when not used (DNIN: why is a parameter?)
	uint32_t EnableChannelTrgout;						//!< 0 = Channel Trgout Disabled, 1 = Enabled (used in Citiroc only)
	uint32_t Enable_2nd_tstamp;							//!< Enable 2nd time stamp relative to the Tref signal
	uint32_t EnableToT;									//!< Enable readout of ToT (time over threshold) in A5202
	uint32_t WaveformLength;							//!< Num of samples in the waveform
	uint32_t WaveformSource;							//!< LG0, HG0, LG1, HG1 (High/Low Gain, chip 0/1) 
	uint32_t Range_14bit;								//!< Use full 14 bit range for the A/D conversion
	uint32_t En_Empty_Ev_Suppr;							//!< Enable event suppression (only in Custom header mode)
	float GateWidth;									//!< Gate window width in ns (will be rounded to steps of 25 ns)
	float TrefWindow;									//!< Tref Windows in ns (Common start/stop)
	float TrefDelay;									//!< Tref delay in ns (can be negative)
	float PtrgPeriod;									//!< period in ns of the internal periodic trigger (dwell time)
	float TrgHoldOff;									//!< Retrigger protection time. Set the busy active for N clock cycles (0=disabled)

	// -------------------------------------------------------------
	// Settings for Channel enabling
	// -------------------------------------------------------------
	uint64_t ChEnableMask;								//!< Channel enable mask (64 ch)
	uint64_t ChEnableMask_e;							//!< Channel enable mask of Mezzanine expansion (128 ch, A5203 only)

	// -------------------------------------------------------------
	// Settings for analog and digital probes
	// -------------------------------------------------------------
	uint32_t AnalogProbe[2];							//!< Analog probe in XROC ASICs (Preamp LG/HG, Slow Shaper HG/LG, Fast Shaper)
	uint32_t DigitalProbe[2];							//!< Digital probe in XROC ASICs (peak Sens HG/LG) or FPGA (start_conv, data_commit...)
	uint32_t ProbeChannel[2];							//!< Channel to probe

	// -------------------------------------------------------------
	// Settings for DT5215 (Concentrator)
	// -------------------------------------------------------------
	float FiberDelayAdjust[FERSLIB_MAX_NCNC][8][16];	//!< Fiber length (in meters) for individual tuning of the propagation delay along the TDL daisy chains
	uint32_t TdlClkPhase;								//!< Recovered clock phase shift: 0=0, 1=90, 2=180, 3=270
	uint32_t MaxPck_Block; 								//!< Max. number of packets (events) that the concentrator can aggregate in one Data Block (0 = use default in FW)
	uint32_t MaxPck_Train;								//!< Max. number of packets (events) that the FERS unit can transmit to the concentrator in a single data train (0 = use default in FW)
	uint32_t CncBufferSize;								//!< Data buffer size (in 32 bit words) in the concentrator; stop trains when this level is reached (0 = use default in FW)
	uint32_t CncProbe_A;								//!< Digital Probe in the concentrator (output FA)
	uint32_t CncProbe_B;								//!< Digital Probe in the concentrator (output FB)

	// -------------------------------------------------------------
	// Settings for FPGA trigger logic
	// -------------------------------------------------------------
	uint64_t Tlogic_Mask;								//!< Trigger Logic enable mask 
	uint32_t TriggerLogic;								//!< Trigger Logic Definition
	uint32_t MajorityLevel;								//!< Majority Level
	float ChTrg_Width;									//!< Self Trg Width in ns => Coinc windows for paired counting and trigger logic
	float Tlogic_Width;									//!< TriggerLogic output width (0=linear)

	// -------------------------------------------------------------
	// Settings for XROC ASICs
	// -------------------------------------------------------------
	uint16_t ZS_Threshold_LG[FERSLIB_MAX_NCH_5202];		//!< Low Threshold for zero suppression (LG)
	uint16_t ZS_Threshold_HG[FERSLIB_MAX_NCH_5202];		//!< Low Threshold for zero suppression (HG)
	uint16_t QD_FineThreshold[FERSLIB_MAX_NCH_5202];	//!< Fine Threshold for Citiroc charge discriminator
	uint16_t TD_FineThreshold[FERSLIB_MAX_NCH_5202];	//!< Fine Threshold for Citiroc time discriminator
	uint16_t HG_Gain[FERSLIB_MAX_NCH_5202];				//!< Gain of the High Gain Preamp
	uint16_t LG_Gain[FERSLIB_MAX_NCH_5202];				//!< Gain of the Low Gain Preamp
	uint16_t PAQ_Gain[FERSLIB_MAX_NCH_5204];			//!< Gain of the Charge Preamp (Psiroc)
	uint16_t PAQ_Comp[FERSLIB_MAX_NCH_5204];			//!< Gain of the Charge Preamp (Psiroc)
	uint16_t HV_IndivAdj[FERSLIB_MAX_NCH_5202];			//!< HV individual bias adjust (Citiroc 8bit input DAC)
	uint16_t InputPolarity[FERSLIB_MAX_NCH_5204];		//!< Preamp Input Polarity
	uint64_t QD_Mask;									//!< Enable mask of Charge Discriminator 
	uint64_t TD1_Mask;									//!< Enable mask of Time Discriminator 1
	uint64_t TD2_Mask;									//!< Enable mask of Time Discriminator 2
	uint64_t TD_Mask;									//!< Enable mask of Fast Shaper Discriminator (Psiroc)
	uint64_t TOTD_Mask;									//!< Enable mask of TOT Discriminator (Psiroc)
	uint32_t TD_CoarseThreshold;						//!< Coarse Threshold for Citiroc time discriminator
	uint32_t HG_ShapingTime;							//!< Shaping Time of the High Gain preamp
	uint32_t LG_ShapingTime;							//!< Shaping Time of the Low Gain preamp
	uint32_t Enable_HV_Adjust;							//!< Enable input DAC for HV fine adjust
	uint16_t HV_Adjust_Range;							//!< HV adj DAC range (reference): 0 = 2.5V, 1 = 4.5V, ?=DISABLED
	uint16_t T_Gain[FERSLIB_MAX_NCH_5204];				//!< T-Preamp gain
	uint16_t TD1_CoarseThreshold;						//!< Coarse Threshold for Time discriminator 1
	uint16_t TD2_CoarseThreshold;						//!< Coarse Threshold for Time discriminator 2 
	uint16_t TOTD_CoarseThreshold;						//!< Coarse Threshold for TOT discriminator
	uint16_t QD_CoarseThreshold;						//!< Coarse Threshold for Charge discriminator
	uint16_t TD1_FineThreshold[FERSLIB_MAX_NCH_5204];	//!< Fine Threshold for Time discriminator 1
	uint16_t TD2_FineThreshold[FERSLIB_MAX_NCH_5204];	//!< Fine Threshold for Time discriminator 2
	uint16_t TOTD_FineThreshold[FERSLIB_MAX_NCH_5204];	//!< Fine Threshold for TOT discriminator
	uint16_t HG_ShapingTime_ind[FERSLIB_MAX_NCH_5204];	//!< Shaping Time of the High Gain preamp (individual)
	uint16_t LG_ShapingTime_ind[FERSLIB_MAX_NCH_5204];	//!< Shaping Time of the Low Gain preamp (individual)
	uint32_t PeakDetectorMode;							//!< Peaking Mode: 0 = Peak Stretcher, 1 = Track&Hold
	uint32_t EnableQdiscrLatch;							//!< Q-dicr mode: 1 = Latched, 0 = Direct
	uint32_t FastShaperInput;							//!< Fast Shaper (Tdiscr) connection: 0 = High Gain PA, 1 = Low Gain PA
	uint32_t TestPulsePreamp;							//!< 1=LG, 2=HG, 3=BOTH
	int TestPulseDestination;							//!< -1=ALL, -2=EVEN, -3=ODD or channel number (0 to 63) for single channel pulsing
	uint32_t CitirocCfgMode;							//!< 0=from regs, 1=from file
	float HoldDelay;									//!< Time between Trigger and Hold
	float MuxClkPeriod;									//!< Period of the Mux Clock
	uint32_t MuxNSmean;									//!< Num of samples for the Mux mean: 0: 4 samples, 1: 16 samples
	uint32_t GainSelect;								//!< Select gain between High/Low/Auto
	uint16_t Pedestal;									//!< Common pedestal added to all channels

	// -------------------------------------------------------------
	// Settings for Analog Test Pulser
	// -------------------------------------------------------------
	int TestPulseSource;								//!< EXT, INT_T0, INT_T1, INT_PTRG, INT_SW
	uint32_t TestPulseAmplitude;						//!< DAC setting for the internal test pulser (12 bit). Meaningless for TestPulseSource=EXT 


	// -------------------------------------------------------------
	// Settings for HV
	// -------------------------------------------------------------
	float HV_Vbias;										//!< Voltage setting for HV
	float HV_Imax;										//!< Imax for HV
	float TempSensCoeff[3];								//!< Temperature Sensor Coefficients (2=quad, 1=lin, 0=offset)
	float TempFeedbackCoeff;							//!< Temperature Feedback Coeff: Vout = Vset - k * (T-25)
	int EnableTempFeedback;								//!< Enable Temp Feedback


	// -------------------------------------------------------------
	// Settings for picoTDC
	// -------------------------------------------------------------
	uint32_t MeasMode;									//!< LEAD_ONLY, LEAD_TRAIL, LEAD_TOT8, LEAD_TOT11
	uint32_t En_Head_Trail;								//!< Enable Header and Trailer: 0=Keep all (group header+trail), 1=One word, 2=Header and trailer suppressed
	uint32_t HighResClock;								//!< High Res clock distribution (MCX connectors)
	uint32_t GlitchFilterDelay;							//!< Delay of the glitch filter (~800 ps to ~10 ns with 16 steps)
	uint32_t GlitchFilterMode;							//!< DISABLED, TRAILING, LEADING, BOTH
	uint32_t TDC_ChBufferSize;							//!< Channel buffer size in the picoTDC (set a limit to the max number of hits acquired by the channel)
	uint32_t TriggerBufferSize;							//!< Size of the trigger buffer in the FPGA (limits the number or pending triggers, already sent to the TDC but not written in the output FIFO yet)
	uint32_t HeaderField0;								//!< Header Field0 (for test only, default=4=near full flags (ch 0..7 of the port) - 00000CCCCCCCC)
	uint32_t HeaderField1;								//!< Header Field1 (for test only, default=5=near full flags (ch 8..15 of the port + RO_buff, TrgBuff) - RT000CCCCCCCC)
	uint32_t LeadTrail_LSB;								//!< Leading/Trailing LSB required by the user: 0: LSB = ~3ps, N: LSB = 3ps * 2^N, (Max N=10; LSB = ~3.125 ns)
	uint32_t ToT_LSB;									//!< ToT LSB required by the user: 0: LSB = 3.125ps, N: LSB = 3.125ps * 2^N, (Max N=18; LSB = ~800 ns)
	uint16_t ToT_reject_low_thr;						//!< The FPGA suppresses the Hits with ToT > low_threshold  (0 disabled)
	uint16_t ToT_reject_high_thr;						//!< The FPGA suppresses the Hits with ToT < high_threshold  (0 disabled)
	float TrgWindowWidth;								//!< Trigger window width in ns (will be rounded to steps of 25 ns)
	float TrgWindowOffset;								//!< Trigger window offset in ns; can be negative (will be rounded to steps of 25 ns)
	//uint8_t  En_128_ch;								//!< Enable 128 channels
	float TDCpulser_Width;								//!< picoTDC Pulser Output (width in ns)
	float TDCpulser_Period;								//!< picoTDC Pulser Output (period in ns)
	uint32_t Ch_Offset[FERSLIB_MAX_NCH_5203]; 			//!< Channel Offset
	//uint8_t InvertEdgePolarity[MAX_NCH];				//!< Invert edge polarity. NOTE: can be used in LEAD_TRAIL mode only


	// -------------------------------------------------------------
	// Settings for Adapters (A5256)
	// -------------------------------------------------------------
	int AdapterType; // MISSING in CFG					//!< Adapter Type
	float DiscrThreshold[FERSLIB_MAX_NCH_5203];			//!< Discriminator Threshold
	float DiscrThreshold2[FERSLIB_MAX_NCH_5203];		//!< Discriminator 2nd Threshold (double thershold mode only)
	int DisableThresholdCalib; 							//!< Disable threshold calibration
	int A5256_Ch0Polarity;								//!< Polarity of Ch0 in A5256 (POS, NEG)


	// -------------------------------------------------------------
	// Generic write accesses 
	// -------------------------------------------------------------
	int GWn;
	uint32_t GWaddr[FERSLIB_MAX_GW];					//!< Register Address
	uint32_t GWdata[FERSLIB_MAX_GW];					//!< Data to write
	uint32_t GWmask[FERSLIB_MAX_GW];					//!< Bit Mask

} Config_t;
/*! @} */

extern Config_t* FERScfg[FERSLIB_MAX_NBRD];				// Configuration parameters


/*!
* @cond EXCLUDE
*/
//****************************************************************************
// Functions
//****************************************************************************
int Configure5202(int handle, int mode);
int Configure5203(int handle, int mode);
int Configure5204(int handle, int mode);
int FERS_DumpBoardRegister5202(int handle, char* filename);
int FERS_DumpBoardRegister5203(int handle, char* filename);
int FERS_DumpBoardRegister5204(int handle, char* filename);
int ConfigureProbe5202(int handle);
int ConfigureProbe5203(int handle);
int ConfigureProbe5204(int handle);
void Set_picoTDC_Default(picoTDC_Cfg_t* pcfg);
int Write_picoTDC_Cfg(int handle, int tdc, picoTDC_Cfg_t pcfg, int skipch);
int Read_picoTDC_Cfg(int handle, int tdc, picoTDC_Cfg_t* pcfg);
int Save_picoTDC_Cfg(int handle, int tdc, char* fname);
/*!
* @endcond
*/

#endif
