From 3f2df0b00cf97f036a3196ca7078c2921647eae2 Mon Sep 17 00:00:00 2001
From: Pascal Raisig <praisig@ikf.uni-frankfurt.de>
Date: Thu, 15 Jul 2021 20:21:33 +0200
Subject: [PATCH] Include the TRD2D into the scheme plus some minor
 improvements

For the current situation with the TRD1D and TRD2D configs trying to create and access in principle the same "TrdDigi" branch a small workaround in the CbmRecoUnpack was required. Such that the first Config does not loose the correct pointer when the seconds overwrites the branch in the FairRootManager.
---
 macro/run/run_unpack_tsa.C                    |  10 +
 reco/base/CbmRecoUnpackAlgo.tmpl              |  16 +-
 reco/base/CbmRecoUnpackConfig.tmpl            |  71 ++++-
 reco/detectors/psd/CMakeLists.txt             |   1 -
 .../detectors/psd/unpack/CbmPsdUnpackAlgo.cxx |   2 +-
 reco/detectors/psd/unpack/CbmPsdUnpackAlgo.h  |   3 -
 reco/detectors/rich/CMakeLists.txt            |   1 -
 .../rich/unpack/CbmRichUnpackAlgo.cxx         |   6 +-
 .../detectors/rich/unpack/CbmRichUnpackAlgo.h |   3 -
 reco/detectors/sts/CMakeLists.txt             |   1 -
 .../detectors/sts/unpack/CbmStsUnpackAlgo.cxx |   2 +-
 reco/detectors/sts/unpack/CbmStsUnpackAlgo.h  |   3 -
 reco/detectors/trd/CMakeLists.txt             |   5 +-
 reco/detectors/trd/CbmTrdRecoLinkDef.h        |   4 +-
 .../trd/unpack/CbmTrdUnpackAlgo2D.cxx         | 154 -----------
 .../detectors/trd/unpack/CbmTrdUnpackAlgo2D.h | 236 ----------------
 .../trd/unpack/CbmTrdUnpackAlgoBaseR.cxx      |   2 +-
 .../trd/unpack/CbmTrdUnpackAlgoBaseR.h        |   3 -
 .../trd/unpack/CbmTrdUnpackAlgoFasp2D.cxx     | 252 ++++++++++++++++++
 .../trd/unpack/CbmTrdUnpackAlgoFasp2D.h       | 169 ++++++++++++
 .../unpack/CbmTrdUnpackAlgoLegacy2020R.cxx    |   2 +-
 .../trd/unpack/CbmTrdUnpackAlgoLegacy2020R.h  |   3 +-
 .../trd/unpack/CbmTrdUnpackAlgoR.cxx          |   2 +-
 reco/detectors/trd/unpack/CbmTrdUnpackAlgoR.h |   3 +-
 .../trd/unpack/CbmTrdUnpackConfig2D.h         | 122 ---------
 ...fig2D.cxx => CbmTrdUnpackConfigFasp2D.cxx} |  30 +--
 .../trd/unpack/CbmTrdUnpackConfigFasp2D.h     |  85 ++++++
 reco/steer/CbmRecoUnpack.cxx                  |  18 +-
 reco/steer/CbmRecoUnpack.h                    |   6 +-
 29 files changed, 618 insertions(+), 597 deletions(-)
 delete mode 100644 reco/detectors/trd/unpack/CbmTrdUnpackAlgo2D.cxx
 delete mode 100644 reco/detectors/trd/unpack/CbmTrdUnpackAlgo2D.h
 create mode 100644 reco/detectors/trd/unpack/CbmTrdUnpackAlgoFasp2D.cxx
 create mode 100644 reco/detectors/trd/unpack/CbmTrdUnpackAlgoFasp2D.h
 delete mode 100644 reco/detectors/trd/unpack/CbmTrdUnpackConfig2D.h
 rename reco/detectors/trd/unpack/{CbmTrdUnpackConfig2D.cxx => CbmTrdUnpackConfigFasp2D.cxx} (63%)
 create mode 100644 reco/detectors/trd/unpack/CbmTrdUnpackConfigFasp2D.h

