diff --git a/reco/detectors/sts/unpack/CbmStsUnpackAlgo.cxx b/reco/detectors/sts/unpack/CbmStsUnpackAlgo.cxx
index 6ee6e00cca669903b03a6169a5d3237c29189cf9..999aebdb067657c2e9b0c41b22beeb2a3c263d3a 100644
--- a/reco/detectors/sts/unpack/CbmStsUnpackAlgo.cxx
+++ b/reco/detectors/sts/unpack/CbmStsUnpackAlgo.cxx
@@ -52,7 +52,13 @@ uint64_t CbmStsUnpackAlgo::getFullTimeStamp(const uint16_t usRawTs)
 }
 
 // ---- init
-Bool_t CbmStsUnpackAlgo::init() { return kTRUE; }
+Bool_t CbmStsUnpackAlgo::init()
+{
+  if (!fbUseFwBinning) {
+    LOG(warning) << "Chosen STS unpacker always uses firmware binning (``false'' setting is ignored).";
+  }
+  return kTRUE;
+}
 
 // ---- initDpbIdIndexMap ----
 void CbmStsUnpackAlgo::initDpbIdIndexMap(CbmMcbm2018StsPar* parset)
@@ -485,9 +491,9 @@ void CbmStsUnpackAlgo::processHitInfo(const stsxyter::Message& mess)
           if (fMonitor) fMonitor->FillDuplicateHitsAdc(uFebIdx, uChanInFeb, usRawAdc);
           return;
         }  // if same TS, (ADC,) TS MSB, TS MSB cycle, reject
-        fvvusLastTsChan[uAsicIdx][usChan]         = usRawTs;
-        fvvusLastAdcChan[uAsicIdx][usChan]        = usRawAdc;
-        fvvulLastTsMsbChan[uAsicIdx][usChan]      = fulTsMsbIndexInTs[fuCurrDpbIdx];
+        fvvusLastTsChan[uAsicIdx][usChan]    = usRawTs;
+        fvvusLastAdcChan[uAsicIdx][usChan]   = usRawAdc;
+        fvvulLastTsMsbChan[uAsicIdx][usChan] = fulTsMsbIndexInTs[fuCurrDpbIdx];
       }  // if (fbRejectDuplicateDigis)
 
       uint32_t uChanInMod = usChan + fNrChsPerAsic * (uAsicIdx % fNrAsicsPerFeb);
@@ -551,8 +557,8 @@ void CbmStsUnpackAlgo::processHitInfo(const stsxyter::Message& mess)
       (static_cast<double_t>(ulHitTime) * stsxyter::kdClockCycleNs - fSystemTimeOffset + fTsStartTime) * 1e-9;
 
     // Prepare monitoring values
-    const uint32_t uAsicInFeb       = uAsicIdx % fNrAsicsPerFeb;
-    const double dCalAdc            = fvdFebAdcOffs[uFebIdx] + (usRawAdc - 1) * fvdFebAdcGain[uFebIdx];
+    const uint32_t uAsicInFeb = uAsicIdx % fNrAsicsPerFeb;
+    const double dCalAdc      = fvdFebAdcOffs[uFebIdx] + (usRawAdc - 1) * fvdFebAdcGain[uFebIdx];
 
     fMonitor->FillHitMonitoringHistos(uFebIdx, usChan, uChanInFeb, usRawAdc, dCalAdc, usRawTs, mess.IsHitMissedEvts());
     fMonitor->FillHitEvoMonitoringHistos(uFebIdx, uAsicIdx, uAsicInFeb, uChanInFeb, dHitTimeAbsSec,
diff --git a/reco/detectors/sts/unpack/CbmStsUnpackAlgoBase.h b/reco/detectors/sts/unpack/CbmStsUnpackAlgoBase.h
index 7c77c64b479a399f60761177221892f47cf92c23..fb3b25d7d85861a2ed0b30c1b16dd926ae9c7cd3 100644
--- a/reco/detectors/sts/unpack/CbmStsUnpackAlgoBase.h
+++ b/reco/detectors/sts/unpack/CbmStsUnpackAlgoBase.h
@@ -75,6 +75,9 @@ public:
     fbDupliWithoutAdc      = bDiffAdc;
   }
 
+  /** @brief Enable/Disable firmware binning (switch only supported by older implementations) */
+  void SetFwBinning(bool useFwBinning) { fbUseFwBinning = useFwBinning; }
+
   /**
    * @brief Get the requested parameter containers. To be defined in the derived classes!
    * Return the required parameter containers together with the paths to the ascii
@@ -134,6 +137,9 @@ protected:
   /** @brief If rejecting duplicate digis, enables rejection even if ADC differs*/
   bool fbDupliWithoutAdc = true;
 
+  /** @brief Enables firmware binning (some implementations ignore this) */
+  bool fbUseFwBinning = true;
+
 private:
   ClassDef(CbmStsUnpackAlgoBase, 2)
 };
