/******************************************************************** DRS.h, S.Ritt, M. Schneebeli - PSI $Id: DRS.h 13347 2009-04-28 08:24:05Z ritt@PSI.CH $ ********************************************************************/ #ifndef DRS_H #define DRS_H #include #include #ifdef HAVE_LIBUSB # ifndef HAVE_USB # define HAVE_USB # endif #endif #ifdef HAVE_USB # include #endif // HAVE_USB #ifdef HAVE_VME # include #endif // HAVE_VME /* disable "deprecated" warning */ #ifdef _MSC_VER #pragma warning(disable: 4996) #endif #ifndef NULL #define NULL 0 #endif /* transport mode */ #define TR_VME 1 #define TR_USB 2 #define TR_USB2 3 /* address types */ #define T_CTRL 1 #define T_STATUS 2 #define T_RAM 3 #define T_FIFO 4 /* 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_EEPROM_WRITE_TRIG (1<<3) // write a "1" to write into serial EEPROM #define BIT_EEPROM_READ_TRIG (1<<4) // write a "1" to read from serial EEPROM #define BIT_AUTOSTART (1<<16) #define BIT_DMODE (1<<17) // (*DRS2*) 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_TCAL_SOURCE (1<<20) #define BIT_REFCLK_SOURCE (1<<20) #define BIT_FREQ_AUTO_ADJ (1<<21) // DRS2/3 #define BIT_TRANSP_MODE (1<<21) // DRS4 #define BIT_ENABLE_TRIGGER1 (1<<22) // External LEMO/FP/TRBUS trigger #define BIT_LONG_START_PULSE (1<<23) // (*DRS2*) 0:short start pulse (>0.8GHz), 1:long start pulse (<0.8GHz) #define BIT_READOUT_MODE (1<<23) // (*DRS3*) 0:start from first bin, 1:start from domino stop #define BIT_DELAYED_START (1<<24) // DRS2: start domino wave 400ns after soft trigger, used for waveform // generator startup #define BIT_NEG_TRIGGER (1<<24) // DRS4: use high-to-low trigger if set #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 #define BIT_STANDBY_MODE (1<<28) // put chip in standby mode #define BIT_TR_SOURCE1 (1<<29) // trigger source selection bits #define BIT_TR_SOURCE2 (1<<30) // trigger source selection bits #define BIT_ENABLE_TRIGGER2 (1<<31) // analog threshold (internal) trigger /* 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) #define BIT_PLL_LOCKED0 (1<<1) // 1 if PLL has locked (DRS4 evaluation board only) #define BIT_PLL_LOCKED1 (1<<2) // 1 if PLL DRS4 B has locked (DRS4 mezzanine board only) #define BIT_PLL_LOCKED2 (1<<3) // 1 if PLL DRS4 C has locked (DRS4 mezzanine board only) #define BIT_PLL_LOCKED3 (1<<4) // 1 if PLL DRS4 D has locked (DRS4 mezzanine board only) #define BIT_EEPROM_BUSY (1<<5) // 1 if EEPROM operation in progress /* configuration register bit definitions */ #define BIT_CONFIG_DMODE (1<<8) // 0: single shot, 1: circular #define BIT_CONFIG_PLLEN (1<<9) // write a "1" to enable the internal PLL #define BIT_CONFIG_WSRLOOP (1<<10) // write a "1" to connect WSROUT to WSRIN internally enum DRSBoardConstants { kNumberOfChannelsV2 = 10, kNumberOfChannelsV4 = 9, kNumberOfCalibChannelsV3 = 10, kNumberOfCalibChannelsV4 = 9, 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 }; /*---- callback class ----*/ class DRSCallback { public: virtual void Progress(int value) = 0; virtual ~DRSCallback() {}; }; /*------------------------*/ 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]; } memset(fLimitGroup, 0, sizeof(fLimitGroup)); memset(fMin, 0, sizeof(fMin)); memset(fRange, 0, sizeof(fRange)); memset(fOffset, 0, sizeof(fOffset)); memset(fGain, 0, sizeof(fGain)); memset(fOffsetADC, 0, sizeof(fOffsetADC)); memset(fLookUp, 0, sizeof(fLookUp)); memset(fLookUpOffset, 0, sizeof(fLookUpOffset)); memset(fNumberOfLookUpPoints, 0, sizeof(fNumberOfLookUpPoints)); } ~CalibrationDataChannel() { int i; delete fTempData; for (i = 0; i < kNumberOfBins; i++) { delete fData[i]; delete fLookUp[i]; } } }; bool fRead; //! CalibrationDataChannel *fChannel[10]; //! 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[10][kNumberOfBins]; float *fResponseY; unsigned short **fWaveFormMode3[10]; unsigned short **fWaveFormMode2[10]; unsigned short **fWaveFormOffset[10]; unsigned short **fWaveFormOffsetADC[10]; 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; double fGainMin; double fGainMax; 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); bool OffsetCalibrationV3(int chipNumber); bool OffsetCalibrationV4(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 offsetCalib); bool Calibrate(unsigned int chipIndex, unsigned int channel, unsigned short *adcWaveform, unsigned short *uWaveform, int triggerCell, float threshold, bool offsetCalib); 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; // DAC channels (USB EVAL1 (Version 5) : DAC_ROFS_1,DAC_CMOFS,DAC_CALN,DAC_CALP,DAC_BIAS,DAC_TLEVEL,DAC_ONOFS) unsigned int fDAC_CMOFS; unsigned int fDAC_CALN; unsigned int fDAC_CALP; unsigned int fDAC_ONOFS; protected: // Fields for DRS int fDRSType; int fBoardType; int fRequiredFirmwareVersion; int fFirmwareVersion; int fBoardSerialNumber; unsigned int fTransport; unsigned int fCtrlBits; int fNumberOfReadoutChannels; double fExternalClockFrequency; #ifdef HAVE_USB MUSB_INTERFACE *fUsbInterface; #endif #ifdef HAVE_VME MVME_INTERFACE *fVmeInterface; mvme_addr_t fBaseAddress; int fSlotNumber; #endif double fFrequency; double fRefClock; int fDominoMode; int fDominoActive; int fChannelConfig; int fWSRLoop; int fReadoutMode; int fTriggerEnable1; int fTriggerEnable2; int fTriggerSource; int fDelayedStart; int fTranspMode; unsigned short fTriggerCell[4]; double fROFS; double fCommonMode; int fAcalMode; double fAcalVolt; int fTcalMode; int fTcalLevel; int fTcalSource; unsigned char fWaveforms[kNumberOfChips * kNumberOfChannelsV2 * 2 * kNumberOfBins]; // Fields for Calibration int fMaxChips; char fCalibDirectory[1000]; // Fields for Response Calibration old method ResponseCalibration *fResponseCalibration; // Fields for Calibration new method bool fCellCalibrationValid; unsigned short fCellOffset[kNumberOfChips * kNumberOfChannelsV4][kNumberOfBins]; double fCellGain[kNumberOfChips * kNumberOfChannelsV4][kNumberOfBins]; bool fTimingCalibrationValid; double fCellT[kNumberOfChips][kNumberOfBins]; signed short fCellDT[kNumberOfChips * kNumberOfChannelsV4][kNumberOfBins]; // Fields for Time Calibration TimeData **fTimeData; int fNumberOfTimeData; // General debugging flag int fDebug; // Fields for wave transfer bool fWaveTransferred[kNumberOfChips * kNumberOfChannelsV2]; // Waveform Rotation int fTriggerStartBin; // Start Bin of the trigger private: DRSBoard(const DRSBoard &c); // not implemented DRSBoard &operator=(const DRSBoard &rhs); // not implemented public: // Public Methods #ifdef HAVE_USB DRSBoard(MUSB_INTERFACE * musb_interface); #endif #ifdef HAVE_VME DRSBoard(MVME_INTERFACE * mvme_interface, mvme_addr_t base_address, int slot_number); MVME_INTERFACE *GetVMEInterface() const { return fVmeInterface; }; #endif ~DRSBoard(); int SetBoardSerialNumber(unsigned short serialNumber); int GetBoardSerialNumber() const { return fBoardSerialNumber; } int GetFirmwareVersion() const { return fFirmwareVersion; } int GetRequiredFirmwareVersion() const { return fRequiredFirmwareVersion; } int GetDRSType() const { return fDRSType; } int GetBoardType() const { return fBoardType; } #ifdef HAVE_VME int GetSlotNumber() const { return fSlotNumber; } #endif int InitFPGA(void); int Write(int type, unsigned int addr, void *data, int size); int Read(int type, void *data, unsigned int addr, int size); int GetTransport() const { return fTransport; } void RegisterTest(void); int RAMTest(int flag); int ChipTest(); unsigned int GetCtrlReg(void); unsigned short GetConfigReg(void); unsigned int GetStatusReg(void); void SetLED(int state); void SetChannelConfig(int firstChannel, int lastChannel, int nConfigChannels); void SetNumberOfChannels(int nChannels); int EnableTrigger(int flag1, int flag2); int SetDelayedTrigger(int flag); int SetTriggerLevel(double value, bool negative, int delay); int SetTriggerSource(int source); int SetDelayedStart(int flag); int SetTranspMode(int flag); int SetStandbyMode(int flag); int IsBusy(void); int IsPLLLocked(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 Debug() { return fDebug; } 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 TransferWaves(int numberOfChannels = kNumberOfChips * kNumberOfChannelsV2); int TransferWaves(unsigned char *p, int numberOfChannels = kNumberOfChips * kNumberOfChannelsV2); int TransferWaves(int firstChannel, int lastChannel); int TransferWaves(unsigned char *p, 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, unsigned short *waveform, bool responseCalib = false, int triggerCell = -1, bool adjustToClock = false, float threshold = 0, bool offsetCalib = true); 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, bool offsetCalib = true); int GetWave(unsigned int chipIndex, unsigned char channel, unsigned short *waveform, bool responseCalib = false, int triggerCell = -1, bool adjustToClock = false, float threshold = 0, bool offsetCalib = true); int GetWave(unsigned int chipIndex, unsigned char channel, float *waveform, bool responseCalib, int triggerCell = -1, bool adjustToClock = false, float threshold = 0, bool offsetCalib = true); int GetWave(unsigned int chipIndex, unsigned char channel, float *waveform); 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); int GetTime(unsigned int chipIndex, double freq, float *time, bool tcalibrated=true, bool rotated=true); int GetTime(unsigned int chipIndex, float *time, bool tcalibrated=true, bool rotated=true); int GetTriggerCell(unsigned int chipIndex); int GetStopCell(unsigned int chipIndex); int GetTriggerCell(unsigned char *waveforms,unsigned int chipIndex); void TestDAC(int channel); void MeasureSpeed(); void InteractSpeed(); void MonitorFrequency(); int TestShift(int n); int EnableAcal(int mode, double voltage); int GetAcalMode() { return fAcalMode; } double GetAcalVolt() { return fAcalVolt; } int EnableTcal(int flag, int level, int source); int SetRefclk(int source); int GetTcalMode() { return fTcalMode; } int GetTcalLevel() { return fTcalLevel; } int GetTcalSource() { return fTcalSource; } int SetCalibVoltage(double value); int SetCalibTiming(int t1, int t2); double GetTemperature(); int GetTriggerBus(); int ReadEEPROM(unsigned short page, void *buffer, int size); int WriteEEPROM(unsigned short page, void *buffer, int size); bool HasCorrectFirmware(); int ConfigureLMK(double demand, int flag); bool InitTimeCalibration(unsigned int chipIndex); void SetCalibrationDirectory(const char *calibrationDirectoryPath); void GetCalibrationDirectory(char *calibrationDirectoryPath); ResponseCalibration *GetResponseCalibration() const { return fResponseCalibration; } int GetStoredTriggerCell(int chipIndex) const { return fTriggerCell[chipIndex]; } double GetPrecision() const { return fResponseCalibration->GetPrecision(); } int CalibrateWaveform(unsigned int chipIndex, unsigned char channel, unsigned short *adcWaveform, unsigned short *waveform, bool responseCalib, int triggerCell, bool adjustToClock, float threshold, bool offsetCalib); static void LinearRegression(double *x, double *y, int n, double *a, double *b); int AverageWaveforms(DRSCallback *pcb, int prog1, int prog2, float awf[8][1024], int n); int CalibrateVolt(DRSCallback *pcb); int CalibrateTiming(DRSCallback *pcb); bool IsCalibrationValid() { return fCellCalibrationValid; } bool IsTimingCalibrationValid() { return fTimingCalibrationValid; } protected: // Protected Methods void ConstructBoard(); void ReadSerialNumber(); void ReadCalibration(void); TimeData *GetTimeCalibration(unsigned int chipIndex, bool reinit = false); int GetStretchedTime(float *time, float *measurement, int numberOfMeasurements, float period); }; class DRS { protected: // constants enum { kMaxNumberOfBoards = 40 }; protected: DRSBoard *fBoard[kMaxNumberOfBoards]; int fNumberOfBoards; char fError[256]; #ifdef HAVE_VME MVME_INTERFACE *fVmeInterface; #endif private: DRS(const DRS &c); // not implemented DRS &operator=(const DRS &rhs); // not implemented public: // Public Methods DRS(); ~DRS(); DRSBoard *GetBoard(int i) { return fBoard[i]; } DRSBoard **GetBoards() { return fBoard; } int GetNumberOfBoards() const { return fNumberOfBoards; } bool GetError(char *str, int size); #ifdef HAVE_VME MVME_INTERFACE *GetVMEInterface() const { return fVmeInterface; }; #endif }; #endif // DRS_H