diff --git a/macro/run/run_unpack_tsa.C b/macro/run/run_unpack_tsa.C
index 7df1efc157..ba18d4be14 100644
--- a/macro/run/run_unpack_tsa.C
+++ b/macro/run/run_unpack_tsa.C
@@ -106,6 +106,15 @@ void run_unpack_tsa(std::string infile = "test.tsa", UInt_t runid = 0, const cha
   trdconfig->SetSpadicObject(GetTrdSpadic(true));
   // -------------
 
+  // ---- TRDFASP2D ----
+  auto trdfasp2dconfig = std::make_shared<CbmTrdUnpackConfigFasp2D>("", runid);
+  // trdfasp2dconfig->SetDebugState();
+  trdfasp2dconfig->SetDoWriteOutput();
+  trdfasp2dconfig->SetOutputBranchName("FaspTrdDigi");
+  std::string parfilesbasepathTrdfasp2d = Form("%s/parameters/trd", srcDir.Data());
+  trdfasp2dconfig->SetParFilesBasePath(parfilesbasepathTrdfasp2d);
+  // -------------
+
   // ------------------------------------------------------------------------
 
   // In general, the following parts need not be touched
@@ -124,6 +133,7 @@ void run_unpack_tsa(std::string infile = "test.tsa", UInt_t runid = 0, const cha
   unpack->SetUnpackConfig(psdconfig);
   unpack->SetUnpackConfig(richconfig);
   unpack->SetUnpackConfig(trdconfig);
+  unpack->SetUnpackConfig(trdfasp2dconfig);
   // ------------------------------------------------------------------------
 
 
diff --git a/reco/base/CbmRecoUnpackAlgo.tmpl b/reco/base/CbmRecoUnpackAlgo.tmpl
index e9393ff78f..c655c0d661 100644
--- a/reco/base/CbmRecoUnpackAlgo.tmpl
+++ b/reco/base/CbmRecoUnpackAlgo.tmpl
@@ -45,7 +45,7 @@ class CbmRecoUnpackAlgo {
 
 public:
   /** @brief Create the Cbm Trd Unpack AlgoBase object */
-  CbmRecoUnpackAlgo(std::uint8_t flesSubsystemId, std::string name) : fFlesSubsystemId(flesSubsystemId), fName(name) {};
+  CbmRecoUnpackAlgo(std::string name) : fName(name) {};
 
   /** @brief Destroy the Cbm Trd Unpack Task object */
   virtual ~CbmRecoUnpackAlgo() {};
@@ -68,8 +68,6 @@ protected:
   std::vector<TOptOutB>* fOptOutBVec = {};
 
   // Parameter storage members
-  /** @brief SubsystemId as defined by fles and encoded in the timeslices. To be set in the derived classes. Ensures, that only data of the asics connected to the given unpacker are passed to it by the Task/Device. */
-  std::uint8_t fFlesSubsystemId;
 
   /** @brief Vector with the parameter containers and the paths to the connected ascii files of the TRD */
   std::vector<std::pair<std::string, std::shared_ptr<FairParGenericSet>>> fParContVec = {};
@@ -81,7 +79,7 @@ protected:
    * @brief Time offset for the system
    * @todo This should be module and channel dependent and included into the asic parameters
   */
-  std::int32_t fSystemTimeoffset = 0;
+  std::int32_t fSystemTimeOffset = 0;
 
   /** @brief Check if we are looking at the first timeslice and if so extract the required TS parameters */
   bool fIsFirstTs = true;
@@ -267,13 +265,6 @@ public:
     finish();
   }
 
-  /**
-   * @brief Get the Fles Subsystem Id stored in fFlesSubsystemId
-   * 
-   * @return std::uint8_t 
-  */
-  std::uint8_t GetFlesSubsystemId() { return fFlesSubsystemId; }
-
   /**
    * @brief Get the Name of the (derived) object
    * 
@@ -352,6 +343,9 @@ public:
   */
   void SetParFilesBasePath(std::string value) { fParFilesBasePath = value; }
 
+  /** @brief Set the global system time offset @remark in princible this should go to parameters */
+  void SetSystemTimeOffset(size_t value) { fSystemTimeOffset = value; }
+
   /** @brief Set the start time of the current TS */
   void SetTsStartTime(size_t value) { fTsStartTime = value; }
 
diff --git a/reco/base/CbmRecoUnpackConfig.tmpl b/reco/base/CbmRecoUnpackConfig.tmpl
index b6b0dd4497..4826ba54cc 100644
--- a/reco/base/CbmRecoUnpackConfig.tmpl
+++ b/reco/base/CbmRecoUnpackConfig.tmpl
@@ -62,7 +62,7 @@ protected:
   /** @brief Pointer to the output vectors connected to the framework. */
   std::vector<TOutput>* fOutputVec = nullptr;
 
-  /** @brief Name for the branch of the output, set together with the write output flag. */
+  /** @brief Name for the branch of the output, set if a non-default name is to be used. */
   std::string fOutputBranchName = "";
 
   /** @brief Pointer to the opt output vectors connected to the framework. */
@@ -101,6 +101,7 @@ protected:
   /** @brief Decision if the info msgs are supposed to be stored to a branch. */
   bool fIsMC = false;
 
+  size_t fSystemTimeOffset = 0;
 
   /** @brief Use this function to implement additional actions to be called once per TS, e.g. needed if more than the default output vector is used. */
   virtual void reset() { return; };
@@ -108,6 +109,13 @@ protected:
 
 public:
   // Getters
+  /**
+   * @brief Get the Output Branch Name
+   * 
+   * @return std::string 
+  */
+  std::string GetOutputBranchName() { return fOutputBranchName.empty() ? TOutput::GetBranchName() : fOutputBranchName; }
+
   /** @brief Get the name of the given derived config */
   std::string GetName() { return fName; }
 
@@ -139,18 +147,34 @@ public:
   */
   std::shared_ptr<CbmRecoUnpackAlgo<TOutput, TOptOutA, TOptOutB>> GetUnpacker() { return fAlgo; };
 
-  void Init(FairRootManager* ioman)
+  /**
+   * @brief Init function of the configs to be called by CbmRecoUnpack()
+   * Initializes the output branches and calls InitUnpacker()
+   * @param ioman Pointer to the FairRootManager instance
+   * @param branchname by default TOutput::GetBranchName() is used for the first output. If branchname is not empty that branchname is used.
+  */
+  void Init(FairRootManager* ioman, std::string branchname = "")
   {
     if (fDoWriteOutput) {
-      fOutputVec = new std::vector<TOutput>();
-      ioman->RegisterAny(TOutput::GetBranchName(), fOutputVec, kTRUE);
-      LOG(info) << fName << "::registerBranchToTree(" << TOutput::GetBranchName() << ")";
+      if (branchname.empty()) {
+        fOutputVec = new std::vector<TOutput>();
+        ioman->RegisterAny(TOutput::GetBranchName(), fOutputVec, kTRUE);
+        LOG(info) << fName << "::registerBranchToTree(" << TOutput::GetBranchName() << ")";
+      }
+      else {
+        fOutputVec = new std::vector<TOutput>();
+        ioman->RegisterAny(branchname.data(), fOutputVec, kTRUE);
+        LOG(info) << fName << "::registerBranchToTree(" << branchname.data() << ")";
+      }
     }
 
+    /** @todo for the optional outputs it is more complicated to check if they exist. Needs exceptions for the std::nullptr_t. Should be added at some point in time. */
     if (fDoWriteOptOutA) {
-      fOptOutAVec = new std::vector<TOptOutA>();
-      ioman->RegisterAny(fOptoutABranchName.data(), fOptOutAVec, kTRUE);
-      LOG(info) << fName << "::registerBranchToTree(" << fOptoutABranchName.data() << ")";
+      if (!fOptOutAVec) {
+        fOptOutAVec = new std::vector<TOptOutA>();
+        ioman->RegisterAny(fOptoutABranchName.data(), fOptOutAVec, kTRUE);
+        LOG(info) << fName << "::registerBranchToTree(" << fOptoutABranchName.data() << ")";
+      }
     }
 
     if (fDoWriteOptOutB) {
@@ -158,10 +182,16 @@ public:
       ioman->RegisterAny(fOptoutBBranchName.data(), fOptOutBVec, kTRUE);
       LOG(info) << fName << "::registerBranchToTree(" << fOptoutBBranchName.data() << ")";
     }
+
+    // Init the unpacker
+    InitUnpacker();
+
+    // Set the global system time offset
+    if (fAlgo) fAlgo->SetSystemTimeOffset(fSystemTimeOffset);
   }
 
   /** @brief Prepare the Unpacker algorithm for the run, to be implemented in the derived classes. */
-  virtual void InitUnpacker() = 0;
+  virtual void InitUnpacker() {};
 
   /** @brief Reset called once per ReadEvent() */
   void Reset()
@@ -181,6 +211,14 @@ public:
    */
   void SetDoWriteOutput(bool value = true) { fDoWriteOutput = value; }
 
+  /**
+   * @brief Set the Output Branch Name
+   * By default TOutput::GetBranchName() is used. Set this if you want to use a 
+   * different output name
+   * @param value 
+  */
+  void SetOutputBranchName(std::string value) { fOutputBranchName = value; }
+
   /**
    * @brief Set the Do Write OptOutput A flag, without activation the opt out is not written to the sink
    * @param branchname name of the branch in the output tree 
@@ -217,6 +255,14 @@ public:
   */
   void SetIsMC(bool value = true) { fIsMC = value; }
 
+  /**
+   * @brief Set the Output Vec
+   * 
+   * @tparam Output 
+   * @param value 
+  */
+  void SetOutputVec(std::vector<TOutput>* value) { fOutputVec = value; }
+
   /**
    * @brief Set the Par Files Base Path (absolute directory path were the files are stored)
    * 
@@ -224,6 +270,9 @@ public:
   */
   void SetParFilesBasePath(std::string value) { fParFilesBasePath = value; }
 
+  /** @brief Set the global system time offset @remark in princible this should go to parameters */
+  void SetSystemTimeOffset(size_t value) { fSystemTimeOffset = value; }
+
 protected:
   /**
    * @brief Initialise the parameter containers requested by the algorithm
@@ -233,6 +282,10 @@ protected:
   virtual Bool_t initParContainers(std::vector<std::pair<std::string, std::shared_ptr<FairParGenericSet>>>* reqparvec)
   {
     if (fDoLog) LOG(info) << GetName() << "::Init - initParContainers";
+    if (!reqparvec) {
+      LOG(info) << GetName() << "::Init - initParContainers - empty requirements vector no parameters initialized.";
+      return kTRUE;
+    }
 
     // Now get the actual ascii files and init the containers with the asciiIo
     for (auto& pair : *reqparvec) {
diff --git a/reco/detectors/psd/CMakeLists.txt b/reco/detectors/psd/CMakeLists.txt
index 1e1aaff405..2ab93daa82 100644
--- a/reco/detectors/psd/CMakeLists.txt
+++ b/reco/detectors/psd/CMakeLists.txt
@@ -47,7 +47,6 @@ set(DEPENDENCIES
     CbmBase 
     Base 
     CbmRecoBase 
-    fles_ipc # for unpacker
 )
 
 GENERATE_LIBRARY()
diff --git a/reco/detectors/psd/unpack/CbmPsdUnpackAlgo.cxx b/reco/detectors/psd/unpack/CbmPsdUnpackAlgo.cxx
index 32e74eabc0..0e6de6b104 100644
--- a/reco/detectors/psd/unpack/CbmPsdUnpackAlgo.cxx
+++ b/reco/detectors/psd/unpack/CbmPsdUnpackAlgo.cxx
@@ -18,7 +18,7 @@
 #include "PsdGbtReader-v0.00.h"
 #include "PsdGbtReader-v1.00.h"
 
-CbmPsdUnpackAlgo::CbmPsdUnpackAlgo() : CbmRecoUnpackAlgo(fgkFlesSubsystemIdTrdR, "CbmPsdUnpackAlgo") {}
+CbmPsdUnpackAlgo::CbmPsdUnpackAlgo() : CbmRecoUnpackAlgo("CbmPsdUnpackAlgo") {}
 
 // ----- Channel address
 Int_t CbmPsdUnpackAlgo::getAddress(size_t channel)
diff --git a/reco/detectors/psd/unpack/CbmPsdUnpackAlgo.h b/reco/detectors/psd/unpack/CbmPsdUnpackAlgo.h
index 9eb2d102b9..b852c2ba83 100644
--- a/reco/detectors/psd/unpack/CbmPsdUnpackAlgo.h
+++ b/reco/detectors/psd/unpack/CbmPsdUnpackAlgo.h
@@ -139,9 +139,6 @@ protected:
   */
   bool unpack(const fles::Timeslice* ts, std::uint16_t icomp, UInt_t imslice);
 
-  /** @brief Fles Subsystem Identifier for the TRD R data */
-  static constexpr int fgkFlesSubsystemIdTrdR = static_cast<int>(fles::SubsystemIdentifier::PSD);
-
   // Settings from parameters
   UInt_t fuRawDataVersion = 0;                    //! Raw data versioning
                                                   /// Readout chain dimensions and mapping
diff --git a/reco/detectors/rich/CMakeLists.txt b/reco/detectors/rich/CMakeLists.txt
index 4de1bb38d6..a1d2c7b217 100644
--- a/reco/detectors/rich/CMakeLists.txt
+++ b/reco/detectors/rich/CMakeLists.txt
@@ -132,7 +132,6 @@ set(LINKDEF  CbmRichRecoLinkDef.h)
 Set(LIBRARY_NAME CbmRichReco)
 Set(DEPENDENCIES
     KF L1 CbmRichBase CbmRecoBase CbmBase CbmData Base MLP boost_regex Gdml 
-    # fles_ipc # for unpacker
     )
 
 GENERATE_LIBRARY()
diff --git a/reco/detectors/rich/unpack/CbmRichUnpackAlgo.cxx b/reco/detectors/rich/unpack/CbmRichUnpackAlgo.cxx
index 83fbf66209..2e7099eab6 100644
--- a/reco/detectors/rich/unpack/CbmRichUnpackAlgo.cxx
+++ b/reco/detectors/rich/unpack/CbmRichUnpackAlgo.cxx
@@ -14,7 +14,7 @@
 #include <cstdint>
 
 
-CbmRichUnpackAlgo::CbmRichUnpackAlgo() : CbmRecoUnpackAlgo(fgkFlesSubsystemIdTrdR, "CbmRichUnpackAlgo") {}
+CbmRichUnpackAlgo::CbmRichUnpackAlgo() : CbmRecoUnpackAlgo("CbmRichUnpackAlgo") {}
 
 CbmRichUnpackAlgo::~CbmRichUnpackAlgo() {}
 
@@ -399,8 +399,8 @@ void CbmRichUnpackAlgo::writeOutputDigi(Int_t fpgaID, Int_t channel, Double_t ti
   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;
-  //   Double_t finalTime = time - fSystemTimeoffset - fTsStartTime;
+  Double_t finalTime = time + (Double_t) fMsRefTime - fSystemTimeOffset;
+  //   Double_t finalTime = time - fSystemTimeOffset - fTsStartTime;
 
   Double_t lastTime = 0.;
 
diff --git a/reco/detectors/rich/unpack/CbmRichUnpackAlgo.h b/reco/detectors/rich/unpack/CbmRichUnpackAlgo.h
index 566492553b..352adaf7de 100644
--- a/reco/detectors/rich/unpack/CbmRichUnpackAlgo.h
+++ b/reco/detectors/rich/unpack/CbmRichUnpackAlgo.h
@@ -310,9 +310,6 @@ protected:
   */
   bool unpack(const fles::Timeslice* ts, std::uint16_t icomp, UInt_t imslice);
 
-  /** @brief Fles Subsystem Identifier for the TRD R data */
-  static constexpr int fgkFlesSubsystemIdTrdR = static_cast<int>(fles::SubsystemIdentifier::RICH);
-
   /** @brief Parameters for the unpacking */
   CbmMcbm2018RichPar fUnpackPar;
 
diff --git a/reco/detectors/sts/CMakeLists.txt b/reco/detectors/sts/CMakeLists.txt
index b1ab46c91e..1321d4bbcf 100644
--- a/reco/detectors/sts/CMakeLists.txt
+++ b/reco/detectors/sts/CMakeLists.txt
@@ -73,7 +73,6 @@ ${Boost_LIBRARY_DIRS}
 # -----   Specify library dependences   -------------------
 Set(DEPENDENCIES
     CbmBase CbmData CbmRecoBase CbmStsBase
-    fles_ipc # for unpacker
 )
 # ---------------------------------------------------------
 
diff --git a/reco/detectors/sts/unpack/CbmStsUnpackAlgo.cxx b/reco/detectors/sts/unpack/CbmStsUnpackAlgo.cxx
index 6a1e6e5ac9..0c76f5a8e0 100644
--- a/reco/detectors/sts/unpack/CbmStsUnpackAlgo.cxx
+++ b/reco/detectors/sts/unpack/CbmStsUnpackAlgo.cxx
@@ -12,7 +12,7 @@
 #include <RtypesCore.h>
 
 
-CbmStsUnpackAlgo::CbmStsUnpackAlgo() : CbmRecoUnpackAlgo(fgkFlesSubsystemIdTrdR, "CbmStsUnpackAlgo") {}
+CbmStsUnpackAlgo::CbmStsUnpackAlgo() : CbmRecoUnpackAlgo("CbmStsUnpackAlgo") {}
 
 CbmStsUnpackAlgo::~CbmStsUnpackAlgo() {}
 
diff --git a/reco/detectors/sts/unpack/CbmStsUnpackAlgo.h b/reco/detectors/sts/unpack/CbmStsUnpackAlgo.h
index 862d89a39f..576dbde875 100644
--- a/reco/detectors/sts/unpack/CbmStsUnpackAlgo.h
+++ b/reco/detectors/sts/unpack/CbmStsUnpackAlgo.h
@@ -114,9 +114,6 @@ protected:
   */
   bool unpack(const fles::Timeslice* ts, std::uint16_t icomp, UInt_t imslice) { return true; }
 
-  /** @brief Fles Subsystem Identifier for the TRD R data */
-  static constexpr int fgkFlesSubsystemIdTrdR = static_cast<int>(fles::SubsystemIdentifier::STS);
-
 private:
   ClassDef(CbmStsUnpackAlgo, 2)
 };
diff --git a/reco/detectors/trd/CMakeLists.txt b/reco/detectors/trd/CMakeLists.txt
index 09e02d3b53..f967f9fe37 100644
--- a/reco/detectors/trd/CMakeLists.txt
+++ b/reco/detectors/trd/CMakeLists.txt
@@ -59,8 +59,8 @@ unpack/CbmTrdUnpackAlgoR.cxx
 unpack/CbmTrdUnpackAlgoLegacy2020R.cxx
 unpack/CbmTrdUnpackMonitor.cxx
 
-unpack/CbmTrdUnpackAlgo2D.cxx
-unpack/CbmTrdUnpackConfig2D.cxx
+unpack/CbmTrdUnpackAlgoFasp2D.cxx
+unpack/CbmTrdUnpackConfigFasp2D.cxx
 
 qa/CbmTrdClusterizerFastQa.cxx
 qa/CbmTrdHitDensityQa.cxx
@@ -103,7 +103,6 @@ Set(DEPENDENCIES
     Base
     CbmTrdBase
     TMVA
-    fles_ipc # for unpacker
 )
 
 GENERATE_LIBRARY()
diff --git a/reco/detectors/trd/CbmTrdRecoLinkDef.h b/reco/detectors/trd/CbmTrdRecoLinkDef.h
index 449f6f2ca0..016bd71606 100644
--- a/reco/detectors/trd/CbmTrdRecoLinkDef.h
+++ b/reco/detectors/trd/CbmTrdRecoLinkDef.h
@@ -33,8 +33,8 @@
 #pragma link C++ class CbmTrdUnpackConfig + ;
 #pragma link C++ class CbmTrdUnpackMonitor + ;
 
-#pragma link C++ class CbmTrdUnpackAlgo2D + ;
-#pragma link C++ class CbmTrdUnpackConfig2D + ;
+#pragma link C++ class CbmTrdUnpackAlgoFasp2D + ;
+#pragma link C++ class CbmTrdUnpackConfigFasp2D + ;
 
 #pragma link C++ class CbmTrdElectronsTrainAnn + ;
 #pragma link C++ class CbmTrdSetTracksPidWkn + ;
diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackAlgo2D.cxx b/reco/detectors/trd/unpack/CbmTrdUnpackAlgo2D.cxx
deleted file mode 100644
index 09adecbb9b..0000000000
--- a/reco/detectors/trd/unpack/CbmTrdUnpackAlgo2D.cxx
+++ /dev/null
@@ -1,154 +0,0 @@
-/* Copyright (C) 2010 - 2021 Goethe-University Frankfurt
-   SPDX-License-Identifier: GPL-3.0-only
-   Authors: Pascal Raisig */
-
-
-#include "CbmTrdUnpackAlgo2D.h"
-
-#include "CbmMcbm2020TrdTshiftPar.h"
-#include "CbmTrdDigi.h"
-#include "CbmTrdHardwareSetupR.h"  // for channel address parameters
-#include "CbmTrdParSetAsic.h"
-
-#include <FairParGenericSet.h>
-#include <FairTask.h>
-#include <Logger.h>
-
-#include <Rtypes.h>
-#include <RtypesCore.h>
-
-
-CbmTrdUnpackAlgo2D::CbmTrdUnpackAlgo2D() : CbmRecoUnpackAlgo(fgkFlesSubsystemIdTrdR, "CbmTrdUnpackAlgo2D") {}
-
-CbmTrdUnpackAlgo2D::~CbmTrdUnpackAlgo2D() {}
-
-// ---- digestOutput ----
-void CbmTrdUnpackAlgo2D::digestOutput(std::unique_ptr<CbmTrdDigi> digi)
-{
-  ++fNrCreatedDigis;
-
-  // If requested lets monitor something
-  if (fMonitor) { fMonitor->FillHistos(digi.get(), nullptr); }
-
-  // Save the digi
-  fOutputVec.emplace_back(*std::move(digi));
-}
-
-// ---- getAsicAddress ----
-std::uint32_t CbmTrdUnpackAlgo2D::getAsicAddress(std::uint32_t criid, std::uint32_t crobid, std::uint32_t elinkid)
-{
-  size_t spadicHwAddress = 0;
-  spadicHwAddress = elinkid + (CbmTrdParAsic::kCriIdPosition * criid) + (CbmTrdParAsic::kCrobIdPosition * crobid);
-  auto mapIt      = fSpadicAddressMap.find(spadicHwAddress);  // check if asic exists
-  if (mapIt == fSpadicAddressMap.end()) {
-    LOG(info) << fName
-              << "::makeDigi - No asic address "
-                 "found for Spadic hardware address "
-              << spadicHwAddress;
-    return 0;
-  }
-
-  return mapIt->second;
-}
-
-// ---- getAsicAddress ----
-std::uint32_t CbmTrdUnpackAlgo2D::getChannelId(std::uint32_t asicaddress, std::uint32_t elinkid,
-                                               std::uint32_t elinkchannelid)
-{
-  // GetChannelId per eLink add NSPADICCH / 2 to the second(first) eLink in the case we start with odd(even) eLinks, since, our mapping is based on odd eLinks
-  auto asicChannelId =
-    (elinkid % 2) == fIsFirstChannelsElinkEven ? elinkchannelid : elinkchannelid + (CbmTrdSpadic::GetNrChannels() / 2);
-
-  auto channelId = (fAsicChannelMap.find(asicaddress))->second.at(asicChannelId);
-
-  return channelId;
-}
-
-// ---- initParSet(FairParGenericSet* parset) ----
-Bool_t CbmTrdUnpackAlgo2D::initParSet(FairParGenericSet* parset)
-{
-  LOG(info) << fName << "::initParSet - for container " << parset->ClassName();
-  if (parset->IsA() == CbmTrdParSetAsic::Class()) return initParSet(static_cast<CbmTrdParSetAsic*>(parset));
-
-  if (parset->IsA() == CbmTrdParSetDigi::Class()) return initParSet(static_cast<CbmTrdParSetDigi*>(parset));
-
-  if (parset->IsA() == CbmMcbm2020TrdTshiftPar::Class())
-    return initParSet(static_cast<CbmMcbm2020TrdTshiftPar*>(parset));
-
-  // If we do not know the derived ParSet class we return false
-  LOG(error)
-    << fName << "::initParSet - for container " << parset->ClassName()
-    << " failed, since CbmTrdUnpackAlgo2D::initParSet() does not know the derived ParSet and what to do with it!";
-  return kFALSE;
-}
-
-// ---- initParSet(CbmTrdParSetAsic* parset) ----
-Bool_t CbmTrdUnpackAlgo2D::initParSet(CbmTrdParSetAsic* parset)
-{
-  LOG(debug) << fName << "::initParSetAsic - ";
-  CbmTrdHardwareSetupR hwSetup;
-  fSpadicAddressMap = hwSetup.CreateHwToSwAsicAddressTranslatorMap(parset);
-  if (fSpadicAddressMap.empty()) {
-    LOG(error) << fName << "::initParSetAsic - SpadicAddressMap creation failed, the map is empty";
-    return kFALSE;
-  }
-  // at least check that the loaded map is not empty
-
-  fAsicChannelMap = hwSetup.CreateAsicChannelMap(parset);
-  if (fAsicChannelMap.empty()) {
-    LOG(error) << fName << "::initParSetAsic - AsicChannelMap creation failed, the map is empty";
-    return kFALSE;
-  }
-
-
-  LOG(info) << fName << "::initParSetAsic - Successfully initialized Spadic hardware address map";
-
-  return kTRUE;
-}
-
-// ---- initParSet(CbmTrdParSetDigi* parset) ----
-Bool_t CbmTrdUnpackAlgo2D::initParSet(CbmTrdParSetDigi* parset)
-{
-  Bool_t initOk = kTRUE;
-  // The monitor needs the ParSetDigi to extract module informations and other stuff
-  if (fMonitor) {
-    LOG(info) << fName << "::initParSet(CbmTrdParSetDigi) - Forwarding ParSetDigi to the monitor";
-    initOk &= fMonitor->Init(parset);
-  }
-
-  return initOk;
-}
-
-// ---- initParSet(CbmMcbm2020TrdTshiftPar* parset) ----
-Bool_t CbmTrdUnpackAlgo2D::initParSet(CbmMcbm2020TrdTshiftPar* parset)
-{
-  auto maptimeshifts = parset->GetTimeshiftsMap();
-  fTimeshiftsMap.clear();
-  fTimeshiftsMap.insert(maptimeshifts->begin(), maptimeshifts->end());
-  LOG(info) << fName << "::initParSetTimeshift2020() - Parsing timeshift correction map to unpacker algo";
-
-  return (!fTimeshiftsMap.empty());
-}
-
-// ---- initR ----
-Bool_t CbmTrdUnpackAlgo2D::initR()
-{
-  auto initOk = kTRUE;
-  // Check if we have already a Spadic object. If not check if we have a raw to digi object, it has by default a Spadic object. If we do not have a rtd object we create a default spadic object on our own.
-  if (!fSpadic) {
-    // First we check if there is a spadic definition stored in the raw to digi method
-    if (fRTDMethod) fSpadic = fRTDMethod->GetSpadicObject();
-    // If we still do not have spadic, we create it on our own
-    if (!fSpadic) fSpadic = std::make_shared<CbmTrdSpadic>();
-  }
-  if (!fSpadic) {
-    LOG(error) << fName
-               << "::initR - We are missing a CbmTrdSpadic object, to extract the basic spadic functionalities!";
-    initOk &= kFALSE;
-  }
-  if (fMonitor) fMonitor->SetSpadicObject(fSpadic);
-
-  return initOk;
-}
-
-ClassImp(CbmTrdUnpackAlgo2D)
diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackAlgo2D.h b/reco/detectors/trd/unpack/CbmTrdUnpackAlgo2D.h
deleted file mode 100644
index fe510cffb0..0000000000
--- a/reco/detectors/trd/unpack/CbmTrdUnpackAlgo2D.h
+++ /dev/null
@@ -1,236 +0,0 @@
-/* Copyright (C) 2010 - 2021 Goethe-University Frankfurt
-   SPDX-License-Identifier: GPL-3.0-only
-   Authors: Pascal Raisig */
-
-/**
- * @file CbmTrdUnpackAlgo2D.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 CbmTrdUnpackAlgo2D_H
-#define CbmTrdUnpackAlgo2D_H
-
-#include "CbmMcbm2020TrdTshiftPar.h"
-#include "CbmRecoUnpackAlgo.tmpl"
-#include "CbmTrdDigi.h"
-#include "CbmTrdParSetAsic.h"
-#include "CbmTrdRawMessageSpadic.h"
-#include "CbmTrdRawToDigiBaseR.h"
-#include "CbmTrdSpadic.h"
-#include "CbmTrdUnpackMonitor.h"
-
-#include "Timeslice.hpp"  // timeslice
-
-#include <Rtypes.h>  // for types
-#include <RtypesCore.h>
-
-#include <cstddef>
-#include <cstdint>
-#include <memory>
-#include <utility>
-
-class CbmTrdUnpackAlgo2D : public CbmRecoUnpackAlgo<CbmTrdDigi> {
-public:
-  /** @brief Create the Cbm Trd Unpack AlgoBase object */
-  CbmTrdUnpackAlgo2D();
-
-  /** @brief Destroy the Cbm Trd Unpack Task object */
-  virtual ~CbmTrdUnpackAlgo2D();
-
-  /** @brief Copy constructor - not implemented **/
-  CbmTrdUnpackAlgo2D(const CbmTrdUnpackAlgo2D&) = delete;
-
-  /** @brief Assignment operator - not implemented **/
-  CbmTrdUnpackAlgo2D& operator=(const CbmTrdUnpackAlgo2D&) = delete;
-
-  // Setters
-  /** @brief Set a predefined monitor @param monitor predefined unpacking monitor */
-  void SetMonitor(std::shared_ptr<CbmTrdUnpackMonitor> monitor) { fMonitor = monitor; }
-
-  /**
-   * @brief Set the Raw To Digi Method
-   * 
-   * @param value 
-  */
-  void SetRawToDigiMethod(std::shared_ptr<CbmTrdRawToDigiBaseR> value) { fRTDMethod = value; }
-
-  /**
-   * @brief Set the Spadic Object
-   * 
-   * @param value 
-  */
-  void SetSpadicObject(std::shared_ptr<CbmTrdSpadic> value) { fSpadic = value; }
-
-protected:
-  /**
-   * @brief Handle the output created by the explicit algorithms. E.g. write to output vectors.
-   * 
-   * @param digi 
-   * @param raw 
-  */
-  void digestOutput(std::unique_ptr<CbmTrdDigi> digi);
-
-  /** @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() = 0;
-  virtual void finishDerived() { return; }
-
-  /**
-   * @brief Get the Asic Address (CbmAddress scheme) for the given hardware Ids
-   * 
-   * @param criid 
-   * @param crobid 
-   * @param elinkid 
-   * @return std::uint32_t 
-  */
-  virtual std::uint32_t getAsicAddress(std::uint32_t criid, std::uint32_t crobid, std::uint32_t elinkid);
-
-  /**
-   * @brief Get the Channel Id (CbmAddress scheme) for the given hardware Ids
-   * 
-   * @param asicaddress 
-   * @param elinkid 
-   * @param elinkchannelid 
-   * @return std::uint32_t 
-  */
-  std::uint32_t getChannelId(std::uint32_t asicaddress, std::uint32_t elinkid, std::uint32_t elinkchannelid);
-
-  /**
-   * @brief Additional initialisation function for all BaseR derived algorithms.
-   * 
-   * @return Bool_t initOk 
-  */
-  virtual Bool_t init() { return initR(); }
-
-  /**
-   * @brief Additional initialisation function for all BaseR derived algorithms.
-   * 
-   * @return Bool_t initOk 
-  */
-  virtual Bool_t initR();
-
-  // Initialise par set, the base function handles the casting to distribute the pointers to their explicit functions
-
-  /**
-   * @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 Transfer parameters from ParSetAsic container to members.
-   *  
-   * Currently we mainly transfer here the addressing, other parameters are yet to come.
-   *  
-   * @param parset 
-   * @return Bool_t initOk 
-  */
-  Bool_t initParSet(CbmTrdParSetAsic* parset);
-
-  /**
-   * @brief Transfer parameters from ParSetDigi container to members.
-   *  
-   * The monitor needs this to extract module informations, e.g. ncols and nrows.
-   *  
-   * @param parset 
-   * @return Bool_t initOk 
-  */
-  Bool_t initParSet(CbmTrdParSetDigi* parset);
-
-  /**
-   * @brief Transfer parameters from CbmMcbm2020TrdTshiftPar container to members.
-   *  
-   * These are mCBM 2020 specific parameters needed to correct in run timeshifts. 
-   *  
-   * @param parset 
-   * @return Bool_t initOk 
-  */
-  Bool_t initParSet(CbmMcbm2020TrdTshiftPar* parset);
-
-  /**
-   * @brief Unpack a given microslice.
-   * 
-   * @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)
-  {
-    LOG(info) << "HelloWorld";
-    return true;
-  }
-
-  // Monitoring
-  /** @brief Potential (online) monitor for the unpacking process */
-  std::shared_ptr<CbmTrdUnpackMonitor> fMonitor = nullptr;
-
-  // Parameter storage members
-  /** @brief Spadic software reprensentation object */
-  std::shared_ptr<CbmTrdSpadic> fSpadic = nullptr;
-
-  /** @brief raw to digi extraction method, set in the task */
-  std::shared_ptr<CbmTrdRawToDigiBaseR> fRTDMethod = nullptr;
-
-  /** @brief Map to retrieve asic address from CriId/CrobId/ElinkId (see CbmTrdHardwareSetupR) */
-  std::map<size_t, Int_t> fSpadicAddressMap = {};
-
-  /** @brief Map to retrieve module channelId from asicAddress and asicChannel */
-  std::map<Int_t, std::vector<Int_t>> fAsicChannelMap = {};
-
-  /** @brief Map containing the timeshift parameters for the correction of the µSlice timeshifts. The keys are the tsIdx, if no key is found, the shifts of the previous tsIdx are used again */
-  std::map<size_t, std::vector<Int_t>> fTimeshiftsMap = {};
-
-  /** @brief Define if the first 16 channels (00..15) are found on the even (set true) or odd (false) eLinkId.
-   * Default for mCbm2020 is false thus, initialized as false */
-  Bool_t fIsFirstChannelsElinkEven = kFALSE;
-
-  /** @brief Number of rda frames outside of a SOM frame range */
-  size_t fNrWildRda = 0;
-
-  /** @brief Number of eom frames outside of a SOM frame range */
-  size_t fNrWildEom = 0;
-
-  /** @brief Number of wild null words, should only appear at the end of a µSlice */
-  size_t fNrWildNul = 0;
-
-  /** @brief Number of unknown words */
-  size_t fNrUnknownWords = 0;
-
-  /** @brief length of one ts_msb in [ns] */
-  static constexpr std::uint16_t fTsMsbLength = 16000;
-
-  /** @brief length of one ts_msb in [cc] */
-  size_t fTsMsbLengthCC = fTsMsbLength / CbmTrdSpadic::GetClockCycle();
-
-  /** @brief Fles Subsystem Identifier for the TRD R data */
-  static constexpr int fgkFlesSubsystemIdTrdR = static_cast<int>(fles::SubsystemIdentifier::TRD);
-
-private:
-  ClassDef(CbmTrdUnpackAlgo2D, 2)
-};
-
-#endif  // CbmTrdUnpackAlgo2D_H
diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackAlgoBaseR.cxx b/reco/detectors/trd/unpack/CbmTrdUnpackAlgoBaseR.cxx
index eaac0c875d..757262548d 100644
--- a/reco/detectors/trd/unpack/CbmTrdUnpackAlgoBaseR.cxx
+++ b/reco/detectors/trd/unpack/CbmTrdUnpackAlgoBaseR.cxx
@@ -17,7 +17,7 @@
 #include <RtypesCore.h>
 
 
-CbmTrdUnpackAlgoBaseR::CbmTrdUnpackAlgoBaseR(std::string name) : CbmRecoUnpackAlgo(fgkFlesSubsystemIdTrdR, name) {}
+CbmTrdUnpackAlgoBaseR::CbmTrdUnpackAlgoBaseR(std::string name) : CbmRecoUnpackAlgo(name) {}
 
 CbmTrdUnpackAlgoBaseR::~CbmTrdUnpackAlgoBaseR() {}
 
diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackAlgoBaseR.h b/reco/detectors/trd/unpack/CbmTrdUnpackAlgoBaseR.h
index 24e7acc474..363bd87079 100644
--- a/reco/detectors/trd/unpack/CbmTrdUnpackAlgoBaseR.h
+++ b/reco/detectors/trd/unpack/CbmTrdUnpackAlgoBaseR.h
@@ -211,9 +211,6 @@ protected:
   /** @brief length of one ts_msb in [cc] */
   size_t fTsMsbLengthCC = fTsMsbLength / CbmTrdSpadic::GetClockCycle();
 
-  /** @brief Fles Subsystem Identifier for the TRD R data */
-  static constexpr int fgkFlesSubsystemIdTrdR = static_cast<int>(fles::SubsystemIdentifier::TRD);
-
 private:
   ClassDef(CbmTrdUnpackAlgoBaseR, 2)
 };
diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackAlgoFasp2D.cxx b/reco/detectors/trd/unpack/CbmTrdUnpackAlgoFasp2D.cxx
new file mode 100644
index 0000000000..89348bfedf
--- /dev/null
+++ b/reco/detectors/trd/unpack/CbmTrdUnpackAlgoFasp2D.cxx
@@ -0,0 +1,252 @@
+/* Copyright (C) 2010 - 2021 Goethe-University Frankfurt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Pascal Raisig, Alexandru Bercuci */
+
+
+#include "CbmTrdUnpackAlgoFasp2D.h"
+
+#include "CbmTrdDigi.h"
+
+#include <FairParGenericSet.h>
+#include <FairTask.h>
+#include <Logger.h>
+
+#include <Rtypes.h>
+#include <RtypesCore.h>
+
+#include <boost/format.hpp>
+
+using namespace std;
+
+CbmTrdUnpackAlgoFasp2D::CbmTrdUnpackAlgoFasp2D() : CbmRecoUnpackAlgo("CbmTrdUnpackAlgoFasp2D")
+{
+  memset(fTime, 0, NCRI * sizeof(ULong64_t));
+}
+
+CbmTrdUnpackAlgoFasp2D::~CbmTrdUnpackAlgoFasp2D() {}
+
+//_________________________________________________________________________________
+CbmTrdUnpackAlgoFasp2D::CbmTrdFaspMessageType CbmTrdUnpackAlgoFasp2D::mess_type(uint32_t wd)
+{
+  if ((wd >> kMessCh) & 0x1) return kData;
+  return kEpoch;
+}
+
+//_________________________________________________________________________________
+void CbmTrdUnpackAlgoFasp2D::mess_readDW(uint32_t w, CbmTrdFaspContent* 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 CbmTrdUnpackAlgoFasp2D::mess_readEW(uint32_t w, CbmTrdFaspContent* 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->cri = (wd >> shift) & 0x3f;
+  printf("DBG :: ");
+  mess_prt(mess);
+}
+
+//_________________________________________________________________________________
+void CbmTrdUnpackAlgoFasp2D::mess_prt(CbmTrdFaspContent* 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: cri_id=%02d ch_id=%02d epoch=%05d\n") % static_cast<unsigned int>(mess->cri)
+              % static_cast<unsigned int>(mess->ch) % static_cast<unsigned int>(mess->epoch);
+}
+
+#define VERBOSE 0
+//_________________________________________________________________________________
+bool CbmTrdUnpackAlgoFasp2D::pushDigis(
+  std::map<UChar_t, std::vector<CbmTrdUnpackAlgoFasp2D::CbmTrdFaspContent*>> messes)
+{
+  bool use(false);
+  UChar_t lFasp(0xff);
+  UShort_t lchR, lchT;
+  Double_t r, t;
+  Int_t dt, dtime;
+  vector<CbmTrdDigi*> digis;
+  for (Int_t col(0); col < NCOLS; col++) {
+    if (!messes[col].size()) continue;
+    if (lFasp == 0xff) lFasp = messes[col][0]->fasp;
+    //printf("col[%d]=%lu\n", col, messes[col].size());
+    for (vector<CbmTrdFaspContent*>::iterator i = messes[col].begin(); i != messes[col].end(); i++) {
+      if (VERBOSE) mess_prt((*i));
+
+      lchR = 0;
+      lchT = 0;
+      use  = false;
+      if ((*i)->ch % 2) lchR = (*i)->data;
+      else
+        lchT = (*i)->data;
+      for (vector<CbmTrdDigi*>::iterator id = digis.begin(); id != digis.end(); id++) {
+        dtime = (*id)->GetTimeDAQ() - (*i)->tlab;
+        if (TMath::Abs(dtime) < 5) {
+          r = (*id)->GetCharge(t, dt);
+          if (lchR && !int(r)) {
+            (*id)->SetCharge(t, lchR, -dtime);
+            use = true;
+            break;
+          }
+          else if (lchT && !int(t)) {
+            (*id)->SetCharge(lchT, r, +dtime);
+            use = true;
+            break;
+          }
+        }
+      }
+      if (!use) digis.push_back(new CbmTrdDigi(lFasp * NCOLS + col, lchT, lchR, (*i)->tlab));
+      delete (*i);
+    }
+
+    // push finalized digits to the next level
+    for (vector<CbmTrdDigi*>::iterator id = digis.begin(); id != digis.end(); id++) {
+      (*id)->SetTimeDAQ(fTime[0] + (*id)->GetTimeDAQ());
+      fOutputVec.emplace_back(*std::move(*id));
+      if (VERBOSE) cout << (*id)->ToString();
+    }
+
+    digis.clear();
+    messes[col].clear();
+  }
+
+
+  return true;
+}
+
+// ---- unpack ----
+bool CbmTrdUnpackAlgoFasp2D::unpack(const fles::Timeslice* ts, std::uint16_t icomp, UInt_t imslice)
+{
+  if (VERBOSE) printf("CbmTrdUnpackAlgoFasp2D::unpack 0x%04x %d\n", icomp, imslice);
+  //LOG(info) << "Component " << icomp << " connected to config CbmTrdUnpackConfig2D. Slice "<<imslice;
+
+  bool unpackOk = true;
+  //Double_t fdMsSizeInNs = 1.28e6;
+
+  auto msdesc = ts->descriptor(icomp, imslice);
+  if (VERBOSE) printf("time start %lu\n", msdesc.idx);
+
+  // Get the µslice size in bytes to calculate the number of completed words
+  auto mssize = msdesc.size;
+
+  // Get the number of complete words in the input MS buffer.
+  std::uint32_t nwords = mssize / 4;  //fBytesPerWord;
+
+  const auto mspointer = ts->content(icomp, imslice);
+
+  // We have 32 bit spadic frames in this readout version
+  const auto mscontent = reinterpret_cast<const size_t*>(mspointer);
+
+  const uint32_t* wd = reinterpret_cast<const uint32_t*>(mscontent);
+
+
+  UChar_t lFaspOld(0xff), col;
+  map<UChar_t, vector<CbmTrdFaspContent*>> vDigi;
+  CbmTrdFaspContent* mess(nullptr);
+  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;
+    //     }
+    //if(VERBOSE) mess_prt(&mess);
+    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;
+    //    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) {
+        if (VERBOSE)
+          cout << boost::format("    EE : cri_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_id] += 128;
+      }
+      else if (ch_id == 1) {
+        if (VERBOSE) cout << boost::format("    PAUSE: fasp_id=%02d\n") % static_cast<unsigned int>(fasp_id);
+      }
+    }
+    else {
+      if (lFaspOld != fasp_id) {
+        // push
+        if (vDigi.size()) { pushDigis(vDigi); }
+        vDigi.clear();
+        lFaspOld = fasp_id;
+      }
+      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);
+      mess       = new CbmTrdFaspContent;
+      mess->ch   = ch_id;
+      mess->type = 1;
+      mess->tlab = slice;
+      mess->data = data >> 1;
+      mess->fasp = lFaspOld;
+      col        = ch_id >> 1;
+      vDigi[col].push_back(mess);
+    }
+    //prt_wd(*wd);
+  }
+  return unpackOk;
+}
+
+//_____________________________________________________________
+void CbmTrdUnpackAlgoFasp2D::prt_wd(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);
+    }
+  }
+  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);
+  }
+}
+
+ClassImp(CbmTrdUnpackAlgoFasp2D)
diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackAlgoFasp2D.h b/reco/detectors/trd/unpack/CbmTrdUnpackAlgoFasp2D.h
new file mode 100644
index 0000000000..401f65a95d
--- /dev/null
+++ b/reco/detectors/trd/unpack/CbmTrdUnpackAlgoFasp2D.h
@@ -0,0 +1,169 @@
+/* Copyright (C) 2010 - 2021 Goethe-University Frankfurt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Pascal Raisig, Alexandru Bercuci */
+
+/**
+ * @file CbmTrdUnpackAlgoFasp2D.h
+ * @author Alexandru Bercuci
+ * @author Pascal Raisig (praisig@ikf.uni-frankfurt.de)
+ * @brief Trd FASP unpacking algorithm
+ * @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 CbmTrdUnpackAlgoFasp2D_H
+#define CbmTrdUnpackAlgoFasp2D_H
+
+#include "CbmRecoUnpackAlgo.tmpl"
+#include "CbmTrdDigi.h"
+
+#include "Timeslice.hpp"  // timeslice
+
+#include <Rtypes.h>  // for types
+#include <RtypesCore.h>
+
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <utility>
+
+#define NCRI 40  // no of CRI in the system (1/TRD-2D_FASP module)
+#define NCOLS 8  // no of cols / FASP
+
+class CbmTrdUnpackAlgoFasp2D : public CbmRecoUnpackAlgo<CbmTrdDigi> {
+public:
+  /** @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
+   */
+  enum CbmTrdFaspMessage
+  {
+    kMessCh    = 4,
+    kMessType  = 1,
+    kMessTlab  = 7,
+    kMessData  = 14,
+    kMessFasp  = 6,
+    kMessEpoch = 21
+  };
+  enum CbmTrdFaspMessageType
+  {
+    kEpoch = 0,
+    kData
+  };
+
+  /** @brief Create the Cbm Trd Unpack AlgoBase object */
+  CbmTrdUnpackAlgoFasp2D();
+
+  /** @brief Destroy the Cbm Trd Unpack Task object */
+  virtual ~CbmTrdUnpackAlgoFasp2D();
+
+  /** @brief Copy constructor - not implemented **/
+  CbmTrdUnpackAlgoFasp2D(const CbmTrdUnpackAlgoFasp2D&) = delete;
+
+  /** @brief Assignment operator - not implemented **/
+  CbmTrdUnpackAlgoFasp2D& operator=(const CbmTrdUnpackAlgoFasp2D&) = delete;
+
+
+  /** @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;
+  };
+
+  // Setters
+
+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, CbmTrdFaspContent* mess);
+  /** @brief Convert the FASP word into a EPOCH message */
+  void mess_readEW(uint32_t wd, CbmTrdFaspContent* mess);
+  /** @brief Print FASP message */
+  void mess_prt(CbmTrdFaspContent* mess);
+  bool pushDigis(std::map<UChar_t, std::vector<CbmTrdUnpackAlgoFasp2D::CbmTrdFaspContent*>> digis);
+  ULong64_t fTime[NCRI];
+
+  /** @brief Finish function for this algorithm base clase */
+  void finish() { return; }
+
+  /**
+   * @brief Additional initialisation function for all BaseR derived algorithms.
+   * 
+   * @return Bool_t initOk 
+  */
+  virtual Bool_t init() { return kTRUE; }
+
+  // Initialise par set, the base function handles the casting to distribute the pointers to their explicit functions
+
+  /**
+   * @brief Handles the distribution of the hidden derived classes to their explicit functions.
+   * 
+   * @param parset 
+   * @return Bool_t initOk 
+  */
+  Bool_t initParSet(FairParGenericSet* /*parset*/) { return kTRUE; }
+
+
+  /**
+   * @brief Unpack a given microslice.
+   * 
+   * @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);
+
+  // 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
+   */
+  static const std::uint8_t fBytesPerWord = 4;
+
+private:
+  void prt_wd(uint32_t w);
+
+  ClassDef(CbmTrdUnpackAlgoFasp2D, 2)
+};
+
+#endif  // CbmTrdUnpackAlgoFasp2D_H
diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackAlgoLegacy2020R.cxx b/reco/detectors/trd/unpack/CbmTrdUnpackAlgoLegacy2020R.cxx
index 2fbb3e4ef2..dacd7b8f7c 100644
--- a/reco/detectors/trd/unpack/CbmTrdUnpackAlgoLegacy2020R.cxx
+++ b/reco/detectors/trd/unpack/CbmTrdUnpackAlgoLegacy2020R.cxx
@@ -293,7 +293,7 @@ void CbmTrdUnpackAlgoLegacy2020R::makeDigi(CbmTrdRawMessageSpadic raw)
     time = time - fTimeshiftsParVec->at(padChNr);
     raw.SetTime(time);
   }
