diff --git a/algo/detectors/trd/ReadoutConfig.cxx b/algo/detectors/trd/ReadoutConfig.cxx
index 828665b6ff2e3ddf0d609db33404904c56f24873..4ffa48492d816efc8c8c6135610ae59eb1d28604 100644
--- a/algo/detectors/trd/ReadoutConfig.cxx
+++ b/algo/detectors/trd/ReadoutConfig.cxx
@@ -131,6 +131,28 @@ namespace cbm::algo::trd
   }
   // ------------------------------------------------------------------------------------
 
+  void ReadoutConfig::SetElinkTimeOffset(uint32_t criid, uint8_t elinkid, int32_t offsetNs)
+  {
+    // create vector for criid if not yet existing
+    if (fElinkTimeOffsetMap.find(criid) == fElinkTimeOffsetMap.end()) {
+      //vector has fixed size of 256 (max elinkid) and is initialized to 0
+      fElinkTimeOffsetMap.insert(std::make_pair(criid, std::vector<int32_t>(256, 0)));
+    }
+
+    fElinkTimeOffsetMap[criid][elinkid] = offsetNs;
+  }
+
+  int32_t ReadoutConfig::GetElinkTimeOffset(uint32_t criid, uint8_t elinkid)
+  {
+    auto it = fElinkTimeOffsetMap.find(criid);
+    if (it == fElinkTimeOffsetMap.end()) {
+      return 0;
+    }
+
+    const auto& elinks = it->second;
+    return elinks.at(elinkid);
+  }
+
 
   // -----   Print readout map   ------------------------------------------------
   std::string ReadoutConfig::PrintReadoutMap()
diff --git a/algo/detectors/trd/ReadoutConfig.h b/algo/detectors/trd/ReadoutConfig.h
index 42cec6d95adb009480019fd4e10bb3cdf0d91900..a20bc9d1ab4ddb8e98a5f2165e3b46df5758660c 100644
--- a/algo/detectors/trd/ReadoutConfig.h
+++ b/algo/detectors/trd/ReadoutConfig.h
@@ -68,6 +68,16 @@ namespace cbm::algo::trd
      */
     std::pair<int32_t, std::vector<uint32_t>> Map(uint16_t equipId, uint16_t crob, uint16_t elink);
 
+    /**
+     * @brief Register a time offeset to be substracted from the digis which come from a specific CRI
+    **/
+    void SetElinkTimeOffset(uint32_t criid, uint8_t elinkid, int32_t offsetNs);
+
+
+    /**
+     * @brief Get the time offeset to be substracted from the digis which come from a specific CRI
+    **/
+    int32_t GetElinkTimeOffset(uint32_t criid, uint8_t elinkid);
 
     /** @brief Debug output of readout map **/
     std::string PrintReadoutMap();
@@ -86,8 +96,14 @@ namespace cbm::algo::trd
     // --- Map index: (equipment, crob, elink, chan), map value: (channel address)
     std::map<uint16_t, std::vector<std::vector<std::vector<uint32_t>>>> fChannelMap = {};  //!
 
-    CBM_YAML_PROPERTIES(yaml::Property(&ReadoutConfig::fReadoutMap, "readoutMap", "TRD readout map", {}, YAML::Hex),
-                   yaml::Property(&ReadoutConfig::fChannelMap, "channelMap", "TRD channel map"));
+    /** @brief Map to store time offsets for each CRI&Elink combination */
+    std::map<uint32_t, std::vector<int32_t>> fElinkTimeOffsetMap;
+
+    CBM_YAML_PROPERTIES(
+      yaml::Property(&ReadoutConfig::fReadoutMap, "readoutMap", "TRD readout map", {}, YAML::Hex),
+      yaml::Property(&ReadoutConfig::fChannelMap, "channelMap", "TRD channel map"),
+      yaml::Property(&ReadoutConfig::fElinkTimeOffsetMap, "elinkTimeOffset", "TRD time offset per CRI&Elink combination")
+    );
   };
 
 }  // namespace cbm::algo::trd
