diff --git a/algo/detectors/trd2d/ReadoutConfig.cxx b/algo/detectors/trd2d/ReadoutConfig.cxx
index 3258171b02f4cf7e758adc311548a52ea4afd5d6..692988991454bed4ae6193b430d0a3707c45d94d 100644
--- a/algo/detectors/trd2d/ReadoutConfig.cxx
+++ b/algo/detectors/trd2d/ReadoutConfig.cxx
@@ -5,6 +5,7 @@
 #include "ReadoutConfig.h"
 
 //#include "CbmTrdAddress.h"
+#include "AlgoFairloggerCompat.h"
 
 #include <cassert>
 #include <iomanip>
@@ -51,6 +52,16 @@ namespace cbm::algo::trd2d
   }
   // ------------------------------------------------------------------------------------
 
+  // ---   List of ASICs registered to the ROB  ---------------------
+  std::vector<uint8_t> ReadoutConfig::GetAsicList(uint16_t equipmentId)
+  {
+    std::vector<uint8_t> result;
+    for (auto& entry : fChannelMap[equipmentId])
+      result.push_back(entry.first);
+    return result;
+  }
+  // ------------------------------------------------------------------------------------
+
 
   // ---   Number of Channels for a component / equipment, asic pair  ---------------------
   size_t ReadoutConfig::GetNumChans(uint16_t equipmentId, uint16_t asicId)