diff --git a/reco/detectors/sts/unpack/CbmStsUnpackAlgoLegacy.cxx b/reco/detectors/sts/unpack/CbmStsUnpackAlgoLegacy.cxx
index 20c411571a1fc169854251d677b0c31726993564..1dc3df147281692a899324b0a7c269b1e5832bdb 100644
--- a/reco/detectors/sts/unpack/CbmStsUnpackAlgoLegacy.cxx
+++ b/reco/detectors/sts/unpack/CbmStsUnpackAlgoLegacy.cxx
@@ -460,8 +460,13 @@ bool CbmStsUnpackAlgoLegacy::unpack(const fles::Timeslice* ts, std::uint16_t uMs
 // -------------------------------------------------------------------------
 void CbmStsUnpackAlgoLegacy::RefreshTsMsbFields(const size_t uMsIdx)
 {
-  const uint32_t uTsMsbCycleHeader =
-    std::floor(fulCurrentMsIdx / (stsxyter::kulTsCycleNbBinsBinning * stsxyter::kdClockCycleNs));
+  uint32_t uTsMsbCycleHeader;
+  if (fbUseFwBinning) {
+    uTsMsbCycleHeader = std::floor(fulCurrentMsIdx / (stsxyter::kulTsCycleNbBinsBinning * stsxyter::kdClockCycleNs));
+  }
+  else {
+    uTsMsbCycleHeader = std::floor(fulCurrentMsIdx / (stsxyter::kulTsCycleNbBins * stsxyter::kdClockCycleNs));
+  }
 
   if (0 == uMsIdx) {
     if (uTsMsbCycleHeader != fvuCurrentTsMsbCycle[fuCurrDpbIdx])
@@ -552,9 +557,13 @@ void CbmStsUnpackAlgoLegacy::LoopMsMessages(const uint8_t* msContent, const uint
 // -------------------------------------------------------------------------
 void CbmStsUnpackAlgoLegacy::ProcessHitInfo(const stsxyter::Message& mess)
 {
-  const uint16_t usElinkIdx = mess.GetLinkIndexHitBinning();
-  const uint32_t uCrobIdx   = usElinkIdx / fUnpackPar->GetNbElinkPerCrob();
-  const int32_t uFebIdx     = fUnpackPar->ElinkIdxToFebIdx(usElinkIdx);
+  uint16_t usElinkIdx;
+  if (fbUseFwBinning) { usElinkIdx = mess.GetLinkIndexHitBinning(); }
+  else {
+    usElinkIdx = mess.GetLinkIndex();
+  }
+  const uint32_t uCrobIdx = usElinkIdx / fUnpackPar->GetNbElinkPerCrob();
+  const int32_t uFebIdx   = fUnpackPar->ElinkIdxToFebIdx(usElinkIdx);
   if (-1 == uFebIdx) {
     LOG(warning) << "CbmStsUnpackAlgoLegacy::ProcessHitInfo => "
                  << "Wrong elink Idx! Elink raw " << Form("%d remap %d", usElinkIdx, uFebIdx);
@@ -566,9 +575,13 @@ void CbmStsUnpackAlgoLegacy::ProcessHitInfo(const stsxyter::Message& mess)
   //LOG(info) << "Test " << uFebIdx << " " << uAsicIdx / fUnpackPar->GetNbAsicsPerFeb();
   //const uint32_t uFebIdx    = uAsicIdx / fUnpackPar->GetNbAsicsPerFeb();  // delete this?
 
-  const uint16_t usChan     = mess.GetHitChannel();
-  const uint16_t usRawAdc   = mess.GetHitAdc();
-  const uint16_t usRawTs    = mess.GetHitTimeBinning();
+  const uint16_t usChan   = mess.GetHitChannel();
+  const uint16_t usRawAdc = mess.GetHitAdc();
+  uint16_t usRawTs;
+  if (fbUseFwBinning) { usRawTs = mess.GetHitTimeBinning(); }
+  else {
+    usRawTs = mess.GetHitTimeFull();
+  }
   const uint32_t uChanInFeb = usChan + fUnpackPar->GetNbChanPerAsic() * (uAsicIdx % fUnpackPar->GetNbAsicsPerFeb());
 
   /// Duplicate hits rejection
@@ -626,7 +639,11 @@ void CbmStsUnpackAlgoLegacy::ProcessHitInfo(const stsxyter::Message& mess)
 
 void CbmStsUnpackAlgoLegacy::ProcessTsMsbInfo(const stsxyter::Message& mess, uint32_t uMessIdx, uint32_t uMsIdx)
 {
-  const uint32_t uVal = mess.GetTsMsbValBinning();
+  uint32_t uVal;
+  if (fbUseFwBinning) { uVal = mess.GetTsMsbValBinning(); }
+  else {
+    uVal = mess.GetTsMsbVal();
+  }
 
   // Update Status counters
   if (uVal < fvulCurrentTsMsb[fuCurrDpbIdx]) {
@@ -714,12 +731,20 @@ void CbmStsUnpackAlgoLegacy::ProcessStatusInfo(const stsxyter::Message& mess, ui
 uint64_t CbmStsUnpackAlgoLegacy::GetFullTimeStamp(const uint16_t usRawTs)
 {
   // Use TS w/o overlap bits as they will anyway come from the TS_MSB
-  const uint64_t ulTime =
-    usRawTs
-    + static_cast<uint64_t>(stsxyter::kuHitNbTsBinsBinning) * static_cast<uint64_t>(fvulCurrentTsMsb[fuCurrDpbIdx])
-    + static_cast<uint64_t>(stsxyter::kulTsCycleNbBinsBinning)
-        * static_cast<uint64_t>(fvuCurrentTsMsbCycle[fuCurrDpbIdx]);
 
+  uint64_t ulTime;
+  if (fbUseFwBinning) {
+    ulTime =
+      usRawTs
+      + static_cast<uint64_t>(stsxyter::kuHitNbTsBinsBinning) * static_cast<uint64_t>(fvulCurrentTsMsb[fuCurrDpbIdx])
+      + static_cast<uint64_t>(stsxyter::kulTsCycleNbBinsBinning)
+          * static_cast<uint64_t>(fvuCurrentTsMsbCycle[fuCurrDpbIdx]);
+  }
+  else {
+    ulTime =
+      usRawTs
+      + static_cast<uint64_t>(stsxyter::kuHitNbTsBins) * (static_cast<uint64_t>(fvulCurrentTsMsb[fuCurrDpbIdx]) % 4);
+  }
   return ulTime;
 }
 
diff --git a/reco/detectors/sts/unpack/CbmStsUnpackAlgoLegacy.h b/reco/detectors/sts/unpack/CbmStsUnpackAlgoLegacy.h
index f3768c5709b09b732abb53c008d05f0548c14b8e..a4b3214ad04197b6a53d9ec6b440e2860939dc3b 100644
--- a/reco/detectors/sts/unpack/CbmStsUnpackAlgoLegacy.h
+++ b/reco/detectors/sts/unpack/CbmStsUnpackAlgoLegacy.h
@@ -81,17 +81,17 @@ private:
    * @brief Handles the distribution of the hidden derived classes to their explicit functions.
    *
    * @param parset
-   * @return Bool_t initOk
+   * @return bool initOk
   */
-  Bool_t initParSet(FairParGenericSet* parset);
+  bool initParSet(FairParGenericSet* parset);
 
   /**
    * @brief Initialize the parameters from CbmMcbm2018StsPar.
    *
    * @param parset
-   * @return Bool_t initOk
+   * @return bool initOk
   */
-  Bool_t initParSet(CbmMcbm2018StsPar* parset);
+  bool initParSet(CbmMcbm2018StsPar* parset);
 
   void InitInternalStatus();
   void InitTempVectors(std::vector<int32_t>* viModuleType, std::vector<int32_t>* viModAddress,
diff --git a/reco/detectors/sts/unpack/CbmStsUnpackConfig.cxx b/reco/detectors/sts/unpack/CbmStsUnpackConfig.cxx
index b1d57860efd15e61612b7a8576ae94f1f1c66fd7..4f872ad8a81bab4ea7c016ed626d3b57acf17598 100644
--- a/reco/detectors/sts/unpack/CbmStsUnpackConfig.cxx
+++ b/reco/detectors/sts/unpack/CbmStsUnpackConfig.cxx
@@ -44,6 +44,9 @@ void CbmStsUnpackConfig::InitAlgo()
 
   if (fMonitor) { fAlgo->SetMonitor(fMonitor); }
 
+  // Set firmware binning (only relevant for legacy mode)
+  if (fbUseFwBinning) { fAlgo->SetFwBinning(true); }
+
   // Now we have all information required to initialise the algorithm
   fAlgo->Init();
 
diff --git a/reco/detectors/sts/unpack/CbmStsUnpackConfig.h b/reco/detectors/sts/unpack/CbmStsUnpackConfig.h
index 8a377c5b51681328260face946a8fe514ca3a90f..7a66125201507d22e44e609957f10e110d3ee2d9 100644
--- a/reco/detectors/sts/unpack/CbmStsUnpackConfig.h
+++ b/reco/detectors/sts/unpack/CbmStsUnpackConfig.h
@@ -111,6 +111,8 @@ public:
   /** @brief Add a monitor to the unpacker. @param value CbmStsUnpackMonitor */
   void SetMonitor(std::shared_ptr<CbmStsUnpackMonitor> value) { fMonitor = value; }
 
+  /** @brief Enable/Disable firmware binning (switch only supported by legacy algo) */
+  void SetFwBinning(bool useFwBinning) { fbUseFwBinning = useFwBinning; }
 
 protected:
   /**
@@ -144,6 +146,9 @@ protected:
   /** @brief If rejecting duplicate digis, enables rejection even if ADC differs*/
   bool fbDupliWithoutAdc = true;
 
+  /** @brief Enables firmware binning (some implementations ignore this) */
+  bool fbUseFwBinning = false;
+
   /// Temporary storage of user parameters
   std::vector<FebChanMaskReco> fvChanMasks = {};