diff --git a/MQ/mcbm/CbmDeviceUnpack.cxx b/MQ/mcbm/CbmDeviceUnpack.cxx
index af97142bd5becb0c481c6686961c186199a375bf..7d0f5d5e671711220da68123928d04c06b008c45 100644
--- a/MQ/mcbm/CbmDeviceUnpack.cxx
+++ b/MQ/mcbm/CbmDeviceUnpack.cxx
@@ -20,7 +20,7 @@
 #include "CbmStsUnpackConfig.h"
 #include "CbmTofUnpackConfig.h"
 #include "CbmTrdUnpackConfig.h"
-#include "CbmTrdUnpackConfigFasp2D.h"
+#include "CbmTrdUnpackFaspConfig.h"
 
 #include "StorableTimeslice.hpp"
 #include "TimesliceMetaData.h"
@@ -211,9 +211,9 @@ Bool_t CbmDeviceUnpack::InitContainers()
   }  // if ("" != trdsetuptag)
   // -------------
   // ---- TRDFASP2D ----
-  std::shared_ptr<CbmTrdUnpackConfigFasp2D> trdfasp2dconfig = nullptr;
+  std::shared_ptr<CbmTrdUnpackFaspConfig> trdfasp2dconfig = nullptr;
   if ("" != trdsetuptag) {
-    trdfasp2dconfig = std::make_shared<CbmTrdUnpackConfigFasp2D>(trdsetuptag.Data(), 3);
+    trdfasp2dconfig = std::make_shared<CbmTrdUnpackFaspConfig>(trdsetuptag.Data(), 3);
     if (trdfasp2dconfig) {
       // trdfasp2dconfig->SetDebugState();
       trdfasp2dconfig->SetDoWriteOutput();
diff --git a/MQ/mcbm/CbmDeviceUnpack.h b/MQ/mcbm/CbmDeviceUnpack.h
index 24a17c916bfb5c20d82e7bf198526493a8d1494f..3b585a3ef5333fd1af079c7b02893c5365ba0a9a 100644
--- a/MQ/mcbm/CbmDeviceUnpack.h
+++ b/MQ/mcbm/CbmDeviceUnpack.h
@@ -32,7 +32,7 @@ class CbmPsdUnpackConfig;
 class CbmRichUnpackConfig;
 class CbmStsUnpackConfig;
 class CbmTofUnpackConfig;
-class CbmTrdUnpackConfigFasp2D;
+class CbmTrdUnpackFaspConfig;
 class CbmTrdUnpackConfig;
 
 class TimesliceMetaData;
@@ -59,7 +59,7 @@ protected:
   void SetUnpackConfig(std::shared_ptr<CbmTrdUnpackConfig> config) { fTrd1DConfig = config; }
 
   /** @brief Set the Trd2D Unpack Config @param config */
-  void SetUnpackConfig(std::shared_ptr<CbmTrdUnpackConfigFasp2D> config) { fTrd2DConfig = config; }
+  void SetUnpackConfig(std::shared_ptr<CbmTrdUnpackFaspConfig> config) { fTrd2DConfig = config; }
 
   /** @brief Set the Rich Unpack Config @param config */
   void SetUnpackConfig(std::shared_ptr<CbmRichUnpackConfig> config) { fRichConfig = config; }
@@ -128,7 +128,7 @@ private:
 
   /// Configuration of the unpackers. Provides the configured algorithm
   std::shared_ptr<CbmStsUnpackConfig> fStsConfig         = nullptr;
-  std::shared_ptr<CbmTrdUnpackConfigFasp2D> fTrd2DConfig = nullptr;
+  std::shared_ptr<CbmTrdUnpackFaspConfig> fTrd2DConfig   = nullptr;
   std::shared_ptr<CbmTrdUnpackConfig> fTrd1DConfig       = nullptr;
   std::shared_ptr<CbmTofUnpackConfig> fTofConfig         = nullptr;
   std::shared_ptr<CbmRichUnpackConfig> fRichConfig       = nullptr;
diff --git a/reco/detectors/trd/CMakeLists.txt b/reco/detectors/trd/CMakeLists.txt
index b822da9fc2d2038136a564d53c33ade66c12e10f..e9a9fc03226d6db00a4329d57e27d3a2e40c1b9b 100644
--- a/reco/detectors/trd/CMakeLists.txt
+++ b/reco/detectors/trd/CMakeLists.txt
@@ -61,8 +61,8 @@ unpack/CbmTrdUnpackAlgoR.cxx
 unpack/CbmTrdUnpackAlgoLegacy2020R.cxx
 unpack/CbmTrdUnpackMonitor.cxx
 
-unpack/CbmTrdUnpackAlgoFasp2D.cxx
-unpack/CbmTrdUnpackConfigFasp2D.cxx
+unpack/CbmTrdUnpackFaspAlgo.cxx
+unpack/CbmTrdUnpackFaspConfig.cxx
 
 qa/CbmTrdClusterizerFastQa.cxx
 qa/CbmTrdHitDensityQa.cxx
diff --git a/reco/detectors/trd/CbmTrdRecoLinkDef.h b/reco/detectors/trd/CbmTrdRecoLinkDef.h
index 31652af8623dff0188aa05a243abe8561eaf2606..1744870f32cd33be4a8e63df4d62d7dd721436f1 100644
--- a/reco/detectors/trd/CbmTrdRecoLinkDef.h
+++ b/reco/detectors/trd/CbmTrdRecoLinkDef.h
@@ -35,8 +35,8 @@
 #pragma link C++ class CbmTrdUnpackConfig + ;
 #pragma link C++ class CbmTrdUnpackMonitor + ;
 
-#pragma link C++ class CbmTrdUnpackAlgoFasp2D + ;
-#pragma link C++ class CbmTrdUnpackConfigFasp2D + ;
+#pragma link C++ class CbmTrdUnpackFaspAlgo + ;
+#pragma link C++ class CbmTrdUnpackFaspConfig + ;
 
 #pragma link C++ class CbmTrdElectronsTrainAnn + ;
 #pragma link C++ class CbmTrdSetTracksPidWkn + ;
diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.cxx b/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..33fe4a095dd7980ed55b4e633154db63030a6ef5
--- /dev/null
+++ b/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.cxx
@@ -0,0 +1,410 @@
+/* Copyright (C) 2021 Goethe-University Frankfurt, Frankfurt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Pascal Raisig [committer], Alexandru Bercuci */
+
+
+#include "CbmTrdUnpackFaspAlgo.h"
+
+#include "CbmTrdDigi.h"
+#include "CbmTrdParFasp.h"
+#include "CbmTrdParModDigi.h"
+#include "CbmTrdParSetDigi.h"
+#include "CbmTrdParSetGain.h"
+#include "CbmTrdParSetGas.h"
+#include "CbmTrdParSpadic.h"
+
+#include <FairParAsciiFileIo.h>
+#include <FairParGenericSet.h>
+#include <FairParamList.h>
+#include <FairRuntimeDb.h>
+#include <FairTask.h>
+#include <Logger.h>
+
+#include <Rtypes.h>
+#include <RtypesCore.h>
+
+#include <boost/format.hpp>
+
+#define VERBOSE 0
+
+using namespace std;
+
+CbmTrdUnpackFaspAlgo::CbmTrdUnpackFaspAlgo() : CbmRecoUnpackAlgo("CbmTrdUnpackFaspAlgo"), fModuleId(), fAsicPar()
+{
+  memset(fTime, 0, NCRI * sizeof(ULong64_t));
+}
+
+//_________________________________________________________________________________
+CbmTrdUnpackFaspAlgo::~CbmTrdUnpackFaspAlgo() {}
+
+//_________________________________________________________________________________
+Bool_t CbmTrdUnpackFaspAlgo::initParSet(FairParGenericSet* parset)
+{
+  FairParamList parList;
+  Int_t nModules(0);
+  if (strcmp(parset->ClassName(), "CbmTrdParSetAsic") == 0) {
+    CbmTrdParSetAsic* setPar = static_cast<CbmTrdParSetAsic*>(parset);
+    for (auto did : fModuleId) {
+      const CbmTrdParSetAsic* setDet = static_cast<const CbmTrdParSetAsic*>(setPar->GetModuleSet(did));
+      if (!setDet) continue;
+      if (setDet->GetAsicType() != Int_t(CbmTrdDigi::eCbmTrdAsicType::kFASP)) continue;
+      nModules++;
+      std::vector<Int_t> a;
+      setDet->GetAsicAddresses(&a);
+      for (auto add : a) {
+        CbmTrdParAsic* asic = (CbmTrdParAsic*) setDet->GetModulePar(add);
+        if (asic->IsA() == CbmTrdParSpadic::Class()) continue;
+        fAsicPar.addParam(asic);
+        if (VERBOSE) asic->Print();
+      }
+    }
+    //      setPar->printParams();
+    LOG(info) << GetName() << "::initParSet - for container " << parset->ClassName() << " modules " << nModules
+              << " asics " << fAsicPar.GetNrOfModules();
+  }
+  else if (strcmp(parset->ClassName(), "CbmTrdParSetDigi") == 0) {
+    fDigiSet                          = static_cast<CbmTrdParSetDigi*>(parset);
+    map<Int_t, CbmTrdParMod*> digiPar = fDigiSet->GetModuleMap();
+    for (auto digi : digiPar)
+      fModuleId.emplace_back(digi.first);
+    // setPar->printParams();
+    LOG(info) << GetName() << "::initParSet - for container " << parset->ClassName() << " modules " << fModuleId.size();
+  }
+  else if (strcmp(parset->ClassName(), "CbmTrdParSetGas") == 0) {
+    CbmTrdParSetGas* setPar = static_cast<CbmTrdParSetGas*>(parset);
+    setPar->printParams();
+    nModules = setPar->GetNrOfModules();
+  }
+  else if (strcmp(parset->ClassName(), "CbmTrdParSetGain") == 0) {
+    CbmTrdParSetGain* setPar = static_cast<CbmTrdParSetGain*>(parset);
+    setPar->printParams();
+    nModules = setPar->GetNrOfModules();
+  }
+  else {
+    LOG(error) << "Parameter set " << parset->ClassName() << " not known. Skip.";
+    return kFALSE;
+  }
+  return kTRUE;
+}
+
+//_________________________________________________________________________________
+std::vector<std::pair<std::string, std::shared_ptr<FairParGenericSet>>>*
+CbmTrdUnpackFaspAlgo::GetParContainerRequest(std::string geoTag, std::uint32_t runId)
+{
+  LOG(info) << GetName() << "::GetParContainerRequest - for container " << geoTag.data() << " run " << runId << "  "
+            << fParFilesBasePath.data();
+
+  // Basepath for default Trd parameter sets (those connected to a geoTag)
+  std::string basepath = Form("%s/trd_%s", fParFilesBasePath.data(), geoTag.data());
+  std::string temppath = "";
+
+  // Digest the runId information in case of runId = 0 we use the default fall back
+  std::string runpath = "";
+  if (runId != 0) { runpath = ".run" + std::to_string(runId); }
+
+  temppath = basepath + runpath + ".digi" + ".par";
+  fParContVec.emplace_back(std::make_pair(temppath, std::make_shared<CbmTrdParSetDigi>()));
+  temppath = basepath + runpath + ".asic" + ".par";
+  fParContVec.emplace_back(std::make_pair(temppath, std::make_shared<CbmTrdParSetAsic>()));
+  //   temppath = basepath + runpath + ".gas" + ".par";
+  //   fParContVec.emplace_back(std::make_pair(temppath, std::make_shared<CbmTrdParSetGas>()));
+  //   temppath = basepath + runpath + ".gain" + ".par";
+  //   fParContVec.emplace_back(std::make_pair(temppath, std::make_shared<CbmTrdParSetGain>()));
+
+  return &fParContVec;
+}
+
+//_________________________________________________________________________________
+void CbmTrdUnpackFaspAlgo::SetAsicMapping(const std::map<uint32_t, uint8_t[NFASPMOD]>& asicMap)
+{
+  if (!fFaspMap) fFaspMap = new std::map<uint32_t, uint8_t[NFASPMOD]>(asicMap);
+  else {
+    delete fFaspMap;
+    fFaspMap = new std::map<uint32_t, uint8_t[NFASPMOD]>(asicMap);
+  }
+}
+
+//_________________________________________________________________________________
+void CbmTrdUnpackFaspAlgo::PrintAsicMapping()
+{
+  if (!fFaspMap) {
+    LOG(info) << GetName() << "No asic mapping loaded.";
+    return;
+  }
+  LOG(info) << GetName() << "Fasp Asic mapping on modules:";
+  for (auto imod : (*fFaspMap)) {
+    printf("Mod [%6d] : ", imod.first);
+    for (int ifasp(0); ifasp < NFASPMOD; ifasp++) {
+      int jfasp = imod.second[ifasp];
+      printf("%2d ", (jfasp == 0xff ? -1 : jfasp));
+    }
+    printf("\n");
+  }
+}
+
+//_________________________________________________________________________________
+CbmTrdUnpackFaspAlgo::CbmTrdFaspMessageType CbmTrdUnpackFaspAlgo::mess_type(uint32_t wd)
+{
+  if ((wd >> kMessCh) & 0x1) return kData;
+  return kEpoch;
+}
+
+//_________________________________________________________________________________
+void CbmTrdUnpackFaspAlgo::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 CbmTrdUnpackFaspAlgo::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 CbmTrdUnpackFaspAlgo::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);
+}
+
+//_________________________________________________________________________________
+bool CbmTrdUnpackFaspAlgo::pushDigis(std::vector<CbmTrdUnpackFaspAlgo::CbmTrdFaspContent*> messes)
+{
+  UChar_t lFasp(0xff);
+  UShort_t lchR, lchT;
+  Double_t r, t;
+  Int_t dt, dtime, ch, pad, row;
+  ULong64_t tlab;
+  CbmTrdParFasp* faspPar(nullptr);
+  const CbmTrdParFaspChannel* chCalib(nullptr);
+  CbmTrdParModDigi* digiPar(nullptr);
+  vector<CbmTrdDigi*> digis;
+  for (auto imess : messes) {
+    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
+                   << " missing. Skip.";
+        return false;
+      }
+      if (!(digiPar = (CbmTrdParModDigi*) fDigiSet->GetModulePar(imess->cri))) {
+        LOG(error) << GetName() << "::pushDigis - DIGI par for module " << imess->cri << " missing. Skip.";
+        return false;
+      }
+      if (VERBOSE) faspPar->Print();
+      pad     = faspPar->GetChannelAddress(imess->ch);
+      chCalib = faspPar->GetChannel(imess->ch);
+      ch      = 2 * pad + chCalib->HasPairingR();
+      row     = digiPar->GetPadRow(pad);
+      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);
+
+    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);
+          use = true;
+          break;
+        }
+        else if (lchT && !int(t)) {
+          tlab = id->GetTimeDAQ();
+          id->SetCharge(lchT, r, +dtime);
+          id->SetTimeDAQ(ULong64_t(tlab - dtime));
+          use = true;
+          break;
+        }
+      }
+    }
+
+    if (!use) {
+      CbmTrdDigi* digi = new CbmTrdDigi(pad, lchT, lchR, imess->tlab);
+      digi->SetAddressModule(imess->cri);
+      digis.push_back(digi);
+    }
+    delete imess;
+  }
+
+  // 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.clear();
+
+  return true;
+}
+
+// ---- unpack ----
+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;
+
+  uint32_t mod_id = 5;
+  bool unpackOk   = true;
+  //Double_t fdMsSizeInNs = 1.28e6;
+
+  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));
+  // define time wrt start of time slice in TRD/FASP clks [80 MHz]
+  fTime[0] = ULong64_t((msdesc.idx - fTsStartTime - fSystemTimeOffset) / 12.5);
+
+  // 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);
+  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;
+    //     }
+    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;
+    // 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 (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_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 (fFaspMap) fasp_id = ((*fFaspMap)[mod_id])[fasp_id];
+
+      if (lFaspOld != fasp_id) {
+        // push
+        if (vDigi.size()) { pushDigis(vDigi); }
+        vDigi.clear();
+        lFaspOld = fasp_id;
+      }
+      if (data & 0x1) {
+        LOG(warn) << GetName() << "::unpack - Data corrupted : detect end bit set.";
+        continue;
+      }
+      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;
+      }
+      mess       = new CbmTrdFaspContent;
+      mess->ch   = ch_id;
+      mess->type = 1;
+      mess->tlab = slice;
+      mess->data = data >> 1;
+      mess->fasp = lFaspOld;
+      mess->cri  = mod_id;
+      vDigi.push_back(mess);
+    }
+    //prt_wd(*wd);
+  }
+  return unpackOk;
+}
+
+//_____________________________________________________________
+void CbmTrdUnpackFaspAlgo::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(CbmTrdUnpackFaspAlgo)
diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.h b/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.h
new file mode 100644
index 0000000000000000000000000000000000000000..64e9fd12615661418b3c993e627a5471776d7808
--- /dev/null
+++ b/reco/detectors/trd/unpack/CbmTrdUnpackFaspAlgo.h
@@ -0,0 +1,191 @@
+/* Copyright (C) 2021 Goethe-University Frankfurt, Frankfurt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Pascal Raisig [committer], Alexandru Bercuci */
+
+/**
+ * @file CbmTrdUnpackFaspAlgo.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 CbmTrdUnpackFaspAlgo_H
+#define CbmTrdUnpackFaspAlgo_H
+
+#include "CbmRecoUnpackAlgo.tmpl"
+#include "CbmTrdDigi.h"
+#include "CbmTrdParFasp.h"
+#include "CbmTrdParSetAsic.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 CbmTrdParSetDigi;
+class CbmTrdUnpackFaspAlgo : 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 */
+  CbmTrdUnpackFaspAlgo();
+
+  /** @brief Destroy the Cbm Trd Unpack Task object */
+  virtual ~CbmTrdUnpackFaspAlgo();
+
+  /** @brief Copy constructor - not implemented **/
+  CbmTrdUnpackFaspAlgo(const CbmTrdUnpackFaspAlgo&) = delete;
+
+  /** @brief Assignment operator - not implemented **/
+  CbmTrdUnpackFaspAlgo& operator=(const CbmTrdUnpackFaspAlgo&) = 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;
+  };
+
+  /**
+   * @brief Get the requested parameter containers.
+   * Return the required parameter containers together with the paths to the ascii 
+   * files to.
+   *  
+   * @param[in] std::string geoTag as used in CbmSetup
+   * @param[in] std::uint32_t runId for runwise defined parameters
+   * @return fParContVec
+  */
+  virtual std::vector<std::pair<std::string, std::shared_ptr<FairParGenericSet>>>*
+  GetParContainerRequest(std::string geoTag, std::uint32_t runId);
+
+  /**
+   * @brief Introduce fasp index mapping
+   */
+  void SetAsicMapping(const std::map<uint32_t, uint8_t[NFASPMOD]>& map);
+  void PrintAsicMapping();
+
+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::vector<CbmTrdUnpackFaspAlgo::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);
+
+  /**
+   * @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);
+  std::map<uint32_t, uint8_t[NFASPMOD]>* fFaspMap = nullptr;
+  std::vector<Int_t> fModuleId;
+  CbmTrdParSetAsic fAsicPar;
+  CbmTrdParSetDigi* fDigiSet = nullptr;
+
+  ClassDef(CbmTrdUnpackFaspAlgo, 2)  // unpack FASP read-out detectors
+};
+
+#endif  // CbmTrdUnpackFaspAlgo_H
diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackFaspConfig.cxx b/reco/detectors/trd/unpack/CbmTrdUnpackFaspConfig.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..6d071530e330e0f9bdd074c30f51826dd47eee4d
--- /dev/null
+++ b/reco/detectors/trd/unpack/CbmTrdUnpackFaspConfig.cxx
@@ -0,0 +1,50 @@
+/* Copyright (C) 2021 Goethe-University Frankfurt, Frankfurt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Pascal Raisig [committer], Alexandru Bercuci*/
+
+#include "CbmTrdUnpackFaspConfig.h"
+
+CbmTrdUnpackFaspConfig::CbmTrdUnpackFaspConfig(std::string detGeoSetupTag, UInt_t runid)
+  : CbmRecoUnpackConfig("CbmTrdUnpackFaspConfig", detGeoSetupTag, runid)
+  , fFaspMap()
+{
+}
+
+CbmTrdUnpackFaspConfig::~CbmTrdUnpackFaspConfig() {}
+
+// ---- Init ----
+
+// ---- chooseAlgo ----
+std::shared_ptr<CbmTrdUnpackFaspAlgo> CbmTrdUnpackFaspConfig::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<CbmTrdUnpackFaspAlgo>();
+  LOG(info) << fName << "::chooseAlgo() - selected algo = " << algo->Class_Name();
+  return algo;
+
+  LOG(error) << fName
+             << "::Init - chooseAlgo() - no algorithm created something went wrong. We can not work like this!";
+  return nullptr;
+}
+
+//_____________________________________________________________________
+void CbmTrdUnpackFaspConfig::InitAlgo()
+{
+  if (fDoLog) LOG(info) << fName << "::InitAlgo - SetFaspMapping";
+  fAlgo->SetAsicMapping(fFaspMap);
+  /*if (fDoLog) */ fAlgo->PrintAsicMapping();
+
+  // Now we have all information required to initialise the algorithm
+  fAlgo->Init();
+}
+
+//_____________________________________________________________________
+void CbmTrdUnpackFaspConfig::SetFaspMapping(int modAddress, uint8_t faspMap[NFASPMOD])
+{
+  memcpy(fFaspMap[modAddress], faspMap, NFASPMOD * sizeof(uint8_t));
+}
+
+ClassImp(CbmTrdUnpackFaspConfig)
diff --git a/reco/detectors/trd/unpack/CbmTrdUnpackFaspConfig.h b/reco/detectors/trd/unpack/CbmTrdUnpackFaspConfig.h
new file mode 100644
index 0000000000000000000000000000000000000000..013a5d6571fdb27f56ca8cebc8b857dbe1cd963f
--- /dev/null
+++ b/reco/detectors/trd/unpack/CbmTrdUnpackFaspConfig.h
@@ -0,0 +1,88 @@
+/* Copyright (C) 2021 Goethe-University Frankfurt, Frankfurt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Pascal Raisig [committer], Alexandru Bercuci*/
+
+/**
+ * @file CbmTrdUnpackFaspConfig.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 CbmTrdUnpackFaspConfig_H
+#define CbmTrdUnpackFaspConfig_H
+
+
+#include "CbmRecoUnpackConfig.tmpl"
+#include "CbmTrdDigi.h"
+#include "CbmTrdParFasp.h"
+#include "CbmTrdUnpackFaspAlgo.h"
+
+#include <FairLogger.h>
+#include <Logger.h>
+
+#include <Rtypes.h>
+#include <RtypesCore.h>
+
+#include <cstddef>
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <vector>
+
+class CbmTrdUnpackFaspConfig : public CbmRecoUnpackConfig<CbmTrdUnpackFaspAlgo, 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...
+  */
+  CbmTrdUnpackFaspConfig(std::string detGeoSetupTag, UInt_t runid = 0);
+
+  /**
+   * @brief Destroy the Cbm Trd Unpack Task object
+   *
+  */
+  virtual ~CbmTrdUnpackFaspConfig();
+
+  /** @brief Copy constructor - not implemented **/
+  CbmTrdUnpackFaspConfig(const CbmTrdUnpackFaspConfig&) = delete;
+
+  /** @brief Assignment operator - not implemented **/
+  CbmTrdUnpackFaspConfig& operator=(const CbmTrdUnpackFaspConfig&) = delete;
+
+  /**
+   * @brief Initialize the algorithm, include all calibration for Trd FASP.
+  */
+  void InitAlgo();
+
+  /** @brief define fasp mapping for each module
+   * @param modAddress module address according to geometry
+   * @param faspMap mapped ids of FASP ASICs for module
+   */
+  void SetFaspMapping(int modAddress, uint8_t faspMap[NFASPMOD]);
+
+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<CbmTrdUnpackFaspAlgo> chooseAlgo();
+
+private:
+  std::map<uint32_t, uint8_t[NFASPMOD]> fFaspMap;  ///> DAQ packing of FASP id
+
+  ClassDef(CbmTrdUnpackFaspConfig, 4)
+};
+
+#endif  // CbmTrdUnpackFaspConfig_H
diff --git a/reco/steer/CbmRecoUnpack.h b/reco/steer/CbmRecoUnpack.h
index 0ae07e425772233536a5dcdafbb38b45938b7bc7..0e9840c314c650672dabb70e3aeef52bda9f7abf 100644
--- a/reco/steer/CbmRecoUnpack.h
+++ b/reco/steer/CbmRecoUnpack.h
@@ -17,7 +17,7 @@
 #include "CbmStsUnpackConfig.h"
 #include "CbmTofUnpackConfig.h"
 #include "CbmTrdUnpackConfig.h"
