diff --git a/include/DoocsIfff.h b/include/DoocsIfff.h
index 338a5309267309c0b488e2c1adee70c7495909ab..c97227add6ec017821804726de5cdf8a2f5bc7de 100644
--- a/include/DoocsIfff.h
+++ b/include/DoocsIfff.h
@@ -29,17 +29,23 @@ namespace ChimeraTK {
 
     void set(EqAdr* eqAdr, EqData* data1, EqData* data2, EqFct* eqFct) override;
     void auto_init(void) override;
-
+    
+    void setMacroPulseNumberSource(boost::shared_ptr<ChimeraTK::NDRegisterAccessor<int64_t>> macroPulseNumberSource);
+    DataConsistencyGroup _consistencyGroup;
+    
    protected:
     void updateAppToDoocs(TransferElementID& elementId);
     void sendToApplication();
+    void registerVariable(const ChimeraTK::TransferElementAbstractor& var);
 
-    DataConsistencyGroup _consistencyGroup;
     boost::shared_ptr<NDRegisterAccessor<int>> _i1Value;
     boost::shared_ptr<NDRegisterAccessor<float>> _f1Value;
     boost::shared_ptr<NDRegisterAccessor<float>> _f2Value;
     boost::shared_ptr<NDRegisterAccessor<float>> _f3Value;
+    DoocsUpdater& _updater;
+    EqFct* _eqFct;
 
     bool isWriteable;
+    boost::shared_ptr<ChimeraTK::NDRegisterAccessor<int64_t>> _macroPulseNumberSource;
   };
 } // namespace ChimeraTK
diff --git a/src/DoocsIfff.cc b/src/DoocsIfff.cc
index 853d1bca480ef9e6104862501002e9a752dd98fc..bef704117effdfe9dbb0b2293b95e4758bb27cfa 100644
--- a/src/DoocsIfff.cc
+++ b/src/DoocsIfff.cc
@@ -2,6 +2,8 @@
 #include "DoocsUpdater.h"
 
 #include <ChimeraTK/OneDRegisterAccessor.h>
