From 183480857c6c610beb27e6fa288c62caa4964507 Mon Sep 17 00:00:00 2001 From: Alexandru Bercuci <abercuci@niham.nipne.ro> Date: Wed, 8 Jun 2022 11:40:14 +0300 Subject: [PATCH] add digi buffering to fix asynchronous ADC read-out. Restore PRF for TRD2D clusters (hint by C.Schiaua) --- .../trd/unpack/CbmTrdUnpackFaspAlgo.cxx | 126 +++++++++++------- .../trd/unpack/CbmTrdUnpackFaspAlgo.h | 1 + 2 files changed, 80 insertions(+), 47 deletions(-) diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.cxx b/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.cxx index 6b838d217a..e839fce3a9 100644 --- a/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.cxx +++ b/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.cxx @@ -35,9 +35,9 @@ using namespace std; CbmTrdUnpackFaspAlgo::CbmTrdUnpackFaspAlgo() : CbmRecoUnpackAlgo("CbmTrdUnpackFaspAlgo") + , fTime(0) , fModuleId() , fAsicPar() - , fTime(0) { } @@ -218,12 +218,11 @@ bool CbmTrdUnpackFaspAlgo::pushDigis(std::vector<CbmTrdUnpackFaspAlgo::CbmTrdFas UChar_t lFasp(0xff); UShort_t lchR, lchT; Double_t r, t; - Int_t dt, dtime, ch, pad, row; - ULong64_t tlab, tdaqOffset(0); + Int_t dt, dtime, ch, pad; + ULong64_t lTime, tdaqOffset(0); CbmTrdParFasp* faspPar(nullptr); const CbmTrdParFaspChannel* chCalib(nullptr); CbmTrdParModDigi* digiPar(nullptr); - vector<CbmTrdDigi*> digis; for (auto imess : messes) { if (lFasp == 0xff) { lFasp = messes[0]->fasp; @@ -237,67 +236,99 @@ bool CbmTrdUnpackFaspAlgo::pushDigis(std::vector<CbmTrdUnpackFaspAlgo::CbmTrdFas LOG(error) << GetName() << "::pushDigis - DIGI par for module " << imess->mod << " missing. Skip."; return false; } + // TODO temporary add DAQ time calibration for FASPRO. + // Should be absorbed in the ASIC parameter definition + if (digiPar->GetPadRow(faspPar->GetChannelAddress(imess->ch)) % 2) tdaqOffset = 3; + if (VERBOSE) faspPar->Print(); - pad = faspPar->GetChannelAddress(imess->ch); - chCalib = faspPar->GetChannel(imess->ch); - ch = 2 * pad + chCalib->HasPairingR(); - row = digiPar->GetPadRow(pad); - if (row % 2) tdaqOffset = 3; - if (VERBOSE) - printf("fasp[%2d] ch[%4d / %2d] pad[%4d] row[%2d] col[%2d] tilt[%d]\n", lFasp, ch, imess->ch, pad, row, - digiPar->GetPadColumn(pad), chCalib->HasPairingT()); } - if (VERBOSE) mess_prt(imess); + pad = faspPar->GetChannelAddress(imess->ch); + chCalib = faspPar->GetChannel(imess->ch); + ch = 2 * pad + chCalib->HasPairingR(); + lTime = fTime + tdaqOffset + imess->tlab; lchR = 0; lchT = 0; - chCalib = faspPar->GetChannel(imess->ch); if (chCalib->HasPairingR()) lchR = imess->data; else lchT = imess->data; - pad = faspPar->GetChannelAddress(imess->ch); - - bool use(false); - for (auto id : digis) { - if (id->GetAddressChannel() != pad) continue; - dtime = id->GetTimeDAQ() - imess->tlab; - if (TMath::Abs(dtime) < 5) { - r = id->GetCharge(t, dt); - if (lchR && !int(r)) { - id->SetCharge(t, lchR, -dtime); + if (VERBOSE) + 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); + + if (fDigiBuffer.find(pad) != fDigiBuffer.end()) { + // check if last digi has both R/T message components. Update if not and is within time window + auto id = fDigiBuffer[pad].rbegin(); + dtime = (*id)->GetTimeDAQ() - lTime; + bool use(false); + if (TMath::Abs(dtime) < 5) { // test message part of (last) digi + r = (*id)->GetCharge(t, dt); + if (lchR && r < 0.1) { // set R charge on an empty slot + (*id)->SetCharge(t, lchR, -dtime); use = true; - break; } - else if (lchT && !int(t)) { - tlab = id->GetTimeDAQ(); - id->SetCharge(lchT, r, +dtime); - id->SetTimeDAQ(ULong64_t(tlab - dtime)); + else if (lchT && t < 0.1) { // set T charge on an empty slot + (*id)->SetCharge(lchT, r, +dtime); + (*id)->SetTimeDAQ(ULong64_t((*id)->GetTimeDAQ() - dtime)); use = true; - break; } } - } - if (!use) { - CbmTrdDigi* digi = new CbmTrdDigi(pad, lchT, lchR, imess->tlab); + // build digi for message when update failed + if (!use) { + CbmTrdDigi* digi = new CbmTrdDigi(pad, lchT, lchR, lTime); + digi->SetAddressModule(imess->mod); + fDigiBuffer[pad].push_back(digi); + id = fDigiBuffer[pad].rbegin(); + } + + if (id != fDigiBuffer[pad].rend()) id++; + + // update charge for previously allocated digis to account for FASPRO ADC buffering and read-out problem + use = false; + for (; id != fDigiBuffer[pad].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); + use = true; + } + else if (lchT && int(t)) { // update T charge and mark on digi + (*id)->SetCharge(lchT, r, dt); + (*id)->SetFlag(0); + use = true; + } + if (use) break; + } + } + else { // init pad position in map and build digi for message + CbmTrdDigi* digi = new CbmTrdDigi(pad, lchT, lchR, lTime); digi->SetAddressModule(imess->mod); - digis.push_back(digi); + fDigiBuffer[pad].push_back(digi); } delete imess; } // push finalized digits to the next level - for (vector<CbmTrdDigi*>::iterator id = digis.begin(); id != digis.end(); id++) { - // TODO temporary add DAQ time calibration for FASPRO. - // Should be absorbed in the ASIC parameter definition - (*id)->SetTimeDAQ(fTime + (*id)->GetTimeDAQ() + tdaqOffset); - fOutputVec.emplace_back(*std::move(*id)); - if (fMonitor) fMonitor->FillHistos((*id)); - if (VERBOSE) cout << (*id)->ToString(); + for (int jd(0); jd < NFASPCH; jd += 2) { + int ipad(faspPar->GetChannelAddress(jd)); + if (fDigiBuffer.find(ipad) == fDigiBuffer.end()) continue; + + 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))) continue; + if (fMonitor) fMonitor->FillHistos(((*id))); + // reset flags as they were used only to mark the correctly setting of the charge/digi + (*id)->SetFlag(0, false); + (*id)->SetFlag(1, false); + fOutputVec.emplace_back(*std::move((*id))); + // clear digi buffer wrt the digi which was forwarded to higher structures + id = fDigiBuffer[ipad].erase(id); + } } - - digis.clear(); messes.clear(); return true; @@ -366,14 +397,15 @@ bool CbmTrdUnpackFaspAlgo::unpack(const fles::Timeslice* ts, std::uint16_t icomp // 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) { + // clear buffer + if (vDigi.size()) { pushDigis(vDigi); } + vDigi.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 (vDigi.size()) { pushDigis(vDigi); } - vDigi.clear(); lFaspOld = 0xff; - fTime += FASP_EPOCH_LENGTH; } else if (ch_id == 1) { @@ -403,7 +435,7 @@ bool CbmTrdUnpackFaspAlgo::unpack(const fles::Timeslice* ts, std::uint16_t icomp } mess = new CbmTrdFaspContent; mess->ch = ch_id; - mess->type = 1; + mess->type = kData; mess->tlab = slice; mess->data = data >> 1; mess->fasp = lFaspOld; diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.h b/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.h index 460d3c40e5..530df41b59 100644 --- a/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.h +++ b/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.h @@ -196,6 +196,7 @@ private: void prt_wd(uint32_t w); std::map<uint32_t, uint8_t[NFASPMOD]>* fFaspMap = nullptr; ///> FASP mapping update wrt the default setting std::map<uint32_t, uint16_t[NCROBMOD]>* fCrobMap = nullptr; ///> CRI mapping setting + std::map<uint32_t, std::vector<CbmTrdDigi*>> fDigiBuffer; ///> Map of buffered digi per pad /** @brief Potential (online) monitor for the unpacking process */ std::shared_ptr<CbmTrdUnpackFaspMonitor> fMonitor = nullptr; std::vector<Int_t> fModuleId; -- GitLab