diff --git a/core/data/DataLinkDef.h b/core/data/DataLinkDef.h
index ac3e3775a2239c7ec904e276dea320cfcc8a1181..75ecb0560e8e03cac23ae9c9bcfffacda7a7011c 100644
--- a/core/data/DataLinkDef.h
+++ b/core/data/DataLinkDef.h
@@ -131,9 +131,18 @@
 #pragma link C++ class CbmDigiVector < CbmPsdDsp> + ;
 #pragma link C++ class vector < CbmEventStore> + ;
 
-#pragma read sourceClass = "CbmTofDigi" version = "[1-2]" targetClass = "CbmTofDigi" source =                          \
-  "UInt_t fuAddress" target = "fuAddress" include = "Logger.h" code =                                                  \
-    "{ UInt_t system = (onfile.fuAddress >> 0) & ((1 << 4) - 1); \
+#pragma read sourceClass="CbmStsDigi" version="[7]" targetClass="CbmStsDigi" \
+    source="Long64_t fTime; Int_t fAddress; UShort_t fChannel; UShort_t fCharge" \
+    target="" \
+    include="Logger.h" \
+    code="{ newObj->SetAddressAndTime(onfile.fAddress, onfile.fTime); \
+            newObj->SetChannelAndCharge(onfile.fChannel, onfile.fCharge); \
+          }"
+
+#pragma read sourceClass="CbmTofDigi" version="[1-2]" targetClass="CbmTofDigi" \
+   source="UInt_t fuAddress" target="fuAddress" \
+   include="Logger.h" \
+   code="{ UInt_t system = (onfile.fuAddress >> 0) & ((1 << 4) - 1); \
            UInt_t smId = (onfile.fuAddress >> 4) & ((1 << 8) - 1); \
            UInt_t smType = (onfile.fuAddress >> 12) & ((1 << 4) - 1); \
            UInt_t rpcId = (onfile.fuAddress >> 16) & ((1 << 7) - 1); \
diff --git a/core/data/sts/CbmStsAddress.cxx b/core/data/sts/CbmStsAddress.cxx
index 81fb9c7959790c8937fc625f72bad6cd735765a1..d6d8331b8e6728e2b222b9cb587186708df88c87 100644
--- a/core/data/sts/CbmStsAddress.cxx
+++ b/core/data/sts/CbmStsAddress.cxx
@@ -19,6 +19,7 @@
 namespace CbmStsAddress
 {
 
+  // clang-format off
   // -----    Definition of address bit field   ------------------------------
   const uint16_t kBits[kCurrentVersion + 1][kStsNofLevels] = {
 
@@ -66,7 +67,7 @@ namespace CbmStsAddress
     {(1 << kBits[1][0]) - 1, (1 << kBits[1][1]) - 1, (1 << kBits[1][2]) - 1, (1 << kBits[1][3]) - 1,
      (1 << kBits[1][4]) - 1, (1 << kBits[1][5]) - 1, (1 << kBits[1][6]) - 1}};
   // -------------------------------------------------------------------------
-
+  // clang-format on
 
 }  // Namespace CbmStsAddress
 
diff --git a/core/data/sts/CbmStsAddress.h b/core/data/sts/CbmStsAddress.h
index e62a00feb13b4fed2b36a6a5cc3d10a807bb623a..c232c6df28af1e2cc95dfef77b4a155e28a359cc 100644
--- a/core/data/sts/CbmStsAddress.h
+++ b/core/data/sts/CbmStsAddress.h
@@ -108,8 +108,8 @@ namespace CbmStsAddress
    ** @param address Unique element address
    ** @value Version number
    **
-   ** The version is encoded in the last 6 bits (58 to 63).
-   ** The maximal number of versions is 64.
+   ** The version is encoded in the last 4 bits (28 to 31).
+   ** The maximal number of versions is 16.
    **/
   uint32_t GetVersion(int32_t address);
 
@@ -138,6 +138,20 @@ namespace CbmStsAddress
   int32_t UnpackDigiAddress(int32_t digiAddress);
 
 