+#include <ChimeraTK/ScalarRegisterAccessor.h>
+#include <doocs/EventId.h>
 
 namespace ChimeraTK {
   DoocsIfff::DoocsIfff(EqFct* eqFct, std::string const& doocsPropertyName,
@@ -9,13 +11,17 @@ namespace ChimeraTK {
       boost::shared_ptr<NDRegisterAccessor<float>> const& f1Value,
       boost::shared_ptr<NDRegisterAccessor<float>> const& f2Value,
       boost::shared_ptr<NDRegisterAccessor<float>> const& f3Value, DoocsUpdater& updater)
-  : D_ifff(eqFct, doocsPropertyName), _i1Value(i1Value), _f1Value(f1Value), _f2Value(f2Value), _f3Value(f3Value) {
+  : D_ifff(eqFct, doocsPropertyName), _i1Value(i1Value), _f1Value(f1Value), _f2Value(f2Value), _f3Value(f3Value),
+    _updater(updater), _eqFct(eqFct) {
     auto registerSource = [&](const ChimeraTK::TransferElementAbstractor& var) {
       if(var.isReadable()) {
         updater.addVariable(var, eqFct, std::bind(&DoocsIfff::updateAppToDoocs, this, var.getId()));
         _consistencyGroup.add(var);
       }
     };
+
+    // FIXME: What if not all 4 are readable? is it still valid to add
+    // all to a consistency group then?
     registerSource(OneDRegisterAccessor<int>(_i1Value));
     registerSource(OneDRegisterAccessor<float>(_f1Value));
     registerSource(OneDRegisterAccessor<float>(_f2Value));
@@ -29,40 +35,51 @@ namespace ChimeraTK {
   }
 
   void DoocsIfff::updateAppToDoocs(TransferElementID& elementId) {
-    if(_consistencyGroup.update(elementId)) {
-      if(_i1Value->dataValidity() != ChimeraTK::DataValidity::ok ||
-          _f1Value->dataValidity() != ChimeraTK::DataValidity::ok ||
-          _f2Value->dataValidity() != ChimeraTK::DataValidity::ok ||
-          _f3Value->dataValidity() != ChimeraTK::DataValidity::ok) {
-        this->d_error(stale_data);
-      }
-      else {
-        this->d_error(no_error);
-      }
+    if(!_consistencyGroup.update(elementId)) {
+      return;
+    }
 
-      IFFF ifff;
-      ifff.i1_data = _i1Value->accessData(0);
-      ifff.f1_data = _f1Value->accessData(0);
-      ifff.f2_data = _f2Value->accessData(0);
-      ifff.f3_data = _f3Value->accessData(0);
-
-      // we must not call set_and_archive if there is no history (otherwise it
-      // will be activated), but we have to if it is there. -> Abstraction,
-      // please!
-      if(this->get_histPointer()) {
-        // Set eventId
-        //doocs::EventId eventId;
-        //if(_macroPulseNumberSource) eventId = doocs::EventId(_macroPulseNumberSource->accessData(0));
-
-        /*FIXME: The archiver also has a status code. Set it correctly.*/
-        /*FIXME: This set_and_archive does not support the timestamp yet (only sec and msec, and I guess m is milli?)*/
-        /*FIXME: This set_and_archive does not support eventIDs yet */
-        this->set_and_archive(&ifff, ArchiveStatus::sts_ok, 0 /*sec*/, 0 /*msec*/);
-      }
-      else {
-        this->set_value(&ifff);
-      }
+    if(_i1Value->dataValidity() != ChimeraTK::DataValidity::ok ||
+        _f1Value->dataValidity() != ChimeraTK::DataValidity::ok ||
+        _f2Value->dataValidity() != ChimeraTK::DataValidity::ok ||
+        _f3Value->dataValidity() != ChimeraTK::DataValidity::ok) {
+      this->d_error(stale_data);
+    }
+    else {
+      this->d_error(no_error);
+    }
+
+    IFFF ifff;
+    ifff.i1_data = _i1Value->accessData(0);
+    ifff.f1_data = _f1Value->accessData(0);
+    ifff.f2_data = _f2Value->accessData(0);
+    ifff.f3_data = _f3Value->accessData(0);
+
+    doocs::Timestamp timestamp(_i1Value->getVersionNumber().getTime());
+    auto sinceEpoch = timestamp.get_seconds_and_microseconds_since_epoch();
+    auto seconds = sinceEpoch.seconds;
+    auto microseconds = sinceEpoch.microseconds;
+    // update global time stamp of DOOCS, but only if our time stamp is newer
+    if(get_global_timestamp() < timestamp) {
+      set_global_timestamp(timestamp);
     }
+
+    if(this->get_histPointer()) {
+      /*
+      doocs::EventId eventId =
+          (_macroPulseNumberSource) ? doocs::EventId(_macroPulseNumberSource->accessData(0)) : doocs::EventId(0);
+      */
+      /*FIXME: The archiver also has a status code. Set it correctly.*/
+      /*FIXME: This set_and_archive does not support the timestamp yet (only sec and msec, and I guess m is milli?)*/
+      /*FIXME: This set_and_archive does not support eventIDs yet */
+      this->set_and_archive(&ifff, ArchiveStatus::sts_ok, 0, 0 /*msec*/);
+    }
+    else {
+      this->set_value(&ifff);
+    }
+
+    this->set_tmstmp(seconds, microseconds);
+    if(_macroPulseNumberSource) this->set_mpnum(_macroPulseNumberSource->accessData(0));
   }
 
   void DoocsIfff::set(EqAdr* eqAdr, EqData* data1, EqData* data2, EqFct* eqFct) {
@@ -93,4 +110,26 @@ namespace ChimeraTK {
     _f3Value->write(v);
   }
 
+  void DoocsIfff::setMacroPulseNumberSource(
+      boost::shared_ptr<ChimeraTK::NDRegisterAccessor<int64_t>> macroPulseNumberSource) {
+    // FIXME: Assuming macroPulseNumberSource is relavent only when all 4
+    // components are readable; correct behavior later if this assumption
+    // does not hold.
+    bool isIfffReadable =
+        (_i1Value->isReadable() && _f1Value->isReadable() && _f2Value->isReadable() && _f3Value->isReadable());
+    if(not isIfffReadable) {
+      return;
+    }
+    _macroPulseNumberSource = macroPulseNumberSource;
+    if(_consistencyGroup.getMatchingMode() != DataConsistencyGroup::MatchingMode::none) {
+      registerVariable(ChimeraTK::ScalarRegisterAccessor<int64_t>(_macroPulseNumberSource));
+    }
+  }
+
+  void DoocsIfff::registerVariable(const ChimeraTK::TransferElementAbstractor& var) {
+    if(var.isReadable()) {
+      _updater.addVariable(var, _eqFct, std::bind(&DoocsIfff::updateAppToDoocs, this, var.getId()));
+      _consistencyGroup.add(var);
+    }
+  }
 } // namespace ChimeraTK
diff --git a/src/DoocsPVFactory.cc b/src/DoocsPVFactory.cc
index 1fb5f7685ff1d78a72c0e470e49710fb350791f1..5b35a4f45d86ce612f68911b66516b58b2cebfe7 100644
--- a/src/DoocsPVFactory.cc
+++ b/src/DoocsPVFactory.cc
@@ -271,6 +271,26 @@ namespace ChimeraTK {
         getDecorator<float>(f2ProcessVariable, DecoratorType::C_style_conversion),
         getDecorator<float>(f3ProcessVariable, DecoratorType::C_style_conversion), _updater));
 
+    // set specified data_matching mode
+    boost::dynamic_pointer_cast<DoocsIfff>(doocsPV)->_consistencyGroup.setMatchingMode(ifffDescription.dataMatching);
+
+    // set macro pulse number source, if configured
+    if(ifffDescription.macroPulseNumberSource.size() > 0) {
+      auto mpnSource = _controlSystemPVManager->getProcessVariable(ifffDescription.macroPulseNumberSource);
+      auto mpnDecorated = getDecorator<int64_t>(mpnSource, DecoratorType::C_style_conversion);
+      if(mpnDecorated->getNumberOfSamples() != 1) {
+        throw ChimeraTK::logic_error("The property '" + mpnDecorated->getName() +
+            "' is used as a macro pulse number source, but it has an array "
+            "length of " +
+            std::to_string(mpnDecorated->getNumberOfSamples()) + ". Length must be exactly 1");
+      }
+      if(!mpnDecorated->isReadable()) {
+        throw ChimeraTK::logic_error("The property '" + mpnDecorated->getName() +
+            "' is used as a macro pulse number source, but it is not readable.");
+      }
+      boost::dynamic_pointer_cast<DoocsIfff>(doocsPV)->setMacroPulseNumberSource(mpnDecorated);
+    }
+
     return doocsPV;
   }