#ifndef DRS_H #define DRS_H #include #include #include #include #include #include #include #include #include #include #include #include "mxml.h" #include "strlcpy.h" // Concurrent Technologies VME single board computer #ifdef CT_VME #include "rcc_error/rcc_error.h" // Error reporting #include "vme_rcc/vme_rcc.h" // VME access #include "cmem_rcc/cmem_rcc.h" // Allocation of contiguous memory #include "rcc_time_stamp/tstamp.h" // Time stamp library #endif // Struck VME interface #ifdef STRUCK_VME #include "mvmestd.h" #endif // Control register bit definitions #define BIT_START_TRIG (1<<0) // Write a "1" to start domino wave #define BIT_REINIT_TRIG (1<<1) // Write a "1" to stop & reset DRS #define BIT_SOFT_TRIG (1<<2) // Write a "1" to stop and read data to RAM #define BIT_FLASH_TRIG (1<<3) // Write a "1" to write DAC0 & DAC1 into serial EEPROM #define BIT_AUTOSTART (1<<16) #define BIT_DMODE (1<<17) // 0: single shot, 1: circular #define BIT_LED (1<<18) // 1=on, 0=blink during readout #define BIT_TCAL_EN (1<<19) // Switch on (1) / off (0) for 33 MHz calib signal #define BIT_ZERO_SUPP (1<<20) #define BIT_FREQ_AUTO_ADJ (1<<21) #define BIT_ENABLE_TRIGGER (1<<22) #define BIT_LONG_START_PULSE (1<<23) // (*DRS2*) 0:short start pulse (> 0.8 GHz), 1:long start pulse (< 0.8 GHz) #define BIT_READOUT_MODE (1<<23) // (*DRS3*) 0:start from first bin, 1:start from domino stop #define BIT_DELAYED_START (1<<24) // Start domino wave 400 ns after soft trigger, used for waveform // Generator startup #define BIT_ACAL_EN (1<<25) // Connect DRS to inputs (0) or to DAC6 (1) #define BIT_TRIGGER_DELAYED (1<<26) // Select delayed trigger from trigger bus #define BIT_DACTIVE (1<<27) // Keep domino wave running during readout // Status register bit definitions #define BIT_RUNNING (1<<0) // One if domino wave running or readout in progress #define BIT_NEW_FREQ1 (1<<1) // One if new frequency measurement available #define BIT_NEW_FREQ2 (1<<2) enum DRSBoardConstants { kNumberOfChannels = 10, kNumberOfCalibChannels = 10, kNumberOfBins = 1024, kNumberOfChips = 2, kFrequencyCacheSize = 10, kBSplineOrder = 4, kPreCaliculatedBSplines = 1000, kPreCaliculatedBSplineGroups = 5, kNumberOfADCBins = 4096, kBSplineXMinOffset = 20, kMaxNumberOfClockCycles = 100, }; enum DRSErrorCodes { kSuccess = 0, kInvalidTriggerSignal = -1, kWrongChannelOrChip = -2, kInvalidTransport = -3, kZeroSuppression = -4, kWaveNotAvailable = -5 }; class DRSBoard; class ResponseCalibration { protected: class CalibrationData { public: class CalibrationDataChannel { public: unsigned char fLimitGroup[kNumberOfBins]; //! float fMin[kNumberOfBins]; //! float fRange[kNumberOfBins]; //! short fOffset[kNumberOfBins]; //! short fGain[kNumberOfBins]; //! unsigned short fOffsetADC[kNumberOfBins]; //! short *fData[kNumberOfBins]; //! unsigned char *fLookUp[kNumberOfBins]; //! unsigned short fLookUpOffset[kNumberOfBins]; //! unsigned char fNumberOfLookUpPoints[kNumberOfBins]; //! float *fTempData; //! private: CalibrationDataChannel(const CalibrationDataChannel &c); // Not implemented CalibrationDataChannel &operator=(const CalibrationDataChannel &rhs); // Not implemented public: CalibrationDataChannel(int numberOfGridPoints) :fTempData(new float[numberOfGridPoints]) { int i; for (i = 0; i < kNumberOfBins; i++) { fData[i] = new short[numberOfGridPoints]; fLookUp[i] = NULL; } } ~CalibrationDataChannel() { int i; delete fTempData; for (i = 0; i < kNumberOfBins; i++) { delete fData[i]; delete fLookUp[i]; } } }; bool fRead; //! CalibrationDataChannel *fChannel[kNumberOfCalibChannels]; //! unsigned char fNumberOfGridPoints; //! int fHasOffsetCalibration; //! float fStartTemperature; //! float fEndTemperature; //! int *fBSplineOffsetLookUp[kNumberOfADCBins]; //! float **fBSplineLookUp[kNumberOfADCBins]; //! float fMin; //! float fMax; //! unsigned char fNumberOfLimitGroups; //! static float fIntRevers[2 * kBSplineOrder - 2]; private: CalibrationData(const CalibrationData &c); // Not implemented CalibrationData &operator=(const CalibrationData &rhs); // Not implemented public: CalibrationData(int numberOfGridPoints); ~CalibrationData(); static int CalculateBSpline(int nGrid, float value, float *bsplines); void PreCalculateBSpline(); void DeletePreCalculatedBSpline(); }; // General Fields DRSBoard *fBoard; double fPrecision; // Fields for creating the Calibration bool fInitialized; bool fRecorded; bool fFitted; bool fOffset; bool fCalibrationValid[2]; int fNumberOfPointsLowVolt; int fNumberOfPoints; int fNumberOfMode2Bins; int fNumberOfSamples; int fNumberOfGridPoints; int fNumberOfXConstPoints; int fNumberOfXConstGridPoints; double fTriggerFrequency; int fShowStatistics; FILE *fCalibFile; int fCurrentLowVoltPoint; int fCurrentPoint; int fCurrentSample; int fCurrentFitChannel; int fCurrentFitBin; float *fResponseX[kNumberOfCalibChannels][kNumberOfBins]; float *fResponseY; unsigned short **fWaveFormMode3[kNumberOfCalibChannels]; unsigned short **fWaveFormMode2[kNumberOfCalibChannels]; short **fWaveFormOffset[kNumberOfCalibChannels]; unsigned short **fWaveFormOffsetADC[kNumberOfCalibChannels]; // Is this used? unsigned short *fSamples; int *fSampleUsed; float *fPntX[2]; float *fPntY[2]; float *fUValues[2]; float *fRes[kNumberOfBins]; float *fResX[kNumberOfBins]; double *fXXFit; double *fYYFit; double *fWWFit; double *fYYFitRes; double *fYYSave; double *fXXSave; float **fStatisticsApprox; float **fStatisticsApproxExt; // Fields for applying the Calibration CalibrationData *fCalibrationData[kNumberOfChips]; private: ResponseCalibration(const ResponseCalibration &c); // Not implemented ResponseCalibration &operator=(const ResponseCalibration &rhs); // Not implemented public: ResponseCalibration(DRSBoard* board); ~ResponseCalibration(); void SetCalibrationParameters(int numberOfPointsLowVolt, int numberOfPoints, int numberOfMode2Bins, int numberOfSamples, int numberOfGridPoints, int numberOfXConstPoints, int numberOfXConstGridPoints, double triggerFrequency, int showStatistics = 0); void ResetCalibration(); bool RecordCalibrationPoints(int chipNumber); bool RecordCalibrationPointsV3(int chipNumber); bool RecordCalibrationPointsV4(int chipNumber); bool FitCalibrationPoints(int chipNumber); bool FitCalibrationPointsV3(int chipNumber); bool FitCalibrationPointsV4(int chipNumber); bool OffsetCalibration(int chipNumber); double GetTemperature(unsigned int chipIndex); bool WriteCalibration(unsigned int chipIndex); bool WriteCalibrationV3(unsigned int chipIndex); bool WriteCalibrationV4(unsigned int chipIndex); bool ReadCalibration(unsigned int chipIndex); bool ReadCalibrationV3(unsigned int chipIndex); bool ReadCalibrationV4(unsigned int chipIndex); bool Calibrate(unsigned int chipIndex, unsigned int channel, float *adcWaveform, float *uWaveform, float threshold); bool Calibrate(unsigned int chipIndex, unsigned int channel, unsigned short *adcWaveform, short *uWaveform, int triggerCell, float threshold); bool SubtractADCOffset(unsigned int chipIndex, unsigned int channel, unsigned short *adcWaveform, unsigned short *adcCalibratedWaveform, unsigned short newBaseLevel); bool IsRead(int chipIndex) const { return fCalibrationValid[chipIndex]; } double GetPrecision() const { return fPrecision; }; double GetOffsetAt(int chip,int chn,int bin) const { return fCalibrationData[chip]->fChannel[chn]->fOffset[bin]; }; double GetGainAt(int chip,int chn,int bin) const { return fCalibrationData[chip]->fChannel[chn]->fGain[bin]; }; double GetMeasPointXAt(int ip) const { return fXXSave[ip]; }; double GetMeasPointYAt(int ip) const { return fYYSave[ip]; }; protected: void InitFields(int numberOfPointsLowVolt, int numberOfPoints, int numberOfMode2Bins, int numberOfSamples, int numberOfGridPoints, int numberOfXConstPoints, int numberOfXConstGridPoints, double triggerFrequency, int showStatistics); void DeleteFields(); void CalibrationTrigger(int mode, double voltage); void CalibrationStart(double voltage); static float GetValue(float *coefficients, float u, int n); static int Approx(float *p, float *uu, int np, int nu, float *coef); static void LeastSquaresAccumulation(float **matrix, int nb, int *ip, int *ir, int mt, int jt); static int LeastSquaresSolving(float **matrix, int nb, int ip, int ir, float *x, int n); static void Housholder(int lpivot, int l1, int m, float **u, int iU1, int iU2, float *up, float **c, int iC1, int iC2, int ice, int ncv); static int MakeDir(const char *path); static void Average(int method,float *samples,int numberOfSamples,float &mean,float &error,float sigmaBoundary); }; class DRSBoard { protected: class TimeData { public: class FrequencyData { public: int fFrequency; double fBin[kNumberOfBins]; }; enum { kMaxNumberOfFrequencies = 4000 }; int fChip; int fNumberOfFrequencies; FrequencyData *fFrequency[kMaxNumberOfFrequencies]; private: TimeData(const TimeData &c); // Not implemented TimeData &operator=(const TimeData &rhs); // Not implemented public: TimeData() :fChip(0) ,fNumberOfFrequencies(0) { } ~TimeData() { int i; for (i = 0; i < fNumberOfFrequencies; i++) { delete fFrequency[i]; } } }; public: // DAC channels (CMC Version 1 : DAC_COFSA,DAC_COFSB,DAC_DRA,DAC_DSA,DAC_TLEVEL,DAC_ACALIB,DAC_DSB,DAC_DRB) unsigned int fDAC_COFSA; unsigned int fDAC_COFSB; unsigned int fDAC_DRA; unsigned int fDAC_DSA; unsigned int fDAC_TLEVEL; unsigned int fDAC_ACALIB; unsigned int fDAC_DSB; unsigned int fDAC_DRB; // DAC channels (CMC Version 2+3 : DAC_COFS,DAC_DSA,DAC_DSB,DAC_TLEVEL,DAC_ADCOFS,DAC_CLKOFS,DAC_ACALIB) unsigned int fDAC_COFS; unsigned int fDAC_ADCOFS; unsigned int fDAC_CLKOFS; // DAC channels (CMC Version 4 : DAC_ROFS_1,DAC_DSA,DAC_DSB,DAC_ROFS_2,DAC_ADCOFS,DAC_ACALIB,DAC_INOFS,DAC_BIAS) unsigned int fDAC_ROFS_1; unsigned int fDAC_ROFS_2; unsigned int fDAC_INOFS; unsigned int fDAC_BIAS; private: #ifdef CT_VME VME_ErrorCode_t ErrorCode; VME_BlockTransferList_t BLT_List; char ErrorString[VME_MAXSTRING]; int CMEM_SegIdentifier; unsigned long PCIAddress; // Physical address of contiguous buffer unsigned long VirtualAddress; // Virtual address of contiguous buffer unsigned int fBaseAddress; unsigned int fBoardAddress; int fMasterMapping; unsigned int GetBaseAddress() const {return fBaseAddress; } unsigned int GetBoardAddress() const {return fBoardAddress; } int AllocateSegmentCMEM(unsigned int SegSize, int *CMEM_SegIdentifier); int AssignPhysicalSegAddressCMEM(int CMEM_SegIdentifier, unsigned long* PCIAddress); int AssignVirtualSegAddressCMEM(int CMEM_SegIdentifier, unsigned long* VirtualAddress); int FreeSegmentCMEM(int CMEM_SegIdentifier); #endif #ifdef STRUCK_VME mvme_addr_t fBaseAddress; MVME_INTERFACE *fVMEInterface; #endif protected: // Fields for DRS int fRequiredFirmwareVersion; int fFirmwareVersion; int fChipVersion; int fBoardVersion; int fCMCSerialNumber; unsigned int fTransport; unsigned int fCtrlBits; int fNumberOfReadoutChannels; double fExternalClockFrequency; int fSlotNumber; double fFrequency; int fDominoMode; int fReadoutMode; int fTriggerEnable; int fDelayedStart; int fTriggerCell; unsigned char fWaveforms[kNumberOfChips * kNumberOfChannels * 2 * kNumberOfBins]; // Fields for Calibration int fMaxChips; char fCalibDirectory[1000]; // Fields for Response Calibration ResponseCalibration *fResponseCalibration; // Fields for Time Calibration TimeData **fTimeData; int fNumberOfTimeData; // General debugging flag int fDebug; // Fields for wave transfer bool fWaveTransferred[kNumberOfChips * kNumberOfChannels]; // Waveform Rotation int fTriggerStartBin; // Start bin of the trigger bool kRotateWave; public: ~DRSBoard(); void SetCMCSerialNumber(unsigned int serialNumber) { fCMCSerialNumber = serialNumber; } int GetCMCSerialNumber() const { return fCMCSerialNumber; } int GetFirmwareVersion() const { return fFirmwareVersion; } int GetRequiredFirmwareVersion() const { return fRequiredFirmwareVersion; } int GetChipVersion() const { return fChipVersion; } int GetCMCVersion() const { return fBoardVersion; } // VME int GetSlotNumber() const { return fSlotNumber; } int Read(int type, void *data, unsigned int addr, int size); int Write(int type, unsigned int addr, void *data, int size); void RegisterTest(void); int RAMTest(int flag); unsigned int GetCtrlReg(void); unsigned int GetStatusReg(void); void SetLED(int state); void SetChannelConfig(int firstChannel, int lastChannel, int nConfigChannels); void SetNumberOfChannels(int nChannels); int EnableTrigger(int mode); int SetDelayedStart(int flag); int IsBusy(void); int IsNewFreq(unsigned char chipIndex); int SetDAC(unsigned char channel, double value); int ReadDAC(unsigned char channel, double *value); int GetRegulationDAC(double *value); int StartDomino(); int Reinit(); int Init(); void SetDebug(int debug) { fDebug = debug; } int SetDominoMode(unsigned char mode); int SetDominoActive(unsigned char mode); int SetReadoutMode(unsigned char mode); int SoftTrigger(void); int ReadFrequency(unsigned char chipIndex, double *f); int SetFrequency(double freq); double VoltToFreq(double volt); double FreqToVolt(double freq); double GetFrequency() const { return fFrequency; } int RegulateFrequency(double freq); int SetExternalClockFrequency(double frequencyMHz); double GetExternalClockFrequency(); void SetVoltageOffset(double offset1, double offset2); int TestRead(unsigned int n, int type); int TransferWaves(int numberOfChannels = kNumberOfChips * kNumberOfChannels); int TransferWaves(unsigned char *p, int numberOfChannels = kNumberOfChips * kNumberOfChannels); int TransferWaves(unsigned char *p, int firstChannel, int lastChannel); int TransferWaves(int firstChannel, int lastChannel); int DecodeWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel, unsigned short *waveform); int DecodeWave(unsigned int chipIndex, unsigned char channel, unsigned short *waveform); int GetWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel, short *waveform, bool responseCalib = false, int triggerCell = -1, bool adjustToClock = false, float threshold = 0); int GetWave(unsigned char *waveforms, unsigned int chipIndex, unsigned char channel, float *waveform, bool responseCalib = false, int triggerCell = -1, bool adjustToClock = false, float threshold = 0); int GetWave(unsigned int chipIndex, unsigned char channel, short *waveform, bool responseCalib = false, int triggerCell = -1, bool adjustToClock = false, float threshold = 0); int GetWave(unsigned int chipIndex, unsigned char channel, float *waveform, bool responseCalib = false, int triggerCell = -1, bool adjustToClock = false, float threshold = 0); int GetADCWave(unsigned int chipIndex, unsigned char channel, unsigned short *waveform); int GetADCWave(unsigned char *waveforms,unsigned int chipIndex, unsigned char channel, unsigned short *waveform); void RotateWave(int triggerCell, short *waveform); void RotateWave(int triggerCell, float *waveform); void SetRotation(bool r) {kRotateWave = r;} int GetTime(unsigned int chipIndex, int frequencyMHz, float *time, int triggerCell); int GetTriggerCell(unsigned int chipIndex); int GetTriggerCell(unsigned char *waveforms,unsigned int chipIndex); int GetTriggerCell(float *waveform); void TestDAC(int channel); void MeasureSpeed(); void InteractSpeed(); void MonitorFrequency(); int EnableTcal(int flag); int EnableAcal(int mode, double voltage); int SetCalibVoltage(double value); int SetCalibTiming(int t1, int t2); double GetTemperature(); int GetTriggerBus(); int FlashEEPROM(unsigned short serial_cmc); bool HasCorrectFirmware(); bool InitTimeCalibration(unsigned int chipIndex); void SetCalibrationDirectory(const char *calibrationDirectoryPath); void GetCalibrationDirectory(char *calibrationDirectoryPath); ResponseCalibration *GetResponseCalibration() const { return fResponseCalibration; } int GetStoredTriggerCell() const { return fTriggerCell; } double GetPrecision() const { return fResponseCalibration->GetPrecision(); } int CalibrateWaveform(unsigned int chipIndex, unsigned char channel, unsigned short *adcWaveform, short *waveform, bool responseCalib, int triggerCell, bool adjustToClock, float threshold); static void LinearRegression(double *x, double *y, int n, double *a, double *b); protected: void ConstructBoard(); void ReadSerialNumber(); TimeData *GetTimeCalibration(unsigned int chipIndex, bool reinit = false); int GetStretchedTime(float *time, float *measurement, int numberOfMeasurements, float period); public: #ifdef CT_VME DRSBoard(int MasterMapping, unsigned int BaseAddress, unsigned int BoardAddress, int SlotNumber); #endif #ifdef STRUCK_VME DRSBoard(MVME_INTERFACE * MVME_Interface, mvme_addr_t BaseAddress, int SlotNumber); MVME_INTERFACE *GetVMEInterface() const { return fVMEInterface; }; #endif void PrintBinary32(unsigned int i); long int GetMicroSeconds(); }; class DRS { protected: enum { kMaxNumberOfBoards = 40 }; protected: DRSBoard *fBoard[kMaxNumberOfBoards]; int fNumberOfBoards; #ifdef STRUCK_VME MVME_INTERFACE *fVMEInterface; #endif private: DRS(const DRS &c); // Not implemented DRS &operator=(const DRS &rhs); // Not implemented #ifdef CT_VME VME_MasterMap_t MasterMap; VME_ErrorCode_t ErrorCode; char ErrorString[VME_MAXSTRING]; int MasterMapping[kMaxNumberOfBoards]; int OpenVME(); int MasterMapVME(int* MMap); int MasterUnMapVME(int MMap); int CloseVME(); int OpenCMEM(); int CloseCMEM(); #endif int First_VME_Slot; int Last_VME_Slot; public: // Public Methods DRS(); ~DRS(); DRSBoard *GetBoard(int i) { return fBoard[i]; } DRSBoard **GetBoards() { return fBoard; } int GetNumberOfBoards() const { return fNumberOfBoards; } #ifdef STRUCK_VME MVME_INTERFACE *GetVMEInterface() const { return fVMEInterface; }; #endif void InitialScan(); void SetFirstVMESlot(int s) { First_VME_Slot = s; } void SetLastVMESlot(int s) { Last_VME_Slot = s; } int GetFirstVMESlot() { return First_VME_Slot; } int GetLastVMESlot() { return Last_VME_Slot; } }; #endif // DRS_H