+  /** @brief Strip address to contain only unit, (half)ladder and module.
+   ** @param address Full address
+   ** @return 17 bit address that can be stored in a Digi
+   **/
+  int32_t PackDigiAddress(int32_t address);
+
+
+  /** @brief Add version and system to compressed address that's stored in a digi
+   ** @param digiAddress Compressed address from digi
+   ** @return Full address
+   **/
+  int32_t UnpackDigiAddress(int32_t digiAddress);
+
+
   /** @brief String output
    ** @param address Unique element address
    **/
diff --git a/core/data/sts/CbmStsDigi.cxx b/core/data/sts/CbmStsDigi.cxx
index 73b9162ac39749ed068e368bd4388ddd383c4716..733544a0e8d23c1a3fceadfd9ff66e42de20b825 100644
--- a/core/data/sts/CbmStsDigi.cxx
+++ b/core/data/sts/CbmStsDigi.cxx
@@ -4,12 +4,17 @@
 
 /** CbmStsDigi.cxx
  ** @author V.Friese <v.friese@gsi.de>
+ ** @author Felix Weiglhofer <weiglhofer@fias.uni-frankfurt.de>
  ** @since 28.08.2006
  ** @version 4.0
  **/
 
 #include "CbmStsDigi.h"
 
+#include "CbmStsAddress.h"
+
+#include <algorithm>
+#include <cstdlib>
 #include <sstream>  // for operator<<, basic_ostream, char_traits
 
 using std::string;
@@ -19,10 +24,29 @@ using std::stringstream;
 string CbmStsDigi::ToString() const
 {
   stringstream ss;
-  ss << "StsDigi: address " << fAddress << " | channel " << fChannel << " | charge " << fCharge << " | time " << fTime;
+  ss << "StsDigi: address " << UnpackAddress() << " | channel " << UnpackChannel() << " | charge " << UnpackCharge()
+     << " | time " << UnpackTime();
   return ss.str();
 }
 
+void CbmStsDigi::PackAddressAndTime(int32_t newAddress, uint32_t newTime)
+{
+  int32_t packedAddr = CbmStsAddress::PackDigiAddress(newAddress);
+
+  uint32_t highestBitAddr = packedAddr >> kNumLowerAddrBits;
+  uint32_t lowerAddr      = packedAddr & ((1 << kNumLowerAddrBits) - 1);
+
+  fAddress = lowerAddr;
+  fTime    = (highestBitAddr << kNumTimestampBits) | newTime;
+}
+
+int32_t CbmStsDigi::UnpackAddress() const
+{
+  int32_t highestBitAddr = fTime >> kNumTimestampBits;
+  int32_t packedAddress  = (highestBitAddr << kNumLowerAddrBits) | int32_t(fAddress);
+  return CbmStsAddress::UnpackDigiAddress(packedAddress);
+}
+
 #ifndef NO_ROOT
 ClassImp(CbmStsDigi)
 #endif
diff --git a/core/data/sts/CbmStsDigi.h b/core/data/sts/CbmStsDigi.h
index 2e7fe4a919f7cef6690aba660a2b509bd4d617c1..94594b483e007cdad3f155a76f71e45aab5613a0 100644
--- a/core/data/sts/CbmStsDigi.h
+++ b/core/data/sts/CbmStsDigi.h
@@ -4,6 +4,7 @@
 
 /** @file CbmStsDigi.h
  ** @author V.Friese <v.friese@gsi.de>
+ ** @author Felix Weiglhofer <weiglhofer@fias.uni-frankfurt.de>
  ** @since 28.08.2006
  ** @version 6
  **/
@@ -13,6 +14,7 @@
 #define CBMSTSDIGI_H 1
 
 #include "CbmDefs.h"  // for ECbmModuleId::kSts
+#include "CbmStsAddress.h"
 
 #ifndef NO_ROOT
 #include <Rtypes.h>  // for ClassDef
@@ -45,23 +47,20 @@ public:
    ** @param  time     Measurement time [ns]
    ** @param  charge   Charge [ADC units]
    **/