-  time -= fSystemTimeoffset;
+  time -= fSystemTimeOffset;
 
   // Set the time relative to the TS start
   time -= fTsStartTime;
diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackAlgoLegacy2020R.h b/reco/detectors/trd/unpack/CbmTrdUnpackAlgoLegacy2020R.h
index b17b1b1e15..5481db2dbe 100644
--- a/reco/detectors/trd/unpack/CbmTrdUnpackAlgoLegacy2020R.h
+++ b/reco/detectors/trd/unpack/CbmTrdUnpackAlgoLegacy2020R.h
@@ -24,8 +24,7 @@
 #include "CbmTrdSpadic.h"
 #include "CbmTrdUnpackAlgoBaseR.h"
 
-#include "Timeslice.hpp"             // timeslice
-#include <MicrosliceDescriptor.hpp>  // fles subsystemId
+#include "Timeslice.hpp"  // timeslice
 
 #include <FairTask.h>  // for InitStatus
 
diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackAlgoR.cxx b/reco/detectors/trd/unpack/CbmTrdUnpackAlgoR.cxx
index 87cafeb82a..d960a16b80 100644
--- a/reco/detectors/trd/unpack/CbmTrdUnpackAlgoR.cxx
+++ b/reco/detectors/trd/unpack/CbmTrdUnpackAlgoR.cxx
@@ -288,7 +288,7 @@ void CbmTrdUnpackAlgoR::makeDigi(CbmTrdRawMessageSpadic raw)
 
   // Get the time information and apply the necessary correction
   ULong64_t time = raw.GetTime();