diff --git a/algo/detectors/trd/Unpack.cxx b/algo/detectors/trd/Unpack.cxx
index f6e3bb135117ab02e2be457145e656335f8d3828..9a5fcdc1e58a7ccb3dc4ec5190a07e3bc81fb1d0 100644
--- a/algo/detectors/trd/Unpack.cxx
+++ b/algo/detectors/trd/Unpack.cxx
@@ -29,7 +29,7 @@ Unpack::Unpack(const ReadoutConfig& readout) : fReadout(readout)
         auto addresses        = fReadout.Map(equip, crob, elink);
         elinkPar.fAddress     = addresses.first;   // Asic address for this elink
         elinkPar.fChanAddress = addresses.second;  // Channel addresses for this elink
-        elinkPar.fTimeOffset  = SystemTimeOffset;
+        elinkPar.fTimeOffset  = SystemTimeOffset + fReadout.GetElinkTimeOffset(crob, elink);
         crobPar.fElinkParams.push_back(elinkPar);
       }
       par.fCrobParams.push_back(crobPar);
diff --git a/algo/global/ParFiles.cxx b/algo/global/ParFiles.cxx
index dc4b359db9b5d5be7a50b79c87d18abf91cc73d2..959ee5180157513374124e9facdcbe3836910690 100644
--- a/algo/global/ParFiles.cxx
+++ b/algo/global/ParFiles.cxx
@@ -64,8 +64,8 @@ ParFiles::ParFiles(uint32_t runId)
       tof.calibrate = "mcbm2024_05/TofCalibratePar.yaml";
       tof.hitfinder = "mcbm2024_05/TofHitfinderPar.yaml";
 
-      trd.readout     = "TrdReadoutSetup_mcbm2024.yaml";
-      trd.readout2d   = "TrdReadout2DSetup_mcbm2022.yaml";  // TODO: no new readout for TRD2D?
+      trd.readout     = "mcbm2024_05/TrdReadoutSetup.yaml";
+      trd.readout2d   = "mcbm2024_05/Trd2dReadoutSetup.yaml";
       trd.hitfinder   = "mcbm2024_05/TrdHitfinderPar.yaml";
       trd.hitfinder2d = "mcbm2024_05/TrdHitfinder2DPar.yaml";
 
diff --git a/external/InstallParameter.cmake b/external/InstallParameter.cmake
index 4ca65d3f18d1d36fdcb42ebb09a1a324b3d373d4..3bc364026971e738d7bb23ba307d38fe9b996619 100644
--- a/external/InstallParameter.cmake
+++ b/external/InstallParameter.cmake
@@ -1,4 +1,4 @@
-set(PARAMETER_VERSION e444a11048669f08b28894150b61d853f8987f7a) # 2024-05-09
+set(PARAMETER_VERSION 051bea5a7434ed876da39649f85187852e679a85) # 2024-05-11
 
 set(PARAMETER_SRC_URL "https://git.cbm.gsi.de/CbmSoft/cbmroot_parameter.git")
 
diff --git a/reco/steer/CbmOnlineParWrite.cxx b/reco/steer/CbmOnlineParWrite.cxx
index 29c33293334e37bce1fe8a35166a17b486b5df18..e41dcc9d0fef17cc031f60c4b8cb2b33a833c4c5 100644
--- a/reco/steer/CbmOnlineParWrite.cxx
+++ b/reco/steer/CbmOnlineParWrite.cxx
@@ -17,6 +17,9 @@
 #include "CbmTaskStsHitFinderParWrite.h"
 #include "CbmTaskTofClusterizerParWrite.h"
 #include "CbmTaskTrdHitFinderParWrite.h"
+#include "CbmTaskTrdUnpackParWrite.h"
+#include "CbmTrdParSetAsic.h"
+#include "CbmTrdParSetDigi.h"
 
 #include <FairParAsciiFileIo.h>
 #include <FairParRootFileIo.h>
@@ -51,22 +54,52 @@ void CbmOnlineParWrite::AddTrd()
 
   // ----- TRD digitisation parameters -------------------------------------
   TString geoTagTrd;