-  CbmStsDigi(int32_t address, int32_t channel, uint64_t time, uint16_t charge)
-    : fTime(time)
-    , fAddress(address)
-    , fChannel(channel)
-    , fCharge(charge)
+  CbmStsDigi(int32_t address, int32_t channel, uint32_t time, uint16_t charge)
   {
+    PackAddressAndTime(address, time);
+    PackChannelAndCharge(channel, charge);
   }
 
 
   /** Destructor **/
   ~CbmStsDigi() {};
 
-
   /** Unique detector element address  (see CbmStsAddress)
    ** @value Unique address of readout channel
    **/
-  int32_t GetAddress() const { return fAddress; }
+  int32_t GetAddress() const { return UnpackAddress(); }
 
 
   /** @brief Get the desired name of the branch for this obj in the cbm output tree  (static)
@@ -73,7 +72,7 @@ public:
   /** @brief Channel number in module
    ** @value Channel number
    **/
-  uint16_t GetChannel() const { return fChannel; }
+  uint16_t GetChannel() const { return UnpackChannel(); }
 
 
   /** @brief Class name (static)
@@ -85,7 +84,7 @@ public:
   /** Charge
    ** @value Charge [ADC units]
    **/
-  double GetCharge() const { return double(fCharge); }
+  double GetCharge() const { return static_cast<double>(UnpackCharge()); }
 
 
   /** System ID (static)
@@ -97,16 +96,15 @@ public:
   /** Time of measurement
    ** @value Time [ns]
    **/
-  double GetTime() const { return double(fTime); }
+  double GetTime() const { return static_cast<double>(UnpackTime()); }
 
 
   template<class Archive>
   void serialize(Archive& ar, const unsigned int /*version*/)
   {
     ar& fTime;
+    ar& fChannelAndCharge;
     ar& fAddress;
-    ar& fChannel;
-    ar& fCharge;
   }
 
 
@@ -115,11 +113,30 @@ public:
    **/
   void SetTime(double dNewTime)
   {
-    // Future versions of StsDigi won't be able to store negative timestamps.
-    assert(dNewTime >= 0);
-    fTime = dNewTime;
+    // StsDigi is not able to store negative timestamps.
+    assert(dNewTime >= 0 && dNewTime <= kMaxTimestamp);
+    PackTime(dNewTime);
   }
 
+  void SetChannel(uint16_t channel) { PackChannelAndCharge(channel, UnpackCharge()); }
+
+  void SetCharge(uint16_t charge) { PackChannelAndCharge(UnpackChannel(), charge); }
+
+  void SetAddress(int32_t address) { PackAddressAndTime(address, UnpackTime()); }
+
+
+  /** Set new channel and charge.
+   **
+   ** Slightly more efficient than calling both individual setters.
+   **/
+  void SetChannelAndCharge(uint16_t channel, uint16_t charge) { PackChannelAndCharge(channel, charge); }
+
+  /** Set new address and time at once.
+   **
+   ** Slightly more efficient than calling both individual setters.
+   **/
+  void SetAddressAndTime(int32_t address, uint32_t time) { PackAddressAndTime(address, time); }
+
 
   /** String output **/
   std::string ToString() const;
@@ -128,14 +145,37 @@ public:
 private:
   friend class boost::serialization::access;
 
-  int64_t fTime     = 0.;  ///< Time [ns]
-  int32_t fAddress  = 0;   ///< Unique element address
-  uint16_t fChannel = 0;   ///< Channel number
-  uint16_t fCharge  = 0;   ///< Charge [ADC units]
 