-#include "CbmTrdUnpackConfigFasp2D.h"
+#include "CbmTrdUnpackFaspConfig.h"
 #include "CbmTsEventHeader.h"
 
 #include <MicrosliceDescriptor.hpp>
@@ -121,7 +121,7 @@ public:
   void SetUnpackConfig(std::shared_ptr<CbmTrdUnpackConfig> config) { fTrd1DConfig = config; }
 
   /** @brief Set the Trd2D Unpack Config @param config */
-  void SetUnpackConfig(std::shared_ptr<CbmTrdUnpackConfigFasp2D> config) { fTrd2DConfig = config; }
+  void SetUnpackConfig(std::shared_ptr<CbmTrdUnpackFaspConfig> config) { fTrd2DConfig = config; }
 
   /** @brief Trigger the unpacking procedure **/
   void Unpack(std::unique_ptr<fles::Timeslice> ts);
@@ -351,7 +351,7 @@ private:
   std::shared_ptr<CbmTrdUnpackConfig> fTrd1DConfig = nullptr;  //!
 
   /** @brief Configuration of the Trd unpacker. Provides the configured algorithm */
-  std::shared_ptr<CbmTrdUnpackConfigFasp2D> fTrd2DConfig = nullptr;  //!
+  std::shared_ptr<CbmTrdUnpackFaspConfig> fTrd2DConfig = 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;