From 368075853f625af09bcb3ba6ff8afa5e2c2d5255 Mon Sep 17 00:00:00 2001 From: Alexandru Bercuci <abercuci@niham.nipne.ro> Date: Wed, 19 Jun 2024 12:29:05 +0300 Subject: [PATCH] new unpacker for the trd2d.v06.24 data format --- core/detectors/trd/CbmTrdParModAsic.cxx | 11 +- core/detectors/trd/CbmTrdParModAsic.h | 6 +- core/detectors/trd/CbmTrdParSetAsic.cxx | 4 +- core/detectors/trd/CbmTrdParSetAsic.h | 2 +- .../trd/unpack/CbmTrdUnpackFaspAlgo.cxx | 360 ++++++++++-------- .../trd/unpack/CbmTrdUnpackFaspAlgo.h | 130 ++++--- 6 files changed, 299 insertions(+), 214 deletions(-) diff --git a/core/detectors/trd/CbmTrdParModAsic.cxx b/core/detectors/trd/CbmTrdParModAsic.cxx index fbb3ac7bd0..a097edcc9b 100644 --- a/core/detectors/trd/CbmTrdParModAsic.cxx +++ b/core/detectors/trd/CbmTrdParModAsic.cxx @@ -134,11 +134,18 @@ CbmTrdDigi::eCbmTrdAsicType CbmTrdParModAsic::GetAsicType() const } //_______________________________________________________________________________ -int CbmTrdParModAsic::HasEqId(uint16_t eq) const +int CbmTrdParModAsic::HasEqId(uint16_t eq, uint8_t& lnk) const { int idx(0); for (auto add : fCrobAdd) { - if (add == eq) return idx; + if ((add & 0xffff) == eq) { + lnk = 0; + return idx; + } + else if (((add >> 16) & 0xffff) == eq) { + lnk = 1; + return idx; + } idx++; } return -1; diff --git a/core/detectors/trd/CbmTrdParModAsic.h b/core/detectors/trd/CbmTrdParModAsic.h index c8dee321af..0595e7b176 100644 --- a/core/detectors/trd/CbmTrdParModAsic.h +++ b/core/detectors/trd/CbmTrdParModAsic.h @@ -79,12 +79,12 @@ public: virtual Int_t GetChamberType() const { return fType; } /** \brief Query the type of chamber*/ - virtual const int* GetCrobAddresses() const { return fCrobAdd.data(); } + virtual const int32_t* GetCrobAddresses() const { return fCrobAdd.data(); } /** \brief Query the existence of an equipment (CROB) by HW id on the current module params. * \return Returns the position of the equipment (CROB) on the current module; -1 in case of failure. */ - virtual int HasEqId(uint16_t eqid) const; + virtual int HasEqId(uint16_t eqid, uint8_t& lnk) const; /** \brief Returns the number of INSTALLED ASICs for the current module * It applies to the list of ASICs. @@ -109,7 +109,7 @@ protected: const CbmTrdParModAsic& operator=(const CbmTrdParModAsic& ref); uint8_t fType; ///< type of chamber for current module - std::vector<int> fCrobAdd; ///< ordered list of Crobs for current module + std::vector<int32_t> fCrobAdd; ///< ordered list of Crobs for current module std::map<int, CbmTrdParAsic*> fModPar; ///< list of ASIC params for module ClassDef(CbmTrdParModAsic, 1); // The set of ASICs for one TRD modules diff --git a/core/detectors/trd/CbmTrdParSetAsic.cxx b/core/detectors/trd/CbmTrdParSetAsic.cxx index d8afe85027..dff470890e 100644 --- a/core/detectors/trd/CbmTrdParSetAsic.cxx +++ b/core/detectors/trd/CbmTrdParSetAsic.cxx @@ -35,10 +35,10 @@ CbmTrdParSetAsic::CbmTrdParSetAsic(const char* name, const char* title, const ch } //_______________________________________________________________________________ -int CbmTrdParSetAsic::FindModuleByEqId(uint16_t eqid, uint8_t& crob_id) const +int CbmTrdParSetAsic::FindModuleByEqId(uint16_t eqid, uint8_t& crob_id, uint8_t& lnk_id) const { for (auto mod : fModuleMap) { - int crob = ((const CbmTrdParModAsic*) mod.second)->HasEqId(eqid); + int crob = ((const CbmTrdParModAsic*) mod.second)->HasEqId(eqid, lnk_id); if (crob < 0) continue; crob_id = crob; return mod.first; diff --git a/core/detectors/trd/CbmTrdParSetAsic.h b/core/detectors/trd/CbmTrdParSetAsic.h index 46993c932e..e5171565d8 100644 --- a/core/detectors/trd/CbmTrdParSetAsic.h +++ b/core/detectors/trd/CbmTrdParSetAsic.h @@ -42,7 +42,7 @@ public: * \param[out] crob_id index of crob on the module * \return module id in the setup */ - virtual int FindModuleByEqId(uint16_t eqid, uint8_t& crob_id) const; + virtual int FindModuleByEqId(uint16_t eqid, uint8_t& crob_id, uint8_t& lnk_id) const; /** \brief Build the ASICs par for the current module from the info stored in the param file * It applies to the list of ASICs. * \param module ASICs par (FASP or SPADIC) diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.cxx b/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.cxx index 5e30aabea8..1ac6e0373b 100644 --- a/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.cxx +++ b/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.cxx @@ -33,16 +33,6 @@ #define VERBOSE 0 using namespace std; -CbmTrdUnpackFaspAlgo::CbmTrdFaspMessage::CbmTrdFaspMessage(uint8_t c, uint8_t typ, uint8_t t, uint16_t d, uint8_t rob, - uint8_t asic) - : ch(c) - , type(typ) - , tlab(t) - , data(d) - , crob(rob) - , fasp(asic) -{ -} CbmTrdUnpackFaspAlgo::CbmTrdUnpackFaspAlgo() : CbmRecoUnpackAlgo("CbmTrdUnpackFaspAlgo") {} @@ -122,62 +112,10 @@ CbmTrdUnpackFaspAlgo::GetParContainerRequest(std::string geoTag, std::uint32_t r return &fParContVec; } -//_________________________________________________________________________________ -CbmTrdUnpackFaspAlgo::CbmTrdFaspMessageType CbmTrdUnpackFaspAlgo::mess_type(uint32_t wd) -{ - if ((wd >> kMessCh) & 0x1) return kData; - return kEpoch; -} - -//_________________________________________________________________________________ -void CbmTrdUnpackFaspAlgo::mess_readDW(uint32_t w, CbmTrdFaspMessage* mess) -{ - uint32_t wd(w), shift(0); - mess->ch = wd & 0xf; - shift += Int_t(kMessCh); - mess->type = (wd >> shift) & 0x1; - shift += Int_t(kMessType); - mess->tlab = (wd >> shift) & 0x7f; - shift += Int_t(kMessTlab); - mess->data = (wd >> shift) & 0x3fff; - shift += Int_t(kMessData); - mess->fasp = (wd >> shift) & 0x3f; - - printf("DBG :: "); - mess_prt(mess); -} - -//_________________________________________________________________________________ -void CbmTrdUnpackFaspAlgo::mess_readEW(uint32_t w, CbmTrdFaspMessage* mess) -{ - uint32_t wd(w), shift(0); - mess->ch = wd & 0xf; - shift += Int_t(kMessCh); - mess->type = (wd >> shift) & 0x1; - shift += Int_t(kMessType); - mess->epoch = (wd >> shift) & 0x1fffff; - shift += Int_t(kMessEpoch); - mess->crob = (wd >> shift) & 0x3f; - printf("DBG :: "); - mess_prt(mess); -} - -//_________________________________________________________________________________ -void CbmTrdUnpackFaspAlgo::mess_prt(CbmTrdFaspMessage* mess) -{ - if (mess->type == kData) - cout << boost::format(" DATA : fasp_id=%02d ch_id=%02d tclk=%03d data=%4d\n") - % static_cast<unsigned int>(mess->fasp) % static_cast<unsigned int>(mess->ch) - % static_cast<unsigned int>(mess->tlab) % static_cast<unsigned int>(mess->data); - else - cout << boost::format(" EPOCH: crob_id=%02d ch_id=%02d epoch=%05d\n") % static_cast<unsigned int>(mess->crob) - % static_cast<unsigned int>(mess->ch) % static_cast<unsigned int>(mess->epoch); -} - //_________________________________________________________________________________ bool CbmTrdUnpackFaspAlgo::pushDigis(std::vector<CbmTrdUnpackFaspAlgo::CbmTrdFaspMessage> messes, const uint16_t mod_id) { - const UChar_t lFasp = messes[0].fasp; + const UChar_t lFasp = messes[0].getFaspIdMod(); const CbmTrdParModAsic* asicPar = (CbmTrdParModAsic*) fAsicSet.GetModulePar(mod_id); const CbmTrdParFasp* faspPar = (CbmTrdParFasp*) asicPar->GetAsicPar(mod_id * 1000 + lFasp); const CbmTrdParModDigi* digiPar = (CbmTrdParModDigi*) fDigiSet->GetModulePar(mod_id); @@ -193,11 +131,11 @@ bool CbmTrdUnpackFaspAlgo::pushDigis(std::vector<CbmTrdUnpackFaspAlgo::CbmTrdFas return false; } - // TODO temporary add DAQ time calibration for FASPRO. - // Should be absorbed in the ASIC parameter definition ULong64_t tdaqOffset(0); - if (digiPar->GetPadRow(faspPar->GetPadAddress(messes[0].ch)) % 2 == 0) tdaqOffset = 3; - + if (fMess->version == eMessageVersion::kMessLegacy) { + // Add DAQ time calibration for legacy FASPRO. + if (digiPar->GetPadRow(faspPar->GetPadAddress(messes[0].ch)) % 2 == 0) tdaqOffset = 3; + } if (VERBOSE) faspPar->Print(); for (auto imess : messes) { @@ -214,7 +152,7 @@ bool CbmTrdUnpackFaspAlgo::pushDigis(std::vector<CbmTrdUnpackFaspAlgo::CbmTrdFas if (VERBOSE) { const Int_t ch = 2 * pad + chCalib->HasPairingR(); - mess_prt(&imess); + imess.print(); printf("fasp[%2d] ch[%4d / %2d] pad[%4d] row[%2d] col[%2d] %c[%4d]\n", lFasp, ch, imess.ch, pad, digiPar->GetPadRow(pad), digiPar->GetPadColumn(pad), (chCalib->HasPairingT() ? 'T' : 'R'), lchT > 0 ? lchT : lchR); @@ -254,18 +192,22 @@ bool CbmTrdUnpackFaspAlgo::pushDigis(std::vector<CbmTrdUnpackFaspAlgo::CbmTrdFas id = digiBuffer.rbegin(); } - // update charge for previously allocated digis to account for FASPRO ADC buffering and read-out feature - for (++id; id != digiBuffer.rend(); ++id) { - r = (*id).GetCharge(t, dt); - if (lchR && int(r)) { // update R charge and mark on digi - (*id).SetCharge(t, lchR, dt); - (*id).SetFlag(1); - break; - } - else if (lchT && int(t)) { // update T charge and mark on digi - (*id).SetCharge(lchT, r, dt); - (*id).SetFlag(0); - break; + // LEGACY CODE: + if (fMess->version == eMessageVersion::kMessLegacy) { + // update charge for previously allocated digis + // to account for FASPRO ADC buffering and read-out feature + for (++id; id != digiBuffer.rend(); ++id) { + r = (*id).GetCharge(t, dt); + if (lchR && int(r)) { // update R charge and mark on digi + (*id).SetCharge(t, lchR, dt); + (*id).SetFlag(1); + break; + } + else if (lchT && int(t)) { // update T charge and mark on digi + (*id).SetCharge(lchT, r, dt); + (*id).SetFlag(0); + break; + } } } } @@ -302,10 +244,14 @@ void CbmTrdUnpackFaspAlgo::FinalizeComponent() uint nIncomplete(0); for (auto id = fDigiBuffer[ipad].begin(); id != fDigiBuffer[ipad].end(); id++) { r = (*id).GetCharge(t, dt); - // check if digi has all signals CORRECTED - if (((t > 0) != (*id).IsFlagged(0)) || ((r > 0) != (*id).IsFlagged(1))) { - nIncomplete++; - continue; + + // LEGACY CODE: + if (fMess->version == eMessageVersion::kMessLegacy) { + // check if digi has all signals CORRECTED + if (((t > 0) != (*id).IsFlagged(0)) || ((r > 0) != (*id).IsFlagged(1))) { + nIncomplete++; + continue; + } } if (fMonitor) fMonitor->FillHistos((&(*id))); // reset flags as they were used only to mark the correctly setting of the charge/digi @@ -325,7 +271,7 @@ void CbmTrdUnpackFaspAlgo::FinalizeComponent() bool CbmTrdUnpackFaspAlgo::unpack(const fles::Timeslice* ts, std::uint16_t icomp, UInt_t imslice) { if (VERBOSE) printf("CbmTrdUnpackFaspAlgo::unpack 0x%04x %d\n", icomp, imslice); - // LOG(info) << "Component " << icomp << " connected to config CbmTrdUnpackConfig2D. Slice "<<imslice; + LOG(debug2) << "Component " << icomp << " connected to config CbmTrdUnpackConfig2D. Slice " << imslice; bool unpackOk = true; //Double_t fdMsSizeInNs = 1.28e6; @@ -333,16 +279,30 @@ bool CbmTrdUnpackFaspAlgo::unpack(const fles::Timeslice* ts, std::uint16_t icomp auto msdesc = ts->descriptor(icomp, imslice); // Cast required to silence a warning on macos (there a uint64_t is a llu) - if (VERBOSE) printf("time start %lu\n", static_cast<size_t>(msdesc.idx)); - + if (VERBOSE) + printf("time start %lu system[0x%x] version[0x%x]\n", static_cast<size_t>(msdesc.idx), msdesc.sys_id, + msdesc.sys_ver); + + // this is executed only once, at the beginning, after discovering the packing version of the data + if (!fMess) { + switch (msdesc.sys_ver) { + case (int) eMessageVersion::kMessLegacy: + LOG(info) << "CbmTrdUnpackFaspAlgo::unpack : Legacy version."; + fMess = new CbmTrdFaspMessage(); + break; + case (int) eMessageVersion::kMess24: + LOG(info) << "CbmTrdUnpackFaspAlgo::unpack : 06.2024 version."; + fMess = new CbmTrdFaspMessage24(); + break; + default: LOG(fatal) << "CbmTrdUnpackFaspAlgo::unpack : Un-registered version " << msdesc.sys_ver; break; + } + } // define time wrt start of time slice in TRD/FASP clks [80 MHz] fTime = ULong64_t((msdesc.idx - fTsStartTime - fSystemTimeOffset) / 12.5); - // get MOD_id and CROB id from the equipment, using the comp map: eq_id -> (mod_id, crob_id) - uint8_t crob_id(0); - const uint16_t eq_id = msdesc.eq_id; - uint16_t mod_id = fAsicSet.FindModuleByEqId(eq_id, crob_id); - + // get MOD_id and ROB id from the equipment, using the comp map: eq_id -> (mod_id, rob_id) + fMess->mod = fAsicSet.FindModuleByEqId(msdesc.eq_id, fMess->rob, fMess->elink); + //printf("AB :: eq_id[0x%x] -> rob[%d] link[%d] mod[%d]\n", msdesc.eq_id, fMess->rob, fMess->elink, fMess->mod); // Get the µslice size in bytes to calculate the number of completed words auto mssize = msdesc.size; @@ -357,90 +317,188 @@ bool CbmTrdUnpackFaspAlgo::unpack(const fles::Timeslice* ts, std::uint16_t icomp const uint32_t* wd = reinterpret_cast<const uint32_t*>(mscontent); - UChar_t lFaspOld(0xff); + uint8_t lFaspOld(0xff); vector<CbmTrdFaspMessage> vMess; for (uint64_t j = 0; j < nwords; j++, wd++) { - // // Select the appropriate conversion type of the word according to the message type - // switch(mess_type(*wd)){ - // case CbmTrdFaspMessageType::kData: - // mess_readDW(*wd, &mess); - // break; - // case CbmTrdFaspMessageType::kEpoch: - // mess_readEW(*wd, &mess); - // break; - // } uint32_t w = *wd; - uint8_t ch_id = w & 0xf; - uint8_t isaux = (w >> 4) & 0x1; - uint8_t slice = (w >> 5) & 0x7f; - uint16_t data = (w >> 12) & 0x3fff; - uint32_t epoch = (w >> 5) & 0x1fffff; - uint8_t fasp_id = ((w >> 26) & 0x3f) + crob_id * NFASPCROB; + // Select the appropriate conversion type of the word according to + // the message version and type + switch (fMess->getType(w)) { + case eMessageType::kData: fMess->readDW(w); break; + case eMessageType::kEpoch: fMess->readEW(w); break; + default: break; + } + + // uint8_t ch_id = w & 0xf; + // uint8_t isaux = (w >> 4) & 0x1; + // uint8_t slice = (w >> 5) & 0x7f; + // uint16_t data = (w >> 12) & 0x3fff; + // uint32_t epoch = (w >> 5) & 0x1fffff; + // uint8_t fasp_id = ((w >> 26) & 0x3f) + crob_id * NFASPCROB; // std::cout<<"fasp_id="<<static_cast<unsigned int>(fasp_id)<<" ch_id="<<static_cast<unsigned int>(ch_id)<<" isaux="<<static_cast<unsigned int>(isaux)<<std::endl; - if (isaux) { - if (!ch_id) { + if (fMess->type == (int) eMessageType::kEpoch) { + if (!fMess->ch) { // clear buffer - if (vMess.size()) { pushDigis(vMess, mod_id); } + if (vMess.size()) pushDigis(vMess, fMess->mod); vMess.clear(); - if (VERBOSE) - cout << boost::format(" EE : fasp_id=%02d ch_id=%02d epoch=%03d\n") % static_cast<unsigned int>(fasp_id) - % static_cast<unsigned int>(ch_id) % static_cast<unsigned int>(epoch); + if (VERBOSE) fMess->print(); lFaspOld = 0xff; fTime += FASP_EPOCH_LENGTH; } - else if (ch_id == 1) { - if (VERBOSE) cout << boost::format(" PAUSE: fasp_id=%02d\n") % static_cast<unsigned int>(fasp_id); + else { + LOG(error) << "CbmTrdUnpackFaspAlgo::unpack : Epoch message with wrong signature. Ask an expert."; } continue; } - if (lFaspOld != fasp_id) { + if (lFaspOld != fMess->getFaspIdMod()) { // push - if (vMess.size()) { pushDigis(vMess, mod_id); } + if (vMess.size()) pushDigis(vMess, fMess->mod); vMess.clear(); - lFaspOld = fasp_id; - } - if (data & 0x1) { - LOG(warn) << GetName() << "::unpack - Data corrupted : detect end bit set."; - continue; + lFaspOld = fMess->getFaspIdMod(); } - if (VERBOSE) - cout << boost::format(" DD : fasp_id=%02d ch_id=%02d slice=%03d data=%4d\n") - % static_cast<unsigned int>(fasp_id) % static_cast<unsigned int>(ch_id) - % static_cast<unsigned int>(slice) % static_cast<unsigned int>(data >> 1); - if (data & 0x2000) { - LOG(debug) << GetName() << "::unpack - Self-triggered data."; - data &= 0x1fff; - } - vMess.emplace_back(ch_id, kData, slice, data >> 1, crob_id, lFaspOld); - //prt_wd(*wd); + if (VERBOSE) fMess->print(); + vMess.emplace_back(*fMess); + //vMess.emplace_back(crob_id, lFaspOld, ch_id, kData, slice, data >> 1); } return unpackOk; } +//_________________________________________________________________________________ +CbmTrdUnpackFaspAlgo::CbmTrdFaspMessage::CbmTrdFaspMessage(uint8_t rdaq, uint8_t asic, uint8_t c, uint8_t typ, + uint8_t t, uint16_t d, uint8_t lnk) + : ch(c) + , type(typ) + , tlab(t) + , data(d) + , rob(rdaq) + , elink(lnk) + , fasp(asic) +{ +} + +//_________________________________________________________________________________ +CbmTrdUnpackFaspAlgo::eMessageType CbmTrdUnpackFaspAlgo::CbmTrdFaspMessage::getType(uint32_t wd) const +{ + if ((wd >> (int) eMessageLength::kMessCh) & 0x1) return eMessageType::kEpoch; + return eMessageType::kData; +} + //_____________________________________________________________ -void CbmTrdUnpackFaspAlgo::prt_wd(uint32_t w) +void CbmTrdUnpackFaspAlgo::CbmTrdFaspMessage::readDW(uint32_t w) { - // out<<w<<std::endl; - uint8_t ch_id = w & 0xf; - uint8_t isaux = (w >> 4) & 0x1; - uint8_t slice = (w >> 5) & 0x7f; - uint16_t data = (w >> 12) & 0x3fff; - uint32_t epoch = (w >> 5) & 0x1fffff; - uint8_t fasp_id = (w >> 26) & 0x3f; - // out<<"fasp_id="<<static_cast<unsigned int>(fasp_id)<<" ch_id="<<static_cast<unsigned int>(ch_id)<<" isaux="<<static_cast<unsigned int>(isaux)<<std::endl; - if (isaux) { - if (!ch_id) { cout << boost::format("EE: %08d\n") % epoch; } - else if (ch_id == 1) { - cout << boost::format(" PAUSE: fasp_id=%02d\n") % static_cast<unsigned int>(fasp_id); - } + uint8_t shift(0); + ch = w & 0xf; + shift += uint8_t(eMessageLength::kMessCh); + type = (w >> shift) & 0x1; + shift += uint8_t(eMessageLength::kMessType); + tlab = (w >> shift) & 0x7f; + shift += uint8_t(eMessageLength::kMessTlab); + data = (w >> shift) & 0x3fff; + data = data >> 1; + shift += uint8_t(eMessageLength::kMessData); + fasp = ((w >> shift) & 0x3f); + + if (VERBOSE >= 2) { + printf("legacyMess_readDW[%x]\n", w); + print(); } - else { - cout << boost::format(" DATA: w=%08x fasp_id=%02d ch_id=%02d slice=%03d data=%04d\n") % w - % static_cast<unsigned int>(fasp_id) % static_cast<unsigned int>(ch_id) % static_cast<unsigned int>(slice) - % static_cast<unsigned int>(data >> 1); +} + +//_________________________________________________________________________________ +void CbmTrdUnpackFaspAlgo::CbmTrdFaspMessage::readEW(uint32_t w) +{ + uint8_t shift(0); + ch = w & 0xf; + shift += uint8_t(eMessageLength::kMessCh); + type = (w >> shift) & 0x1; + shift += uint8_t(eMessageLength::kMessType); + epoch = (w >> shift) & 0x1fffff; + shift += uint8_t(eMessageLength::kMessEpoch); + fasp = (w >> shift) & 0x3f; + + if (VERBOSE >= 2) { + printf("legacyMess_readEW[%x]\n", w); + print(); + } +} + +//_________________________________________________________________________________ +void CbmTrdUnpackFaspAlgo::CbmTrdFaspMessage::print() const +{ + if (type == (uint8_t) eMessageType::kData) + cout << Form(" DATA : rob=%d%c fasp_id=%02d [%03d] ch_id=%02d tclk=%03d data=%4d\n", rob, (elink ? 'u' : 'd'), + fasp, getFaspIdMod(), ch, tlab, data); + else if (type == (uint8_t) eMessageType::kEpoch) + cout << Form(" EPOCH: eq_id=%d%c ch_id=%02d epoch=%05d\n", rob, (elink ? 'u' : 'd'), ch, epoch); + else + cout << " MTYPE: unknown"; +} + +//_________________________________________________________________________________ +CbmTrdUnpackFaspAlgo::CbmTrdFaspMessage24::CbmTrdFaspMessage24() : CbmTrdFaspMessage() +{ + version = eMessageVersion::kMess24; +} + +//_________________________________________________________________________________ +CbmTrdUnpackFaspAlgo::eMessageType CbmTrdUnpackFaspAlgo::CbmTrdFaspMessage24::getType(uint32_t wd) const +{ + //printf("mess_type[%x]\n", wd); + if ((wd >> 31) & 0x1) return eMessageType::kEpoch; + return eMessageType::kData; +} + +//_____________________________________________________________ +void CbmTrdUnpackFaspAlgo::CbmTrdFaspMessage24::readDW(uint32_t w) +{ + uint8_t shift(0); + uint16_t adc_data = (w >> shift) & 0x3fff; + // TODO This data format version delivers the ADC value as bit_sgn + 13 significant bits + // TODO The CbmTrdDigi supports digi data with only 12bits unsigned. The first tests will + // TODO convert the measurement to the old format leaving the implementation of the new storage to // TODO later time. (AB 14.06.2024) + uint16_t sign = adc_data >> 13; // sign + int value_i; + if (!sign) + value_i = adc_data; + else + value_i = (-1) * ((adc_data ^ 0xffff) & 0x1fff); + // convert to 12bit unsigned + data = (value_i + 0x1fff) >> 2; + shift += uint8_t(eMessageLength::kMessData); + tlab = (w >> shift) & 0x7f; + shift += uint8_t(eMessageLength::kMessTlab); + ch = (w >> shift) & 0xf; + shift += uint8_t(eMessageLength::kMessCh); + fasp = ((w >> shift) & 0x3f); + shift += uint8_t(eMessageLength::kMessFasp); + type = (w >> shift) & 0x1; + shift += uint8_t(eMessageLength::kMessType); + + if (VERBOSE >= 2) { + printf("v06.24Mess_readDW[%x] signed charge = %+d\n", w, value_i); + print(); + } +} + +//_________________________________________________________________________________ +void CbmTrdUnpackFaspAlgo::CbmTrdFaspMessage24::readEW(uint32_t w) +{ + uint8_t shift(0); + epoch = (w >> shift) & 0x1fffff; + shift += uint8_t(eMessageLength::kMessEpoch); + ch = (w >> shift) & 0xf; + shift += uint8_t(eMessageLength::kMessCh); + fasp = (w >> shift) & 0x3f; + shift += uint8_t(eMessageLength::kMessFasp); + type = (w >> shift) & 0x1; + shift += uint8_t(eMessageLength::kMessType); + + if (VERBOSE >= 2) { + printf("v06.24Mess_readEW[%x]\n", w); + print(); } } diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.h b/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.h index 007781bf30..a5c68f9b5c 100644 --- a/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.h +++ b/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.h @@ -45,36 +45,56 @@ class CbmTrdParSetDigi; class CbmTrdUnpackFaspAlgo : public CbmRecoUnpackAlgo<CbmTrdDigi> { public: - /** @brief Bytes per FASP frame stored in the microslices (32 bits words) - * - DATA WORD - + /** @brief Bytes per FASP frame stored in the microslices (32 bits words) + * - DATA WORD - for legacy version * ffff.ffdd dddd.dddd dddd.tttt ttta.cccc * f - FASP id * d - ADC signal * t - time label inside epoch - * a - word type (0) + * a - word type (1) * c - channel id * - EPOCH WORD - * ffff.fftt tttt.tttt tttt.tttt ttta.cccc * f - FASP id * t - epoch index + * a - word type (0) + * c - channel id + * ===================================================== + * - DATA WORD - for 06.2024 version + * afff.fffc ccct.tttt ttdd.dddd dddd.dddd + * f - FASP id + * d - ADC signal + * t - time label inside epoch * a - word type (1) * c - channel id + * - EPOCH WORD - + * afff.fffc ccct.tttt tttt tttt tttt.tttt + * a - word type (0) + * f - FASP id + * t - epoch index + * c - channel id */ - enum CbmTrdFaspMessageLength - { - kMessCh = 4, - kMessType = 1, - kMessTlab = 7, - kMessData = 14, - kMessFasp = 6, - kMessEpoch = 21 - }; - enum CbmTrdFaspMessageType - { - kEpoch = 0, - kData - }; - + enum class eMessageLength : int + { + kMessCh = 4, + kMessType = 1, + kMessTlab = 7, + kMessData = 14, + kMessFasp = 6, + kMessEpoch = 21 + }; + enum eMessageType + { + kData = 0, + kEpoch = 1, + kNone + }; + enum class eMessageVersion : int + { + kMessLegacy = 2, /// unpacker version for 2-board FASPRO+GETS HW + kMess24 = 3, /// unpacker version for 1-board FASPRO HW first used 18.06.24 (mCBM) + kMessNoDef /// default unpacker version + }; /** @brief Create the Cbm Trd Unpack AlgoBase object */ CbmTrdUnpackFaspAlgo(); @@ -89,16 +109,36 @@ public: /** @brief Data structure for unpacking the FASP word */ - struct CbmTrdFaspMessage { - CbmTrdFaspMessage(uint8_t c, uint8_t typ, uint8_t t, uint16_t d, uint8_t rob, uint8_t asic); + class CbmTrdFaspMessage { + public: + CbmTrdFaspMessage() = default; + CbmTrdFaspMessage(const CbmTrdFaspMessage&) = default; + virtual ~CbmTrdFaspMessage() = default; + CbmTrdFaspMessage(uint8_t rob, uint8_t asic, uint8_t c, uint8_t typ, uint8_t t, uint16_t d, uint8_t l); + virtual int getFaspIdMod() const { return fasp + rob * NFASPCROB; } + virtual eMessageType getType(uint32_t w) const; + virtual void print() const; + virtual void readDW(uint32_t w); + virtual void readEW(uint32_t w); + + public: + eMessageVersion version = eMessageVersion::kMessLegacy; ///< format version uint8_t ch = 0; ///< ch id in the FASP - uint8_t type = 0; ///< message type 0 = epoch, 1 = data (not used for the moment) + uint8_t type = 0; ///< message type 0 = data, 1 = epoch uint8_t tlab = 0; ///< time of the digi inside the epoch uint16_t data = 0; ///< ADC value uint32_t epoch = 0; ///< epoch id (not used for the moment) uint32_t mod = 0; ///< full module address according to CbmTrdAddress - uint8_t crob = 0; ///< CROB id in the module - uint8_t fasp = 0; ///< FASP id in the module + uint8_t rob = 0; ///< Read-Out unit id in the module + uint8_t elink = 0; ///< optical link for read-out unit (up or down, starting with v2024) + uint8_t fasp = 0; ///< FASP id in the module + }; + class CbmTrdFaspMessage24 : public CbmTrdFaspMessage { + public: + CbmTrdFaspMessage24(); + virtual eMessageType getType(uint32_t w) const; + virtual void readDW(uint32_t w); + virtual void readEW(uint32_t w); }; /** Access the asic parameter list, read-only*/ virtual const CbmTrdParSetAsic* GetAsicPar() const { return &fAsicSet; } @@ -122,26 +162,20 @@ public: protected: /** @brief Get message type from the FASP word */ - CbmTrdFaspMessageType mess_type(uint32_t wd); - /** @brief Convert the FASP word into a DATA message */ - void mess_readDW(uint32_t wd, CbmTrdFaspMessage* mess); - /** @brief Convert the FASP word into a EPOCH message */ - void mess_readEW(uint32_t wd, CbmTrdFaspMessage* mess); - /** @brief Print FASP message */ - void mess_prt(CbmTrdFaspMessage* mess); - bool pushDigis(std::vector<CbmTrdUnpackFaspAlgo::CbmTrdFaspMessage> messages, const uint16_t mod_id); - /** @brief Time offset for digi wrt the TS start, expressed in 80 MHz clks. It contains: + eMessageType mess_type(uint32_t wd); + bool pushDigis(std::vector<CbmTrdUnpackFaspAlgo::CbmTrdFaspMessage> messages, const uint16_t mod_id); + /** @brief Time offset for digi wrt the TS start, expressed in 80 MHz clks. It contains: * - relative offset of the MS wrt the TS * - FASP epoch offset for current CROB * - TRD2D system offset wrt to experiment time (e.g. Bmon) */ - ULong64_t fTime = 0; + ULong64_t fTime = 0; - /** @brief Finish function for this algorithm base clase */ - void finish() - { - if (fMonitor) fMonitor->Finish(); - } + /** @brief Finish function for this algorithm base clase */ + void finish() + { + if (fMonitor) fMonitor->Finish(); + } /** * @brief Additional initialisation function for all BaseR derived algorithms. @@ -178,25 +212,10 @@ protected: void FinalizeComponent(); // Constants - /** @brief Bytes per FASP frame stored in the microslices (32 bits words) - * - DATA WORD - - * ffff.ffdd dddd.dddd dddd.tttt ttta.cccc - * f - FASP id - * d - ADC signal - * t - time label inside epoch - * a - word type (1) - * c - channel id - * - EPOCH WORD - - * ffff.fftt tttt.tttt tttt.tttt ttta.cccc - * f - FASP id - * t - epoch index - * a - word type (0) - * c - channel id - */ + /** @brief Bytes per FASP frame stored in the microslices (32 bits words)*/ static const std::uint8_t fBytesPerWord = 4; private: - void prt_wd(uint32_t w); std::map<uint16_t, std::pair<uint16_t, uint16_t>>* fCompMap = nullptr; ///> Map eq_id -> (mod_id, crob_id) std::array<std::vector<CbmTrdDigi>, NFASPMOD* NFASPCH> fDigiBuffer = { {}}; ///> Buffered digi for each pad in CROB component @@ -205,8 +224,9 @@ private: std::vector<uint16_t> fModuleId = {}; ///> list of modules for which there is are calibration parameters CbmTrdParSetAsic fAsicSet; CbmTrdParSetDigi* fDigiSet = nullptr; + CbmTrdFaspMessage* fMess = nullptr; ///> current message version - ClassDef(CbmTrdUnpackFaspAlgo, 3) // unpack FASP read-out detectors + ClassDef(CbmTrdUnpackFaspAlgo, 4) // unpack FASP read-out detectors }; #endif // CbmTrdUnpackFaspAlgo_H -- GitLab