-  if (fSetup->IsActive(ECbmModuleId::kTrd)) {
-    if (fSetup->GetGeoTag(ECbmModuleId::kTrd, geoTagTrd)) {
-      TString paramFilesTrd(Form("%s/parameters/trd/trd_%s", fSrcDir.Data(), geoTagTrd.Data()));
-      std::vector<TString> paramFilesVecTrd = {"asic", "digi", "gas", "gain"};
-      for (auto parIt : paramFilesVecTrd) {
-        fParList->Add(new TObjString(Form("%s.%s.par", paramFilesTrd.Data(), parIt.Data())));
-      }
-    }
-    for (auto parFileVecIt : *fParList) {
-      std::cout << Form("TrdParams - %s - added to parameter file list", parFileVecIt->GetName()) << std::endl;
-    }
+  if (!fSetup->IsActive(ECbmModuleId::kTrd)) {
+    throw std::runtime_error{"TRD not enabled in current geometry!"};
+  }
+
+  if (!fSetup->GetGeoTag(ECbmModuleId::kTrd, geoTagTrd)) {
+    throw std::runtime_error{"Failed to get TRD geo tag from CbmSetup!"};
+  }
+
+  TString paramFilesTrd(Form("%s/parameters/trd/trd_%s", fSrcDir.Data(), geoTagTrd.Data()));
+  std::vector<TString> paramFilesVecTrd = {"asic", "digi", "gas", "gain"};
+  for (auto parIt : paramFilesVecTrd) {
+    fParList->Add(new TObjString(Form("%s.%s.par", paramFilesTrd.Data(), parIt.Data())));
+  }
+
+  for (auto parFileVecIt : *fParList) {
+    std::cout << Form("TrdParams - %s - added to parameter file list", parFileVecIt->GetName()) << std::endl;
   }
 
   // ----- TRD task ---------------------------------------------------------
-  auto* trdHitfinderPar = new CbmTaskTrdHitFinderParWrite();
+  auto* trdHitfinderPar = new CbmTaskTrdHitFinderParWrite{};
   fRun->AddTask(trdHitfinderPar);
+
+
+  // Initialize input files
+  FairParAsciiFileIo asciiInput;
+  std::string digiparfile = Form("%s/parameters/trd/trd_%s.digi.par", fSrcDir.Data(), geoTagTrd.Data());
+  std::string asicparfile = Form("%s/parameters/trd/trd_%s.asic.par", fSrcDir.Data(), geoTagTrd.Data());
+
+  // Read the .digi file and store result
+  auto* digiparset = new CbmTrdParSetDigi{};
+  if (asciiInput.open(digiparfile.data())) {
+    digiparset->init(&asciiInput);
+  }
+  asciiInput.close();
+
+  // Read the .asic file and store result
+  auto* asicparset = new CbmTrdParSetAsic{};
+  if (asciiInput.open(asicparfile.data())) {
+    asicparset->init(&asciiInput);
+  }
+  asciiInput.close();
+
+  // Unpack
+  CbmTaskTrdUnpackParWrite::Pars parFilesUnpack{.asic = asicparset, .digi = digiparset, .setup = fConfig.setupType};
+  auto* trdUnpackPar = new CbmTaskTrdUnpackParWrite{parFilesUnpack};
+  fRun->AddTask(trdUnpackPar);
 }
 
 // ===========================================================================
@@ -99,15 +132,18 @@ void CbmOnlineParWrite::AddTof()
   switch (fConfig.setupType) {
     case Setup::mCBM2022:
       doCalibration = true;
-      cCalId  = "2391.5.000";
-      iCalSet = 22002500;
+      cCalId        = "2391.5.000";
+      iCalSet       = 22002500;
       break;
     case Setup::mCBM2024_03:
       doCalibration = true;
-      cCalId  = "2912.1";
-      iCalSet = 012032500;
+      cCalId        = "2912.1";
+      iCalSet       = 012032500;
+      break;
+    case Setup::mCBM2024_05:
+      doCalibration = true;
+      cFname        = Form("%s/3036_1_TofCal.hst.root", TofFileFolder.Data());
       break;
-    case Setup::mCBM2024_05: doCalibration = false; break;
     default: throw std::runtime_error("TOF: Unknown setup type");
   }
 
