From 7ea221c87c06bfa4a4ad07f02adbe1a27d5c8250 Mon Sep 17 00:00:00 2001
From: Alexandru Bercuci <abercuci@niham.nipne.ro>
Date: Wed, 13 Jul 2022 15:37:34 +0200
Subject: [PATCH] add support for multiple CRI boards in the TRD2D detectors

Includes follow-up patches (squashed):
- rename inner variables, fix backward compatibility
- fix CROB timming
---
 core/detectors/trd/CbmTrdParFasp.h            |  4 ++
 .../trd/unpack/CbmTrdUnpackFaspAlgo.cxx       | 53 ++++++++++++++-----
 .../trd/unpack/CbmTrdUnpackFaspAlgo.h         | 30 +++++++----
 .../trd/unpack/CbmTrdUnpackFaspConfig.cxx     |  7 +++
 .../trd/unpack/CbmTrdUnpackFaspConfig.h       |  8 ++-
 5 files changed, 77 insertions(+), 25 deletions(-)

diff --git a/core/detectors/trd/CbmTrdParFasp.h b/core/detectors/trd/CbmTrdParFasp.h
index 1cc222e48b..b97bb87057 100644
--- a/core/detectors/trd/CbmTrdParFasp.h
+++ b/core/detectors/trd/CbmTrdParFasp.h
@@ -6,8 +6,12 @@
 #define CBMTRDPARFASP_H
 
 #define NFASPMOD 180
+#define NCROBMOD 5
+#define NFASPCROB NFASPMOD / NCROBMOD
 #define NFASPCH 16
 
+#define FASP_EPOCH_LENGTH 128
+
 #include "CbmTrdParAsic.h"  // for CbmTrdParAsic
 
 #include <Rtypes.h>      // for THashConsistencyHolder, ClassDef, TESTBIT
diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.cxx b/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.cxx
index d245ff7670..6b838d217a 100644
--- a/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.cxx
+++ b/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.cxx
@@ -25,13 +25,20 @@
 
 #include <boost/format.hpp>
 
+// select verbosity level
+// 0 : none
+// 1 : data unpacker
+// 2 : digi packing
 #define VERBOSE 0
 
 using namespace std;
 
-CbmTrdUnpackFaspAlgo::CbmTrdUnpackFaspAlgo() : CbmRecoUnpackAlgo("CbmTrdUnpackFaspAlgo"), fModuleId(), fAsicPar()
+CbmTrdUnpackFaspAlgo::CbmTrdUnpackFaspAlgo()
+  : CbmRecoUnpackAlgo("CbmTrdUnpackFaspAlgo")
+  , fModuleId()
+  , fAsicPar()
+  , fTime(0)
 {
-  memset(fTime, 0, NCRI * sizeof(ULong64_t));
 }
 
 //_________________________________________________________________________________
@@ -127,6 +134,13 @@ void CbmTrdUnpackFaspAlgo::SetAsicMapping(const std::map<uint32_t, uint8_t[NFASP
   }
 }
 
+//_________________________________________________________________________________
+void CbmTrdUnpackFaspAlgo::SetCrobMapping(const std::map<uint32_t, uint16_t[NCROBMOD]>& map)
+{
+  if (fCrobMap) delete fCrobMap;
+  fCrobMap = new std::map<uint32_t, uint16_t[NCROBMOD]>(map);
+}
+
 //_________________________________________________________________________________
 void CbmTrdUnpackFaspAlgo::PrintAsicMapping()
 {
@@ -181,7 +195,7 @@ void CbmTrdUnpackFaspAlgo::mess_readEW(uint32_t w, CbmTrdFaspContent* mess)
   shift += Int_t(kMessType);
   mess->epoch = (wd >> shift) & 0x1fffff;
   shift += Int_t(kMessEpoch);
-  mess->cri = (wd >> shift) & 0x3f;
+  mess->crob = (wd >> shift) & 0x3f;
   printf("DBG :: ");
   mess_prt(mess);
 }
@@ -194,7 +208,7 @@ void CbmTrdUnpackFaspAlgo::mess_prt(CbmTrdFaspContent* mess)
               % 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: cri_id=%02d ch_id=%02d epoch=%05d\n") % static_cast<unsigned int>(mess->cri)
+    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);
 }
 