+  static constexpr int kNumAdcBits              = 5;
+  static constexpr uint32_t kAdcMask            = (1u << kNumAdcBits) - 1u;
+  static constexpr int kNumLowerAddrBits        = 16;
+  static constexpr int kNumTimestampBits        = 31;
+  static constexpr uint32_t kTimestampMask      = (1u << kNumTimestampBits) - 1u;
+  static constexpr uint32_t kMaxTimestamp       = kTimestampMask;
+  static constexpr uint32_t kTimeAddressBitMask = ~kTimestampMask;
+
+  uint32_t fTime             = 0;  ///< Time [ns] in lower 31 bits, highest bit is the 17th address bit.
+  uint16_t fChannelAndCharge = 0;  ///< Channel number (lower 11 bits) and charge [ADC Units] in upper 5 bits.
+  uint16_t fAddress          = 0;  ///< Unique element address (lower 16 bits of 17)
+
+
+  void PackTime(uint32_t newTime) { fTime = (fTime & kTimeAddressBitMask) | (newTime & kTimestampMask); }
+  uint32_t UnpackTime() const { return fTime & kTimestampMask; }
+
+
+  void PackChannelAndCharge(uint16_t channel, uint16_t charge)
+  {
+    fChannelAndCharge = (channel << kNumAdcBits) | charge;
+  }
+  uint16_t UnpackChannel() const { return fChannelAndCharge >> kNumAdcBits; }
+  uint16_t UnpackCharge() const { return fChannelAndCharge & kAdcMask; }
+
+
+  void PackAddressAndTime(int32_t address, uint32_t time);
+  int32_t UnpackAddress() const;
 
 #ifndef NO_ROOT
-  ClassDefNV(CbmStsDigi, 7);
+  ClassDefNV(CbmStsDigi, 8);
 #endif
 };
 
diff --git a/core/data/test/sts/_GTestCbmStsDigi.cxx b/core/data/test/sts/_GTestCbmStsDigi.cxx
index e906ba158da78d74d0005b09170fabd7f8023af7..5912fd2928b13954e0d32c5c84310a824ef4d669 100644
--- a/core/data/test/sts/_GTestCbmStsDigi.cxx
+++ b/core/data/test/sts/_GTestCbmStsDigi.cxx
@@ -2,61 +2,66 @@
    SPDX-License-Identifier: GPL-3.0-only
    Authors: Florian Uhlig [committer] */
 
+#include "CbmStsAddress.h"
 #include "CbmStsDigi.h"
 
 #include "compareStsDigi.h"
 #include "gtest/gtest-spi.h"
 #include "gtest/gtest.h"
 
+static const Int_t kTestAddress = CbmStsAddress::GetAddress(5, 6, 1, 8, 0, 0, 1);
+
 TEST(_GTestCbmStsDigi, CheckDefaultConstructor)
 {
   // Create object
   CbmStsDigi test;
 
-  compareStsDigiDataMembers(test, 0, 0, 0, ECbmModuleId::kSts, 0);
+  const Int_t defaultAddr = CbmStsAddress::GetAddress(0, 0, 0, 0, 0, 0, 1);
+
+  compareStsDigiDataMembers(test, defaultAddr, 0, 0, ECbmModuleId::kSts, 0);
 
   CbmStsDigi* test1 = new CbmStsDigi();
 
-  compareStsDigiDataMembers(*test1, 0, 0, 0, ECbmModuleId::kSts, 0);
+  compareStsDigiDataMembers(*test1, defaultAddr, 0, 0, ECbmModuleId::kSts, 0);
 }
 
 TEST(_GTestCbmStsDigi, CheckStandardConstructor)
 {
   // Create object
-  CbmStsDigi test(111, 42, 987654321, 23);
+  CbmStsDigi test(kTestAddress, 42, 987654321, 23);
 
-  compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 987654321);
+  compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321);
 
-  CbmStsDigi* test1 = new CbmStsDigi(111, 42, 897654321, 23);
+  CbmStsDigi* test1 = new CbmStsDigi(kTestAddress, 42, 987654321, 23);
 
-  compareStsDigiDataMembers(*test1, 111, 23, 42, ECbmModuleId::kSts, 897654321);
+  compareStsDigiDataMembers(*test1, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321);
 }
 
 TEST(_GTestCbmStsDigi, CheckCopyConstructor)
 {
   // Create object
-  CbmStsDigi test(111, 42, 987654321, 23);
+  CbmStsDigi test(kTestAddress, 42, 987654321, 23);
 
-  compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 987654321);
+  compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321);
 
   // Create object by copy constructing
   // test should be equal to test2 and
   // test should not be changed
   CbmStsDigi test2 {test};
 