@@ -141,6 +177,10 @@ void CbmOnlineParWrite::AddSts()
   // recoSts->SetTimeCutDigisAbs(20.0);     // cluster finder: time cut in ns
   // recoSts->SetTimeCutClustersAbs(20.0);  // hit finder: time cut in ns
 
+  TString geoTag;
+  fSetup->GetGeoTag(ECbmModuleId::kTof, geoTag);
+  LOG(info) << "STS geo tag: " << geoTag;
+
   // Sensor params
   CbmStsParSensor sensor6cm(CbmStsSensorClass::kDssdStereo);
   sensor6cm.SetPar(0, 6.2092);  // Extension in x
@@ -379,4 +419,7 @@ void CbmOnlineParWrite::Run(const Config& config)
   gGeoManager->GetListOfVolumes()->Delete();
   gGeoManager->GetListOfShapes()->Delete();
   delete gGeoManager;
+
+  // Delete files created by FairRun that I don't know how disable otherwise
+  gSystem->Exec("rm all_*.par");
 }
diff --git a/reco/tasks/CMakeLists.txt b/reco/tasks/CMakeLists.txt
index 394be81dfde62c6c028f16cd86cd4332a95c058a..e16f986287de76cc2da9a0681360e50c28b01171 100644
--- a/reco/tasks/CMakeLists.txt
+++ b/reco/tasks/CMakeLists.txt
@@ -21,6 +21,7 @@ set(SRCS
   CbmTaskTofClusterizerParWrite.cxx
   CbmTaskTrdHitFinder.cxx
   CbmTaskTrdHitFinderParWrite.cxx
+  CbmTaskTrdUnpackParWrite.cxx
   CbmTaskStsHitFinderParWrite.cxx
   CbmTaskUnpack.cxx
 )
