diff --git a/src/constants.h b/src/constants.h
index 35b5e4f81ad006202d37482cc0e08002ce38f520..f86fe46083c88b1a202a4540cb91fded2b5c38d6 100644
--- a/src/constants.h
+++ b/src/constants.h
@@ -34,6 +34,7 @@
 #define C_S_pn 12
 #define C_W_adc 14
 #define C_F_adc 200E6
+#define C_T_adc (1 / C_F_adc)
 
 #define C_WG_MODE_OFF  0
 #define C_WG_MODE_CALC 1
@@ -49,6 +50,7 @@
 #define C_N_step 1
 #define C_N_crosslets_max 7
 #define C_N_scrap 512  // Number of 32 bit words in FPGA scrap memory.
+#define C_N_fft 1024  // The FFT size defines the number of samples per block.
 #define C_N_pol 2  // Number of antenna polarizations, X and Y.
 #define C_A_pn 6  // Number of dual polarization antennas per Processing Node (PN) FPGA.
 // #define C_N_beamlets 976  // Number of beamlets per antenna band  488, 976
diff --git a/src/fpga.cpp b/src/fpga.cpp
index 53ba9e9739a4ec99ed2ffd99e0196dddf354fbc1..4f5ece24f4f558a95528f9954cc488ecb6278cf9 100644
--- a/src/fpga.cpp
+++ b/src/fpga.cpp
@@ -89,12 +89,16 @@ Fpga::Fpga(list<class Node*>& nodelist, const int32_t n_beamsets):
     pointMap->add_register("FPGA_xst_processing_enable_RW",                  "fpga/xst_processing_enable",                  nodes.size(), 1, "RW", REG_FORMAT_BOOLEAN);
     pointMap->add_register("FPGA_xst_offload_enable_R",                      "fpga/xst_offload_enable",                     nodes.size(), 1, "RO", REG_FORMAT_BOOLEAN);
     pointMap->add_register("FPGA_xst_offload_enable_RW",                     "fpga/xst_offload_enable",                     nodes.size(), 1, "RW", REG_FORMAT_BOOLEAN);
+    pointMap->add_register("FPGA_xst_offload_nof_crosslets_R",               "fpga/xst_offload_nof_crosslets",              nodes.size(), 1, "RO", REG_FORMAT_UINT32);
+    pointMap->add_register("FPGA_xst_offload_nof_crosslets_RW",              "fpga/xst_offload_nof_crosslets",              nodes.size(), 1, "RW", REG_FORMAT_UINT32);
     pointMap->add_register("FPGA_xst_offload_hdr_eth_destination_mac_R",     "fpga/xst_offload_hdr_eth_destination_mac",    nodes.size(), 1, "RO", REG_FORMAT_STRING);
     pointMap->add_register("FPGA_xst_offload_hdr_eth_destination_mac_RW",    "fpga/xst_offload_hdr_eth_destination_mac",    nodes.size(), 1, "RW", REG_FORMAT_STRING);
     pointMap->add_register("FPGA_xst_offload_hdr_ip_destination_address_R",  "fpga/xst_offload_hdr_ip_destination_address", nodes.size(), 1, "RO", REG_FORMAT_STRING);
     pointMap->add_register("FPGA_xst_offload_hdr_ip_destination_address_RW", "fpga/xst_offload_hdr_ip_destination_address", nodes.size(), 1, "RW", REG_FORMAT_STRING);
     pointMap->add_register("FPGA_xst_offload_hdr_udp_destination_port_R",    "fpga/xst_offload_hdr_udp_destination_port",   nodes.size(), 1, "RO", REG_FORMAT_UINT16);
     pointMap->add_register("FPGA_xst_offload_hdr_udp_destination_port_RW",   "fpga/xst_offload_hdr_udp_destination_port",   nodes.size(), 1, "RW", REG_FORMAT_UINT16);