@@ -58,8 +69,10 @@ namespace cbm::algo::trd2d
     size_t result = 0;
     auto it       = fChannelMap.find(equipmentId);
     if (it != fChannelMap.end()) {
-      if (asicId < fChannelMap[equipmentId].size()) {
-        result = fChannelMap[equipmentId][asicId].size();
+      auto fiberMap = fChannelMap[equipmentId];
+      auto jt       = fiberMap.find(asicId);
+      if (jt != fiberMap.end()) {
+        result = fiberMap[asicId].size();
       }
     }
     return result;
@@ -67,16 +80,17 @@ namespace cbm::algo::trd2d
   // ------------------------------------------------------------------------------------
 
   // ---  Initialise the component mapping structure   ----------------------------------
-  void ReadoutConfig::InitComponentMap(const std::map<uint32_t, uint16_t[NCROBMOD]>& map)
+  void ReadoutConfig::InitComponentMap(const std::map<uint32_t, std::vector<uint16_t>>& map)
   {
     // Receive map (moduleId, crobId) -> (equipId)
     // Invert to obtain component map (equipId) -> (module iq, crob id)
     for (auto& entry : map) {
       uint16_t mod_id = entry.first;
-      for (uint8_t rob_id = 0; rob_id < NCROBMOD; rob_id++) {
-        uint16_t eq_id = entry.second[rob_id];
-        if (!eq_id) continue;
-        fReadoutMap[eq_id] = {mod_id, rob_id};
+      //for (uint8_t eq_id = 0; eq_id < NROBMOD * NELINKROB; eq_id++) {
+      uint8_t eq_id = 0;
+      for (const auto& eq_add : entry.second) {
+        //uint16_t eq_id = entry.second[elink_id];
+        fReadoutMap[eq_add] = {mod_id, eq_id++};
       }
     }
   }
@@ -90,12 +104,10 @@ namespace cbm::algo::trd2d
     for (auto compMap : channelMap) {
       uint16_t equipmentId = compMap.first;
       uint16_t numAsics    = compMap.second.size();
-      fChannelMap[equipmentId].resize(numAsics);
-
       for (auto asicMap : compMap.second) {
         uint16_t asicId   = asicMap.first;
         uint16_t numChans = asicMap.second.size();
-        fChannelMap[equipmentId][asicId].resize(numChans);
+        fChannelMap[equipmentId][asicId].resize(16);
         for (auto chanMap : asicMap.second) {
           uint16_t chanId                              = chanMap.first;
           std::tuple<int32_t, bool, uint64_t> chanPars = chanMap.second;
@@ -109,14 +121,17 @@ namespace cbm::algo::trd2d
 
 
   // ---  Mapping (equimentId, asicId, channel) -> (pad address, mask flag, daq offset)  -----
-  ReadoutConfig::ChanMapping ReadoutConfig::ChanMap(uint16_t equipId, uint16_t asic, uint16_t chan)
+  ReadoutConfig::ChanMapping ReadoutConfig::ChanMap(uint16_t equipId, uint16_t asicId, uint16_t chanId)
   {
     ChanMapping result = {-1, false, 0};
     auto it            = fChannelMap.find(equipId);
     if (it != fChannelMap.end()) {
-      if (asic < fChannelMap[equipId].size()) {
-        if (chan < fChannelMap[equipId][asic].size()) {
-          result = fChannelMap[equipId][asic][chan];
+      auto fiberMap = fChannelMap[equipId];
+      auto jt       = fiberMap.find(asicId);
+      if (jt != fiberMap.end()) {
+        auto asic = fiberMap[asicId];
+        if (chanId < asic.size()) {
+          result = asic[chanId];
         }
       }
     }
@@ -146,27 +161,33 @@ namespace cbm::algo::trd2d
       uint16_t equipmentId = comp.first;
       auto value           = comp.second;
       uint16_t moduleId    = value.moduleId;
-      uint16_t robId       = value.robId;
-      ss << "Equipment " << equipmentId << " Module " << moduleId << " Rob " << robId << "\n";
+      uint16_t fiberId     = value.fiberId;
+      ss << "Equipment 0x" << std::hex << (int) equipmentId << " Module " << moduleId << " fiberId " << fiberId << "\n";
     }
     ss << "\n";
 
     for (auto asicMap : fChannelMap) {
       uint16_t equipmentId = asicMap.first;
       uint16_t numAsics    = asicMap.second.size();
-      ss << "\n Equipment " << equipmentId << " nAsics " << numAsics;
-      for (size_t asicId = 0; asicId < numAsics; asicId++) {
-
-        uint16_t numChans = asicMap.second.at(asicId).size();
-        ss << "\n Equipment " << equipmentId << " AsicId " << asicId << " nChans " << numChans;
+      ss << "\n Equipment 0x" << std::hex << (int) equipmentId << " nAsics " << numAsics;
+
+      int asicCnt(0);
+      auto asics = asicMap.second;
+      for (auto asic : asics) {
+        int asicId        = asic.first;
+        auto asicChs      = asic.second;
+        uint16_t numChans = asicChs.size();
+        ss << "\n    " << asicCnt << " AsicId " << asicId << " nChans " << numChans;
         for (size_t chanId = 0; chanId < numChans; chanId++) {
-          auto entry         = asicMap.second.at(asicId).at(chanId);
-          int32_t address    = entry.padAddress;
-          bool isMasked      = entry.rPairingFlag;
-          uint64_t daqOffset = entry.daqOffset;
-          ss << "\n Equipment " << equipmentId << " AsicId " << asicId << " chanID " << chanId << " pad address "
-             << address << " mask " << isMasked << " daq offset " << daqOffset;
+          auto entry      = asicChs.at(chanId);
+          int32_t address = entry.padAddress;
+          bool isMasked   = entry.maskFlag;
+          uint8_t tOffset = entry.tOffset;
+          uint16_t thres  = entry.lThreshold;
+          ss << "\n      chanID " << chanId << " {pad " << address << " mask " << isMasked << " time offset[clk] "
+             << (int) tOffset << " threshold[" << (thres > 0 ? "on" : "off") << "]}";
         }
+        asicCnt++;
       }
     }
     ss << "\n";
diff --git a/algo/detectors/trd2d/ReadoutConfig.h b/algo/detectors/trd2d/ReadoutConfig.h
index 4631e1c0a5b0f499df7223dd2aa15c683780b19d..a4b189c8f9d35a6f12ea07b3737e02bad9f102c6 100644
--- a/algo/detectors/trd2d/ReadoutConfig.h
+++ b/algo/detectors/trd2d/ReadoutConfig.h
@@ -34,22 +34,25 @@ namespace cbm::algo::trd2d
    public:
     struct CompMapping {
       uint16_t moduleId;
-      uint8_t robId;
+      uint8_t fiberId;
 
       CBM_YAML_FORMAT(YAML::Flow);
       CBM_YAML_PROPERTIES(yaml::Property(&CompMapping::moduleId, "moduleId", "Module ID"),
-                     yaml::Property(&CompMapping::robId, "crobId", "CROB ID"));
+                     yaml::Property(&CompMapping::fiberId, "fiberId", "Optical Fibre ID"));
     };
 
     struct ChanMapping {
-      int32_t padAddress;
-      bool rPairingFlag;
-      uint64_t daqOffset;
+      int32_t padAddress;   /// map pad and pairing to FASP channel
+      bool maskFlag;        /// HW mask flag for channel
+      uint8_t tOffset;      /// time correction in clk
+      uint16_t lThreshold;  /// SW threshold for ringing channels
 
       CBM_YAML_FORMAT(YAML::Flow);
-      CBM_YAML_PROPERTIES(yaml::Property(&ChanMapping::padAddress, "padAddress", "Pad address"),
-                     yaml::Property(&ChanMapping::rPairingFlag, "rPairingFlag", "R pairing flag"),
-                     yaml::Property(&ChanMapping::daqOffset, "daqOffset", "DAQ offset"));
+      CBM_YAML_PROPERTIES(
+        yaml::Property(&ChanMapping::padAddress, "address", "Pad address"),
+        yaml::Property(&ChanMapping::maskFlag, "mask", "Channel masking flag"),
+        yaml::Property(&ChanMapping::tOffset, "toff", "Channel wise time offset"),
+        yaml::Property(&ChanMapping::lThreshold, "thres", "SW masking by threshold"));
     };
 
     /** @brief Constructor **/
@@ -73,6 +76,13 @@ namespace cbm::algo::trd2d
     size_t GetNumAsics(uint16_t equipmentId);
 
 
+    /** @brief Number of ASICS of a component
+     ** @param Equipment ID
+     ** @return List of ASICS linked to the curent ROB
+     **/
+    std::vector<uint8_t> GetAsicList(uint16_t equipmentId);
+
+
     /** @brief Number of channels of a component - ASIC pair
      ** @param Equipment ID
      ** @param ASIC ID
@@ -102,7 +112,7 @@ namespace cbm::algo::trd2d
     std::string PrintReadoutMap();
 
     /** @brief Initialisation of readout map **/
-    void InitComponentMap(const std::map<uint32_t, uint16_t[NCROBMOD]>& crob_map);
+    void InitComponentMap(const std::map<uint32_t, std::vector<uint16_t>>& map);
 
     /** @brief Initialisation of channel map **/
     void InitChannelMap(
@@ -124,14 +134,14 @@ namespace cbm::algo::trd2d
 
     // --- TRD2D channel map
     // --- Map index: (equipment, asic, chan), map value: (pad address, mask flag, daq offset)
-    std::map<uint16_t, std::vector<std::vector<ChanMapping>>> fChannelMap = {};  //!
-
-    CBM_YAML_PROPERTIES(yaml::Property(&ReadoutConfig::fSystemTimeOffset, "timeOffset", "System time offset for TRD2D"),
-		    yaml::Property(&ReadoutConfig::fReadoutMap, "readoutMap", "Maps equipment to module and CROB ID",
-                                    YAML::Hex),
-                   yaml::Property(&ReadoutConfig::fChannelMap, "channelMap",
-                                    "Maps equipment, ASIC and channel to pad address, R pairing flag and DAQ offset",
-                                    {}, YAML::Hex));
+    std::map<uint16_t, std::map<uint8_t, std::vector<ChanMapping>>> fChannelMap = {};  //!
+
+    CBM_YAML_PROPERTIES(
+      yaml::Property(&ReadoutConfig::fSystemTimeOffset, "timeOffset", "System time offset for TRD2D"),
+      yaml::Property(&ReadoutConfig::fReadoutMap, "readoutMap", "Maps equipment to module and Optical fibre Id", YAML::Hex),
+      yaml::Property(&ReadoutConfig::fChannelMap, "channelMap",
+                                    "Maps equipment, ASIC and channel to pad address, mask flag and DAQ offset",
+                                    YAML::Hex));
   };
 
 }  // namespace cbm::algo::trd2d
diff --git a/algo/detectors/trd2d/Unpack.cxx b/algo/detectors/trd2d/Unpack.cxx
index c8a1ee803427197cb628b478b6e965ce7a2a51bd..f42c1851484cf6ce8822d42d2ab7ed72dcb7aaba 100644
--- a/algo/detectors/trd2d/Unpack.cxx
+++ b/algo/detectors/trd2d/Unpack.cxx
@@ -17,8 +17,7 @@ Unpack::Unpack(const ReadoutConfig& readout) : fReadout(readout)
  * eMessageVersion::kMessLegacy - refers to the version WITH digi buffering
  * eMessageVersion::kMess24     - refers to the version WITHOUT digi buffering
  */
-  constexpr std::array<u8, int(eMessageVersion::kMessNoDef)> AlgoVersion = {(u8) eMessageVersion::kMessLegacy,
-                                                                            (u8) eMessageVersion::kMess24};
+  constexpr std::array<u8, 2> AlgoVersion = {(u8) eMessageVersion::kMessLegacy, (u8) eMessageVersion::kMess24};
 
   // Create one algorithm per component for TRD and configure it with parameters
   auto equipIdsTrd2d = fReadout.GetEquipmentIds();
@@ -27,42 +26,53 @@ Unpack::Unpack(const ReadoutConfig& readout) : fReadout(readout)
     trd2d::UnpackPar par{};
     const size_t numAsics = fReadout.GetNumAsics(equip);
 
-    for (size_t asic = 0; asic < numAsics; asic++) {
+    auto asics = fReadout.GetAsicList(equip);
+    for (auto asic : asics) {
       trd2d::UnpackAsicPar asicPar;
       const size_t numChans = fReadout.GetNumChans(equip, asic);
 
       for (size_t chan = 0; chan < numChans; chan++) {
         trd2d::UnpackChannelPar chanPar;
-        auto pars           = fReadout.ChanMap(equip, asic, chan);
-        chanPar.fPadAddress = pars.padAddress;    // Pad address for channel
-        chanPar.fMask       = pars.rPairingFlag;  // Flag channel mask
-        chanPar.fDaqOffset  = pars.daqOffset;     // Time calibration parameter
+        auto pars            = fReadout.ChanMap(equip, asic, chan);
+        chanPar.fPadAddress  = pars.padAddress;  // Pad address for channel
+        chanPar.fMask        = pars.maskFlag;    // Flag channel mask
+        chanPar.fDaqOffset   = pars.tOffset;     // Time calibration parameter
+        chanPar.fSignalThres = pars.lThreshold;  // Threshold cut
         asicPar.fChanParams.push_back(chanPar);
       }
+      L_(debug) << "--- Configured asic " << (int) asic << " with " << numChans << " channels";
       auto comppars         = fReadout.CompMap(equip);
       par.fSystemTimeOffset = fReadout.GetSystemTimeOffset();
       par.fModId            = comppars.moduleId;
-      par.fRobId            = comppars.robId;
-      par.fAsicParams.push_back(asicPar);
+      par.fEqAdd            = equip;
+      par.fEqId             = comppars.fiberId;
+      par.fAsicParams[asic] = asicPar;
     }
+    L_(debug) << "--- Configured equipment 0x" << std::hex << (int) equip << " with " << std::dec << numAsics
+              << " asics";
+
     // build all algorithms defined for data unpacking ! Why ?? (AB 25.01.15)
     std::unique_ptr<UnpackMSBase<CbmTrdDigi, UnpackMonitorData, UnpackAuxData>> algo;
     for (auto ver : AlgoVersion) {
       switch (ver) {
         case (int) eMessageVersion::kMessLegacy:
-          algo = std::make_unique<UnpackMS<(u8) eMessageVersion::kMessLegacy>>(par);
+          algo = std::make_unique<UnpackMS<(u8) eMessageVersion::kMessLegacy>>(std::move(par));
           break;
         case (int) eMessageVersion::kMess24:
-          algo = std::make_unique<UnpackMS<(u8) eMessageVersion::kMess24>>(par);
+          algo = std::make_unique<UnpackMS<(u8) eMessageVersion::kMess24>>(std::move(par));
           break;
       }
       // register algorithm
+      L_(debug) << "Register algo for ver=" << (int) ver << " eqId=0x" << std::hex << (int) equip;
       fAlgos[{equip, ver}] = std::move(algo);
     }
-
-    L_(debug) << "--- Configured equipment " << equip << " with " << numAsics << " asics";
   }
   L_(info) << "--- Configured " << fAlgos.size() << " unpacker algorithms for TRD2D.";
+  //   for (const auto& [key, algo] : fAlgos) {
+  //     L_(info) << "eq=0x" << std::hex << key.eqId << " ver=" << int(key.sysVer);
+  //     if (key.sysVer ==2 ) continue;
+  //     (dynamic_cast<const UnpackMS<3>&>(*algo)).DumpParameters();
+  //   }
 }
 
 Unpack::Result_t Unpack::operator()(const fles::Timeslice& ts) const { return DoUnpack(Subsystem::TRD2D, ts); }
diff --git a/algo/detectors/trd2d/UnpackMS.cxx b/algo/detectors/trd2d/UnpackMS.cxx
index 9bdf5b40d394b0e801152652af6b3fdfe51900db..1c0e77249c18b94780513a75dcadaa21e16318a6 100644
--- a/algo/detectors/trd2d/UnpackMS.cxx
+++ b/algo/detectors/trd2d/UnpackMS.cxx
@@ -8,6 +8,8 @@
 
 #include <algorithm>
 #include <cassert>
+#include <iomanip>
+#include <iostream>
 #include <sstream>
 #include <vector>
 
@@ -16,13 +18,11 @@ using std::unique_ptr;
 namespace cbm::algo::trd2d
 {
   // ----   Fasp message constructor  ----------------------------------------
-  FaspMessage::FaspMessage(uint8_t c, uint8_t typ, uint8_t t, uint16_t d, uint8_t r, uint8_t asic, uint8_t e)
+  FaspMessage::FaspMessage(uint8_t c, uint8_t typ, uint8_t t, uint16_t d, uint8_t asic)
     : ch(c)
     , type(eMessageType::kNone)
     , tlab(t)
     , data(d)
-    , rob(r)
-    , elink(e)
     , fasp(asic)
   {
     if (typ == uint8_t(eMessageType::kData))
@@ -36,12 +36,10 @@ namespace cbm::algo::trd2d
     std::stringstream ss;
     switch (type) {
       case eMessageType::kData:
-        ss << "    DATA : rob=" << rob << (elink ? 'u' : 'd') << " fasp_id=" << fasp << " [" << getFaspIdMod()
-           << "] ch_id=" << ch << " tclk=" << tlab << " data=" << data << std::endl;
-        break;
-      case eMessageType::kEpoch:
-        ss << "    EPOCH: eq_id=" << rob << (elink ? 'u' : 'd') << " ch_id=" << ch << " epoch=" << epoch << std::endl;
+        ss << "    DATA : fasp=" << std::setw(2) << (int) fasp << " ch=" << std::setw(2) << (int) ch
+           << " t=" << std::setw(3) << (int) tlab << " data=" << std::setw(4) << (int) data << std::endl;
         break;
+      case eMessageType::kEpoch: ss << "    EPOCH: ch=" << (int) ch << " epoch=" << (int) epoch << std::endl; break;
       default: ss << "    MTYPE: unknown" << std::endl; break;
     }
 
@@ -135,6 +133,40 @@ namespace cbm::algo::trd2d
     return;
   }
 
+  void UnpackPar::dump() const
+  {
+    L_(debug) << "UnpackPar::dump()";
+    L_(debug) << "mod=" << fModId << " elink[" << (int) fEqId << "]=0x" << std::hex << (int) fEqAdd
+              << " nAsics=" << std::dec << fAsicParams.size();
+    for (const auto& [fasp, par] : fAsicParams) {
+      L_(debug) << "  fasp=" << int(fasp) << " par=" << std::hex << &par;
+    }
+    L_(debug) << "UnpackPar::dump(-----------------------)";
+  }
+
+  template<>
+  uint8_t UnpackPar::mapFaspId2Mod<uint8_t(eMessageVersion::kMessLegacy)>(uint8_t fasp_id) const
+  {
+    /** Use the mapping 36 fasp -> 1 optical fiber (equipment id)
+   * Applies to FASPRO/FW v1 (e.g. mCBM22)
+   */
+    L_(debug) << "<vLegacy> Eq[" << (int) fEqId << "] = 0x" << std::hex << fEqAdd;
+    return fEqId * NFASPROB + fasp_id;
+  }
+
+  template<>
+  uint8_t UnpackPar::mapFaspId2Mod<uint8_t(eMessageVersion::kMess24)>(uint8_t fasp_id) const
+  {
+    /** Use the mapping 36 fasp -> 2 optical fiber (equipment id)
+   * Applies to FASPRO/FW v2 (e.g. mCBM25)
+   */
+
+    int rob = fEqId / 2;  // ROB on the current chamber
+    //L_(debug) << "<v24> ROB=" << rob << " Eq[" << (int)fEqId << "] = 0x" << std::hex << fEqAdd;
+
+    return rob * NFASPROB + fasp_id;
+  }
+
   // ----   Algorithm execution   ---------------------------------------------
   template<>
   typename UnpackMS<uint8_t(eMessageVersion::kMessLegacy)>::Result_t
@@ -157,7 +189,7 @@ namespace cbm::algo::trd2d
     uint64_t time = uint64_t((msDescr.idx - tTimeslice - fParams.fSystemTimeOffset) / 12.5);
 
     // Get parameters for current eq id.
-    const uint8_t crob_id = fParams.fRobId;
+    //const uint8_t crob_id = fParams.fEqId;
 
     // Get the number of complete words in the input MS buffer.
     const uint32_t nwords = msDescr.size / 4;
@@ -203,7 +235,7 @@ namespace cbm::algo::trd2d
         ctx.fMonitor.fNumSelfTriggeredData++;
         data &= 0x1fff;
       }
-      vMess.emplace_back(ch_id, (uint8_t) eMessageType::kData, slice, data >> 1, crob_id, lFaspOld);
+      vMess.emplace_back(ch_id, (uint8_t) eMessageType::kData, slice, data >> 1, lFaspOld);
     }
     std::get<0>(result) = FinalizeComponent(ctx);  //TO DO: Original (non-algo) version calls this after MS loop!!
     std::get<1>(result) = ctx.fMonitor;
@@ -214,8 +246,11 @@ namespace cbm::algo::trd2d
   template<uint8_t sys_ver>
   bool UnpackMS<sys_ver>::pushDigis(std::vector<FaspMessage> messes, const uint64_t time, MsContext& ctx) const
   {
+    constexpr uint8_t mLegacy =
+      uint8_t(eMessageVersion::kMessLegacy);  // message versions compatible with the current algo specialization
     const uint16_t mod_id        = fParams.fModId;
-    const UnpackAsicPar& asicPar = fParams.fAsicParams[messes[0].fasp];
+    const uint8_t fasp_mod_id    = fParams.mapFaspId2Mod<mLegacy>(messes[0].fasp);
+    const UnpackAsicPar& asicPar = fParams.fAsicParams.at(fasp_mod_id);
     const uint64_t tdaqOffset    = asicPar.fChanParams[messes[0].ch].fDaqOffset;
 
     for (auto imess : messes) {
@@ -334,6 +369,8 @@ namespace cbm::algo::trd2d
 
     // Get the number of complete words in the input MS buffer.
     const uint32_t nwords = msDescr.size / 4;
+    L_(debug) << "UnpackMS<kMess24>::op() param.elink[" << (int) fParams.fEqId << "]=0x" << std::hex
+              << (int) fParams.fEqAdd << " data.rob=0x" << int(msDescr.eq_id) << " words=" << std::dec << nwords;
 
     // We have 32 bit FASP frames in this readout version
     const uint32_t* wd = reinterpret_cast<const uint32_t*>(msContent);
@@ -349,7 +386,6 @@ namespace cbm::algo::trd2d
         case eMessageType::kEpoch: ctx.fMess.readEW<m24>(w); break;
         default: break;  // no way to reach this line
       }
-      ctx.fMess.rob = fParams.fRobId;
 
       // PROCESS EPOCH MESSAGES
       if (ctx.fMess.type == eMessageType::kEpoch) {
@@ -377,10 +413,6 @@ namespace cbm::algo::trd2d
         vMess.clear();
         lFaspOld = ctx.fMess.fasp;
       }
-      if (ctx.fMess.data & 0x1) {  // kept for backward compatibility TODO
-        ctx.fMonitor.fNumErrEndBitSet++;
-        continue;
-      }
       if (ctx.fMess.data & 0x2000) {  // kept for backward compatibility TODO
         ctx.fMonitor.fNumSelfTriggeredData++;
         ctx.fMess.data &= 0x1fff;
@@ -390,10 +422,12 @@ namespace cbm::algo::trd2d
 
     // combine all digis from this ROB
     std::vector<CbmTrdDigi> outputDigis;
-    for (uint16_t ipad(0); ipad < NFASPMOD * NFASPCH; ipad++) {
+    for (uint16_t ipad(0); ipad < NFASPMOD * NFASPPAD; ipad++) {
       if (!ctx.fRobDigi[ipad].size()) continue;
-      for (auto id : ctx.fRobDigi[ipad])
+      for (auto id : ctx.fRobDigi[ipad]) {
+        L_(debug) << id.ToString();
         outputDigis.emplace_back(std::move(id));
+      }
     }
     std::get<0>(result) = outputDigis;
     std::get<1>(result) = ctx.fMonitor;
@@ -403,14 +437,18 @@ namespace cbm::algo::trd2d
   bool UnpackMS<uint8_t(eMessageVersion::kMess24)>::pushDigis(std::vector<FaspMessage> messes, const uint64_t time,
                                                               MsContext& ctx) const
   {
-    const uint16_t mod_id        = fParams.fModId;
-    const UnpackAsicPar& asicPar = fParams.fAsicParams[messes[0].fasp];
-    const uint64_t tdaqOffset    = asicPar.fChanParams[messes[0].ch].fDaqOffset;
+    constexpr uint8_t m24 =
+      uint8_t(eMessageVersion::kMess24);  // message versions compatible with the current algo specialization
+    const uint8_t fasp_mod_id    = fParams.mapFaspId2Mod<m24>(messes[0].fasp);
+    const UnpackAsicPar& asicPar = fParams.fAsicParams.at(fasp_mod_id);
 
     for (auto imess : messes) {
-      const int32_t pad                   = std::abs(asicPar.fChanParams[imess.ch].fPadAddress);
-      const bool hasPairingR              = bool(asicPar.fChanParams[imess.ch].fPadAddress > 0);
-      const uint64_t lTime                = time + tdaqOffset + imess.tlab;
+      const UnpackChannelPar& chPar = asicPar.fChanParams[imess.ch];
+      // skip message if threshold set and signal under
+      if (chPar.fSignalThres && imess.data <= chPar.fSignalThres) continue;
+      const int32_t pad                   = std::abs(chPar.fPadAddress) / 2;
+      const bool hasPairingR              = bool(chPar.fPadAddress > 0);
+      const uint64_t lTime                = time + chPar.fDaqOffset + imess.tlab;
       const uint16_t lchR                 = hasPairingR ? imess.data : 0;
       const uint16_t lchT                 = hasPairingR ? 0 : imess.data;
       std::vector<CbmTrdDigi>& digiBuffer = ctx.fRobDigi[pad];
@@ -418,14 +456,14 @@ namespace cbm::algo::trd2d
       // init pad position in array and build digi for message
       if (digiBuffer.size() == 0) {
         digiBuffer.emplace_back(pad, lchT, lchR, lTime);
-        digiBuffer.back().SetAddressModule(mod_id);
+        digiBuffer.back().SetAddressModule(fParams.fModId);
         continue;
       }
 
       // check if last digi has both R/T message components.
       // Update if not and is within time window
-      auto id = digiBuffer.back();  // Should always be valid here.
-                                    // No need to extra check
+      auto& id = digiBuffer.back();  // Should always be valid here.
+                                     // No need to extra check
       double r, t;
       int32_t dt;
       const int32_t dtime = id.GetTimeDAQ() - lTime;
@@ -446,7 +484,7 @@ namespace cbm::algo::trd2d
       // build digi for message when update failed
       if (!use) {
         digiBuffer.emplace_back(pad, lchT, lchR, lTime);
-        digiBuffer.back().SetAddressModule(mod_id);
+        digiBuffer.back().SetAddressModule(fParams.fModId);
       }
     }
     messes.clear();
diff --git a/algo/detectors/trd2d/UnpackMS.h b/algo/detectors/trd2d/UnpackMS.h
index 6491945e0e1590f582058ae043ab777ca85c0d45..1babd7e8535aa955c768ef02deea1a6dc8b08c0a 100644
--- a/algo/detectors/trd2d/UnpackMS.h
+++ b/algo/detectors/trd2d/UnpackMS.h
@@ -12,11 +12,12 @@
 #include <sstream>
 
 #define NFASPMOD 180
-#define NCROBMOD 5
-#define NFASPCROB NFASPMOD / NCROBMOD
+#define NROBMOD 5
+#define NFASPROB NFASPMOD / NROBMOD
 #define NFASPCH 16
+#define NFASPPAD 8
 
-#define FASP_EPOCH_LENGTH 128
+#define FASP_EPOCH_LENGTH 128  // the length in clks of FASP epoch [1600ns @ 40MHz]
 
 namespace cbm::algo::trd2d
 {
@@ -34,7 +35,6 @@ namespace cbm::algo::trd2d
   {
     kMessLegacy = 2,  /// unpacker version for 2-board FASPRO+GETS HW
     kMess24     = 3,  /// unpacker version for 1-board FASPRO HW first used 18.06.24 (mCBM)
-    kMessNoDef        /// default unpacker version
   };
 
   enum class eMessageType : int
@@ -78,8 +78,7 @@ namespace cbm::algo::trd2d
   struct FaspMessage {
     FaspMessage()                   = default;
     FaspMessage(const FaspMessage&) = default;
-    FaspMessage(uint8_t c, uint8_t typ, uint8_t t, uint16_t d, uint8_t rob, uint8_t asic, uint8_t e = 0);
-    int getFaspIdMod() const { return fasp + rob * NFASPCROB; }
+    FaspMessage(uint8_t c, uint8_t typ, uint8_t t, uint16_t d, uint8_t asic);
 
     /** \brief Implementation of message type descriptor according to message version
      * \param w the message word
@@ -106,9 +105,6 @@ namespace cbm::algo::trd2d
     uint8_t tlab      = 0;                    ///< time of the digi inside the epoch
     uint16_t data     = 0;                    ///< ADC value
     uint32_t epoch    = 0;                    ///< epoch id (not used for the moment)
-    uint32_t mod      = 0;                    ///< full module address according to CbmTrdAddress
-    uint8_t rob       = 0;                    ///< ROB id in the module
-    uint8_t elink     = 0;                    ///< optical link for read-out unit (up or down, starting with kMess24)
     uint8_t fasp      = 0;                    ///< FASP id in the module
   };
 
@@ -120,7 +116,8 @@ namespace cbm::algo::trd2d
   struct UnpackChannelPar {
     int32_t fPadAddress;      ///< Pad address for channel
     bool fMask;               ///< Flag for channel masking
-    uint64_t fDaqOffset = 0;  ///< Time calibration parameter
+    uint8_t fDaqOffset    = 0;  ///< Time calibration parameter
+    uint16_t fSignalThres = 0;  ///< Signal threshold to remove ringing channels
   };
 
   /** @struct UnpackAsicPar
@@ -138,10 +135,22 @@ namespace cbm::algo::trd2d
    ** @brief Parameters required for the TRD2D unpacking (specific to one component)
    **/
   struct UnpackPar {
-    int32_t fSystemTimeOffset              = 0;   ///< Time calibration parameter
-    uint16_t fModId                        = 0;   ///< Module ID of component
-    uint8_t fRobId                         = 0;   ///< ROB ID of component
-    std::vector<UnpackAsicPar> fAsicParams = {};  ///< Parameters for each ASIC
+    int32_t fSystemTimeOffset                    = 0;     ///< Time calibration parameter
+    uint16_t fModId                              = 0;     ///< Module ID of component
+    uint16_t fEqAdd                              = 0;     ///< Equipment (optical fiber) address [HEX]
+    uint8_t fEqId                                = 0xff;  ///< Equipment (optical fiber) ID of component
+    std::map<uint8_t, UnpackAsicPar> fAsicParams = {};    ///< Parameters for each ASIC
+
+    /** \brief Write to the debug stream the content of the current param object*/
+    void dump() const;
+
+    /** \brief Calculate the module wise FASP id from the FASP id provided at the level
+     * of equipment Id (optical fibre in TRD2D case).
+     * \param fasp_id index of fasp as written on the message
+     * \return fasp id on the module as it is used in the parameter file 
+     */
+    template<uint8_t ver>
+    uint8_t mapFaspId2Mod(uint8_t fasp_id) const;
   };
 
 
@@ -183,12 +192,12 @@ namespace cbm::algo::trd2d
    ** @since 31 January 2023
    ** @brief Unpack algorithm for TRD2D
    **/
-  template<std::uint8_t sys_ve>
+  template<std::uint8_t sys_ver>
   class UnpackMS : public UnpackMSBase<CbmTrdDigi, UnpackMonitorData, UnpackAuxData> {
 
    public:
     /** @brief Construct from parameters **/
-    UnpackMS(const UnpackPar& /*pars*/) {}
+    UnpackMS(const UnpackPar& pars) : fParams(pars) {}
 
     /** @brief Destructor **/
     ~UnpackMS() override = default;
@@ -239,7 +248,7 @@ namespace cbm::algo::trd2d
 
    public:
     /** @brief Construct from parameters **/
-    UnpackMS(const UnpackPar& /*pars*/) {}
+    UnpackMS(const UnpackPar& pars) : fParams(pars) {}
 
     /** @brief Destructor **/
     ~UnpackMS() override = default;
@@ -262,7 +271,7 @@ namespace cbm::algo::trd2d
    private:  // Types
     struct MsContext {
       UnpackMonitorData fMonitor;  ///< Container for monitoring data
-      std::array<std::vector<CbmTrdDigi>, NFASPMOD* NFASPCH> fRobDigi = {
+      std::array<std::vector<CbmTrdDigi>, NFASPMOD* NFASPPAD> fRobDigi = {
         {}};              ///> Buffered digi for each pad in one Epoch-ROB component
       FaspMessage fMess;  ///< encapsulation of the FASP message.
     };
diff --git a/reco/tasks/CbmTaskTrdUnpackParWrite.cxx b/reco/tasks/CbmTaskTrdUnpackParWrite.cxx
index c7c3667f31426582748a8ec18bdf0a6f7c9447ea..6a19ff16bf719e0b89908d6efdb28eb89535fd6d 100644
--- a/reco/tasks/CbmTaskTrdUnpackParWrite.cxx
+++ b/reco/tasks/CbmTaskTrdUnpackParWrite.cxx
@@ -37,7 +37,7 @@ InitStatus CbmTaskTrdUnpackParWrite::Init()
     cbm::algo::trd2d::ReadoutConfig trd2dConfig;
 
     // Map (moduleId) -> (array of crobId)
-    std::map<uint32_t, uint16_t[NCROBMOD]> crobMap;
+    std::map<uint32_t, std::vector<uint16_t>> 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;
 
@@ -53,9 +53,12 @@ InitStatus CbmTaskTrdUnpackParWrite::Init()
       auto digipar = entry.second;
 
       const int* crobs = setDet->GetCrobAddresses();
-      for (int icrob(0); icrob < NCROBMOD; icrob++)
-        crobMap[moduleId][icrob] = crobs[icrob];
-
+      for (int icrob(0); icrob < NCROBMOD; icrob++) {
+        crobMap[moduleId].emplace_back(crobs[icrob] & 0xffff);
+        // check if there is an extra fiber defined on this ROB (version 2025 -)
+        uint16_t eq_id = (crobs[icrob] >> 16) & 0xffff;
+        if (eq_id) crobMap[moduleId].emplace_back(eq_id);
+      }
       // Loop through ASICs for this module
       std::vector<int32_t> addresses;
       setDet->GetAsicAddresses(&addresses);