-  time -= fSystemTimeoffset;
+  time -= fSystemTimeOffset;
 
   // Set the time relative to the TS start
   time -= fTsStartTime;
diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackAlgoR.h b/reco/detectors/trd/unpack/CbmTrdUnpackAlgoR.h
index 2806e91982..716e4eac30 100644
--- a/reco/detectors/trd/unpack/CbmTrdUnpackAlgoR.h
+++ b/reco/detectors/trd/unpack/CbmTrdUnpackAlgoR.h
@@ -22,8 +22,7 @@
 #include "CbmTrdRawMessageSpadic.h"
 #include "CbmTrdUnpackAlgoBaseR.h"
 
-#include <MicrosliceDescriptor.hpp>  // fles subsystemId
-#include <Timeslice.hpp>             // timeslice
+#include <Timeslice.hpp>  // timeslice
 
 #include <FairTask.h>  // for InitStatus
 
diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackConfig2D.h b/reco/detectors/trd/unpack/CbmTrdUnpackConfig2D.h
deleted file mode 100644
index f5a1137a0d..0000000000
--- a/reco/detectors/trd/unpack/CbmTrdUnpackConfig2D.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/* Copyright (C) 2010 - 2021 Goethe-University Frankfurt
-   SPDX-License-Identifier: GPL-3.0-only
-   Authors: Pascal Raisig */
-
-/**
- * @file CbmTrdUnpackConfig2D.h
- * @author Pascal Raisig (praisig@ikf.uni-frankfurt.de)
- * @brief Configuration class for an unpacker algorithm
- * @version 0.1
- * @date 2021-04-21
- * 
- * @copyright Copyright (c) 2021
- * 
- * This is the common configuration class for unpacking algorithms
- * 
-*/
-
-#ifndef CbmTrdUnpackConfig2D_H
-#define CbmTrdUnpackConfig2D_H
-
-
-#include "CbmRecoUnpackConfig.tmpl"
-#include "CbmTrdRawToDigiBaseR.h"
-#include "CbmTrdRawToDigiMaxAdcR.h"
-#include "CbmTrdUnpackAlgo2D.h"
-#include "CbmTrdUnpackMonitor.h"
-
-#include <FairLogger.h>
-#include <Logger.h>
-
-#include <Rtypes.h>
-#include <RtypesCore.h>
-
-#include <cstddef>
-#include <cstdint>
-#include <memory>
-#include <vector>
-
-class CbmTrdUnpackConfig2D : public CbmRecoUnpackConfig<CbmTrdUnpackAlgo2D, CbmTrdDigi> {
-
-public:
-  /**
-   * @brief Create the Cbm Trd Unpack Task object
-   * 
-   * @param geoSetupTag Geometry setup tag for the given detector as used by CbmSetup objects
-   * @param runid set if unpacker is rerun on a special run with special parameters
-   *@remark We use the string instead of CbmSetup here, to not having to link against sim/steer...
-  */
-  CbmTrdUnpackConfig2D(std::string detGeoSetupTag, UInt_t runid = 0);
-
-  /**
-   * @brief Destroy the Cbm Trd Unpack Task object
-   * 
-  */
-  virtual ~CbmTrdUnpackConfig2D();
-
-  /** @brief Copy constructor - not implemented **/
-  CbmTrdUnpackConfig2D(const CbmTrdUnpackConfig2D&) = delete;
-
-  /** @brief Assignment operator - not implemented **/
-  CbmTrdUnpackConfig2D& operator=(const CbmTrdUnpackConfig2D&) = delete;
-
-  // Getters
-  /** @brief Get the potentially added monitor. */
-  std::shared_ptr<CbmTrdUnpackMonitor> GetMonitor() { return fMonitor; }
-
-  /** @brief Get the spadic object attached to this config. @return CbmTrdSpadic */
-  std::shared_ptr<CbmTrdSpadic> GetSpadicObject() { return fSpadic; }
-
-  /**
-   * @brief Prepare the unpacker to be ready to run.
-   * In this function all initialization steps of the unpacker algorithms happen.
-  */
-  void InitUnpacker();
-
-  // Setters
-
-  /** @brief Add a monitor to the unpacker. @param value CbmTrdUnpackMonitor */
-  void SetMonitor(std::shared_ptr<CbmTrdUnpackMonitor> value) { fMonitor = value; }
-
-  /**
-   * @brief Set the raw to digi method
-   * 
-   * @param value 
-  */
-  void SetRawToDigiMethod(std::shared_ptr<CbmTrdRawToDigiBaseR> value) { fRTDMethod = value; }
-
-  /**
-   * @brief Set the Spadic Object
-   * 
-   * @param value 
-  */
-  void SetSpadicObject(std::shared_ptr<CbmTrdSpadic> value) { fSpadic = value; }
-
-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<CbmTrdUnpackAlgo2D> chooseAlgo();
-
-  /** @brief pointer to the raw msg to digi method */
-  std::shared_ptr<CbmTrdRawToDigiBaseR> fRTDMethod = std::make_shared<CbmTrdRawToDigiMaxAdcR>();
-
-  /** @brief Spadic software reprensentation object */
-  std::shared_ptr<CbmTrdSpadic> fSpadic = nullptr;
-
-  /** @brief pointer to the monitor object */
-  std::shared_ptr<CbmTrdUnpackMonitor> fMonitor = nullptr;
-
-  /** @brief Geometry setup tag for the given detector as used by CbmSetup objects */
-  std::string fGeoSetupTag = "";
-
-  /** @brief RunId of the current run, if not known 0 is a valid runtime case. Used runId based parameter loading. */
-  UInt_t fRunId = 0;
-
-private:
-  ClassDef(CbmTrdUnpackConfig2D, 2)
-};
-
-#endif  // CbmTrdUnpackConfig2D_H
diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackConfig2D.cxx b/reco/detectors/trd/unpack/CbmTrdUnpackConfigFasp2D.cxx
similarity index 63%
rename from reco/detectors/trd/unpack/CbmTrdUnpackConfig2D.cxx
rename to reco/detectors/trd/unpack/CbmTrdUnpackConfigFasp2D.cxx
index c66a9964ec..daa723b51b 100644
--- a/reco/detectors/trd/unpack/CbmTrdUnpackConfig2D.cxx
+++ b/reco/detectors/trd/unpack/CbmTrdUnpackConfigFasp2D.cxx
@@ -2,9 +2,9 @@
    SPDX-License-Identifier: GPL-3.0-only
    Authors: Pascal Raisig */
 
