diff --git a/reco/detectors/rich/CMakeLists.txt b/reco/detectors/rich/CMakeLists.txt index c766bcf688acf0c56cc1da382582458ef6ff11de..b1defbaef25ea164664355f3e3226a2b57f75f6d 100644 --- a/reco/detectors/rich/CMakeLists.txt +++ b/reco/detectors/rich/CMakeLists.txt @@ -84,6 +84,8 @@ qa/CbmRichGeoTestOpt.cxx qa/CbmRichRecoQa.cxx unpack/CbmRichUnpackAlgo.cxx +unpack/CbmRichUnpackAlgo2022.cxx +unpack/CbmRichUnpackAlgoBase.cxx unpack/CbmRichUnpackConfig.cxx ) diff --git a/reco/detectors/rich/CbmRichRecoLinkDef.h b/reco/detectors/rich/CbmRichRecoLinkDef.h index 80a8254f47b1769bfc1ff8dc2244eb7a41f7edbb..667b0bf5d4eb63129c81bc1d0ccd7cb4a84796b7 100644 --- a/reco/detectors/rich/CbmRichRecoLinkDef.h +++ b/reco/detectors/rich/CbmRichRecoLinkDef.h @@ -34,6 +34,8 @@ //unpack #pragma link C++ class CbmRichUnpackAlgo + ; +#pragma link C++ class CbmRichUnpackAlgo2022 + ; +#pragma link C++ class CbmRichUnpackAlgoBase + ; #pragma link C++ class CbmRichUnpackConfig + ; diff --git a/reco/detectors/rich/unpack/CbmRichUnpackAlgo.cxx b/reco/detectors/rich/unpack/CbmRichUnpackAlgo.cxx index 2a997dc41180b756d2688d2354208f963476e94f..3d0e08f8f50bd925e51a7b221da034c5ce009262 100644 --- a/reco/detectors/rich/unpack/CbmRichUnpackAlgo.cxx +++ b/reco/detectors/rich/unpack/CbmRichUnpackAlgo.cxx @@ -14,75 +14,10 @@ #include <cstdint> -CbmRichUnpackAlgo::CbmRichUnpackAlgo() : CbmRecoUnpackAlgo("CbmRichUnpackAlgo") {} +CbmRichUnpackAlgo::CbmRichUnpackAlgo() : CbmRichUnpackAlgoBase("CbmRichUnpackAlgo") {} CbmRichUnpackAlgo::~CbmRichUnpackAlgo() {} -// ---- GetParContainerRequest ---- -std::vector<std::pair<std::string, std::shared_ptr<FairParGenericSet>>>* - CbmRichUnpackAlgo::GetParContainerRequest(std::string /*geoTag*/, std::uint32_t /*runId*/) -{ - // Basepath for default Trd parameter sets (those connected to a geoTag) - std::string basepath = Form("%s", fParFilesBasePath.data()); - std::string temppath = ""; - - // // Get parameter container - temppath = basepath + "mRichPar_70.par"; - - fParContVec.emplace_back(std::make_pair(temppath, std::make_shared<CbmMcbm2018RichPar>())); - - return &fParContVec; -} - -// ---- calculateTime -double CbmRichUnpackAlgo::calculateTime(uint32_t epoch, uint32_t coarse, uint32_t fine) -{ - return ((double) epoch) * 2048. * 5. + ((double) coarse) * 5. - ((double) fine) * 0.005; -} - -// ---- getLogHeader -std::string CbmRichUnpackAlgo::getLogHeader(CbmRichUnpackAlgoMicrosliceReader& reader) -{ - std::stringstream stream; - stream << "[" << fNrProcessedTs << "-" << reader.GetWordCounter() << "/" << reader.GetSize() / 4 << " " - << reader.GetWordAsHexString(reader.GetCurWord()) << "] "; - return stream.str(); -} - -// ---- init -Bool_t CbmRichUnpackAlgo::init() { return kTRUE; } - -// ---- initParSet(FairParGenericSet* parset) ---- -Bool_t CbmRichUnpackAlgo::initParSet(FairParGenericSet* parset) -{ - LOG(info) << fName << "::initParSet - for container " << parset->ClassName(); - if (parset->IsA() == CbmMcbm2018RichPar::Class()) return initParSet(static_cast<CbmMcbm2018RichPar*>(parset)); - - // If we do not know the derived ParSet class we return false - LOG(error) << fName << "::initParSet - for container " << parset->ClassName() << " failed, since" << fName - << "::initParSet() does not know the derived ParSet and what to do with it!"; - return kFALSE; -} - -// ---- initParSet(CbmTrdParSetAsic* parset) ---- -Bool_t CbmRichUnpackAlgo::initParSet(CbmMcbm2018RichPar* parset) -{ - LOG(debug) << fName << "::initParSetAsic - "; - fUnpackPar = *parset; - fUnpackPar.Print(); - - LOG(info) << fName << "::initParSetRichMcbm2018 - Successfully initialized RICH unpacking parameters"; - - return kTRUE; -} - -// ---- isLog ---- -bool CbmRichUnpackAlgo::isLog() -{ - //if (fTsCounter == 25215) return true; - return false; -} - // ---- unpack bool CbmRichUnpackAlgo::unpack(const fles::Timeslice* ts, std::uint16_t icomp, UInt_t imslice) { @@ -440,13 +375,5 @@ void CbmRichUnpackAlgo::writeOutputDigi(Int_t fpgaID, Int_t channel, Double_t ti */ } -bool CbmRichUnpackAlgo::checkMaskedDiRICH(Int_t subSubEventId) -{ - for (unsigned int i = 0; i < fMaskedDiRICHes->size(); ++i) { - if (fMaskedDiRICHes->at(i) == subSubEventId) return true; - } - - return false; -} ClassImp(CbmRichUnpackAlgo) diff --git a/reco/detectors/rich/unpack/CbmRichUnpackAlgo.h b/reco/detectors/rich/unpack/CbmRichUnpackAlgo.h index 489fd43ac7e668eada28a4f847cb6de0401faf0d..2e5503cb462dd376c4a45246da97216f07a28b4a 100644 --- a/reco/detectors/rich/unpack/CbmRichUnpackAlgo.h +++ b/reco/detectors/rich/unpack/CbmRichUnpackAlgo.h @@ -24,6 +24,7 @@ #include "CbmMcbm2018RichPar.h" #include "CbmRecoUnpackAlgo.tmpl" #include "CbmRichDigi.h" +#include "CbmRichUnpackAlgoBase.h" #include "Timeslice.hpp" // timeslice @@ -36,164 +37,8 @@ #include <memory> #include <utility> -enum class CbmRichUnpackAlgoErrorType -{ - mtsError, - tdcHeader, - tdcTrailer, - ctsHeader, - ctsTrailer, - subEventError -}; - -enum class CbmRichUnpackAlgoTdcWordType -{ - TimeData, - Header, - Epoch, - Trailer, - Debug, - Error -}; - -class CbmRichUnpackAlgoTdcTimeData { -public: - uint32_t fCoarse = 0; // 11 bits - uint32_t fEdge = 0; // 1 bit - uint32_t fFine = 0; // 10 bits - uint32_t fChannel = 0; // 7 bits - - std::string ToString() - { - std::stringstream stream; - stream << "channel:" << fChannel << " coarse:" << fCoarse << " fine:" << fFine - << " edge:" << ((fEdge == 1) ? "R" : "F"); - return stream.str(); - } - - bool IsRisingEdge() { return (fEdge == 1); } -}; - -class CbmRichUnpackAlgoTdcWordReader { -public: - static CbmRichUnpackAlgoTdcWordType GetTdcWordType(uint32_t tdcWord) - { - uint32_t tdcTimeDataMarker = (tdcWord >> 31) & 0x1; // 1 bit - uint32_t tdcMarker = (tdcWord >> 29) & 0x7; // 3 bits - - if (tdcTimeDataMarker == 0x1) { - // TODO: I also include tdcMarker == 0x5, some tdc time data words have this marker. Is it correct? - if (tdcMarker == 0x4 || tdcMarker == 0x5) { return CbmRichUnpackAlgoTdcWordType::TimeData; } - else { - return CbmRichUnpackAlgoTdcWordType::Error; - } - } - - if (tdcMarker == 0x0) return CbmRichUnpackAlgoTdcWordType::Trailer; - if (tdcMarker == 0x1) return CbmRichUnpackAlgoTdcWordType::Header; - if (tdcMarker == 0x2) return CbmRichUnpackAlgoTdcWordType::Debug; - if (tdcMarker == 0x3) return CbmRichUnpackAlgoTdcWordType::Epoch; - - return CbmRichUnpackAlgoTdcWordType::Error; - } - - static void ProcessTimeData(uint32_t tdcWord, CbmRichUnpackAlgoTdcTimeData& outData) - { - outData.fCoarse = static_cast<uint32_t>(tdcWord & 0x7ff); // 11 bits - outData.fEdge = static_cast<uint32_t>((tdcWord >> 11) & 0x1); // 1 bit - outData.fFine = static_cast<uint32_t>((tdcWord >> 12) & 0x3ff); // 10 bits - outData.fChannel = static_cast<uint32_t>((tdcWord >> 22) & 0x7f); // 7 bits - } - - static uint32_t ProcessEpoch(uint32_t tdcWord) { return static_cast<uint32_t>(tdcWord & 0xfffffff); } - - static uint16_t ProcessHeader(uint32_t tdcWord) - { - // for the moment just extract error bits - return static_cast<uint16_t>(tdcWord & 0xff); //8 bits - } - - static uint16_t ProcessTrailer(uint32_t tdcWord) - { - // for the moment just extract error bits - return static_cast<uint16_t>(tdcWord & 0xffff); - } - - static void ProcessDebug(uint32_t tdcWord) - { - LOG(debug4) << "ProcessDebug is not implemented. tdcWord:0x" << std::hex << tdcWord << std::dec; - // for the moment do nothing - } -}; - -class CbmRichUnpackAlgoMicrosliceReader { -private: - const uint8_t* fData = nullptr; - size_t fSize = 0; - size_t fOffset = 0; // offset in bytes - size_t fWordCounter = 0; - uint32_t fCurWord; - -public: - void SetData(const uint8_t* data, size_t size) - { - fData = data; - fSize = size; - fOffset = 0; - fWordCounter = 0; - fCurWord = 0; - } - - const uint8_t* GetData() { return fData; } - - size_t GetSize() { return fSize; } - - size_t GetOffset() { return fOffset; } - - size_t GetWordCounter() { return fWordCounter; } - - uint32_t GetCurWord() { return fCurWord; } - - std::string GetWordAsHexString(uint32_t word) - { - std::stringstream stream; - stream << "0x" << std::setfill('0') << std::setw(sizeof(uint32_t) * 2) << std::hex << word; - return stream.str(); - } - - uint32_t NextWord() - { - //mRichSupport::SwapBytes(4, fData + fOffset); - //Int_t* dataPtr = (Int_t*) (fData + fOffset); - uint32_t i = ((uint32_t*) (fData + fOffset))[0]; - //swap bytes - i = (i >> 24) | ((i << 8) & 0x00FF0000) | ((i >> 8) & 0x0000FF00) | (i << 24); - //i = ((i&0xFF)<<24) | (((i>>8)&0xFF)<<16) | (((i>>16)&0xFF)<<8) | (((i>>24)&0xFF)<<0); - - fOffset += 4; - fWordCounter++; - fCurWord = i; - //return (Int_t)(dataPtr[0]); - return i; - } - - bool IsNextPadding() - { - uint32_t nextWord = ((uint32_t*) (fData + fOffset))[0]; - if (nextWord == 0xffffffff) return true; - return false; - } - bool IsLastSubSubEvent(uint32_t subSubEventSize) - { - uint32_t i = ((uint32_t*) (fData + fOffset + 4 * subSubEventSize))[0]; - i = (i >> 24) | ((i << 8) & 0x00ff0000) | ((i >> 8) & 0x0000ff00) | (i << 24); - if (i == 0x00015555) return true; - return false; - } -}; - -class CbmRichUnpackAlgo : public CbmRecoUnpackAlgo<CbmRichDigi> { +class CbmRichUnpackAlgo : public CbmRichUnpackAlgoBase { public: /** @brief Create the Cbm Trd Unpack AlgoBase object */ CbmRichUnpackAlgo(); @@ -207,67 +52,8 @@ public: /** @brief Assignment operator - not implemented **/ CbmRichUnpackAlgo& operator=(const CbmRichUnpackAlgo&) = delete; - /** - * @brief Get the requested parameter containers. To be defined in the derived classes! - * Return the required parameter containers together with the paths to the ascii - * files to. - * - * @param[in] std::string geoTag as used in CbmSetup - * @param[in] std::uint32_t runId for runwise defined parameters - * @return fParContVec - */ - virtual std::vector<std::pair<std::string, std::shared_ptr<FairParGenericSet>>>* - GetParContainerRequest(std::string geoTag, std::uint32_t runId); - - void SetMaskedDiRICHes(std::vector<Int_t>* maskedDiRICHes) { fMaskedDiRICHes = maskedDiRICHes; } protected: - double calculateTime(uint32_t epoch, uint32_t coarse, uint32_t fine); - - /** @brief Finish function for this algorithm base clase */ - void finish() - { - finishDerived(); - // Finish the monitor if we have one - // if (fMonitor) fMonitor->Finish(); - } - - /** @brief Function that allows special calls during Finish in the derived algos */ - virtual void finishDerived() { return; } - - std::string getLogHeader(CbmRichUnpackAlgoMicrosliceReader& reader); - - Int_t getPixelUID(Int_t fpgaID, Int_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)); - } - - /** - * @brief Intialisation at begin of run. Special inits of the derived algos. - * - * @retval Bool_t initOk - */ - Bool_t init(); - - /** - * @brief Handles the distribution of the hidden derived classes to their explicit functions. - * - * @param parset - * @return Bool_t initOk - */ - Bool_t initParSet(FairParGenericSet* parset); - - /** - * @brief Handles the distribution of the hidden derived classes to their explicit functions. - * - * @param parset - * @return Bool_t initOk - */ - Bool_t initParSet(CbmMcbm2018RichPar* parset); - - bool isLog(); void processTrbPacket(CbmRichUnpackAlgoMicrosliceReader& reader); @@ -288,16 +74,6 @@ protected: */ void writeOutputDigi(Int_t fpgaID, Int_t channel, Double_t time, Double_t tot); - /** - * @brief Set the Derived Ts Parameters - * - * In this function parameters required by the explicit algo connected to the timeslice can be set. - * - * @param itimeslice - * @return true - * @return false - */ - bool setDerivedTsParameters(size_t /*itimeslice*/) { return true; } /** * @brief Unpack a given microslice. To be implemented in the derived unpacker algos. @@ -312,25 +88,13 @@ protected: */ bool unpack(const fles::Timeslice* ts, std::uint16_t icomp, UInt_t imslice); - bool checkMaskedDiRICH(Int_t subSubEventId); - - /** @brief Parameters for the unpacking */ - CbmMcbm2018RichPar fUnpackPar; - - std::vector<Int_t>* fMaskedDiRICHes = nullptr; double fMbsPrevTimeCh0 = 0.; double fMbsPrevTimeCh1 = 0.; - size_t fMsRefTime = 0; - - double fToTMin = -20.; - double fToTMax = 100.; - std::map<uint32_t, double> fLastCh0ReTime; //key:TDC ID, value:Full time of last rising edge from ch 0 std::map<uint32_t, double> fPrevLastCh0ReTime; // key:TDC ID, value:Full time of previous last rising edge from ch 0 - Bool_t fbDoToTCorr = true; // kTRUE activates ToT correction from Parameterfile private: ClassDef(CbmRichUnpackAlgo, 2) diff --git a/reco/detectors/rich/unpack/CbmRichUnpackAlgo2022.cxx b/reco/detectors/rich/unpack/CbmRichUnpackAlgo2022.cxx new file mode 100644 index 0000000000000000000000000000000000000000..2b91a3a958ed30e12087f36679415db8143e4a7f --- /dev/null +++ b/reco/detectors/rich/unpack/CbmRichUnpackAlgo2022.cxx @@ -0,0 +1,407 @@ +/* Copyright (C) 2021 Goethe-University Frankfurt, Frankfurt + SPDX-License-Identifier: GPL-3.0-only + Authors: Pascal Raisig [committer] */ + +#include "CbmRichUnpackAlgo2022.h" + +#include <FairParGenericSet.h> +#include <FairTask.h> +#include <Logger.h> + +#include <Rtypes.h> +#include <RtypesCore.h> + +#include <cstdint> + + +CbmRichUnpackAlgo2022::CbmRichUnpackAlgo2022() : CbmRichUnpackAlgoBase("CbmRichUnpackAlgo2022") {} + +CbmRichUnpackAlgo2022::~CbmRichUnpackAlgo2022() {} + +// ---- unpack +bool CbmRichUnpackAlgo2022::unpack(const fles::Timeslice* ts, std::uint16_t icomp, UInt_t imslice) +{ + + const fles::MicrosliceView mv = ts->get_microslice(icomp, imslice); + const fles::MicrosliceDescriptor& msDesc = mv.desc(); + //std::cout<< "startMS"<<std::endl; + CbmRichUnpackAlgoMicrosliceReader reader; + reader.SetData(mv.content(), msDesc.size); + + auto mstime = msDesc.idx; + fMsRefTime = mstime - fTsStartTime; + //std::cout<< fMsRefTime <<" "<< fTsStartTime << std::endl; + // There are a lot of MS with 8 bytes size + // Does one need these MS? + if (reader.GetSize() <= 8) return true; + + while (true) { + processTrbPacket(reader); + // -4*2 for 2 last words which contain microslice index + if (reader.GetOffset() >= reader.GetSize() - 8) break; + // -4*3 for 0xffffffff padding and 2 last words which contain microslice index + if (reader.IsNextPadding() && reader.GetOffset() >= reader.GetSize() - 12) break; + } + + uint32_t msIndexWord1 = reader.NextWord(); + if (isLog()) LOG(DEBUG4) << getLogHeader(reader) << "Microslice Index 1:" << reader.GetWordAsHexString(msIndexWord1); + + uint32_t msIndexWord2 = reader.NextWord(); + if (isLog()) LOG(DEBUG4) << getLogHeader(reader) << "Microslice Index 2:" << reader.GetWordAsHexString(msIndexWord2); + + + return true; +} + +void CbmRichUnpackAlgo2022::processHubBlock(CbmRichUnpackAlgoMicrosliceReader& reader) +{ + uint32_t word = reader.NextWord(); + uint32_t hubId = word & 0xffff; // 16 bits + uint32_t hubSize = (word >> 16) & 0xffff; // 16 bits + if (isLog()) + LOG(debug4) << getLogHeader(reader) << "hubId:0x" << std::hex << hubId << std::dec << " hubSize:" << hubSize; + + //if ((HubId == 0xc001) || (HubId == 0xc000)) //CTS subevent? + //if (HubId == 0x5555) + //if (((HubId >> 8) & 0xff) == 0x82) // TRB subevent? // TODO: check if it starts from 0x82 + + // if true then it is CTS sub-sub-event + bool isLast = false; + size_t counter = 0; + size_t totalSize = 0; + fCurrentSubSubEvent = 1; + while (!isLast) { + word = reader.NextWord(); + uint32_t subSubEventId = word & 0xffff; // 16 bits + uint32_t subSubEventSize = (word >> 16) & 0xffff; // 16 bits + isLast = reader.IsLastSubSubEvent(subSubEventSize); // if true then it is CTS sub-sub-event + counter++; + totalSize += (1 + subSubEventSize); + + if (isLog()) + LOG(debug4) << getLogHeader(reader) << counter << ((isLast) ? " CTS" : " DiRICH") << " subSubEventId:0x" + << std::hex << subSubEventId << std::dec << " subSubEventSize:" << subSubEventSize; + + if (!isLast) { // DiRICH event + // check correctness of subsub event, for safety reasons + if (((subSubEventId >> 12) & 0xF) != 0x7) { + LOG(error) << getLogHeader(reader) << "ERROR: subSubEventId has strange value:0x" << std::hex << subSubEventId + << std::dec; + } + processSubSubEvent(reader, subSubEventSize, subSubEventId); + } + else { // CTS event + fCurrentSubSubEvent = 0; + processCtsSubSubEvent(reader, subSubEventSize, subSubEventId); + } + + // if (fbDebugMonitorMode) { + // //This address calculation is just for mCBM; will be a problem when using full CBM RICH acceptance + // uint16_t histAddr = ((subSubEventId >> 8) & 0xF) * 18 + ((subSubEventId >> 4) & 0xF) * 2 + (subSubEventId & 0xF); + // fhSubSubEventSize->Fill(histAddr, subSubEventSize); // Words in a DiRICH + // } + + if ((totalSize == hubSize && !isLast) || (totalSize != hubSize && isLast)) { + if (isLog()) LOG(error) << "ERROR: totalSize OR isLast is wrong"; + } + + if (totalSize >= hubSize || isLast) break; + + fCurrentSubSubEvent++; + } + + // read last words + int lastWordsCounter = 0; + while (true) { + lastWordsCounter++; + word = reader.NextWord(); + if (isLog()) LOG(debug4) << getLogHeader(reader); + if (word == 0x600dda7a) { + if (reader.IsNextPadding()) word = reader.NextWord(); + break; + } + if (lastWordsCounter >= 7) { + LOG(error) << getLogHeader(reader) + << "CbmMcbm2018UnpackerAlgoRich::ProcessHubBlock() ERROR: No word == 0x600dda7a"; + } + } +} + +void CbmRichUnpackAlgo2022::processCtsSubSubEvent(CbmRichUnpackAlgoMicrosliceReader& reader, uint32_t subSubEventSize, + uint32_t subSubEventId) +{ + uint32_t word = reader.NextWord(); + uint32_t ctsState = word & 0xffff; // 16 bits + uint32_t nofInputs = (word >> 16) & 0xf; // 4 bits + uint32_t nofTrigCh = (word >> 20) & 0x1f; // 5 bits + uint32_t inclLastIdle = (word >> 25) & 0x1; // 1 bit + uint32_t inclTrigInfo = (word >> 26) & 0x1; // 1 bit + uint32_t inclTime = (word >> 27) & 0x1; // 1 bit + uint32_t ETM = (word >> 28) & 0x3; // 2 bits + uint32_t ctsInfoSize = 2 * nofInputs + 2 * nofTrigCh + 2 * inclLastIdle + 3 * inclTrigInfo + inclTime; // in words + switch (ETM) { + case 0: break; + case 1: ctsInfoSize += 1; break; + case 2: ctsInfoSize += 4; break; + case 3: break; + } + if (isLog()) LOG(debug4) << getLogHeader(reader) << "CTS ctsState:" << ctsState << " ctsInfoSize:" << ctsInfoSize; + for (uint32_t i = 0; i < ctsInfoSize; i++) { + word = reader.NextWord(); // do nothing? + if (isLog()) LOG(debug4) << getLogHeader(reader) << "CTS info words"; + } + int nofTimeWords = subSubEventSize - ctsInfoSize - 1; + processSubSubEvent(reader, nofTimeWords, subSubEventId); +} + +void CbmRichUnpackAlgo2022::processSubSubEvent(CbmRichUnpackAlgoMicrosliceReader& reader, int nofTimeWords, + uint32_t subSubEventId) +{ + // Store if a certain TDC word type was analysed, + // later one can check if the order is correct + bool wasHeader = false; + bool wasEpoch = false; + bool wasTime = false; + bool wasTrailer = false; + uint32_t epoch = 0; // store last epoch obtained in sub-sub-event + bool errorInData = false; + + // Store last raising edge time for each channel or -1. if no time + // this array is used to match raising and falling edges + std::vector<double> raisingTime(33, -1.); + + // check if DiRICH (SubSubEvId) is masked + bool DiRICH_masked = false; + if (checkMaskedDiRICH(subSubEventId)) { DiRICH_masked = true; } + + for (int i = 0; i < nofTimeWords; i++) { + uint32_t word = reader.NextWord(); + if (DiRICH_masked) continue; + CbmRichUnpackAlgoTdcWordType type = CbmRichUnpackAlgoTdcWordReader::GetTdcWordType(word); + + if (type == CbmRichUnpackAlgoTdcWordType::TimeData) { + if (!wasHeader || !wasEpoch || wasTrailer) { + LOG(error) << getLogHeader(reader) << "DiRICH 0x" << std::hex << subSubEventId << std::dec + << ": illegal position of TDC Time (before header/epoch or after trailer)"; + errorInData = true; + continue; + } + wasTime = true; + processTimeDataWord(reader, i, epoch, word, subSubEventId, raisingTime); + } + else if (type == CbmRichUnpackAlgoTdcWordType::Epoch) { + if (!wasHeader || wasTrailer) { + LOG(error) << getLogHeader(reader) << "DiRICH 0x" << std::hex << subSubEventId << std::dec + << ": illegal position of TDC Epoch (before header or after trailer)"; + errorInData = true; + continue; + } + wasEpoch = true; + epoch = CbmRichUnpackAlgoTdcWordReader::ProcessEpoch(word); + if (isLog()) LOG(debug4) << getLogHeader(reader) << "SubSubEv[" << i << "] epoch:" << epoch; + } + else if (type == CbmRichUnpackAlgoTdcWordType::Header) { + if (wasEpoch || wasTime || wasTrailer) { + LOG(error) << getLogHeader(reader) << "DiRICH 0x" << std::hex << subSubEventId << std::dec + << ": illegal position of TDC Header (after time/epoch/trailer)"; + errorInData = true; + continue; + } + wasHeader = true; + // uint16_t errorBits = CbmRichUnpackAlgoTdcWordReader::ProcessHeader(word); + // ErrorMsg(errorBits, CbmRichUnpackAlgoErrorType::tdcHeader, subSubEventId); + if (isLog()) LOG(debug4) << getLogHeader(reader) << "SubSubEv[" << i << "] header"; + } + else if (type == CbmRichUnpackAlgoTdcWordType::Trailer) { + if (!wasEpoch || !wasTime || !wasHeader) { + LOG(error) << getLogHeader(reader) << "DiRICH 0x" << std::hex << subSubEventId << std::dec + << ": illegal position of TDC Trailer (before time/epoch/header)"; + errorInData = true; + continue; + } + wasTrailer = true; + // uint16_t errorBits = CbmRichUnpackAlgoTdcWordReader::ProcessTrailer(word); + // ErrorMsg(errorBits, CbmRichUnpackAlgoErrorType::tdcTrailer, subSubEventId); + if (isLog()) LOG(debug4) << getLogHeader(reader) << "SubSubEv[" << i << "] trailer"; + } + else if (type == CbmRichUnpackAlgoTdcWordType::Debug) { + // for the moment do nothing + } + else if (type == CbmRichUnpackAlgoTdcWordType::Error) { + LOG(error) << getLogHeader(reader) << "Wrong TDC word!!! marker:" << ((word >> 29) & 0x7); + errorInData = true; + } + } + + if (errorInData) { + //TODO: + } +} + +void CbmRichUnpackAlgo2022::processTrbPacket(CbmRichUnpackAlgoMicrosliceReader& reader) +{ + processCBMtime(reader); + uint32_t trigNum_this = reader.NextWord() & 0xFFFFFF; + for (auto l = 0; l < 5; ++l) + reader.NextWord(); + + //prev CBM time (64bit) + uint32_t cbmtime0 = reader.NextWord(); // CBM 63:32 + uint32_t cbmtime1 = reader.NextWord(); // CBM 31: 0 + uint64_t CbmTimePacket_prev = (uint64_t) cbmtime0 << 32 | cbmtime1; + + uint32_t trigNum_prevMes = reader.NextWord() & 0xFFFFFF; + + reader.NextWord(); // reserved + //std::cout<<"trigNum: "<<std::hex<< trigNum_this <<std::dec << " trigNum_prev: " <<std::hex<< trigNum_prevMes <<std::dec<<std::endl; + //std::cout<<"CBM time: "<<std::hex<< fCbmTimePacket <<std::dec<< " CBM time prev: " <<std::hex<< CbmTimePacket_prev <<std::dec<<std::endl; + for (auto l = 0; l < 14; ++l) { + uint32_t wordEpoch = reader.NextWord(); + uint32_t epoch = CbmRichUnpackAlgoTdcWordReader::ProcessEpoch(wordEpoch); + uint32_t wordTime = reader.NextWord(); + CbmRichUnpackAlgoTdcTimeData td; + CbmRichUnpackAlgoTdcWordReader::ProcessTimeData(wordTime, td); + + double fullTime = calculateTime(epoch, td.fCoarse, td.fFine); + + if (l == 0) { + fMbsPrevTimeCh0 = fullTime; + fPrevLastCh0ReTime[0] = fullTime; + } + if (l == 1) fMbsPrevTimeCh1 = fullTime; + if (l > 1) fPrevLastCh0ReTime[l - 1] = fullTime; + } + //processMbs(reader, false); // Current MBS + //processMbs(reader, true); // Previous MBS + + uint32_t trbNum = reader.NextWord(); // TRB trigger number + if (isLog()) LOG(debug4) << getLogHeader(reader) << "TRB Num:" << reader.GetWordAsHexString(trbNum); + + processHubBlock(reader); +} + +void CbmRichUnpackAlgo2022::processCBMtime(CbmRichUnpackAlgoMicrosliceReader& reader) +{ + uint32_t word_MSB = reader.NextWord(); // CBM 63:32 + uint32_t word_LSB = reader.NextWord(); // CBM 31: 0 + //fCbmTimePacket = 0; + //fCbmTimePacket = (uint64_t) word_MSB<<32 | word_LSB; +} + +void CbmRichUnpackAlgo2022::processMbs(CbmRichUnpackAlgoMicrosliceReader& reader, bool isPrev) +{ + uint32_t word = reader.NextWord(); + uint32_t mbsNum = word & 0xffffff; //24 bits + uint32_t nofCtsCh = (word >> 24) & 0xff; // 8 bits + if (isLog()) + LOG(debug4) << getLogHeader(reader) << "MBS mbsNum:0x" << std::hex << mbsNum << std::dec + << " nofCtsCh:" << nofCtsCh; + + for (uint32_t i = 0; i < nofCtsCh; i++) { + uint32_t wordEpoch = reader.NextWord(); + uint32_t epoch = CbmRichUnpackAlgoTdcWordReader::ProcessEpoch(wordEpoch); + if (isLog()) LOG(debug4) << getLogHeader(reader) << "MBS ch:" << i << " epoch:" << epoch; + + uint32_t wordTime = reader.NextWord(); + CbmRichUnpackAlgoTdcTimeData td; + CbmRichUnpackAlgoTdcWordReader::ProcessTimeData(wordTime, td); + if (isLog()) LOG(debug4) << getLogHeader(reader) << "MBS ch:" << i << " " << td.ToString(); + + double fullTime = calculateTime(epoch, td.fCoarse, td.fFine); + + if (isPrev && td.fChannel == 0) fMbsPrevTimeCh0 = fullTime; + if (isPrev && td.fChannel == 1) fMbsPrevTimeCh1 = fullTime; + } + + double mbsCorr = fMbsPrevTimeCh1 - fMbsPrevTimeCh0; + if (isLog()) + LOG(debug4) << getLogHeader(reader) << "MBS Prev ch1:" << std::setprecision(15) << fMbsPrevTimeCh1 + << " ch0:" << fMbsPrevTimeCh0 << " corr:" << mbsCorr; +} + +// ---- processTimeDataWord ---- +void CbmRichUnpackAlgo2022::processTimeDataWord(CbmRichUnpackAlgoMicrosliceReader& reader, int iTdc, uint32_t epoch, + uint32_t tdcWord, uint32_t subSubEventId, + std::vector<double>& raisingTime) +{ + CbmRichUnpackAlgoTdcTimeData td; + CbmRichUnpackAlgoTdcWordReader::ProcessTimeData(tdcWord, td); + double fullTime = calculateTime(epoch, td.fCoarse, td.fFine); + + + if (td.fChannel == 0) { + if (td.IsRisingEdge()) { + if (isLog()) + LOG(debug4) << getLogHeader(reader) << "SubSubEv[" << iTdc << "] " << td.ToString() + << " CH0 Last:" << std::setprecision(15) << fullTime + << " PrevLast:" << fPrevLastCh0ReTime[fCurrentSubSubEvent] + << " diff:" << fullTime - fPrevLastCh0ReTime[fCurrentSubSubEvent]; + } + } + else { + double dT = fullTime - fPrevLastCh0ReTime[fCurrentSubSubEvent]; + double mbsCorr = fMbsPrevTimeCh1 - fMbsPrevTimeCh0; + double fullTimeCorr = dT - mbsCorr; + + // std::cout<< dT <<" " + // << fullTimeCorr <<" "<< std::setprecision(15) + // << fullTime <<" " + // << fPrevLastCh0ReTime[fCurrentSubSubEvent] <<" " + // << mbsCorr <<" " + // << fCurrentSubSubEvent <<" " <<std::hex + // << subSubEventId << std::dec <<std::endl; + if (isLog()) + LOG(debug4) << getLogHeader(reader) << "SubSubEv[" << iTdc << "] " << td.ToString() + << " time:" << std::setprecision(15) << fullTime << " fullTimeCorr:" << fullTimeCorr; + + if (td.fChannel < 1 || td.fChannel >= raisingTime.size()) { + LOG(error) << "ERROR: channel number is out of limit. Channel:" << td.fChannel; + } + + if (td.IsRisingEdge()) { + // always store the latest raising edge. It means that in case RRFF situation only middle RF will be matched. + raisingTime[td.fChannel] = fullTimeCorr; + } + else { + if (raisingTime[td.fChannel] == -1.) { + //No raising channel was found before. Skip this falling edge time. + if (isLog()) + LOG(debug4) << getLogHeader(reader) << "SubSubEv[" << iTdc << "] " + << "No raising channel was found before. Skip this falling edge time."; + } + else { + // Matching was found, calculate ToT, if tot is in a good range -> create digi + double ToT = fullTimeCorr - raisingTime[td.fChannel]; + if (isLog()) + LOG(debug4) << getLogHeader(reader) << "SubSubEv[" << iTdc << "] " + << "ToT:" << ToT; + if (ToT >= fToTMin && ToT <= fToTMax) { + // if (fbMonitorMode) { + // TH1D* h = GetTotH1(subSubEventId, td.fChannel); + // if (h != nullptr) h->Fill(ToT); + + // TH2D* h2 = GetTotH2(subSubEventId); + // if (h2 != nullptr) h2->Fill(td.fChannel, ToT); + // } + if (fullTimeCorr >= 0.0) { writeOutputDigi(subSubEventId, td.fChannel, raisingTime[td.fChannel], ToT); } + } + // pair was created, set raising edge to -1. + raisingTime[td.fChannel] = -1.; + } + } + } +} + +void CbmRichUnpackAlgo2022::writeOutputDigi(Int_t fpgaID, Int_t channel, Double_t time, Double_t tot) +{ + Double_t ToTcorr = fbDoToTCorr ? fUnpackPar.GetToTshift(fpgaID, channel) : 0.; + Int_t pixelUID = this->getPixelUID(fpgaID, channel); + //check ordering + Double_t finalTime = time + (Double_t) fMsRefTime - fSystemTimeOffset; + //printf("time: %.3f %.3f %d\n",finalTime, time, fSystemTimeOffset); + // Double_t finalTime = time - fSystemTimeOffset - fTsStartTime; + + fOutputVec.emplace_back(pixelUID, finalTime, tot - ToTcorr); +} + +ClassImp(CbmRichUnpackAlgo2022) diff --git a/reco/detectors/rich/unpack/CbmRichUnpackAlgo2022.h b/reco/detectors/rich/unpack/CbmRichUnpackAlgo2022.h new file mode 100644 index 0000000000000000000000000000000000000000..7eaaa8ef7e48fa8bbc0987909406bc6bd20697f2 --- /dev/null +++ b/reco/detectors/rich/unpack/CbmRichUnpackAlgo2022.h @@ -0,0 +1,117 @@ +/* Copyright (C) 2021 Goethe-University Frankfurt, Frankfurt + SPDX-License-Identifier: GPL-3.0-only + Authors: Pascal Raisig [committer] */ + +/** + * @file CbmRichUnpackAlgo.h + * @author Pascal Raisig (praisig@ikf.uni-frankfurt.de) + * @brief Baseclass for the TrdR unpacker algorithms + * @version 0.1 + * @date 2021-04-21 + * + * @copyright Copyright (c) 2021 + * + * This is the base class for the algorithmic part of the tsa data unpacking + * processes of the CbmTrd. + * The actual translation from tsa to digi happens in the derived classes. + * + * +*/ + +#ifndef CbmRichUnpackAlgo2022_H +#define CbmRichUnpackAlgo2022_H + +#include "CbmMcbm2018RichPar.h" +#include "CbmRecoUnpackAlgo.tmpl" +#include "CbmRichDigi.h" +#include "CbmRichUnpackAlgoBase.h" + +#include "Timeslice.hpp" // timeslice + +#include <Rtypes.h> // for types +#include <RtypesCore.h> + +#include <cstddef> +#include <cstdint> +#include <iomanip> +#include <memory> +#include <utility> + +class CbmRichUnpackAlgo2022 : public CbmRichUnpackAlgoBase { +public: + /** @brief Create the Cbm Trd Unpack AlgoBase object */ + CbmRichUnpackAlgo2022(); + + /** @brief Destroy the Cbm Trd Unpack Task object */ + virtual ~CbmRichUnpackAlgo2022(); + + /** @brief Copy constructor - not implemented **/ + CbmRichUnpackAlgo2022(const CbmRichUnpackAlgo2022&) = delete; + + /** @brief Assignment operator - not implemented **/ + CbmRichUnpackAlgo2022& operator=(const CbmRichUnpackAlgo2022&) = delete; + + +protected: + void processCBMtime(CbmRichUnpackAlgoMicrosliceReader& reader); + + void processTrbPacket(CbmRichUnpackAlgoMicrosliceReader& reader); + + void processMbs(CbmRichUnpackAlgoMicrosliceReader& reader, bool isPrev); + + void processHubBlock(CbmRichUnpackAlgoMicrosliceReader& reader); + + void processCtsSubSubEvent(CbmRichUnpackAlgoMicrosliceReader& reader, uint32_t subSubEventSize, + uint32_t subSubEventId); + + void processSubSubEvent(CbmRichUnpackAlgoMicrosliceReader& reader, int nofTimeWords, uint32_t subSubEventId); + + void processTimeDataWord(CbmRichUnpackAlgoMicrosliceReader& reader, int iTdc, uint32_t epoch, uint32_t tdcWord, + uint32_t subSubEventId, std::vector<double>& raisingTime); + + /** + * Write a gidi object into the output collection + */ + void writeOutputDigi(Int_t fpgaID, Int_t channel, Double_t time, Double_t tot); + + + /** + * @brief Unpack a given microslice. To be implemented in the derived unpacker algos. + * + * @param ts timeslice pointer + * @param icomp index to the component to be unpacked + * @param imslice index of the microslice to be unpacked + * @return true + * @return false + * + * @remark The content of the µslice can only be accessed via the timeslice. Hence, we need to pass the pointer to the full timeslice + */ + bool unpack(const fles::Timeslice* ts, std::uint16_t icomp, UInt_t imslice); + + //bool checkMaskedDiRICH(Int_t subSubEventId); + + /** @brief Parameters for the unpacking */ + //CbmMcbm2018RichPar fUnpackPar; + + //std::vector<Int_t>* fMaskedDiRICHes = nullptr; + + double fMbsPrevTimeCh0 = 0.; + double fMbsPrevTimeCh1 = 0.; + + //size_t fMsRefTime = 0; + + //double fToTMin = -20.; + //double fToTMax = 100.; + + //uint64_t fCbmTimePacket = 0; + + double fPrevLastCh0ReTime[13]; // 12 DiRICHes chnl0 + 1 CTS chnl0 + int fCurrentSubSubEvent = 0; + + //Bool_t fbDoToTCorr = true; // kTRUE activates ToT correction from Parameterfile + +private: + ClassDef(CbmRichUnpackAlgo2022, 2) +}; + +#endif // CbmRichUnpackAlgo2022_H diff --git a/reco/detectors/rich/unpack/CbmRichUnpackAlgoBase.cxx b/reco/detectors/rich/unpack/CbmRichUnpackAlgoBase.cxx new file mode 100644 index 0000000000000000000000000000000000000000..fd057ba80b71bfae8a78ca43f3c5692e4bdea325 --- /dev/null +++ b/reco/detectors/rich/unpack/CbmRichUnpackAlgoBase.cxx @@ -0,0 +1,96 @@ +/* Copyright (C) 2021 Goethe-University Frankfurt, Frankfurt + SPDX-License-Identifier: GPL-3.0-only + Authors: Pascal Raisig [committer] */ + +#include "CbmRichUnpackAlgoBase.h" + +#include <FairParGenericSet.h> +#include <FairTask.h> +#include <Logger.h> + +#include <Rtypes.h> +#include <RtypesCore.h> + +#include <cstdint> + + +CbmRichUnpackAlgoBase::CbmRichUnpackAlgoBase(std::string name) : CbmRecoUnpackAlgo(name) {} + +CbmRichUnpackAlgoBase::~CbmRichUnpackAlgoBase() {} + +// ---- GetParContainerRequest ---- +std::vector<std::pair<std::string, std::shared_ptr<FairParGenericSet>>>* + CbmRichUnpackAlgoBase::GetParContainerRequest(std::string /*geoTag*/, std::uint32_t /*runId*/) +{ + // Basepath for default Trd parameter sets (those connected to a geoTag) + std::string basepath = Form("%s", fParFilesBasePath.data()); + std::string temppath = ""; + + // // Get parameter container + temppath = basepath + "mRichPar_70.par"; + + fParContVec.emplace_back(std::make_pair(temppath, std::make_shared<CbmMcbm2018RichPar>())); + + return &fParContVec; +} + +// ---- calculateTime +double CbmRichUnpackAlgoBase::calculateTime(uint32_t epoch, uint32_t coarse, uint32_t fine) +{ + return ((double) epoch) * 2048. * 5. + ((double) coarse) * 5. - ((double) fine) * 0.005; +} + +// ---- getLogHeader +std::string CbmRichUnpackAlgoBase::getLogHeader(CbmRichUnpackAlgoMicrosliceReader& reader) +{ + std::stringstream stream; + stream << "[" << fNrProcessedTs << "-" << reader.GetWordCounter() << "/" << reader.GetSize() / 4 << " " + << reader.GetWordAsHexString(reader.GetCurWord()) << "] "; + return stream.str(); +} + +// ---- init +Bool_t CbmRichUnpackAlgoBase::init() { return kTRUE; } + +// ---- initParSet(FairParGenericSet* parset) ---- +Bool_t CbmRichUnpackAlgoBase::initParSet(FairParGenericSet* parset) +{ + LOG(info) << fName << "::initParSet - for container " << parset->ClassName(); + if (parset->IsA() == CbmMcbm2018RichPar::Class()) return initParSet(static_cast<CbmMcbm2018RichPar*>(parset)); + + // If we do not know the derived ParSet class we return false + LOG(error) << fName << "::initParSet - for container " << parset->ClassName() << " failed, since" << fName + << "::initParSet() does not know the derived ParSet and what to do with it!"; + return kFALSE; +} + +// ---- initParSet(CbmTrdParSetAsic* parset) ---- +Bool_t CbmRichUnpackAlgoBase::initParSet(CbmMcbm2018RichPar* parset) +{ + LOG(debug) << fName << "::initParSetAsic - "; + fUnpackPar = *parset; + fUnpackPar.Print(); + + LOG(info) << fName << "::initParSetRichMcbm2018 - Successfully initialized RICH unpacking parameters"; + + return kTRUE; +} + +// ---- isLog ---- +bool CbmRichUnpackAlgoBase::isLog() +{ + //if (fTsCounter == 25215) return true; + return false; +} + + +bool CbmRichUnpackAlgoBase::checkMaskedDiRICH(Int_t subSubEventId) +{ + for (unsigned int i = 0; i < fMaskedDiRICHes->size(); ++i) { + if (fMaskedDiRICHes->at(i) == subSubEventId) return true; + } + + return false; +} + +ClassImp(CbmRichUnpackAlgoBase) diff --git a/reco/detectors/rich/unpack/CbmRichUnpackAlgoBase.h b/reco/detectors/rich/unpack/CbmRichUnpackAlgoBase.h new file mode 100644 index 0000000000000000000000000000000000000000..2f6cfc61113614cf49ff4d04ddf56ac64f117f81 --- /dev/null +++ b/reco/detectors/rich/unpack/CbmRichUnpackAlgoBase.h @@ -0,0 +1,314 @@ +/* Copyright (C) 2021 Goethe-University Frankfurt, Frankfurt + SPDX-License-Identifier: GPL-3.0-only + Authors: Pascal Raisig [committer] */ + +/** + * @file CbmRichUnpackAlgo.h + * @author Pascal Raisig (praisig@ikf.uni-frankfurt.de) + * @brief Baseclass for the TrdR unpacker algorithms + * @version 0.1 + * @date 2021-04-21 + * + * @copyright Copyright (c) 2021 + * + * This is the base class for the algorithmic part of the tsa data unpacking + * processes of the CbmTrd. + * The actual translation from tsa to digi happens in the derived classes. + * + * +*/ + +#ifndef CbmRichUnpackAlgoBase_H +#define CbmRichUnpackAlgoBase_H + +#include "CbmMcbm2018RichPar.h" +#include "CbmRecoUnpackAlgo.tmpl" +#include "CbmRichDigi.h" + +#include "Timeslice.hpp" // timeslice + +#include <Rtypes.h> // for types +#include <RtypesCore.h> + +#include <cstddef> +#include <cstdint> +#include <iomanip> +#include <memory> +#include <utility> + +enum class CbmRichUnpackAlgoErrorType +{ + mtsError, + tdcHeader, + tdcTrailer, + ctsHeader, + ctsTrailer, + subEventError +}; + +enum class CbmRichUnpackAlgoTdcWordType +{ + TimeData, + Header, + Epoch, + Trailer, + Debug, + Error +}; + +class CbmRichUnpackAlgoTdcTimeData { +public: + uint32_t fCoarse = 0; // 11 bits + uint32_t fEdge = 0; // 1 bit + uint32_t fFine = 0; // 10 bits + uint32_t fChannel = 0; // 7 bits + + std::string ToString() + { + std::stringstream stream; + stream << "channel:" << fChannel << " coarse:" << fCoarse << " fine:" << fFine + << " edge:" << ((fEdge == 1) ? "R" : "F"); + return stream.str(); + } + + bool IsRisingEdge() { return (fEdge == 1); } +}; + +class CbmRichUnpackAlgoTdcWordReader { +public: + static CbmRichUnpackAlgoTdcWordType GetTdcWordType(uint32_t tdcWord) + { + uint32_t tdcTimeDataMarker = (tdcWord >> 31) & 0x1; // 1 bit + uint32_t tdcMarker = (tdcWord >> 29) & 0x7; // 3 bits + + if (tdcTimeDataMarker == 0x1) { + // TODO: I also include tdcMarker == 0x5, some tdc time data words have this marker. Is it correct? + if (tdcMarker == 0x4 || tdcMarker == 0x5) { return CbmRichUnpackAlgoTdcWordType::TimeData; } + else { + return CbmRichUnpackAlgoTdcWordType::Error; + } + } + + if (tdcMarker == 0x0) return CbmRichUnpackAlgoTdcWordType::Trailer; + if (tdcMarker == 0x1) return CbmRichUnpackAlgoTdcWordType::Header; + if (tdcMarker == 0x2) return CbmRichUnpackAlgoTdcWordType::Debug; + if (tdcMarker == 0x3) return CbmRichUnpackAlgoTdcWordType::Epoch; + + return CbmRichUnpackAlgoTdcWordType::Error; + } + + static void ProcessTimeData(uint32_t tdcWord, CbmRichUnpackAlgoTdcTimeData& outData) + { + outData.fCoarse = static_cast<uint32_t>(tdcWord & 0x7ff); // 11 bits + outData.fEdge = static_cast<uint32_t>((tdcWord >> 11) & 0x1); // 1 bit + outData.fFine = static_cast<uint32_t>((tdcWord >> 12) & 0x3ff); // 10 bits + outData.fChannel = static_cast<uint32_t>((tdcWord >> 22) & 0x7f); // 7 bits + } + + static uint32_t ProcessEpoch(uint32_t tdcWord) { return static_cast<uint32_t>(tdcWord & 0xfffffff); } + + static uint16_t ProcessHeader(uint32_t tdcWord) + { + // for the moment just extract error bits + return static_cast<uint16_t>(tdcWord & 0xff); //8 bits + } + + static uint16_t ProcessTrailer(uint32_t tdcWord) + { + // for the moment just extract error bits + return static_cast<uint16_t>(tdcWord & 0xffff); + } + + static void ProcessDebug(uint32_t tdcWord) + { + LOG(debug4) << "ProcessDebug is not implemented. tdcWord:0x" << std::hex << tdcWord << std::dec; + // for the moment do nothing + } +}; + +class CbmRichUnpackAlgoMicrosliceReader { +private: + const uint8_t* fData = nullptr; + size_t fSize = 0; + size_t fOffset = 0; // offset in bytes + size_t fWordCounter = 0; + uint32_t fCurWord; + +public: + void SetData(const uint8_t* data, size_t size) + { + fData = data; + fSize = size; + fOffset = 0; + fWordCounter = 0; + fCurWord = 0; + } + + const uint8_t* GetData() { return fData; } + + size_t GetSize() { return fSize; } + + size_t GetOffset() { return fOffset; } + + size_t GetWordCounter() { return fWordCounter; } + + uint32_t GetCurWord() { return fCurWord; } + + std::string GetWordAsHexString(uint32_t word) + { + std::stringstream stream; + stream << "0x" << std::setfill('0') << std::setw(sizeof(uint32_t) * 2) << std::hex << word; + return stream.str(); + } + + uint32_t NextWord() + { + //mRichSupport::SwapBytes(4, fData + fOffset); + //Int_t* dataPtr = (Int_t*) (fData + fOffset); + uint32_t i = ((uint32_t*) (fData + fOffset))[0]; + //swap bytes + i = (i >> 24) | ((i << 8) & 0x00FF0000) | ((i >> 8) & 0x0000FF00) | (i << 24); + //i = ((i&0xFF)<<24) | (((i>>8)&0xFF)<<16) | (((i>>16)&0xFF)<<8) | (((i>>24)&0xFF)<<0); + + fOffset += 4; + fWordCounter++; + fCurWord = i; + //return (Int_t)(dataPtr[0]); + return i; + } + + bool IsNextPadding() + { + uint32_t nextWord = ((uint32_t*) (fData + fOffset))[0]; + if (nextWord == 0xffffffff) return true; + return false; + } + + bool IsLastSubSubEvent(uint32_t subSubEventSize) + { + uint32_t i = ((uint32_t*) (fData + fOffset + 4 * subSubEventSize))[0]; + i = (i >> 24) | ((i << 8) & 0x00ff0000) | ((i >> 8) & 0x0000ff00) | (i << 24); + if (i == 0x00015555) return true; + return false; + } +}; + +class CbmRichUnpackAlgoBase : public CbmRecoUnpackAlgo<CbmRichDigi> { +public: + /** @brief Create the Cbm Trd Unpack AlgoBase object */ + CbmRichUnpackAlgoBase(std::string name); + + /** @brief Destroy the Cbm Trd Unpack Task object */ + virtual ~CbmRichUnpackAlgoBase(); + + /** @brief Copy constructor - not implemented **/ + CbmRichUnpackAlgoBase(const CbmRichUnpackAlgoBase&) = delete; + + /** @brief Assignment operator - not implemented **/ + CbmRichUnpackAlgoBase& operator=(const CbmRichUnpackAlgoBase&) = delete; + + /** + * @brief Get the requested parameter containers. To be defined in the derived classes! + * Return the required parameter containers together with the paths to the ascii + * files to. + * + * @param[in] std::string geoTag as used in CbmSetup + * @param[in] std::uint32_t runId for runwise defined parameters + * @return fParContVec + */ + virtual std::vector<std::pair<std::string, std::shared_ptr<FairParGenericSet>>>* + GetParContainerRequest(std::string geoTag, std::uint32_t runId); + + void SetMaskedDiRICHes(std::vector<Int_t>* maskedDiRICHes) { fMaskedDiRICHes = maskedDiRICHes; } + +protected: + double calculateTime(uint32_t epoch, uint32_t coarse, uint32_t fine); + + /** @brief Finish function for this algorithm base clase */ + void finish() + { + finishDerived(); + // Finish the monitor if we have one + // if (fMonitor) fMonitor->Finish(); + } + + /** @brief Function that allows special calls during Finish in the derived algos */ + virtual void finishDerived() { return; } + + std::string getLogHeader(CbmRichUnpackAlgoMicrosliceReader& reader); + + Int_t getPixelUID(Int_t fpgaID, Int_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)); + } + + /** + * @brief Intialisation at begin of run. Special inits of the derived algos. + * + * @retval Bool_t initOk + */ + Bool_t init(); + + /** + * @brief Handles the distribution of the hidden derived classes to their explicit functions. + * + * @param parset + * @return Bool_t initOk + */ + Bool_t initParSet(FairParGenericSet* parset); + + /** + * @brief Handles the distribution of the hidden derived classes to their explicit functions. + * + * @param parset + * @return Bool_t initOk + */ + Bool_t initParSet(CbmMcbm2018RichPar* parset); + + bool isLog(); + + /** + * @brief Set the Derived Ts Parameters + * + * In this function parameters required by the explicit algo connected to the timeslice can be set. + * + * @param itimeslice + * @return true + * @return false + */ + bool setDerivedTsParameters(size_t /*itimeslice*/) { return true; } + + /** + * @brief Unpack a given microslice. To be implemented in the derived unpacker algos. + * + * @param ts timeslice pointer + * @param icomp index to the component to be unpacked + * @param imslice index of the microslice to be unpacked + * @return true + * @return false + * + * @remark The content of the µslice can only be accessed via the timeslice. Hence, we need to pass the pointer to the full timeslice + */ + //bool unpack(const fles::Timeslice* ts, std::uint16_t icomp, UInt_t imslice); + + bool checkMaskedDiRICH(Int_t subSubEventId); + + /** @brief Parameters for the unpacking */ + CbmMcbm2018RichPar fUnpackPar; + + std::vector<Int_t>* fMaskedDiRICHes = nullptr; + + size_t fMsRefTime = 0; + + double fToTMin = -20.; + double fToTMax = 100.; + + Bool_t fbDoToTCorr = true; // kTRUE activates ToT correction from Parameterfile + +private: + ClassDef(CbmRichUnpackAlgoBase, 2) +}; + +#endif // CbmRichUnpackAlgoBase diff --git a/reco/detectors/rich/unpack/CbmRichUnpackConfig.cxx b/reco/detectors/rich/unpack/CbmRichUnpackConfig.cxx index a2d2700dcfda7013fe6690a6b8821b240ee5bc7c..6aa968f57d8064078d295b1d11a65604124e5fed 100644 --- a/reco/detectors/rich/unpack/CbmRichUnpackConfig.cxx +++ b/reco/detectors/rich/unpack/CbmRichUnpackConfig.cxx @@ -5,6 +5,7 @@ #include "CbmRichUnpackConfig.h" #include "CbmRichUnpackAlgo.h" +#include "CbmRichUnpackAlgo2022.h" #include <Logger.h> @@ -32,15 +33,23 @@ void CbmRichUnpackConfig::InitAlgo() } // ---- chooseAlgo ---- -std::shared_ptr<CbmRichUnpackAlgo> CbmRichUnpackConfig::chooseAlgo() +std::shared_ptr<CbmRichUnpackAlgoBase> CbmRichUnpackConfig::chooseAlgo() { if (fDoLog) LOG(info) << fName << "::Init - chooseAlgo"; // Default unpacker selection // Unpacker algo from mcbm 2021 on and hopefully default for a long time. - auto algo = std::make_shared<CbmRichUnpackAlgo>(); - LOG(info) << fName << "::chooseAlgo() - selected algo = " << algo->Class_Name(); - return algo; + if (fUnpackerVersion == CbmRichUnpackerVersion::v02) { + auto algo = std::make_shared<CbmRichUnpackAlgo>(); + LOG(info) << fName << "::chooseAlgo() - selected algo = " << algo->Class_Name(); + return algo; + } + + if (fUnpackerVersion == CbmRichUnpackerVersion::v03) { + auto algo = std::make_shared<CbmRichUnpackAlgo2022>(); + LOG(info) << fName << "::chooseAlgo() - selected algo = " << algo->Class_Name(); + return algo; + } LOG(error) << fName << "::Init - chooseAlgo() - no algorithm created something went wrong. We can not work like this!"; diff --git a/reco/detectors/rich/unpack/CbmRichUnpackConfig.h b/reco/detectors/rich/unpack/CbmRichUnpackConfig.h index f73bd36f95305d3501d7157c7e1574ea27beb9c5..68c5da1d5999592bc0504c5e465618a7df73717b 100644 --- a/reco/detectors/rich/unpack/CbmRichUnpackConfig.h +++ b/reco/detectors/rich/unpack/CbmRichUnpackConfig.h @@ -20,7 +20,7 @@ #include "CbmRecoUnpackConfig.tmpl" #include "CbmRichDigi.h" -#include "CbmRichUnpackAlgo.h" +#include "CbmRichUnpackAlgoBase.h" #include <FairLogger.h> #include <Logger.h> @@ -33,7 +33,14 @@ #include <memory> #include <vector> -class CbmRichUnpackConfig : public CbmRecoUnpackConfig<CbmRichUnpackAlgo, CbmRichDigi, std::nullptr_t, std::nullptr_t> { +enum class CbmRichUnpackerVersion +{ + v02, + v03 +}; + +class CbmRichUnpackConfig : + public CbmRecoUnpackConfig<CbmRichUnpackAlgoBase, CbmRichDigi, std::nullptr_t, std::nullptr_t> { public: /** @@ -70,16 +77,21 @@ public: void MaskDiRICH(Int_t DiRICH) { fMaskedDiRICHes.push_back(DiRICH); } + void SetUnpackerVersion(CbmRichUnpackerVersion vers) { fUnpackerVersion = vers; } + protected: /** * @brief Choose the derived unpacker algorithm to be used for the DAQ output to Digi translation. If algo was already set manually by the user this algorithm is used. * * @return Bool_t initOk */ - virtual std::shared_ptr<CbmRichUnpackAlgo> chooseAlgo(); + virtual std::shared_ptr<CbmRichUnpackAlgoBase> chooseAlgo(); std::vector<Int_t> fMaskedDiRICHes = {}; + /** @brief Selector of Unpacker Version. */ + CbmRichUnpackerVersion fUnpackerVersion = CbmRichUnpackerVersion::v02; + private: ClassDef(CbmRichUnpackConfig, 3) };