+    pointMap->add_register("FPGA_xst_input_bsn_at_sync_R",                   "fpga/xst_input_sync_at_bsn",                  nodes.size(), 1, "RO", REG_FORMAT_INT64);
+    pointMap->add_register("FPGA_xst_output_sync_bsn_R",                     "fpga/xst_output_sync_bsn",                    nodes.size(), 1, "RO", REG_FORMAT_INT64);
 
     pointMap->add_register("FPGA_processing_enable_R",                       "fpga/processing_enable",                      nodes.size(), 1, "RO", REG_FORMAT_BOOLEAN);
     pointMap->add_register("FPGA_processing_enable_RW",                      "fpga/processing_enable",                      nodes.size(), 1, "RW", REG_FORMAT_BOOLEAN);
diff --git a/src/periph/fpga.cpp b/src/periph/fpga.cpp
index cfdc546d306a718675d90de44f6b6facf630fdf4..0ecb6275fb6a32495b7ea52e8b15fd4ec8683f0b 100644
--- a/src/periph/fpga.cpp
+++ b/src/periph/fpga.cpp
@@ -68,6 +68,8 @@ Periph_fpga::Periph_fpga(uint global_nr, string ipaddr, uint n_beamsets):
     my_current_fw_version("-.-"),
     my_bsn_input_sync_timeout(false),
     my_bsn_input_bsn(0),
+    my_xst_input_bsn_at_sync(0),
+    my_xst_output_sync_bsn(0),
     my_bsn_input_nof_packets(0),
     my_bsn_input_nof_valid(0),
     my_bsn_input_nof_err(0),
@@ -75,7 +77,6 @@ Periph_fpga::Periph_fpga(uint global_nr, string ipaddr, uint n_beamsets):
     my_jesd_csr_dev_syncn {0},
     my_jesd_rx_err0 {0},
     my_jesd_rx_err1 {0},
-    my_xst_processing_enable(false),
     my_pps_offset_cnt(0),
     my_signal_input_mean {0.0},
     my_signal_input_rms {0.0}
