diff --git a/algo/detectors/rich/Unpack.cxx b/algo/detectors/rich/Unpack.cxx index 9f9db43ce10118b4143b322d0daf4bb989f4dc77..a66fb923c4fbbc9cbda0730e7e12848d2fdee5b5 100644 --- a/algo/detectors/rich/Unpack.cxx +++ b/algo/detectors/rich/Unpack.cxx @@ -12,30 +12,27 @@ namespace cbm::algo::rich { // ---- Algorithm execution --------------------------------------------- Unpack::resultType Unpack::operator()(const uint8_t* msContent, const fles::MicrosliceDescriptor& msDescr, - const uint64_t tTimeslice) + const uint64_t tTimeslice) const { - // --- Output data - resultType result = {}; - - fMonitor = UnpackMonitorData(); - fOutputVec.clear(); + MSContext ctx; // Clear CbmTime of MS. Used to get time offset of subtriggers to MS start - fCbmTimeMS = 0; + ctx.cbmTimeMS = 0; + ctx.digis.reserve(msDescr.size / sizeof(u32)); rich::MicrosliceReader reader; reader.SetData(msContent, msDescr.size); const auto mstime = msDescr.idx; - fMsRefTime = mstime - tTimeslice; + ctx.refTime = mstime - tTimeslice; // There are a lot of MS with 8 bytes size // Does one need these MS? - if (reader.GetSize() <= 8) return result; + if (reader.GetSize() <= 8) return {}; while (true) { - ProcessTrbPacket(reader); - ProcessHubBlock(reader); + ProcessTrbPacket(reader, ctx); + ProcessHubBlock(reader, ctx); // -4*2 for 2 last words which contain microslice index if (reader.GetOffset() >= reader.GetSize() - 8) break; @@ -45,19 +42,17 @@ namespace cbm::algo::rich uint32_t msIndexWord1 = reader.NextWord(); uint32_t msIndexWord2 = reader.NextWord(); - result.first = fOutputVec; - result.second = fMonitor; - return result; + return std::make_pair(std::move(ctx.digis), std::move(ctx.monitor)); } - void Unpack::ProcessTrbPacket(rich::MicrosliceReader& reader) + void Unpack::ProcessTrbPacket(rich::MicrosliceReader& reader, MSContext& ctx) const { //process CBM time const uint32_t word_MSB = reader.NextWord(); // CBM 63:32 const uint32_t word_LSB = reader.NextWord(); // CBM 31: 0 - fCbmTimePacket = (uint64_t) word_MSB << 32 | word_LSB; - if (fCbmTimeMS == 0) fCbmTimeMS = fCbmTimePacket; + ctx.cbmTimePacket = (uint64_t) word_MSB << 32 | word_LSB; + if (ctx.cbmTimeMS == 0) ctx.cbmTimeMS = ctx.cbmTimePacket; //discard unused words for (auto l = 0; l < 10; ++l) { @@ -72,9 +67,9 @@ namespace cbm::algo::rich const TdcTimeData td = ProcessTimeData(wordTime); const double fullTime = CalculateTime(epoch, td.fCoarse, td.fFine); - if (l == 0) fPrevLastCh0ReTime[12] = fullTime; - if (l == 1) fMbsCorr = fullTime - fPrevLastCh0ReTime[12]; // = MbsPrevTimeCh1 - MbsPrevTimeCh0 - if (l > 1) fPrevLastCh0ReTime[l - 2] = fullTime; + if (l == 0) ctx.prevLastCh0ReTime[12] = fullTime; + if (l == 1) ctx.mbsCorr = fullTime - ctx.prevLastCh0ReTime[12]; // = MbsPrevTimeCh1 - MbsPrevTimeCh0 + if (l > 1) ctx.prevLastCh0ReTime[l - 2] = fullTime; } const uint32_t trbNum = reader.NextWord(); // TRB trigger number @@ -82,7 +77,7 @@ namespace cbm::algo::rich } - void Unpack::ProcessHubBlock(rich::MicrosliceReader& reader) + void Unpack::ProcessHubBlock(rich::MicrosliceReader& reader, MSContext& ctx) const { uint32_t word = reader.NextWord(); const uint32_t hubId = word & 0xffff; // 16 bits @@ -90,7 +85,7 @@ namespace cbm::algo::rich bool isLast = false; // if true then it is CTS sub-sub-event size_t totalSize = 0; - fCurrentSubSubEvent = 0; + ctx.currentSubSubEvent = 0; uint32_t subSubEventId, subSubEventSize; @@ -104,18 +99,18 @@ namespace cbm::algo::rich if (!isLast) { // all except last are DiRICH events if (((subSubEventId >> 12) & 0xF) != 0x7) { // catch invalid ids - fMonitor.fNumErrInvalidHubId++; + ctx.monitor.fNumErrInvalidHubId++; } - if (totalSize == hubSize) { fMonitor.fNumErrInvalidHubSize++; } - ProcessSubSubEvent(reader, subSubEventSize, subSubEventId); - fCurrentSubSubEvent++; + if (totalSize == hubSize) { ctx.monitor.fNumErrInvalidHubSize++; } + ProcessSubSubEvent(reader, subSubEventSize, subSubEventId, ctx); + ctx.currentSubSubEvent++; } } //last event ist expected to be CTS - if (totalSize != hubSize || !isLast) { fMonitor.fNumErrInvalidHubSize++; } + if (totalSize != hubSize || !isLast) { ctx.monitor.fNumErrInvalidHubSize++; } subSubEventSize = ProcessCtsHeader(reader, subSubEventSize, subSubEventId); - ProcessSubSubEvent(reader, subSubEventSize, subSubEventId); + ProcessSubSubEvent(reader, subSubEventSize, subSubEventId, ctx); // read last words int lastWordsCounter = 0; @@ -126,11 +121,11 @@ namespace cbm::algo::rich if (reader.IsNextPadding()) word = reader.NextWord(); break; } - if (lastWordsCounter >= 7) { fMonitor.fNumErrExcessLastWords++; } + if (lastWordsCounter >= 7) { ctx.monitor.fNumErrExcessLastWords++; } } } - int Unpack::ProcessCtsHeader(rich::MicrosliceReader& reader, uint32_t subSubEventSize, uint32_t subSubEventId) + int Unpack::ProcessCtsHeader(rich::MicrosliceReader& reader, uint32_t subSubEventSize, uint32_t subSubEventId) const { const uint32_t word = reader.NextWord(); const uint32_t ctsState = word & 0xffff; // 16 bits @@ -154,7 +149,8 @@ namespace cbm::algo::rich return nofTimeWords; } - void Unpack::ProcessSubSubEvent(rich::MicrosliceReader& reader, int nofTimeWords, uint32_t subSubEventId) + void Unpack::ProcessSubSubEvent(rich::MicrosliceReader& reader, int nofTimeWords, uint32_t subSubEventId, + MSContext& ctx) const { uint32_t epoch = 0; // store last epoch obtained in sub-sub-event @@ -171,11 +167,11 @@ namespace cbm::algo::rich } // First word is expected to be of type "header" - if (GetTdcWordType(reader.NextWord()) != TdcWordType::Header) { fMonitor.fNumErrInvalidFirstMessage++; } + if (GetTdcWordType(reader.NextWord()) != TdcWordType::Header) { ctx.monitor.fNumErrInvalidFirstMessage++; } // Second word is expected to be of type "epoch" uint32_t word = reader.NextWord(); - if (GetTdcWordType(word) != TdcWordType::Epoch) { fMonitor.fNumErrInvalidSecondMessage++; } + if (GetTdcWordType(word) != TdcWordType::Epoch) { ctx.monitor.fNumErrInvalidSecondMessage++; } else { epoch = ProcessEpoch(word); } @@ -185,7 +181,7 @@ namespace cbm::algo::rich word = reader.NextWord(); switch (GetTdcWordType(word)) { case TdcWordType::TimeData: { - ProcessTimeDataWord(epoch, word, subSubEventId, raisingTime); + ProcessTimeDataWord(epoch, word, subSubEventId, raisingTime, ctx); break; } case TdcWordType::Epoch: { @@ -193,43 +189,44 @@ namespace cbm::algo::rich break; } case TdcWordType::Header: { - fMonitor.fNumErrWildHeaderMessage++; + ctx.monitor.fNumErrWildHeaderMessage++; break; } case TdcWordType::Trailer: { - fMonitor.fNumErrWildTrailerMessage++; + ctx.monitor.fNumErrWildTrailerMessage++; break; } case TdcWordType::Debug: { break; // for the moment do nothing - fMonitor.fNumDebugMessage++; + ctx.monitor.fNumDebugMessage++; break; } case TdcWordType::Error: { - fMonitor.fNumErrTdcErrorWord++; + ctx.monitor.fNumErrTdcErrorWord++; break; } } } // Last word is expected to be of type "trailer" - if (GetTdcWordType(reader.NextWord()) != TdcWordType::Trailer) { fMonitor.fNumErrInvalidLastMessage++; } + if (GetTdcWordType(reader.NextWord()) != TdcWordType::Trailer) { ctx.monitor.fNumErrInvalidLastMessage++; } } // ---- ProcessTimeDataWord ---- void Unpack::ProcessTimeDataWord(uint32_t epoch, uint32_t tdcWord, uint32_t subSubEventId, - std::vector<double>& raisingTime) + std::vector<double>& raisingTime, MSContext& ctx) const { const TdcTimeData td = ProcessTimeData(tdcWord); const double fullTime = CalculateTime(epoch, td.fCoarse, td.fFine); if (td.fChannel != 0) { - const double dT = fullTime - fPrevLastCh0ReTime[fCurrentSubSubEvent]; - const double subtrigOffset = (fCbmTimePacket - fCbmTimeMS) * 25.0; // offset of SubTrigger to MS start in ns - const double fullTimeCorr = dT - fMbsCorr + subtrigOffset; + const double dT = fullTime - ctx.prevLastCh0ReTime[ctx.currentSubSubEvent]; + const double subtrigOffset = + (ctx.cbmTimePacket - ctx.cbmTimeMS) * 25.0; // offset of SubTrigger to MS start in ns + const double fullTimeCorr = dT - ctx.mbsCorr + subtrigOffset; - if (td.fChannel < 1 || td.fChannel >= raisingTime.size()) { fMonitor.fNumErrChannelOutOfBounds++; } + if (td.fChannel < 1 || td.fChannel >= raisingTime.size()) { ctx.monitor.fNumErrChannelOutOfBounds++; } if (td.fIsRisingEdge) { // always store the latest raising edge. It means that in case RRFF situation only middle RF will be matched. raisingTime[td.fChannel] = fullTimeCorr; @@ -239,7 +236,9 @@ namespace cbm::algo::rich // Matching was found, calculate ToT, if tot is in a good range -> create digi const double ToT = fullTimeCorr - raisingTime[td.fChannel]; if (ToT >= fToTMin && ToT <= fToTMax) { - if (fullTimeCorr >= 0.0) { WriteOutputDigi(subSubEventId, td.fChannel, raisingTime[td.fChannel], ToT); } + if (fullTimeCorr >= 0.0) { + WriteOutputDigi(subSubEventId, td.fChannel, raisingTime[td.fChannel], ToT, ctx); + } } // pair was created, set raising edge to -1. raisingTime[td.fChannel] = -1.; @@ -248,25 +247,25 @@ namespace cbm::algo::rich } } - double Unpack::CalculateTime(uint32_t epoch, uint32_t coarse, uint32_t fine) + double Unpack::CalculateTime(uint32_t epoch, uint32_t coarse, uint32_t fine) const { return ((double) epoch) * 2048. * 5. + ((double) coarse) * 5. - ((double) fine) * 0.005; } - void Unpack::WriteOutputDigi(int32_t fpgaID, int32_t channel, double time, double tot) + void Unpack::WriteOutputDigi(int32_t fpgaID, int32_t channel, double time, double tot, MSContext& ctx) const { - double ToTcorr = fbDoToTCorr ? fParams.fElinkParams[fpgaID].fToTshift[channel] : 0.; + double ToTcorr = fbDoToTCorr ? fParams.fElinkParams.at(fpgaID).fToTshift[channel] : 0.; int32_t pixelUID = GetPixelUID(fpgaID, channel); //check ordering - double finalTime = time + (double) fMsRefTime - fParams.fElinkParams[fpgaID].fTimeOffset; + double finalTime = time + (double) ctx.refTime - fParams.fElinkParams.at(fpgaID).fTimeOffset; // Do not accept digis, where the MS und TS differs by more than 6 sec (mainly TS0) if (6e9 < finalTime) return; - fOutputVec.emplace_back(pixelUID, finalTime, tot - ToTcorr); + ctx.digis.emplace_back(pixelUID, finalTime, tot - ToTcorr); } - bool Unpack::CheckMaskedDiRICH(int32_t subSubEventId) + bool Unpack::CheckMaskedDiRICH(int32_t subSubEventId) const { for (unsigned int i = 0; i < fMaskedDiRICHes.size(); ++i) { if (fMaskedDiRICHes.at(i) == subSubEventId) return true; @@ -274,7 +273,7 @@ namespace cbm::algo::rich return false; } - TdcWordType Unpack::GetTdcWordType(uint32_t tdcWord) + TdcWordType Unpack::GetTdcWordType(uint32_t tdcWord) const { uint32_t tdcTimeDataMarker = (tdcWord >> 31) & 0x1; // 1 bit uint32_t tdcMarker = (tdcWord >> 29) & 0x7; // 3 bits @@ -293,14 +292,14 @@ namespace cbm::algo::rich return TdcWordType::Error; } - int32_t Unpack::GetPixelUID(int32_t fpgaID, int32_t ch) + int32_t Unpack::GetPixelUID(int32_t fpgaID, int32_t ch) const { // First 16 bits are used for the FPGA ID, then // 8 bits unused and then 8 bits are used for the channel return ((fpgaID << 16) | (ch & 0x00FF)); } - TdcTimeData Unpack::ProcessTimeData(uint32_t tdcWord) + TdcTimeData Unpack::ProcessTimeData(uint32_t tdcWord) const { TdcTimeData out; out.fCoarse = static_cast<uint32_t>(tdcWord & 0x7ff); // 11 bits @@ -310,13 +309,13 @@ namespace cbm::algo::rich return out; } - uint32_t Unpack::ProcessEpoch(uint32_t tdcWord) { return static_cast<uint32_t>(tdcWord & 0xfffffff); } + uint32_t Unpack::ProcessEpoch(uint32_t tdcWord) const { return static_cast<uint32_t>(tdcWord & 0xfffffff); } - uint16_t Unpack::ProcessHeader(uint32_t tdcWord) + uint16_t Unpack::ProcessHeader(uint32_t tdcWord) const { return static_cast<uint16_t>(tdcWord & 0xff); //8 bits } - uint16_t Unpack::ProcessTrailer(uint32_t tdcWord) { return static_cast<uint16_t>(tdcWord & 0xffff); } + uint16_t Unpack::ProcessTrailer(uint32_t tdcWord) const { return static_cast<uint16_t>(tdcWord & 0xffff); } } // namespace cbm::algo::rich diff --git a/algo/detectors/rich/Unpack.h b/algo/detectors/rich/Unpack.h index e668c2b1ffa995b8fb1afe6822f92a623ad0f13f..7786e7b3f39983416e96ddb2b85566acaa41b812 100644 --- a/algo/detectors/rich/Unpack.h +++ b/algo/detectors/rich/Unpack.h @@ -16,6 +16,8 @@ #include <sstream> #include <utility> +#include "Definitions.h" + namespace cbm::algo::rich { class MicrosliceReader; @@ -118,7 +120,7 @@ namespace cbm::algo::rich ** @return RICH digi data **/ resultType operator()(const uint8_t* msContent, const fles::MicrosliceDescriptor& msDescr, - const uint64_t tTimeslice); + const uint64_t tTimeslice) const; /** @brief Set the parameter container ** @param params Pointer to parameter container @@ -126,34 +128,49 @@ namespace cbm::algo::rich void SetParams(std::unique_ptr<UnpackPar> params) { fParams = *(std::move(params)); } private: - void ProcessTrbPacket(MicrosliceReader& reader); + struct MSContext { + u64 cbmTimeMS = 0; // CbmTime of MS. Used to get time offset of subtriggers to MS start + u64 cbmTimePacket = 0; + u64 refTime = 0; + + double prevLastCh0ReTime[13]; // 12 DiRICHes chnl0 + 1 CTS chnl0 + double mbsCorr = 0.; + + uint16_t currentSubSubEvent = 0; - void ProcessHubBlock(MicrosliceReader& reader); + std::vector<CbmRichDigi> digis; + UnpackMonitorData monitor; + }; + + private: + void ProcessTrbPacket(MicrosliceReader& reader, MSContext& ctx) const; - int ProcessCtsHeader(MicrosliceReader& reader, uint32_t subSubEventSize, uint32_t subSubEventId); + void ProcessHubBlock(MicrosliceReader& reader, MSContext& ctx) const; - void ProcessSubSubEvent(MicrosliceReader& reader, int nofTimeWords, uint32_t subSubEventId); + int ProcessCtsHeader(MicrosliceReader& reader, uint32_t subSubEventSize, uint32_t subSubEventId) const; - void ProcessTimeDataWord(uint32_t epoch, uint32_t tdcWord, uint32_t subSubEventId, - std::vector<double>& raisingTime); + void ProcessSubSubEvent(MicrosliceReader& reader, int nofTimeWords, uint32_t subSubEventId, MSContext& ctx) const; - TdcWordType GetTdcWordType(uint32_t tdcWord); + void ProcessTimeDataWord(uint32_t epoch, uint32_t tdcWord, uint32_t subSubEventId, std::vector<double>& raisingTime, + MSContext& ctx) const; - TdcTimeData ProcessTimeData(uint32_t tdcWord); + TdcWordType GetTdcWordType(uint32_t tdcWord) const; - uint32_t ProcessEpoch(uint32_t tdcWord); + TdcTimeData ProcessTimeData(uint32_t tdcWord) const; - uint16_t ProcessHeader(uint32_t tdcWord); + uint32_t ProcessEpoch(uint32_t tdcWord) const; - uint16_t ProcessTrailer(uint32_t tdcWord); + uint16_t ProcessHeader(uint32_t tdcWord) const; - void WriteOutputDigi(int32_t fpgaID, int32_t channel, double time, double tot); + uint16_t ProcessTrailer(uint32_t tdcWord) const; - double CalculateTime(uint32_t epoch, uint32_t coarse, uint32_t fine); + void WriteOutputDigi(int32_t fpgaID, int32_t channel, double time, double tot, MSContext& ctx) const; - int32_t GetPixelUID(int32_t fpgaID, int32_t ch); + double CalculateTime(uint32_t epoch, uint32_t coarse, uint32_t fine) const; - bool CheckMaskedDiRICH(int32_t subSubEventId); + int32_t GetPixelUID(int32_t fpgaID, int32_t ch) const; + + bool CheckMaskedDiRICH(int32_t subSubEventId) const; private: UnpackPar fParams = {}; ///< Parameter container @@ -162,23 +179,15 @@ namespace cbm::algo::rich bool fbDoToTCorr = true; //activates ToT correction from parameter file - uint64_t fCbmTimeMS; - uint64_t fCbmTimePacket; - - double fMbsCorr = 0.; - double fPrevLastCh0ReTime[13]; // 12 DiRICHes chnl0 + 1 CTS chnl0 - uint16_t fCurrentSubSubEvent = 0; + // uint64_t fCbmTimeMS; + // uint64_t fCbmTimePacket; - uint64_t fMsRefTime = 0; + // double fMbsCorr = 0.; + // double fPrevLastCh0ReTime[13]; // 12 DiRICHes chnl0 + 1 CTS chnl0 + // uint16_t fCurrentSubSubEvent = 0; double fToTMin = -20.; double fToTMax = 100.; - - /** @brief Default return vector for Unpack function. */ - std::vector<CbmRichDigi> fOutputVec = {}; - - /** @brief Storage of monitoring data. */ - UnpackMonitorData fMonitor; };