-#include "CbmTrdUnpackConfig2D.h"
+#include "CbmTrdUnpackConfigFasp2D.h"
 
-#include "CbmTrdUnpackAlgo2D.h"
+#include "CbmTrdUnpackAlgoFasp2D.h"
 
 #include <Logger.h>
 
@@ -14,17 +14,17 @@
 #include <memory>
 #include <vector>
 
-CbmTrdUnpackConfig2D::CbmTrdUnpackConfig2D(std::string detGeoSetupTag, UInt_t runid)
-  : CbmRecoUnpackConfig("CbmTrdUnpackConfig2D")
+CbmTrdUnpackConfigFasp2D::CbmTrdUnpackConfigFasp2D(std::string detGeoSetupTag, UInt_t runid)
+  : CbmRecoUnpackConfig("CbmTrdUnpackConfigFasp2D")
   , fGeoSetupTag(detGeoSetupTag)
   , fRunId(runid)
 {
 }
 
-CbmTrdUnpackConfig2D::~CbmTrdUnpackConfig2D() {}
+CbmTrdUnpackConfigFasp2D::~CbmTrdUnpackConfigFasp2D() {}
 
 // ---- Init ----
-void CbmTrdUnpackConfig2D::InitUnpacker()
+void CbmTrdUnpackConfigFasp2D::InitUnpacker()
 {
   LOG(info) << fName << "::Init -";
 
@@ -33,21 +33,9 @@ void CbmTrdUnpackConfig2D::InitUnpacker()
   // First choose the derived unpacking algorithm to be used and pass the raw to digi method
   auto algo = chooseAlgo();
 
-  // If we got a handmade spadic we pass it to the algorithm and the RTD method
-  if (fSpadic) {
-    algo->SetSpadicObject(fSpadic);
-    fRTDMethod->SetSpadicObject(fSpadic);
-  }
-
-  if (fDoLog) LOG(info) << fName << "::Init - SetRawToDigiMethod";
-  algo->SetRawToDigiMethod(fRTDMethod);
-
   if (fDoLog) LOG(info) << fName << "::Init - SetParFilesBasePath";
   algo->SetParFilesBasePath(fParFilesBasePath);
 
-  // If we have a monitor in the config add it to the algo
-  if (fMonitor) algo->SetMonitor(fMonitor);
-
   // Initialise the parameter containers required by the unpacker algo. Includes loading the corresponding ascii files
   auto reqparvec = algo->GetParContainerRequest(fGeoSetupTag, fRunId);
   initOk &= initParContainers(reqparvec);
@@ -60,13 +48,13 @@ void CbmTrdUnpackConfig2D::InitUnpacker()
 }
 
 // ---- chooseAlgo ----