@@ -210,6 +211,9 @@ bool Periph_fpga::read(TermOutput& termout, const string addr,
         else if (addr == "fpga/xst_offload_enable") {
             retval = read_mm_port(termout, "REG_STAT_ENABLE_XST", "enable", format);
         }
+        else if (addr == "fpga/xst_offload_nof_crosslets") {
+            retval = read_mm_port(termout, "REG_NOF_CROSSLETS", "nof_crosslets", format);
+        }
         else if (addr == "fpga/xst_offload_hdr_eth_destination_mac") {
             retval = read_xst_offload_hdr_eth_destination_mac(termout, format);
         }
@@ -228,6 +232,12 @@ bool Periph_fpga::read(TermOutput& termout, const string addr,
         else if (addr == "fpga/xst_subband_select") {
             retval = read_xst_subband_select(termout, format);
         }
+        else if (addr == "fpga/xst_input_sync_at_bsn") {
+            retval = read_xst_input_sync_at_bsn(termout, format, R_MEM);
+        }
+        else if (addr == "fpga/xst_output_sync_bsn") {
+            retval = read_xst_output_sync_bsn(termout, format, R_MEM);
+        }
         else if (addr == "fpga/processing_enable") {
             retval = read_mm_port(termout, "REG_BSN_SOURCE_V2", "dp_on", format);
         }
@@ -414,6 +424,9 @@ bool Periph_fpga::write(TermOutput& termout, const string addr, const string typ
         else if (addr == "fpga/xst_offload_enable") {
             retval = write_xst_offload_enable(data);
         }
+        else if (addr == "fpga/xst_offload_nof_crosslets") {
+            retval = write_xst_offload_nof_crosslets(data);
+        }
         else if (addr == "fpga/xst_offload_hdr_eth_destination_mac") {
             retval = write_xst_offload_hdr_eth_destination_mac(data);
         }
@@ -483,6 +496,8 @@ bool Periph_fpga::monitor(TermOutput& termout)
         read_time_since_last_pps(termout, REG_FORMAT_INT64, R_UCP);
         read_bsn_monitor_input_sync_timeout(termout, REG_FORMAT_INT64, R_UCP);
         read_bsn_monitor_input_bsn(termout, REG_FORMAT_INT64, R_UCP);
+        read_xst_input_sync_at_bsn(termout, REG_FORMAT_INT64, R_UCP);
+        read_xst_output_sync_bsn(termout, REG_FORMAT_INT64, R_UCP);
         read_bsn_monitor_input_nof_packets(termout, REG_FORMAT_INT32, R_UCP);
         read_bsn_monitor_input_nof_valid(termout, REG_FORMAT_INT32, R_UCP);
         read_bsn_monitor_input_nof_err(termout, REG_FORMAT_INT32, R_UCP);
@@ -1292,6 +1307,11 @@ bool Periph_fpga::write_xst_offload_enable(const char *data)
     return Write("mm/0/REG_STAT_ENABLE_XST/0/enable", _data);
 }
 
+bool Periph_fpga::write_xst_offload_nof_crosslets(const char *data)
+{
+    uint32_t *_ptr = (uint32_t *)data;
+    return Write("mm/0/REG_NOF_CROSSLETS/0/nof_crosslets", _ptr);
+}
 
 bool Periph_fpga::read_xst_offload_hdr_eth_destination_mac(TermOutput& termout, int format)
 {
@@ -1398,13 +1418,12 @@ bool Periph_fpga::read_xst_processing_enable(TermOutput& termout, int format)
 {
     bool retval = true;
 
-    // uint32_t data[20];
-    // memset((void *)data, 0, sizeof(data));
-    // retval = Read("mm/0/REG_BSN_SCHEDULER_XSUB/0/enable", data);
-    // bool processing_enable = (bool)data[0];
+    uint32_t data[1];
+    memset((void *)data, 0, sizeof(data));
+    retval = Read("mm/0/REG_BSN_SYNC_SCHEDULER_XSUB/0/mon_output_enable", data);
 
     bool *_ptr = (bool *)termout.val;
-    *_ptr = my_xst_processing_enable;
+    *_ptr = (bool)data[0];;
     termout.nof_vals = 1;
     termout.datatype = format;
     return retval;
@@ -1415,38 +1434,41 @@ bool Periph_fpga::write_xst_processing_enable(const char *data)
     bool retval = true;
     uint32_t *reg = new uint32_t[2];
     bool processing_enable = (bool)data[0];
-    uint64_t scheduled_bsn;
+    uint64_t start_bsn;
     if (processing_enable == true) {
         // get bsn and add latency
-        retval &= Read("mm/0/REG_BSN_SCHEDULER_XSUB/0/scheduled_bsn", reg);
+        retval &= Read("mm/0/REG_BSN_SYNC_SCHEDULER_XSUB/0/mon_input_bsn_at_sync", reg);
         if (retval == true) {
-            scheduled_bsn = (((uint64_t)reg[1] << 32) + reg[0]);
-            cout << "bsn=" << to_string(scheduled_bsn) << endl;
-            scheduled_bsn += C_BSN_LATENCY;
-            cout << "new bsn=" << to_string(scheduled_bsn) << endl;
-            reg[0] = (uint32_t)(scheduled_bsn & 0xffffffff);
-            reg[1] = (uint32_t)((scheduled_bsn >> 32) & 0xffffffff);
+            start_bsn = (((uint64_t)reg[1] << 32) + reg[0]);
+            cout << "bsn=" << to_string(start_bsn) << endl;
+            start_bsn = start_bsn + (2 * C_F_adc) / C_N_fft;
+            cout << "new bsn=" << to_string(start_bsn) << endl;
+            reg[0] = (uint32_t)(start_bsn & 0xffffffff);
+            reg[1] = (uint32_t)((start_bsn >> 32) & 0xffffffff);
             // write sheduled bsn
-            retval &= Write("mm/0/REG_BSN_SCHEDULER_XSUB/0/scheduled_bsn", reg);
-            if (retval == true) {
-                my_xst_processing_enable = processing_enable;
-            }
+            retval &= Write("mm/0/REG_BSN_SYNC_SCHEDULER_XSUB/0/ctrl_start_bsn", reg);
+            reg[0] = 1;
+            // write ctrl_enable = 1
+            retval &= Write("mm/0/REG_BSN_SYNC_SCHEDULER_XSUB/0/ctrl_enable", reg);
         }
     }
+    else {
+        reg[0] = 0;
+        // write ctrl_enable = 0
+        retval &= Write("mm/0/REG_BSN_SYNC_SCHEDULER_XSUB/0/ctrl_enable", reg);
+    }
     return retval;
 }
 
 bool Periph_fpga::read_xst_integration_interval(TermOutput& termout, int format)
 {
-    // TODO, fill in if supported in FW
     bool retval = true;
 
-    // uint32_t data[20];
-    // memset((void *)data, 0, sizeof(data));
-    // retval = Read("mm/0/REG_STAT_HDR_DAT_XST/0/??", data);
-    // double interval = ??;
+    uint32_t data[20];
+    memset((void *)data, 0, sizeof(data));
+    retval = Read("mm/0/REG_BSN_SYNC_SCHEDULER_XSUB/0/ctrl_interval_size", data);
+    double interval = (double)data[0] * C_T_adc;
 
-    double interval = 1.0;
     double *_ptr = (double *)termout.val;
     *_ptr = interval;
     termout.nof_vals = 1;
@@ -1456,10 +1478,10 @@ bool Periph_fpga::read_xst_integration_interval(TermOutput& termout, int format)
 
 bool Periph_fpga::write_xst_integration_interval(const char *data)
 {
-    // uint32_t *_ptr = (uint32_t *)data;
-    // TODO, fill in if supported in FW
-    // return Write("mm/0/REG_STAT_HDR_DAT_XST/0/??", data);
-    return true;
+    double *_ptr = (double *)data;
+    uint32_t *reg = new uint32_t[1];
+    reg[0] = (uint32_t)round(_ptr[0] * C_F_adc);
+    return Write("mm/0/REG_BSN_SYNC_SCHEDULER_XSUB/0/ctrl_interval_size", reg);
 }
 
 bool Periph_fpga::read_xst_subband_select(TermOutput& termout, int format)
@@ -1481,6 +1503,44 @@ bool Periph_fpga::read_xst_subband_select(TermOutput& termout, int format)
     return retval;
 }
 
+bool Periph_fpga::read_xst_input_sync_at_bsn(TermOutput& termout, int format, int mode) {
+    bool retval = true;
+    int64_t bsn = my_xst_input_bsn_at_sync;
+    if (mode == R_UCP) {
+        uint32_t data[2];
+        memset((void *)data, 0, sizeof(data));
+        string regname;
+        regname = "mm/0/REG_BSN_SYNC_SCHEDULER_XSUB/0/mon_input_bsn_at_sync";
+        retval = Read(regname, data);
+        bsn = (((int64_t)data[1] << 32) + data[0]);
+    }
+    int64_t *_ptr = (int64_t *)termout.val;
+    *_ptr = bsn;
+    termout.nof_vals = 1;
+    termout.datatype = format;
+    my_xst_input_bsn_at_sync = bsn;
+    return retval;
+}
+
+bool Periph_fpga::read_xst_output_sync_bsn(TermOutput& termout, int format, int mode) {
+    bool retval = true;
+    int64_t bsn = my_xst_output_sync_bsn;
+    if (mode == R_UCP) {
+        uint32_t data[2];
+        memset((void *)data, 0, sizeof(data));
+        string regname;
+        regname = "mm/0/REG_BSN_SYNC_SCHEDULER_XSUB/0/mon_output_sync_bsn";
+        retval = Read(regname, data);
+        bsn = (((int64_t)data[1] << 32) + data[0]);
+    }
+    int64_t *_ptr = (int64_t *)termout.val;
+    *_ptr = bsn;
+    termout.nof_vals = 1;
+    termout.datatype = format;
+    my_xst_output_sync_bsn = bsn;
+    return retval;
+}
+
 bool Periph_fpga::write_xst_subband_select(const char *data)
 {
     uint32_t *_ptr = (uint32_t *)data;
@@ -1579,10 +1639,10 @@ When FPGA_wg_enable_RW is set True, then enable the WG via mode = c_mode_calc =
 WG starts or restarts when it gets a trigger from the BSN scheduler. The trigger has to occur at the
 same BSN for all WG that are enabled, to ensure that they start synchronously. Any WG that are not
 enabled will ignore the trigger. The exact BSN at which the WG start is don't care. The trigger is
-scheduled via scheduled_bsn in REG_BSN_SCHEDULER. The current BSN can be read from the REG_BSN_SCHEDULER
-on one of the FPGAs. Assume the communication to write the scheduled_bsn in all FPGAs will take
+scheduled via start_bsn in REG_BSN_SCHEDULER. The current BSN can be read from the REG_BSN_SCHEDULER
+on one of the FPGAs. Assume the communication to write the start_bsn in all FPGAs will take
 less than 1 ms, then a margin of 10 - 100 ms is sufficient. The BSN period corresponds to 5.12 μs, so
-a c_bsn_latency = 20000 (≈ 100 ms) is sufficient for scheduled_bsn = current_bsn + c_bsn_latency.
+a c_bsn_latency = 20000 (≈ 100 ms) is sufficient for start_bsn = current_bsn + c_bsn_latency.
 The MP reports False when mode = c_mode_off = 0, else True.
 Note:
   The nof_samples field and mode field share an address in REG_DIAG_WG. The nof_samples = 2**W_wg_buf = 1024.
diff --git a/src/periph/fpga.h b/src/periph/fpga.h
index a537008216f50593c5d9dd7c431e8b2ec099cffd..6fd292664b3ebe9e1db014f254c93d8d6598e465 100644
--- a/src/periph/fpga.h
+++ b/src/periph/fpga.h
@@ -61,6 +61,8 @@ private:
 
   bool    my_bsn_input_sync_timeout;
   int64_t my_bsn_input_bsn;
+  int64_t my_xst_input_bsn_at_sync;
+  int64_t my_xst_output_sync_bsn;
   int32_t my_bsn_input_nof_packets;
   int32_t my_bsn_input_nof_valid;
   int32_t my_bsn_input_nof_err;
@@ -128,11 +130,14 @@ private:
 
   bool read_xst_subband_select(TermOutput& termout, int format);
   bool write_xst_subband_select(const char *data);
+  bool read_xst_input_sync_at_bsn(TermOutput& termout, int format, int mode);
+  bool read_xst_output_sync_bsn(TermOutput& termout, int format, int mode);  
   bool read_xst_integration_interval(TermOutput& termout, int format);
   bool write_xst_integration_interval(const char *data);
   bool read_xst_processing_enable(TermOutput& termout, int format);
   bool write_xst_processing_enable(const char *data);
   bool write_xst_offload_enable(const char *data);
+  bool write_xst_offload_nof_crosslets(const char *data);
   bool read_xst_offload_hdr_eth_destination_mac(TermOutput& termout, int format);
   bool write_xst_offload_hdr_eth_destination_mac(const char *data);
   bool read_xst_offload_hdr_ip_destination_address(TermOutput& termout, int format);
diff --git a/src/sdptr.cpp b/src/sdptr.cpp
index 4002c3b7b54624e0ba2f9a865b38e3f3485404eb..1c3a7224ed4da8dfd5349d5d4a48e5308f9a4c85 100644
--- a/src/sdptr.cpp
+++ b/src/sdptr.cpp
@@ -70,13 +70,28 @@ void monitor()
     pthread_cond_init(&SD.newpoint_cond, NULL);
 
     SD.uptime = 0;
-    
+
     gettimeofday(&current_time, NULL);
     SD.start_time = current_time.tv_sec;
 
 
     while (ServerRunning) {
+        struct timespec current_time_timespec;
+        clock_gettime(CLOCK_REALTIME, (struct timespec *)&current_time_timespec);
+
         SD.t0.tv_sec = SD.t0.tv_sec + SD.timetick;  // specify next position in time
+        if (SD.t0.tv_sec < current_time_timespec.tv_sec) {
+            // skip ahead if we already are beyond the next tick.
+            // this prevents us from trying to catch up if the host system
+            // was in hibernation or this process was otherwise suspended.
+            // this means that SD.uptime will reflect the number of seconds
+            // this process was actually running, and now - SD.start_time
+            // reflects the wall-clock time that passed since start.
+            time_t missed = current_time_timespec.tv_sec - SD.t0.tv_sec;
+            SD.uptime += (uint32_t)missed;
+            cerr << "!!!!!   MONITOR THREAD: Missed " << missed << " seconds   !!!!!" << endl;
+            SD.t0.tv_sec = current_time_timespec.tv_sec + SD.timetick;
+        }
         SD.t0.tv_nsec = 10000000L;  // 0..999999999 // offset 10ms in a new second
         pthread_mutex_lock(&SD.newpoint_lock);
         pthread_cond_timedwait(&SD.newpoint_cond, &SD.newpoint_lock, (const struct timespec *)&SD.t0);
@@ -104,12 +119,12 @@ void server_init(bool warm_start)
     ConfigReader* p = ConfigReader::getInstance();  // create object of the class ConfigReader
     p->parseFile(SD.configfile);  // parse the configuration file
     p->dumpFileValues();  // print map on the console after parsing it
-    
+
     p->getValue(SD.ant_band_station_type, "n_fpgas", SD.n_fpgas);
     p->getValue(SD.ant_band_station_type, "first_fpga_nr", SD.first_fpga_nr);
     p->getValue(SD.ant_band_station_type, "n_beamsets", SD.n_beamsets);
     p->getValue(SD.ant_band_station_type, "ip_prefix", SD.ip_prefix);
-    
+
     if (SD.n_fpgas == 0) {
         cerr << "ERROR, no settings found for '" << SD.ant_band_station_type << "'" <<endl;
         exit(EXIT_FAILURE);
@@ -178,7 +193,7 @@ int main (int argc, char* argv[])
 
     SD.configfile = "/etc/sdptr.conf";
     SD.ant_band_station_type = "-";
-    
+
     // set default values
     SD.n_fpgas = 16;
     SD.first_fpga_nr = 0;
diff --git a/src/tools/mmap.cpp b/src/tools/mmap.cpp
index 1dd0a2e0db9e8f5f71f1df2b789c7705953e6066..0363e98b06a5dab2903f87de08443b6060c364e1 100644
--- a/src/tools/mmap.cpp
+++ b/src/tools/mmap.cpp
@@ -42,7 +42,7 @@ typedef struct {
     string   field_name;
     uint32_t base_addr;  // in MM words
     uint32_t n_fields;
-    string   acces_mode;
+    string   access_mode;
     string   radix;
     uint32_t mm_mask;
     uint32_t user_mask;
@@ -78,7 +78,7 @@ void mmap_add_register(CMMap& regmap, mm_info_t mm_info)
                                        mm_info.mm_mask,
                                        mm_info.shift,
                                        mm_info.n_fields,
-                                       mm_info.acces_mode,
+                                       mm_info.access_mode,
                                        mm_info.radix,
                                        mm_info.port_type,
                                        mm_info.peripheral_span,
@@ -93,7 +93,7 @@ void mmap_add_register(CMMap& regmap, mm_info_t mm_info)
                                     mm_info.mm_mask,
                                     mm_info.shift,
                                     mm_info.n_fields,
-                                    mm_info.acces_mode,
+                                    mm_info.access_mode,
                                     mm_info.radix,
                                     mm_info.port_type,
                                     mm_info.peripheral_span,
@@ -177,9 +177,9 @@ CMMap mmap_to_regmap(istringstream& iss)
             mm_info.n_fields = stoi(val_str);
         }
 
-        strs >> val_str;  // get acces_mode
+        strs >> val_str;  // get access_mode
         if (val_str != "-") {
-            mm_info.acces_mode = val_str;
+            mm_info.access_mode = val_str;
         }
 
         strs >> val_str;  // get radix