-  compareStsDigiDataMembers(test2, 111, 23, 42, ECbmModuleId::kSts, 987654321);
+  compareStsDigiDataMembers(test2, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321);
 
   // Test if the original object wasn't changed
-  compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 987654321);
+  compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321);
 }
 
 TEST(_GTestCbmStsDigi, CheckAssignmentOperator)
 {
 
   // Create object
-  CbmStsDigi test(111, 42, 987654321, 23);
+  CbmStsDigi test(kTestAddress, 42, 987654321, 23);
 
-  compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 987654321);
+  compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321);
 
   // Create object by copy assignment
   // test should be equal to test2 and
@@ -64,73 +69,77 @@ TEST(_GTestCbmStsDigi, CheckAssignmentOperator)
   CbmStsDigi test2;
   test2 = test;
 
-  compareStsDigiDataMembers(test2, 111, 23, 42, ECbmModuleId::kSts, 987654321);
+  compareStsDigiDataMembers(test2, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321);
 
   // Test if the original object wasn't changed
-  compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 987654321);
+  compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321);
 }
 
 TEST(_GTestCbmStsDigi, CheckMoveConstructor)
 {
   // Create object
-  CbmStsDigi test(111, 42, 987654321, 23);
+  CbmStsDigi test(kTestAddress, 42, 987654321, 23);
 
-  compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 987654321);
+  compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321);
 
   // Create object by move constructing
   CbmStsDigi test2 {std::move(test)};
 
-  compareStsDigiDataMembers(test2, 111, 23, 42, ECbmModuleId::kSts, 987654321);
+  compareStsDigiDataMembers(test2, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321);
 
   // For objects with simple types move fall back to copy so
   // the original object is kept unchanged
-  compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 987654321);
+  compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321);
 }
 
 TEST(_GTestCbmStsDigi, CheckAssignmentMoveConstructor)
 {
   // Create object
-  CbmStsDigi test(111, 42, 987654321, 23);
+  CbmStsDigi test(kTestAddress, 42, 987654321, 23);
 
-  compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 987654321);
+  compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321);
 
   // Create object by move constructing
   CbmStsDigi test2 {};
   test2 = std::move(test);
 
-  compareStsDigiDataMembers(test2, 111, 23, 42, ECbmModuleId::kSts, 987654321);
+  compareStsDigiDataMembers(test2, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321);
 
   // For objects with simple types move fall back to copy so
   // the original object is kept unchanged
-  compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 987654321);
+  compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321);
 }
 
 TEST(_GTestCbmStsDigi, CheckSetTime)
 {
   // Create object
-  CbmStsDigi test(111, 42, 987654321, 23);
+  CbmStsDigi test(kTestAddress, 42, 987654321, 23);
 
-  compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 987654321);
+  compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321);
 
   test.SetTime(897654321.0);
 
-  compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 897654321);
+  compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 897654321);
 }
 
 TEST(_GTestCbmStsDigi, CheckToString)
 {
-  CbmStsDigi test(111, 42, 987654321, 23);
+  CbmStsDigi test(kTestAddress, 42, 987654321, 23);
 
-  compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 987654321);
+  compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321);
 
-  EXPECT_STREQ("StsDigi: address 111 | channel 42 | charge 23 | time 987654321", test.ToString().c_str());
+  std::string expected =
+    "StsDigi: address " + std::to_string(kTestAddress) + " | channel 42 | charge 23 | time 987654321";
+
+  EXPECT_STREQ(expected.c_str(), test.ToString().c_str());
 }
 
+
 TEST(_GTestCbmStsDigi, CheckGetClassName)
 {
-  CbmStsDigi test(111, 42, 987654321, 23);
+  CbmStsDigi test(kTestAddress, 42, 987654321, 23);
 
-  compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 987654321);
+  compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321);
 
   EXPECT_STREQ("CbmStsDigi", test.GetClassName());
 }