diff --git a/reco/tasks/CbmTaskTrdUnpackParWrite.cxx b/reco/tasks/CbmTaskTrdUnpackParWrite.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..f4baf1a72bacc09fb95709c274abd5383923d7dc
--- /dev/null
+++ b/reco/tasks/CbmTaskTrdUnpackParWrite.cxx
@@ -0,0 +1,166 @@
+/* Copyright (C) 2024 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Felix Weiglhofer [committer] */
+
+#include "CbmTaskTrdUnpackParWrite.h"
+
+#include "CbmTrdParFasp.h"
+#include "CbmTrdParModAsic.h"
+#include "CbmTrdParModDigi.h"
+#include "CbmTrdParSetAsic.h"
+#include "CbmTrdParSetDigi.h"
+#include "CbmTrdParSpadic.h"
+#include "trd/ReadoutConfig.h"
+#include "trd2d/ReadoutConfig.h"
+#include "yaml/Yaml.h"
+
+#include <FairParamList.h>
+#include <fairlogger/Logger.h>
+
+#include <fstream>
+
+using namespace cbm::algo;
+
+InitStatus CbmTaskTrdUnpackParWrite::Init()
+{
+
+  assert(fPars.digi != nullptr);
+  auto& digiparset = *fPars.digi;
+
+  assert(fPars.asic != nullptr);
+  auto& asicparset = *fPars.asic;
+
+
+  // TRD2D ===================================================================
+  {
+    // Output object
+    cbm::algo::trd2d::ReadoutConfig trd2dConfig;
+
+    // Map (moduleId) -> (array of crobId)
+    std::map<uint32_t, uint16_t[NCROBMOD]> crobMap;
+    // Map (equipId, asicId, chanId) -> (pad address, mask flag, daq offset [FASP clk])
+    std::map<size_t, std::map<size_t, std::map<size_t, std::tuple<int32_t, bool, uint64_t>>>> channelMap;
+
+    // Loop through a list of module IDs from the .digi file (can in principle contradict crob_map).
+    for (auto entry : digiparset.GetModuleMap()) {
+
+      const auto moduleId = entry.first;
+
+      // Get ASIC parameters for this module
+      CbmTrdParModAsic* setDet = static_cast<CbmTrdParModAsic*>(asicparset.GetModulePar(moduleId));
+      if (!setDet) continue;
+      if (setDet->GetAsicType() != CbmTrdDigi::eCbmTrdAsicType::kFASP) continue;
+      auto digipar = entry.second;
+
+      const int* crobs = setDet->GetCrobAddresses();
+      for (int icrob(0); icrob < NCROBMOD; icrob++)
+        crobMap[moduleId][icrob] = crobs[icrob];
+
+      // Loop through ASICs for this module
+      std::vector<int32_t> addresses;
+      setDet->GetAsicAddresses(&addresses);
+      for (auto add : addresses) {
+        //Get local IDs for this component / equipment.
+        const int32_t fasp_in_mod = add - 1000 * moduleId;
+        const int32_t fasp_in_eq  = fasp_in_mod % (NFASPCROB);
+        const int32_t crob_in_mod = fasp_in_mod / (NFASPCROB);
+        const uint16_t eq_id      = crobMap[moduleId][crob_in_mod];
+
+        // ASIC parameter set
+        CbmTrdParFasp* fasppar = (CbmTrdParFasp*) setDet->GetAsicPar(add);
+
+        // Loop through channels for this ASIC and fill map
+        for (int chan = 0; chan < fasppar->GetNchannels(); chan++) {
+          const CbmTrdParFaspChannel* faspch = fasppar->GetChannel(chan);
+          const int32_t pad                  = fasppar->GetPadAddress(chan) * (faspch->HasPairingR() ? 1 : -1);
+          const bool isMasked                = faspch->IsMasked();
+          uint64_t daq_offset                = 0;
+          if (((CbmTrdParModDigi*) digipar)->GetPadRow(pad) % 2 == 0) daq_offset = 3;
+          channelMap[eq_id][fasp_in_eq][chan] = std::make_tuple(pad, isMasked, daq_offset);
+        }
+      }
+    }
+
+    trd2dConfig.InitComponentMap(crobMap);
+    trd2dConfig.InitChannelMap(channelMap);
+
+    std::ofstream("Trd2dReadoutSetup.yaml") << yaml::Dump{}(trd2dConfig);
+  }
+
+  // TRD1D ===================================================================
+  {
+    // Output object
+    cbm::algo::trd::ReadoutConfig trdConfig;
+
+    FairParamList parlist;
+    asicparset.putParams(&parlist);
+
+    std::vector<int> moduleIds(asicparset.GetNrOfModules());
+    parlist.fill("ModuleId", moduleIds.data(), moduleIds.size());
+
+    std::map<size_t, std::map<size_t, std::map<size_t, size_t>>> addressMap;  //[criId][crobId][elinkId] -> asicAddress
+    std::map<size_t, std::map<size_t, std::map<size_t, std::map<size_t, size_t>>>>
+      channelMap;  //[criId][crobId][elinkId][chanId] -> chanAddress
+
+    for (auto module : moduleIds) {
+      CbmTrdParModAsic* moduleSet = (CbmTrdParModAsic*) asicparset.GetModulePar(module);
+
+      // Skip entries for "Fasp" modules in .asic.par file
+      if (moduleSet->GetAsicType() != CbmTrdDigi::eCbmTrdAsicType::kSPADIC) continue;
+
+      std::vector<int> asicAddresses;
+      moduleSet->GetAsicAddresses(&asicAddresses);
+
+      for (auto address : asicAddresses) {
+        CbmTrdParSpadic* asicPar = (CbmTrdParSpadic*) moduleSet->GetAsicPar(address);
+        const uint16_t criId     = asicPar->GetCriId();
+        const uint8_t crobId     = asicPar->GetCrobId();
+        const uint8_t elinkId    = asicPar->GetElinkId(0);
+        if (elinkId >= 98) {
+          continue;
+        }  // Don't add not connected asics to the map
+        addressMap[criId][crobId][elinkId]     = address;
+        addressMap[criId][crobId][elinkId + 1] = address;
+
+        const uint8_t numChans = 16;
+        for (uint8_t chan = 0; chan < numChans; chan++) {
+          auto asicChannelId                       = (elinkId % 2) == 0 ? chan : chan + numChans;
+          auto chanAddr                            = asicPar->GetChannelAddresses().at(asicChannelId);
+          channelMap[criId][crobId][elinkId][chan] = chanAddr;
+        }
+        for (uint8_t chan = 0; chan < numChans; chan++) {
+          auto asicChannelId                           = (elinkId + 1 % 2) == 0 ? chan : chan + numChans;
+          auto chanAddr                                = asicPar->GetChannelAddresses().at(asicChannelId);
+          channelMap[criId][crobId][elinkId + 1][chan] = chanAddr;
+        }
+        LOG(debug) << "componentID " << asicPar->GetComponentId() << " "
+                   << "address " << address << " key " << criId << " " << unsigned(crobId) << " " << unsigned(elinkId);
+      }
+    }
+    trdConfig.Init(addressMap, channelMap);
+
+    // Apply time offset per elink
+    // See: https://git.cbm.gsi.de/computing/cbmroot/-/merge_requests/1751
+    if (fPars.setup == Setup::mCBM2024_05) {
+      for (int elinkId = 0; elinkId < 36; ++elinkId) {
+        trdConfig.SetElinkTimeOffset(20736, elinkId, -36);
+        trdConfig.SetElinkTimeOffset(20737, elinkId, -37);
+        trdConfig.SetElinkTimeOffset(20738, elinkId, -65);
+        trdConfig.SetElinkTimeOffset(20739, elinkId, -52);
+        trdConfig.SetElinkTimeOffset(20740, elinkId, -50);
+        trdConfig.SetElinkTimeOffset(20741, elinkId, -49);
+
+        //trdConfig.SetElinkTimeOffset(20992, elinkId, 0); //no correlation
+        trdConfig.SetElinkTimeOffset(20993, elinkId, -50);
+        trdConfig.SetElinkTimeOffset(20994, elinkId, -57);
+        trdConfig.SetElinkTimeOffset(20995, elinkId, -52);
+        trdConfig.SetElinkTimeOffset(20996, elinkId, -52);
+        trdConfig.SetElinkTimeOffset(20997, elinkId, -53);
+      }
+    }
+
+    std::ofstream("TrdReadoutSetup.yaml") << yaml::Dump{}(trdConfig);
+  }
+
+  return kSUCCESS;
+}
diff --git a/reco/tasks/CbmTaskTrdUnpackParWrite.h b/reco/tasks/CbmTaskTrdUnpackParWrite.h
new file mode 100644
index 0000000000000000000000000000000000000000..09203a69ff02e4882afc6ed9f0572f110d2059be
--- /dev/null
+++ b/reco/tasks/CbmTaskTrdUnpackParWrite.h
@@ -0,0 +1,45 @@
+/* Copyright (C) 2024 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Felix Weiglhofer [committer] */
+
+#pragma once
+
+#include "Definitions.h"
+
+#include <FairTask.h>
+
+class CbmTrdParSetAsic;
+class CbmTrdParSetDigi;
+
+class CbmTaskTrdUnpackParWrite : public FairTask {
+
+ public:
+  struct Pars {
+    CbmTrdParSetAsic* asic;  ///< parameter list for ASIC characterization
+    CbmTrdParSetDigi* digi;  ///< parameter list for read-out geometry
+    cbm::algo::Setup setup;  ///< Setup type
+  };
+
+  /**
+   * \brief Default constructor.
+   */
+  CbmTaskTrdUnpackParWrite(Pars pars) : fPars(pars) {}
+
+  /**
+   * \brief Default destructor.
+   */
+  virtual ~CbmTaskTrdUnpackParWrite(){};
+
+  /** Initialisation **/
+  virtual InitStatus Init();
+  virtual void SetParContainers(){};
+
+  /** \brief Executed task **/
+  virtual void Exec(Option_t* /*option*/){};
+
+  /** Finish task **/
+  virtual void Finish(){};
+
+ private:
+  Pars fPars;
+};