@@ -214,13 +228,13 @@ bool CbmTrdUnpackFaspAlgo::pushDigis(std::vector<CbmTrdUnpackFaspAlgo::CbmTrdFas
     if (lFasp == 0xff) {
       lFasp = messes[0]->fasp;
       // link data to the position on the padplane
-      if (!(faspPar = (CbmTrdParFasp*) fAsicPar.GetAsicPar(imess->cri * 1000 + lFasp))) {
-        LOG(error) << GetName() << "::pushDigis - Par for FASP " << (int) lFasp << " in module " << imess->cri
+      if (!(faspPar = (CbmTrdParFasp*) fAsicPar.GetAsicPar(imess->mod * 1000 + lFasp))) {
+        LOG(error) << GetName() << "::pushDigis - Par for FASP " << (int) lFasp << " in module " << imess->mod
                    << " missing. Skip.";
         return false;
       }
-      if (!(digiPar = (CbmTrdParModDigi*) fDigiSet->GetModulePar(imess->cri))) {
-        LOG(error) << GetName() << "::pushDigis - DIGI par for module " << imess->cri << " missing. Skip.";
+      if (!(digiPar = (CbmTrdParModDigi*) fDigiSet->GetModulePar(imess->mod))) {
+        LOG(error) << GetName() << "::pushDigis - DIGI par for module " << imess->mod << " missing. Skip.";
         return false;
       }
       if (VERBOSE) faspPar->Print();
@@ -267,7 +281,7 @@ bool CbmTrdUnpackFaspAlgo::pushDigis(std::vector<CbmTrdUnpackFaspAlgo::CbmTrdFas
 
     if (!use) {
       CbmTrdDigi* digi = new CbmTrdDigi(pad, lchT, lchR, imess->tlab);
-      digi->SetAddressModule(imess->cri);
+      digi->SetAddressModule(imess->mod);
       digis.push_back(digi);
     }
     delete imess;
@@ -277,7 +291,7 @@ bool CbmTrdUnpackFaspAlgo::pushDigis(std::vector<CbmTrdUnpackFaspAlgo::CbmTrdFas
   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[0] + (*id)->GetTimeDAQ() + tdaqOffset);
+    (*id)->SetTimeDAQ(fTime + (*id)->GetTimeDAQ() + tdaqOffset);
     fOutputVec.emplace_back(*std::move(*id));
     if (fMonitor) fMonitor->FillHistos((*id));
     if (VERBOSE) cout << (*id)->ToString();
@@ -296,6 +310,8 @@ bool CbmTrdUnpackFaspAlgo::unpack(const fles::Timeslice* ts, std::uint16_t icomp
   //LOG(info) << "Component " << icomp << " connected to config CbmTrdUnpackConfig2D. Slice "<<imslice;
 
   uint32_t mod_id = 5;
+  uint8_t crob_id = 0;
+  uint16_t eq_id;
   bool unpackOk   = true;
   //Double_t fdMsSizeInNs = 1.28e6;
 
@@ -303,7 +319,15 @@ bool CbmTrdUnpackFaspAlgo::unpack(const fles::Timeslice* ts, std::uint16_t icomp
   // 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));
   // define time wrt start of time slice in TRD/FASP clks [80 MHz]
-  fTime[0] = ULong64_t((msdesc.idx - fTsStartTime - fSystemTimeOffset) / 12.5);
+  fTime = ULong64_t((msdesc.idx - fTsStartTime - fSystemTimeOffset) / 12.5);
+  eq_id = msdesc.eq_id;  // read the CROB id
+  for (; crob_id < NCROBMOD; crob_id++) {
+    if (((*fCrobMap)[mod_id])[crob_id] == eq_id) break;
+  }
+  if (crob_id == NCROBMOD) {
+    LOG(error) << GetName() << "::unpack - CROB eq_id=" << eq_id << " not registered in the unpacker.";
+    return false;
+  }
 
   // Get the µslice size in bytes to calculate the number of completed words
   auto mssize = msdesc.size;
@@ -338,7 +362,7 @@ bool CbmTrdUnpackFaspAlgo::unpack(const fles::Timeslice* ts, std::uint16_t icomp
     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;
+    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) {
@@ -350,7 +374,7 @@ bool CbmTrdUnpackFaspAlgo::unpack(const fles::Timeslice* ts, std::uint16_t icomp
         vDigi.clear();
         lFaspOld = 0xff;
 
-        fTime[fasp_id] += 128;
+        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);
@@ -383,7 +407,8 @@ bool CbmTrdUnpackFaspAlgo::unpack(const fles::Timeslice* ts, std::uint16_t icomp
       mess->tlab = slice;
       mess->data = data >> 1;
       mess->fasp = lFaspOld;
-      mess->cri  = mod_id;
+      mess->mod  = mod_id;
+      mess->crob = crob_id;
       vDigi.push_back(mess);
     }
     //prt_wd(*wd);
diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.h b/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.h
index 3eedd67f9a..460d3c40e5 100644
--- a/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.h
+++ b/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.h
@@ -38,7 +38,8 @@
 #include <memory>
 #include <utility>
 
-#define NCRI 40  // no of CRI in the system (1/TRD-2D_FASP module)
+// TODO to be defined in correlation with time offsets (AB 20.05.22)
+#define NCRI 40  // no of CRI in the system (5/TRD-2D_FASP module)
 #define NCOLS 8  // no of cols / FASP
 
 class CbmTrdParSetDigi;
@@ -89,13 +90,14 @@ public:
 
   /** @brief Data structure for unpacking the FASP word */
   struct CbmTrdFaspContent {
-    uint8_t ch;
-    uint8_t type;
-    uint8_t tlab;
-    uint16_t data;
-    uint32_t epoch;
-    uint8_t fasp;
-    uint8_t cri;
+    uint8_t ch;      ///< ch id in the FASP
+    uint8_t type;    ///< message type 0 = epoch, 1 = data (not used for the moment)
+    uint8_t tlab;    ///< time of the digi inside the epoch
+    uint16_t data;   ///< ADC value
+    uint32_t epoch;  ///< epoch id (not used for the moment)
+    uint32_t mod;    ///< full module address according to CbmTrdAddress
+    uint8_t crob;    ///< CROB id in the module
+    uint8_t fasp;    ///< FASP id in the module
   };
 
   /**
@@ -113,6 +115,8 @@ public:
 
   /** @brief Introduce fasp index mapping*/
   void SetAsicMapping(const std::map<uint32_t, uint8_t[NFASPMOD]>& map);
+  /** @brief Initialize CROB mapping for all modules*/
+  void SetCrobMapping(const std::map<uint32_t, uint16_t[NCROBMOD]>& map);
   /** @brief Set a predefined monitor 
    *  @param monitor predefined unpacking monitor */
   void SetMonitor(std::shared_ptr<CbmTrdUnpackFaspMonitor> monitor) { fMonitor = monitor; }
@@ -127,7 +131,12 @@ protected:
   /** @brief Print FASP message */
   void mess_prt(CbmTrdFaspContent* mess);
   bool pushDigis(std::vector<CbmTrdUnpackFaspAlgo::CbmTrdFaspContent*> digis);
-  ULong64_t fTime[NCRI];
+  /** @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. T0) 
+   */
+  ULong64_t fTime;
 
   /** @brief Finish function for this algorithm base clase */
   void finish()
@@ -185,7 +194,8 @@ protected:
 
 private:
   void prt_wd(uint32_t w);
-  std::map<uint32_t, uint8_t[NFASPMOD]>* fFaspMap = nullptr;
+  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
   /** @brief Potential (online) monitor for the unpacking process */
   std::shared_ptr<CbmTrdUnpackFaspMonitor> fMonitor = nullptr;
   std::vector<Int_t> fModuleId;
diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackFaspConfig.cxx b/reco/detectors/trd/unpack/CbmTrdUnpackFaspConfig.cxx
index 34909da4e5..683dde77bc 100644
--- a/reco/detectors/trd/unpack/CbmTrdUnpackFaspConfig.cxx
+++ b/reco/detectors/trd/unpack/CbmTrdUnpackFaspConfig.cxx
@@ -35,6 +35,7 @@ void CbmTrdUnpackFaspConfig::InitAlgo()
 {
   if (fDoLog) LOG(info) << fName << "::InitAlgo - Setup Fasp mapping";
   fAlgo->SetAsicMapping(fFaspMap);
+  fAlgo->SetCrobMapping(fCrobMap);
   /*if (fDoLog) */ fAlgo->PrintAsicMapping();
 
   // If we have a monitor in the config add it to the algo
@@ -56,4 +57,10 @@ void CbmTrdUnpackFaspConfig::SetFaspMapping(int modAddress, uint8_t faspMap[NFAS
   memcpy(fFaspMap[modAddress], faspMap, NFASPMOD * sizeof(uint8_t));
 }
 
+//_____________________________________________________________________
+void CbmTrdUnpackFaspConfig::SetCrobMapping(int modAddress, uint16_t crobMap[NCROBMOD])
+{
+  memcpy(fCrobMap[modAddress], crobMap, NCROBMOD * sizeof(uint16_t));
+}
+
 ClassImp(CbmTrdUnpackFaspConfig)
diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackFaspConfig.h b/reco/detectors/trd/unpack/CbmTrdUnpackFaspConfig.h
index ec9435808a..54a377eca6 100644
--- a/reco/detectors/trd/unpack/CbmTrdUnpackFaspConfig.h
+++ b/reco/detectors/trd/unpack/CbmTrdUnpackFaspConfig.h
@@ -72,6 +72,11 @@ public:
    * @param faspMap mapped ids of FASP ASICs for module
    */
   void SetFaspMapping(int modAddress, uint8_t faspMap[NFASPMOD]);
+  /** @brief define crob id mapping for each module
+   * @param modAddress module address according to geometry
+   * @param crobMap mapped ids of CROBs eq_id for module
+   */
+  void SetCrobMapping(int modAddress, uint16_t crobMap[NFASPMOD]);
 
   /** @brief Add a monitor to the unpacker. 
    *  @param value CbmTrdUnpackFaspMonitor */
@@ -86,7 +91,8 @@ protected:
   virtual std::shared_ptr<CbmTrdUnpackFaspAlgo> chooseAlgo();
 
 private:
-  std::map<uint32_t, uint8_t[NFASPMOD]> fFaspMap;  ///> DAQ packing of FASP id
+  std::map<uint32_t, uint8_t[NFASPMOD]> fFaspMap;   ///> Module address to FASP id mapping
+  std::map<uint32_t, uint16_t[NCROBMOD]> fCrobMap;  ///> Module address to CROB id mapping
   /** @brief pointer to the monitor object */
   std::shared_ptr<CbmTrdUnpackFaspMonitor> fMonitor = nullptr;
 
-- 
GitLab