-std::shared_ptr<CbmTrdUnpackAlgo2D> CbmTrdUnpackConfig2D::chooseAlgo()
+std::shared_ptr<CbmTrdUnpackAlgoFasp2D> CbmTrdUnpackConfigFasp2D::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<CbmTrdUnpackAlgo2D>();
+  auto algo = std::make_shared<CbmTrdUnpackAlgoFasp2D>();
   LOG(info) << fName << "::chooseAlgo() - selected algo = " << algo->Class_Name();
   return algo;
 
@@ -76,4 +64,4 @@ std::shared_ptr<CbmTrdUnpackAlgo2D> CbmTrdUnpackConfig2D::chooseAlgo()
 }
 
 
-ClassImp(CbmTrdUnpackConfig2D)
+ClassImp(CbmTrdUnpackConfigFasp2D)
diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackConfigFasp2D.h b/reco/detectors/trd/unpack/CbmTrdUnpackConfigFasp2D.h
new file mode 100644
index 0000000000..d636bc1601
--- /dev/null
+++ b/reco/detectors/trd/unpack/CbmTrdUnpackConfigFasp2D.h
@@ -0,0 +1,85 @@
+/* Copyright (C) 2010 - 2021 Goethe-University Frankfurt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Pascal Raisig */
+
+/**
+ * @file CbmTrdUnpackConfigFasp2D.h
+ * @author Pascal Raisig (praisig@ikf.uni-frankfurt.de)
+ * @brief Configuration class for an unpacker algorithm
+ * @version 0.1
+ * @date 2021-04-21
+ * 
+ * @copyright Copyright (c) 2021
+ * 
+ * This is the common configuration class for unpacking algorithms
+ * 
+*/
+
+#ifndef CbmTrdUnpackConfigFasp2D_H
+#define CbmTrdUnpackConfigFasp2D_H
+
+
+#include "CbmRecoUnpackConfig.tmpl"
+#include "CbmTrdDigi.h"
+#include "CbmTrdUnpackAlgoFasp2D.h"
+
+#include <FairLogger.h>
+#include <Logger.h>
+
+#include <Rtypes.h>
+#include <RtypesCore.h>
+
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+class CbmTrdUnpackConfigFasp2D : public CbmRecoUnpackConfig<CbmTrdUnpackAlgoFasp2D, CbmTrdDigi> {
+
+public:
+  /**
+   * @brief Create the Cbm Trd Unpack Task object
+   * 
+   * @param geoSetupTag Geometry setup tag for the given detector as used by CbmSetup objects
+   * @param runid set if unpacker is rerun on a special run with special parameters
+   *@remark We use the string instead of CbmSetup here, to not having to link against sim/steer...
+  */
+  CbmTrdUnpackConfigFasp2D(std::string detGeoSetupTag, UInt_t runid = 0);
+
+  /**
+   * @brief Destroy the Cbm Trd Unpack Task object
+   * 
+  */
+  virtual ~CbmTrdUnpackConfigFasp2D();
+
+  /** @brief Copy constructor - not implemented **/
+  CbmTrdUnpackConfigFasp2D(const CbmTrdUnpackConfigFasp2D&) = delete;
+
+  /** @brief Assignment operator - not implemented **/
+  CbmTrdUnpackConfigFasp2D& operator=(const CbmTrdUnpackConfigFasp2D&) = delete;
+
+  /**
+   * @brief Prepare the unpacker to be ready to run.
+   * In this function all initialization steps of the unpacker algorithms happen.
+  */
+  void InitUnpacker();
+
+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<CbmTrdUnpackAlgoFasp2D> chooseAlgo();
+
+  /** @brief Geometry setup tag for the given detector as used by CbmSetup objects */
+  std::string fGeoSetupTag = "";
+
+  /** @brief RunId of the current run, if not known 0 is a valid runtime case. Used runId based parameter loading. */
+  UInt_t fRunId = 0;
+
+private:
+  ClassDef(CbmTrdUnpackConfigFasp2D, 2)
+};
+
+#endif  // CbmTrdUnpackConfigFasp2D_H
diff --git a/reco/steer/CbmRecoUnpack.cxx b/reco/steer/CbmRecoUnpack.cxx
index d8dc446850..6e3aacf795 100644
--- a/reco/steer/CbmRecoUnpack.cxx
+++ b/reco/steer/CbmRecoUnpack.cxx
@@ -7,6 +7,7 @@
 
 #include "CbmRecoUnpack.h"
 
