///////////////////////////////////////////////////////////// // // HTrbCtdcUnpacker // // This is class to unpack and calibrate data of single FPGA Clock TDC // It should be similar to functionality of hadaq::MdcProcessor from 'stream' framework // ///////////////////////////////////////////////////////////// #ifndef HTRBCTDCUNPACKER_H #define HTRBCTDCUNPACKER_H #include "htrb3unpacker.h" #include "htrbctdcmessage.h" #include "hades.h" #include "hevent.h" #include "heventheader.h" #include "TObject.h" #include #include // this define may switch off the overflow correction of time differences and ToT values #define CLOCKTDC_OVERFLOW_CORRECTION 1 // maximum hits allowed for each channel per event. Might change arrays later to std::vector #define CLOCKTDC_MAXHITS 10 // may exclude hits with larger tot than this (units seconds here) //#define CLOCKTDC_MAXTOT 500e-9 class HTrbCtdcUnpacker: public HTrb3Unpacker { public: // first define internal classes ////////////////////////////////////////////////////////////////////////////////////// ///////// Channel record structure: struct ChannelRec { Double_t rising_tm[CLOCKTDC_MAXHITS]; // rising time in seconds Double_t falling_tm[CLOCKTDC_MAXHITS]; // falling time in seconds UInt_t mult; Bool_t hasData; ChannelRec() : mult(0), hasData(kFALSE) { } void clear() { mult = 0; hasData = kFALSE; } void addHit(Double_t tm_rising, Double_t tm_falling) { if (mult >= CLOCKTDC_MAXHITS) return; rising_tm[mult] = tm_rising; falling_tm[mult] = tm_falling; mult++; hasData = kTRUE; } Double_t getHit(Bool_t rising, UInt_t cnt) { return rising ? (cnt < mult ? rising_tm[cnt] : 0.) : (cnt < mult ? falling_tm[cnt] : 0.); } Double_t getLastHit(Bool_t rising) { return rising ? (mult > 0 ? rising_tm[mult - 1] : 0.) : (mult > 0 ? falling_tm[mult - 1] : 0.); } void substractRefTime(Double_t reftm) { if (mult > CLOCKTDC_MAXHITS) { mult = CLOCKTDC_MAXHITS; } for (UInt_t n = 0; n < mult; n++) { rising_tm[n] -= reftm; falling_tm[n] -= reftm; #ifdef CLOCKTDC_OVERFLOW_CORRECTION // here also correct for overflow by long signal suppression limit // JAM 11-02-25: changed like in stream MDCProcessor: if (rising_tm[n] < CLOCKTDC_OVERFLOW_LOW){ rising_tm[n] += CLOCKTDC_MAXVALUE_S; } else if (rising_tm[n] > CLOCKTDC_OVERFLOW_HI){ rising_tm[n] -= CLOCKTDC_MAXVALUE_S; } if (falling_tm[n] < CLOCKTDC_OVERFLOW_LOW){ falling_tm[n] += CLOCKTDC_MAXVALUE_S; } else if (falling_tm[n] > CLOCKTDC_OVERFLOW_HI){ falling_tm[n] -= CLOCKTDC_MAXVALUE_S; } #endif } // for n } }; ////////////////////////////////////////////////////////////////////////////////////// ///////// TDC structure: static const size_t maxchan = 32; // JAM2024: first use for MDC with format version 0? struct TDC { UInt_t pSubEvtId; UInt_t fTdcId; UInt_t nChan; UInt_t fCalibr[2]; //!< temporary fine time calibration info from data stream TODO Int_t fNcalibr; // counter of available fine time calibration values TODO Bool_t fFoundInStream; // TDC was found in the data stream ChannelRec fCh[maxchan]; std::vector chanList; // list of channels containing data (if USE_FILLED_TDC is defined) Bool_t fhasData; //! Double_t fReferenceTime; // JAM24 - new, for clock tdc there is reference time independent from channels /** JAM2021: ctor checks if numchans are in allowed range */ TDC(size_t numchannels = maxchan) : pSubEvtId(0), fTdcId(0), nChan( numchannels <= maxchan ? numchannels : maxchan), fNcalibr( 0), fFoundInStream(kFALSE) { chanList.reserve(maxchan); } void clear() { for (UInt_t i = 0; i < nChan; ++i) fCh[i].clear(); chanList.clear(); fhasData = kFALSE; } Bool_t hasData() { for (UInt_t ch = 0; ch < numChannels(); ch++) { //if(ch==REFCHAN) continue; if (fCh[ch].hasData) return kTRUE; } return kFALSE; } UInt_t getTrbAddr() const { return fTdcId; } UInt_t numChannels() const { return nChan; } ChannelRec& getCh(UInt_t n) { return fCh[n]; } void setReftime(Double_t tm) { fReferenceTime = tm; } Int_t correctRefTime() { // calculates all times to first hit in channel 0 if (!fhasData) return kTRUE; if (!fFoundInStream) return kTRUE; // skipp empty data if (fTdcId == 0) { std::cout << "Warning: subevent 0x" << std::hex << pSubEvtId << " has not configured tdc id!" << std::endl; return kTRUE; // JAM2021: workaround for not configured unpacker LUT? } /* if (fReferenceTime == 0) { Long_t seqnum = -1; if (gHades != 0 && gHades->getCurrentEvent() != 0 && gHades->getCurrentEvent()->getHeader() != 0) { seqnum = gHades->getCurrentEvent()->getHeader()->getEventSeqNumber(); } cerr << " Warning: No reference time for trb=0x" << hex << getTrbAddr() << " sub event 0x" << pSubEvtId << dec << " in evt seq=" << seqnum << endl; return kFALSE; } */ for (UInt_t ch = 0; ch < numChannels(); ch++) fCh[ch].substractRefTime(fReferenceTime); return kTRUE; } }; // END TDC structure ////////////////////////////////////////////////////////////////////////////////// protected: std::vector fTDCs; //! std::vector factiveTDCs; //! list of TDCs found in the data stream std::vector fFilledTDCs; //! if USE_FILLED_TDC is defined this list contains TDC with data std::map fTDCsMap; //! Int_t nCalSrc; //! 0 -auto, 1 - no calibration, 2 - calpar, 3 - DAQ UInt_t fMinAddress; //!< for check of address range when autoregistration of tdcs UInt_t fMaxAddress; //!< for check of address range when autoregistration of tdcs Bool_t fUseTDCFromLookup; //! kTRUE : list of TDC build from lookup table, kFALSE : autoregister mode Double_t fTimeShift; //shift all times by a constant (to positive). Pendant to trb2 unpacker timeShift JAM Int_t getEventSeqNumber(); // void addCalpar(UInt_t id1, HTrb3CalparTdc*); public: HTrbCtdcUnpacker(vector &ids); virtual ~HTrbCtdcUnpacker(); virtual Bool_t reinit(); UInt_t numTDC() const { return fTDCs.size(); } TDC* getTDC(UInt_t n) { return &(fTDCs[n]); } UInt_t numActiveTDC() const { return factiveTDCs.size(); } TDC* getActiveTDC(UInt_t n) { return &(fTDCs[factiveTDCs[n]]); } UInt_t numFilledTDC() const { return fFilledTDCs.size(); } TDC* getFilledTDC(UInt_t n) { return &(fTDCs[fFilledTDCs[n]]); } /** preassign tdc of expected trbnet address. returns index in map*/ Int_t addTDC(UInt_t trbaddr, size_t numchannels = maxchan); void setCalibrationSource(UInt_t s) { nCalSrc = s; } Bool_t scanTdcData(UInt_t trbaddr, UInt_t *data, UInt_t datalen); Bool_t correctRefTime(); void setMinAddress(UInt_t trbnetaddress) { fMinAddress = trbnetaddress; } void setMaxAddress(UInt_t trbnetaddress) { fMaxAddress = trbnetaddress; } void shiftTimes(Double_t ts) { fTimeShift = ts; } protected: void clearAll(); virtual Bool_t decodeData(UInt_t trbaddr, UInt_t n, UInt_t *data); ClassDef(HTrbCtdcUnpacker,0); // Unpacker for TRB3 FPGA TDC }; #endif /* !HTRB3TDCUNPACKER_H */