+#include "CbmTrdDigi.h"
 #include "CbmTsEventHeader.h"
 
 #include "MicrosliceDescriptor.hpp"
@@ -61,24 +62,23 @@ Bool_t CbmRecoUnpack::Init()
 
   // --- Psd
   if (fPsdConfig) fPsdConfig->Init(ioman);
-  if (fPsdConfig) fPsdConfig->InitUnpacker();
   // --- Rich
   if (fRichConfig) fRichConfig->Init(ioman);
-  if (fRichConfig) fRichConfig->InitUnpacker();
   // --- Sts
   if (fStsConfig) fStsConfig->Init(ioman);
-  if (fStsConfig) fStsConfig->InitUnpacker();
   // --- Tof
   // if (fTofConfig) fTofConfig->Init(ioman);
-  // if (fTofConfig) fTofConfig->InitUnpacker();
-
   // --- Trd
   if (fTrdConfig) fTrdConfig->Init(ioman);
-  if (fTrdConfig) fTrdConfig->InitUnpacker();
-
   // --- TRD2D
-  if (fTrdConfig2D) fTrdConfig2D->Init(ioman);
-  if (fTrdConfig2D) fTrdConfig2D->InitUnpacker();
+  if (fTrdConfig2D->GetOutputBranchName() == CbmTrdDigi::GetBranchName()) {
+    fTrdConfig2D->SetOutputVec(fTrdConfig->GetOutputVec());
+    if (fTrdConfig2D) fTrdConfig2D->InitUnpacker();
+  }
+  else {
+    if (fTrdConfig2D) fTrdConfig2D->Init(ioman, fTrdConfig2D->GetOutputBranchName());
+  }
+  // This is an ugly work around, because the TRD and TRD2D want to access the same vector and there is no function to retrieve a writeable vector<obj> from the FairRootManager, especially before the branches are created, as far as I am aware. The second option workaround is in in Init() to look for the fasp config and create a separate branch for fasp created CbmTrdDigis PR 072021
 
   return kTRUE;
 }
diff --git a/reco/steer/CbmRecoUnpack.h b/reco/steer/CbmRecoUnpack.h
index e3fe856897..062618127f 100644
--- a/reco/steer/CbmRecoUnpack.h
+++ b/reco/steer/CbmRecoUnpack.h
@@ -12,7 +12,7 @@
 #include "CbmRichUnpackConfig.h"
 #include "CbmStsUnpackConfig.h"
 #include "CbmTrdUnpackConfig.h"
-#include "CbmTrdUnpackConfig2D.h"
+#include "CbmTrdUnpackConfigFasp2D.h"
 #include "CbmTsEventHeader.h"
 
 #include <MicrosliceDescriptor.hpp>
@@ -86,7 +86,7 @@ public:
   void SetUnpackConfig(std::shared_ptr<CbmTrdUnpackConfig> config) { fTrdConfig = config; }
 
   /** @brief Set the Trd2D Unpack Config @param config */
-  void SetUnpackConfig(std::shared_ptr<CbmTrdUnpackConfig2D> config) { fTrdConfig2D = config; }
+  void SetUnpackConfig(std::shared_ptr<CbmTrdUnpackConfigFasp2D> config) { fTrdConfig2D = config; }
 
   /** @brief Trigger the unpacking procedure **/
   void Unpack(std::unique_ptr<fles::Timeslice> ts);
@@ -211,7 +211,7 @@ private:
   std::shared_ptr<CbmTrdUnpackConfig> fTrdConfig = nullptr;  //!
 
   /** @brief Configuration of the Trd unpacker. Provides the configured algorithm */
-  std::shared_ptr<CbmTrdUnpackConfig2D> fTrdConfig2D = nullptr;  //!
+  std::shared_ptr<CbmTrdUnpackConfigFasp2D> fTrdConfig2D = nullptr;  //!
 
   /** @brief Pointer to the Timeslice start time used to write it to the output tree @remark since we hand this to the FairRootManager it also wants to delete it and we do not have to take care of deletion */
   CbmTsEventHeader* fCbmTsEventHeader = nullptr;
-- 
GitLab