diff --git a/src/Makefile.am b/src/Makefile.am
index 6420450f8e800dd5ebdbea23cdabc22e30d7ff07..febbac37a7329af1a44b16e0de06821aa69f2f97 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -17,7 +17,7 @@ AM_CXXFLAGS = -std=c++11 -ggdb -pedantic -Wall -Woverloaded-virtual -Wwrite-stri
 ############################################################################
 
 sdptr_SOURCES = sdptr.cpp board.h board.cpp fpga.h fpga.cpp tr.h tr.cpp map.h map.cpp \
-		node.h node.cpp registers.h registers.cpp unb_config.h unb_config.cpp config.h
+		node.h node.cpp registers.h registers.cpp unb_config.h unb_config.cpp config.h constants.h
 sdptr_LDADD = periph/libperiph.a io/libio.a tools/libtools.a opcua/libopcua.a -lboost_regex -lboost_system -lpthread -lboost_program_options -lm -lopen62541
 
 
diff --git a/src/constants.h b/src/constants.h
new file mode 100644
index 0000000000000000000000000000000000000000..0e883ad7830c60c58a032c48f720f5aba2b66a2f
--- /dev/null
+++ b/src/constants.h
@@ -0,0 +1,44 @@
+/* *************************************************************************
+* Copyright 2020
+* ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+* P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+* *********************************************************************** */
+
+/* *************************************************************************
+* Author:
+* . Leon Hiemstra
+* . Pieter Donker
+* Purpose:
+* . opc-ua to ucp translator
+* Description:
+* . used constants
+* *********************************************************************** */
+
+#ifndef CONSTANTS_H
+#define CONSTANTS_H
+
+#define C_S_pn 12
+#define C_W_adc 14
+#define C_F_adc 200E6
+
+#define C_WG_MODE_OFF  0
+#define C_WG_MODE_CALC 1
+#define C_WG_AMPL_UNIT 65536  // 2^16
+#define C_WG_PHASE_UNIT (65536.0 / 360.0)  // 2^16 / 360
+#define C_WG_FREQ_UNIT 2147483648  // 2^31
+
+#define C_BSN_LATENCY 20000  // 1 period = 5.12us, 20000 = +/- 100ms
+
+#endif
\ No newline at end of file
diff --git a/src/fpga.cpp b/src/fpga.cpp
index 4aed0a2ce3ffec514b98455371547b5b18da7e9c..16403202ecbcde1dd4abe06c111b2675c1b06841 100644
--- a/src/fpga.cpp
+++ b/src/fpga.cpp
@@ -36,6 +36,7 @@
 #include <sstream>
 #include <exception>
 
+#include "constants.h"
 #include "fpga.h"
 #include "tools/parse.h"
 
@@ -53,35 +54,44 @@ Fpga::Fpga(list<class Node*>& nodelist)
     // Add points:
     vector<int> nodes = get_all_nodes();
 
-    pointMap->add_register("FPGA_mask_R",                                    "fpga/enable_mask",                            nodes.size(), "RO", REG_FORMAT_BOOLEAN, 1);
-    pointMap->add_register("FPGA_mask_RW",                                   "fpga/enable_mask",                            nodes.size(), "RW", REG_FORMAT_BOOLEAN, 1);
-    pointMap->add_register("FPGA_status_R",                                  "fpga/status",                                 nodes.size(), "RO", REG_FORMAT_BOOLEAN, 1);
-    pointMap->add_register("FPGA_temp_R",                                    "fpga/temp",                                   nodes.size(), "RO", REG_FORMAT_FLOAT,   1);
-    pointMap->add_register("FPGA_version_R",                                 "fpga/name",                                   nodes.size(), "RO", REG_FORMAT_STRING,  1);
-    pointMap->add_register("FPGA_firmware_version_R",                        "fpga/firmware_version",                       nodes.size(), "RO", REG_FORMAT_STRING,  1);
-    pointMap->add_register("FPGA_hardware_version_R",                        "fpga/hardware_version",                       nodes.size(), "RO", REG_FORMAT_STRING,  1);
-    pointMap->add_register("FPGA_sst_offload_selector_R",                    "fpga/sst_offload_selector",                   nodes.size(), "RO", REG_FORMAT_BOOLEAN, 1);
-    pointMap->add_register("FPGA_sst_offload_selector_RW",                   "fpga/sst_offload_selector",                   nodes.size(), "RW", REG_FORMAT_BOOLEAN, 1);
-    pointMap->add_register("FPGA_sst_offload_enable_R",                      "fpga/sst_offload_enable",                     nodes.size(), "RO", REG_FORMAT_BOOLEAN, 1);
-    pointMap->add_register("FPGA_sst_offload_enable_RW",                     "fpga/sst_offload_enable",                     nodes.size(), "RW", REG_FORMAT_BOOLEAN, 1);
-    pointMap->add_register("FPGA_sst_offload_hdr_eth_destination_mac_R",     "fpga/sst_offload_hdr_eth_destination_mac",    nodes.size(), "RO", REG_FORMAT_STRING,  1);
-    pointMap->add_register("FPGA_sst_offload_hdr_eth_destination_mac_RW",    "fpga/sst_offload_hdr_eth_destination_mac",    nodes.size(), "RW", REG_FORMAT_STRING,  1);
-    pointMap->add_register("FPGA_sst_offload_hdr_ip_destination_address_R",  "fpga/sst_offload_hdr_ip_destination_address", nodes.size(), "RO", REG_FORMAT_STRING,  1);
-    pointMap->add_register("FPGA_sst_offload_hdr_ip_destination_address_RW", "fpga/sst_offload_hdr_ip_destination_address", nodes.size(), "RW", REG_FORMAT_STRING,  1);
-    pointMap->add_register("FPGA_sst_offload_hdr_udp_destination_port_R",    "fpga/sst_offload_hdr_udp_destination_port",   nodes.size(), "RO", REG_FORMAT_UINT16,  1);
-    pointMap->add_register("FPGA_sst_offload_hdr_udp_destination_port_RW",   "fpga/sst_offload_hdr_udp_destination_port",   nodes.size(), "RW", REG_FORMAT_UINT16,  1);
-    pointMap->add_register("FPGA_processing_enable_R",                       "fpga/processing_enable",                      nodes.size(), "RO", REG_FORMAT_BOOLEAN, 1);
-    pointMap->add_register("FPGA_processing_enable_RW",                      "fpga/processing_enable",                      nodes.size(), "RW", REG_FORMAT_BOOLEAN, 1);
-    pointMap->add_register("FPGA_sdp_info_station_id_R",                     "fpga/sdp_info_station_id",                    nodes.size(), "RO", REG_FORMAT_UINT32,  1);
-    pointMap->add_register("FPGA_sdp_info_station_id_RW",                    "fpga/sdp_info_station_id",                    nodes.size(), "RW", REG_FORMAT_UINT32,  1);
-    pointMap->add_register("FPGA_sdp_info_observation_id_R",                 "fpga/sdp_info_observation_id",                nodes.size(), "RO", REG_FORMAT_UINT32,  1);
-    pointMap->add_register("FPGA_sdp_info_observation_id_RW",                "fpga/sdp_info_observation_id",                nodes.size(), "RW", REG_FORMAT_UINT32,  1);
-    pointMap->add_register("FPGA_sdp_info_nyquist_sampling_zone_index_R",    "fpga/sdp_info_nyquist_sampling_zone_index",   nodes.size(), "RO", REG_FORMAT_UINT32,  1);
-    pointMap->add_register("FPGA_sdp_info_nyquist_sampling_zone_index_RW",   "fpga/sdp_info_nyquist_sampling_zone_index",   nodes.size(), "RW", REG_FORMAT_UINT32,  1);
-    pointMap->add_register("FPGA_sdp_info_antenna_band_index_R",             "fpga/sdp_info_antenna_band_index",            nodes.size(), "RO", REG_FORMAT_UINT32,  1);
-    pointMap->add_register("FPGA_sdp_info_f_adc_R",                          "fpga/sdp_info_f_adc",                         nodes.size(), "RO", REG_FORMAT_UINT32,  1);
-    pointMap->add_register("FPGA_sdp_info_fsub_type_R",                      "fpga/sdp_info_fsub_type",                     nodes.size(), "RO", REG_FORMAT_UINT32,  1);
-    pointMap->add_register("FPGA_sdp_info_block_period_R",                   "fpga/sdp_info_block_period",                  nodes.size(), "RO", REG_FORMAT_UINT32,  1);
+    pointMap->add_register("FPGA_mask_R",                                    "fpga/enable_mask",                            nodes.size(), 1, "RO", REG_FORMAT_BOOLEAN, 1);
+    pointMap->add_register("FPGA_mask_RW",                                   "fpga/enable_mask",                            nodes.size(), 1, "RW", REG_FORMAT_BOOLEAN, 1);
+    pointMap->add_register("FPGA_status_R",                                  "fpga/status",                                 nodes.size(), 1, "RO", REG_FORMAT_BOOLEAN, 1);
+    pointMap->add_register("FPGA_temp_R",                                    "fpga/temp",                                   nodes.size(), 1, "RO", REG_FORMAT_FLOAT,   1);
+    pointMap->add_register("FPGA_version_R",                                 "fpga/name",                                   nodes.size(), 1, "RO", REG_FORMAT_STRING,  1);
+    pointMap->add_register("FPGA_firmware_version_R",                        "fpga/firmware_version",                       nodes.size(), 1, "RO", REG_FORMAT_STRING,  1);
+    pointMap->add_register("FPGA_hardware_version_R",                        "fpga/hardware_version",                       nodes.size(), 1, "RO", REG_FORMAT_STRING,  1);
+    pointMap->add_register("FPGA_sst_offload_selector_R",                    "fpga/sst_offload_selector",                   nodes.size(), 1, "RO", REG_FORMAT_BOOLEAN, 1);
+    pointMap->add_register("FPGA_sst_offload_selector_RW",                   "fpga/sst_offload_selector",                   nodes.size(), 1, "RW", REG_FORMAT_BOOLEAN, 1);
+    pointMap->add_register("FPGA_sst_offload_enable_R",                      "fpga/sst_offload_enable",                     nodes.size(), 1, "RO", REG_FORMAT_BOOLEAN, 1);
+    pointMap->add_register("FPGA_sst_offload_enable_RW",                     "fpga/sst_offload_enable",                     nodes.size(), 1, "RW", REG_FORMAT_BOOLEAN, 1);
+    pointMap->add_register("FPGA_sst_offload_hdr_eth_destination_mac_R",     "fpga/sst_offload_hdr_eth_destination_mac",    nodes.size(), 1, "RO", REG_FORMAT_STRING,  1);
+    pointMap->add_register("FPGA_sst_offload_hdr_eth_destination_mac_RW",    "fpga/sst_offload_hdr_eth_destination_mac",    nodes.size(), 1, "RW", REG_FORMAT_STRING,  1);
+    pointMap->add_register("FPGA_sst_offload_hdr_ip_destination_address_R",  "fpga/sst_offload_hdr_ip_destination_address", nodes.size(), 1, "RO", REG_FORMAT_STRING,  1);
+    pointMap->add_register("FPGA_sst_offload_hdr_ip_destination_address_RW", "fpga/sst_offload_hdr_ip_destination_address", nodes.size(), 1, "RW", REG_FORMAT_STRING,  1);
+    pointMap->add_register("FPGA_sst_offload_hdr_udp_destination_port_R",    "fpga/sst_offload_hdr_udp_destination_port",   nodes.size(), 1, "RO", REG_FORMAT_UINT16,  1);
+    pointMap->add_register("FPGA_sst_offload_hdr_udp_destination_port_RW",   "fpga/sst_offload_hdr_udp_destination_port",   nodes.size(), 1, "RW", REG_FORMAT_UINT16,  1);
+    pointMap->add_register("FPGA_processing_enable_R",                       "fpga/processing_enable",                      nodes.size(), 1, "RO", REG_FORMAT_BOOLEAN, 1);
+    pointMap->add_register("FPGA_processing_enable_RW",                      "fpga/processing_enable",                      nodes.size(), 1, "RW", REG_FORMAT_BOOLEAN, 1);
+    pointMap->add_register("FPGA_sdp_info_station_id_R",                     "fpga/sdp_info_station_id",                    nodes.size(), 1, "RO", REG_FORMAT_UINT32,  1);
+    pointMap->add_register("FPGA_sdp_info_station_id_RW",                    "fpga/sdp_info_station_id",                    nodes.size(), 1, "RW", REG_FORMAT_UINT32,  1);
+    pointMap->add_register("FPGA_sdp_info_observation_id_R",                 "fpga/sdp_info_observation_id",                nodes.size(), 1, "RO", REG_FORMAT_UINT32,  1);
+    pointMap->add_register("FPGA_sdp_info_observation_id_RW",                "fpga/sdp_info_observation_id",                nodes.size(), 1, "RW", REG_FORMAT_UINT32,  1);
+    pointMap->add_register("FPGA_sdp_info_nyquist_sampling_zone_index_R",    "fpga/sdp_info_nyquist_sampling_zone_index",   nodes.size(), 1, "RO", REG_FORMAT_UINT32,  1);
+    pointMap->add_register("FPGA_sdp_info_nyquist_sampling_zone_index_RW",   "fpga/sdp_info_nyquist_sampling_zone_index",   nodes.size(), 1, "RW", REG_FORMAT_UINT32,  1);
+    pointMap->add_register("FPGA_sdp_info_antenna_band_index_R",             "fpga/sdp_info_antenna_band_index",            nodes.size(), 1, "RO", REG_FORMAT_UINT32,  1);
+    pointMap->add_register("FPGA_sdp_info_f_adc_R",                          "fpga/sdp_info_f_adc",                         nodes.size(), 1, "RO", REG_FORMAT_UINT32,  1);
+    pointMap->add_register("FPGA_sdp_info_fsub_type_R",                      "fpga/sdp_info_fsub_type",                     nodes.size(), 1, "RO", REG_FORMAT_UINT32,  1);
+    pointMap->add_register("FPGA_sdp_info_block_period_R",                   "fpga/sdp_info_block_period",                  nodes.size(), 1, "RO", REG_FORMAT_UINT32,  1);
+
+    pointMap->add_register("FPGA_wg_enable_R",                               "fpga/wg_enable",                              nodes.size(), C_S_pn, "RO", REG_FORMAT_BOOLEAN,  1);
+    pointMap->add_register("FPGA_wg_enable_RW",                              "fpga/wg_enable",                              nodes.size(), C_S_pn, "RW", REG_FORMAT_BOOLEAN,  1);
+    pointMap->add_register("FPGA_wg_amplitude_R",                            "fpga/wg_amplitude",                           nodes.size(), C_S_pn, "RO", REG_FORMAT_FLOAT,  1);
+    pointMap->add_register("FPGA_wg_amplitude_RW",                           "fpga/wg_amplitude",                           nodes.size(), C_S_pn, "RW", REG_FORMAT_FLOAT,  1);
+    pointMap->add_register("FPGA_wg_phase_R",                                "fpga/wg_phase",                               nodes.size(), C_S_pn, "RO", REG_FORMAT_FLOAT,  1);
+    pointMap->add_register("FPGA_wg_phase_RW",                               "fpga/wg_phase",                               nodes.size(), C_S_pn, "RW", REG_FORMAT_FLOAT,  1);
+    pointMap->add_register("FPGA_wg_frequency_R",                            "fpga/wg_frequency",                           nodes.size(), C_S_pn, "RO", REG_FORMAT_FLOAT,  1);
+    pointMap->add_register("FPGA_wg_frequency_RW",                           "fpga/wg_frequency",                           nodes.size(), C_S_pn, "RW", REG_FORMAT_FLOAT,  1);
 
     uint32_t scrap_span = 0;
     uint32_t scrap_span_next = 0;
@@ -89,34 +99,31 @@ Fpga::Fpga(list<class Node*>& nodelist)
     for (uint idx=0; idx<nodes.size(); idx++) {
         auto node = select_node(nodes[idx]);
         CPointMap *regmap = node->get_RegisterMap();
-        scrap_span_next = regmap->getSpan("fpga/scrap_W");
+        scrap_span_next = regmap->getDataSize("fpga/scrap");
         if (scrap_span_next > scrap_span_prev) {
             scrap_span = scrap_span_next;
         }
         scrap_span_prev = scrap_span_next;
     }
-    cout << "scrap_span=" << scrap_span;
-    scrap_span *= nodes.size();
-    cout << ", new scrap_span=" << scrap_span << endl;
-    pointMap->add_register("FPGA_scrap_R",                                   "fpga/scrap_R",                                scrap_span, "RO", REG_FORMAT_UINT32, 1);
-    pointMap->add_register("FPGA_scrap_RW",                                  "fpga/scrap_W",                                scrap_span, "RW", REG_FORMAT_UINT32, 1);
+    cout << "scrap_span=" << scrap_span << endl;
+    pointMap->add_register("FPGA_scrap_R",                                   "fpga/scrap",                                  nodes.size(), scrap_span, "RO", REG_FORMAT_UINT32, 1);
+    pointMap->add_register("FPGA_scrap_RW",                                  "fpga/scrap",                                  nodes.size(), scrap_span, "RW", REG_FORMAT_UINT32, 1);
+    
     uint32_t weights_span = 0;
     uint32_t weights_span_next = 0;
     uint32_t weights_span_prev = 0;
     for (uint idx=0; idx<nodes.size(); idx++) {
         auto node = select_node(nodes[idx]);
         CPointMap *regmap = node->get_RegisterMap();
-        weights_span_next = regmap->getSpan("fpga/weights_W");
+        weights_span_next = regmap->getDataSize("fpga/weights");
         if (weights_span_next > weights_span_prev) {
             weights_span = weights_span_next;
         }
         weights_span_prev = weights_span_next;
     }
-    cout << "weights_span=" << weights_span;
-    weights_span *= nodes.size();
-    cout << ", new weights_span=" << weights_span << endl;
-    pointMap->add_register("FPGA_weights_R",                                 "fpga/weights_R",                              weights_span, "RO", REG_FORMAT_INT16, 1);
-    pointMap->add_register("FPGA_weights_RW",                                "fpga/weights_W",                              weights_span, "RW", REG_FORMAT_INT16, 1);
+    cout << "weights_span=" << weights_span << endl;
+    pointMap->add_register("FPGA_weights_R",                                 "fpga/weights",                                nodes.size(), weights_span, "RO", REG_FORMAT_INT16, 1);
+    pointMap->add_register("FPGA_weights_RW",                                "fpga/weights",                                nodes.size(), weights_span, "RW", REG_FORMAT_INT16, 1);
 }
 
 Fpga::~Fpga()
@@ -197,7 +204,7 @@ bool Fpga::point(TermOutput& termout, const char cmd, const string addr,
         retval = true;
     }
     else if (cmd == 'W') {
-        if (nvalues < (int)pointMap->getSpan(addr)) {
+        if (nvalues < (int)pointMap->getDataSize(addr)) {
             return false;
         }
         retval = true;
@@ -206,14 +213,15 @@ bool Fpga::point(TermOutput& termout, const char cmd, const string addr,
     for (uint idx = 0; idx<nodes.size(); idx++) {
         auto node = select_node(nodes[idx]);
         // if (node->getEnabled() == false) { continue; }
-        
-        uint node_nr = node_number(node);
+
+        // uint node_nr = node_number(node);
 
         CPointMap *regmap = node->get_RegisterMap();
-        int span = regmap->getSpan(relative_addr);
+        int span = regmap->getDataSize(relative_addr);
+        
         // CMMap *mmap = node->get_MMap();
         // int span = mmap->getSpan(addr);
-        
+
         int nof_values = nvalues;
         if (nvalues < 0 || nvalues > span) {
             nof_values = span;
@@ -223,19 +231,20 @@ bool Fpga::point(TermOutput& termout, const char cmd, const string addr,
         bool done = false;
         try {
             if ((cmd == 'W') && (cm.getFormat() == FORMAT_STRING)) {
-                uint *data = new uint[20];
-                memset((void *)data, 0, sizeof(data));
-                memcpy((void *)data, (void *)cm.getStrPtr(idx), cm.getStrLen(idx));
-                nof_values = cm.getStrLen(idx) / 4;
-                if (cm.getStrLen(idx) % 4 > 0) {
-                    nof_values += 1;
-                }
+                uint *data2 = new uint[20];
+                memset((void *)data2, 0, sizeof(data2));
+                cout << "str=" << cm.getStr(idx) << " len=" << cm.getStrLen(idx) << endl;
+                memcpy((void *)data2, (void *)cm.getStrPtr(idx), cm.getStrLen(idx));
+                nof_values = cm.getStrLen(idx);
+                // if (cm.getStrLen(idx) % 4 > 0) {
+                //     nof_values += 1;
+                // }
                 if ((ret = node->exec_cmd(cmd, relative_addr, type, instance,
-                                          data, nof_values, format))) {
+                                          data2, nof_values, format))) {
                     retcnt++;
                     done = true;
                 }
-                delete[] data;
+                delete[] data2;
             }
             if (!done) {
                 uint didx = 0;
@@ -243,7 +252,7 @@ bool Fpga::point(TermOutput& termout, const char cmd, const string addr,
                     didx = idx * nof_values;
                 }
                 if ((ret = node->exec_cmd(cmd, relative_addr, type, instance,
-                                          &data[didx], nof_values, format))) {
+                                          &data[didx], nof_values*sizeof(unsigned int), format))) {
                     retcnt++;
                 }
             }
@@ -257,7 +266,7 @@ bool Fpga::point(TermOutput& termout, const char cmd, const string addr,
         return false;
     }
 
-    termout.nof_vals = pointMap->getSpan(addr);
+    termout.nof_vals = pointMap->getNodesSize(addr) * pointMap->getDataSize(addr);
     termout.datatype = pointMap->getFormat(addr);
 
     for (uint idx=0; idx<nodes.size(); idx++) {
diff --git a/src/node.cpp b/src/node.cpp
index 940f3513563dcdb719e253f73d67d587f2928ce5..fe7e36f503223e0ef19ecec8c3d87ddc9f318f76 100644
--- a/src/node.cpp
+++ b/src/node.cpp
@@ -284,7 +284,7 @@ bool Node::exec_cmd(const char cmd, const string relative_addr,
     p.nvalues = nvalues;
     p.format = format;
     if (cmd == 'W') {
-        memcpy((void *)p.data, (void *)data, nvalues*sizeof(unsigned int)); // FIXME should be char
+        memcpy((void *)p.data, (void *)data, nvalues);
         // cout << " p.relative_addr=" << p.relative_addr << endl;
         // cout << " p.nvalues=" << p.nvalues << endl;
         // cout << " p.format=" << p.format << endl;
diff --git a/src/opcua/ua_server.cpp b/src/opcua/ua_server.cpp
index be648c061e11f3a62fe0377b636e730e95052362..583932ef6a3217a37fe0ba7933180e676950d55d 100644
--- a/src/opcua/ua_server.cpp
+++ b/src/opcua/ua_server.cpp
@@ -109,8 +109,6 @@ static UA_StatusCode ua_read_DataSource(UA_Server *server,
     // weird...  must do -1
     // see: https://open62541.org/doc/current/types.html
 
-
-
     // Translator regnames start with "TR_" others "FPGA_"
     bool regname_is_for_translator = false;
     if (strncmp(regname,"TR_", 3) == 0) {
@@ -273,7 +271,6 @@ static UA_StatusCode ua_write_DataSource(UA_Server *server,
 
     UA_NodeId currentNodeId = UA_NODEID_STRING(mUaLofarNameSpace, (char *)regname);
     UA_NodeId ntype;
-    //UA_StatusCode st =
     UA_Server_readDataType(server, currentNodeId, &ntype);
 
 
@@ -288,7 +285,8 @@ static UA_StatusCode ua_write_DataSource(UA_Server *server,
         // TR_* has only scalars
         if (data->hasValue) {
             unsigned int array_length = 1;
-            unsigned int *data_sdp = new unsigned int[array_length];
+            uint32_t *data_sdp = new uint32_t[array_length];
+            // unsigned int *data_sdp = new unsigned int[array_length];
             //CMData cm = CMData(array_length);
             //cm.clear();
 
@@ -303,21 +301,21 @@ static UA_StatusCode ua_write_DataSource(UA_Server *server,
                     retval = true;
                     int16_t *dptr = (int16_t *)data->value.data;
                     for (uint i=0; i<array_length; i++) {
-                      data_sdp[i] = (int16_t)dptr[i];
+                      data_sdp[i] = (uint32_t)dptr[i];
                     }
                 } break;
                 case UA_TYPES_UINT16: {
                     retval = true;
                     uint16_t *dptr = (uint16_t *)data->value.data;
                     for (uint i=0; i<array_length; i++) {
-                      data_sdp[i] = (uint16_t)dptr[i];
+                      data_sdp[i] = (uint32_t)dptr[i];
                     }
                 } break;
                 case UA_TYPES_INT32: {
                     retval = true;
                     int32_t *dptr = (int32_t *)data->value.data;
                     for (uint i=0; i<array_length; i++) {
-                      data_sdp[i] = (int32_t)dptr[i];
+                      data_sdp[i] = (uint32_t)dptr[i];
                     }
                 } break;
                 case UA_TYPES_UINT32: {
@@ -331,7 +329,7 @@ static UA_StatusCode ua_write_DataSource(UA_Server *server,
                     retval = true;
                     bool *dptr = (bool *)data->value.data;
                     for (unsigned int i=0; i<array_length; i++) {
-                      data_sdp[i] = (unsigned int)dptr[i];
+                      data_sdp[i] = (uint32_t)dptr[i];
                     }
                 } break;
                 default: {
@@ -359,53 +357,54 @@ static UA_StatusCode ua_write_DataSource(UA_Server *server,
 
         if (data->hasValue && data->value.arrayLength > 0) {
             //data.value is a UA_Variant
-            cout << "data.value.arrayLength=" << data->value.arrayLength << endl;
+            // cout << "data.value.arrayLength=" << data->value.arrayLength << endl;
 
-            unsigned int *data_sdp = new unsigned int[data->value.arrayLength];
+            // unsigned int *data_sdp = new unsigned int[data->value.arrayLength];
+            uint32_t *data_sdp = new uint32_t[data->value.arrayLength];
             CMData cm(data->value.arrayLength);
             cm.clear();
 
             switch (ntype.identifier.numeric - 1) {
                 case UA_TYPES_STRING: {
                     cm.setFormat(FORMAT_STRING);
-                    cout << "dataformat=" << cm.getFormat() << endl;
+                    // cout << "dataformat=" << cm.getFormat() << endl;
                     UA_String *dptr = (UA_String *)data->value.data;
                     UA_String str_data;
                     for (int i=0; i<(int)data->value.arrayLength; i++){
                         str_data = dptr[i];
-                        cout << "n_chars=" << str_data.length << endl;
+                        // cout << "n_chars=" << to_string(str_data.length) << endl;
                         cm.clearStr(i);
                         memcpy((void *)cm.getStrPtr(i), (void *)str_data.data, str_data.length);
                         cout << dec << i << " [" << cm.getStr(i) << "] " << endl;
                     }
                     retval = true;
-
-                    //cout << "UA_TYPES_STRING: not implemented yet" << endl;
-                    //retval = false;
                 } break;
                 case UA_TYPES_FLOAT: {
-                    cout << "UA_TYPES_FLOAT: not implemented yet" << endl;
-                    retval = false;
+                    retval = true;
+                    float *dptr = (float *)data->value.data;
+                    for (uint i=0; i<data->value.arrayLength; i++) {
+                      data_sdp[i] = (uint32_t)dptr[i];
+                    }
                 } break;
                 case UA_TYPES_INT16: {
                     retval = true;
                     int16_t *dptr = (int16_t *)data->value.data;
                     for (uint i=0; i<data->value.arrayLength; i++) {
-                      data_sdp[i] = (int16_t)dptr[i];
+                      data_sdp[i] = (uint32_t)dptr[i];
                     }
                 } break;
                 case UA_TYPES_UINT16: {
                     retval = true;
                     uint16_t *dptr = (uint16_t *)data->value.data;
                     for (uint i=0; i<data->value.arrayLength; i++) {
-                      data_sdp[i] = (uint16_t)dptr[i];
+                      data_sdp[i] = (uint32_t)dptr[i];
                     }
                 } break;
                 case UA_TYPES_INT32: {
                     retval = true;
                     int32_t *dptr = (int32_t *)data->value.data;
                     for (uint i=0; i<data->value.arrayLength; i++) {
-                        data_sdp[i] = (int32_t)dptr[i];
+                        data_sdp[i] = (uint32_t)dptr[i];
                     }
                 } break;
                 case UA_TYPES_UINT32: {
@@ -419,7 +418,7 @@ static UA_StatusCode ua_write_DataSource(UA_Server *server,
                     retval = true;
                     bool *dptr = (bool *)data->value.data;
                     for (unsigned int i=0; i<data->value.arrayLength; i++) {
-                      data_sdp[i] = (unsigned int)dptr[i];
+                      data_sdp[i] = (uint32_t)dptr[i];
                     }
                 } break;
                 default: {
@@ -878,23 +877,16 @@ int ua_server_init(bool warm_start)
         mUaServer = UA_Server_new();
         UA_ServerConfig_setDefault(UA_Server_getConfig(mUaServer));
 
-
         mUaLofarNameSpace = UA_Server_addNamespace(mUaServer, UA_LOFAR_NAMESPACE);
         UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "UA Server ns=%d for %s\n",
                     mUaLofarNameSpace,UA_LOFAR_NAMESPACE);
 
-        // TermOutput termout;
-        //vector<int> nodes = SD.unb->get_nodes(); // all nodes
-
-        // UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "UA Server add nodes");
-
-
         UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "UA Server add pointMap");
         CPointMap *pointmap = SD.unb->get_pointMap();
         vector<string> regnames = pointmap->getRegnames("");
         for (auto m : regnames) {
             int format = pointmap->getFormat(m);
-            unsigned int size = pointmap->getSpan(m);
+            unsigned int size = pointmap->getNodesSize(m) * pointmap->getDataSize(m);
             string perm = pointmap->getPerm(m);
             ua_add_Variable(mUaServer, m, format, size, perm, false);
         }
@@ -904,7 +896,7 @@ int ua_server_init(bool warm_start)
         vector<string> trregnames = trmap->getRegnames("");
         for (auto m : trregnames) {
             int format = trmap->getFormat(m);
-            unsigned int size = trmap->getSpan(m);
+            unsigned int size = pointmap->getNodesSize(m) * pointmap->getDataSize(m);
             string perm = trmap->getPerm(m);
             ua_add_Variable(mUaServer, m, format, size, perm, true);
         }
@@ -914,7 +906,6 @@ int ua_server_init(bool warm_start)
 
 int ua_server(void)
 {
-
     UA_StatusCode retval = UA_Server_run(mUaServer, &ServerRunning);
 
     UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "UA Server Stopped");
diff --git a/src/periph/fpga.cpp b/src/periph/fpga.cpp
index 00d9d01e1c3a7895668a4841781503452068912f..a2e48f3ad82d5415f8b97cdb2dfd5a78c3d7af35 100644
--- a/src/periph/fpga.cpp
+++ b/src/periph/fpga.cpp
@@ -34,6 +34,7 @@
 #include <cstdint>
 #include <algorithm>
 #include <cstdlib>
+#include <cmath>
 
 #include <stdexcept>
 #include <iostream>
@@ -45,6 +46,7 @@
 #include <arpa/inet.h> // htons, inet_pton
 
 #include "fpga.h"
+#include "../constants.h"
 #include "../tools/mmap.h"
 #include "../tools/util.h"
 
@@ -81,46 +83,49 @@ Periph_fpga::Periph_fpga(string ipaddr, string expected_design_name, uint expect
     registerMap = new CPointMap();
     //                                                                                                         update interval
     //                                                                                                         |
-    registerMap->add_register("fpga/system",                                 "-", 0, "RO", REG_FORMAT_STRING,  2);
-    registerMap->add_register("fpga/name",                                   "-", 1, "RO", REG_FORMAT_STRING,  1);
-    registerMap->add_register("fpga/stamps",                                 "-", 0, "RO", REG_FORMAT_STRING,  1);
-    registerMap->add_register("fpga/note",                                   "-", 0, "RO", REG_FORMAT_STRING,  1);
-    registerMap->add_register("fpga/firmware_version",                       "-", 0, "RO", REG_FORMAT_STRING,  10);
-    registerMap->add_register("fpga/hardware_version",                       "-", 0, "RO", REG_FORMAT_STRING,  10);
-    registerMap->add_register("fpga/temp",                                   "-", 1, "RO", REG_FORMAT_STRING,  5);
-    registerMap->add_register("fpga/status",                                 "-", 1, "RO", REG_FORMAT_STRING,  1);
-    registerMap->add_register("fpga/enable_mask",                            "-", 1, "RW", REG_FORMAT_BOOLEAN, 1);
-    registerMap->add_register("fpga/rbf",                                    "-", 0, "RW", REG_FORMAT_STRING,  1);
-    registerMap->add_register("fpga/flash_init",                             "-", 0, "WO", REG_FORMAT_STRING,  1);
-    registerMap->add_register("fpga/flash_erase",                            "-", 0, "WO", REG_FORMAT_STRING,  1);
-    registerMap->add_register("fpga/flash_pages",                            "-", 0, "WO", REG_FORMAT_STRING,  1);
-    registerMap->add_register("fpga/flash_page",                             "-", 0, "WO", REG_FORMAT_STRING,  1);
-    registerMap->add_register("fpga/flash_prot",                             "-", 0, "WO", REG_FORMAT_STRING,  1);
-    registerMap->add_register("fpga/epcs_wait_busy",                         "-", 0, "RO", REG_FORMAT_STRING,  1);
-    registerMap->add_register("fpga/epcs_mmdp_data",                         "-", 0, "WO", REG_FORMAT_STRING,  1);
-
-    uint32_t scrap_span = mmap->getSpan("mm/0/RAM_SCRAP/data");
-    registerMap->add_register("fpga/scrap_R",                                "-", scrap_span, "RO", REG_FORMAT_UINT32, 1);
-    registerMap->add_register("fpga/scrap_W",                                "-", scrap_span, "RW", REG_FORMAT_UINT32, 1);
+    registerMap->add_register("fpga/system",                                 "-", 0, 1, "RO", REG_FORMAT_STRING,  2);
+    registerMap->add_register("fpga/name",                                   "-", 1, 1, "RO", REG_FORMAT_STRING,  1);
+    registerMap->add_register("fpga/stamps",                                 "-", 0, 1, "RO", REG_FORMAT_STRING,  1);
+    registerMap->add_register("fpga/note",                                   "-", 0, 1, "RO", REG_FORMAT_STRING,  1);
+    registerMap->add_register("fpga/firmware_version",                       "-", 0, 1, "RO", REG_FORMAT_STRING,  10);
+    registerMap->add_register("fpga/hardware_version",                       "-", 0, 1, "RO", REG_FORMAT_STRING,  10);
+    registerMap->add_register("fpga/temp",                                   "-", 1, 1, "RO", REG_FORMAT_STRING,  5);
+    registerMap->add_register("fpga/status",                                 "-", 1, 1, "RO", REG_FORMAT_STRING,  1);
+    registerMap->add_register("fpga/enable_mask",                            "-", 1, 1, "RW", REG_FORMAT_BOOLEAN, 1);
+    registerMap->add_register("fpga/rbf",                                    "-", 0, 1, "RW", REG_FORMAT_STRING,  1);
+    registerMap->add_register("fpga/flash_init",                             "-", 0, 1, "WO", REG_FORMAT_STRING,  1);
+    registerMap->add_register("fpga/flash_erase",                            "-", 0, 1, "WO", REG_FORMAT_STRING,  1);
+    registerMap->add_register("fpga/flash_pages",                            "-", 0, 1, "WO", REG_FORMAT_STRING,  1);
+    registerMap->add_register("fpga/flash_page",                             "-", 0, 1, "WO", REG_FORMAT_STRING,  1);
+    registerMap->add_register("fpga/flash_prot",                             "-", 0, 1, "WO", REG_FORMAT_STRING,  1);
+    registerMap->add_register("fpga/epcs_wait_busy",                         "-", 0, 1, "RO", REG_FORMAT_STRING,  1);
+    registerMap->add_register("fpga/epcs_mmdp_data",                         "-", 0, 1, "WO", REG_FORMAT_STRING,  1);
+
+    uint32_t scrap_span = mmap->getSpan("mm/0/RAM_SCRAP/0/data");
+    registerMap->add_register("fpga/scrap",                                "-", 1, scrap_span, "RW", REG_FORMAT_UINT32, 20);
 
     uint32_t weights_span = (187392 / 16);  // = 11712
-    registerMap->add_register("fpga/weights_R",                              "-", weights_span, "RO", REG_FORMAT_INT16, 1);
-    registerMap->add_register("fpga/weights_W",                              "-", weights_span, "RW", REG_FORMAT_INT16, 1);
-
-    registerMap->add_register("fpga/processing_enable",                      "-", 1, "RW", REG_FORMAT_BOOLEAN, 1);
-    registerMap->add_register("fpga/sst_offload_selector",                   "-", 1, "RW", REG_FORMAT_BOOLEAN, 1);
-    registerMap->add_register("fpga/sst_offload_enable",                     "-", 1, "RW", REG_FORMAT_BOOLEAN, 1);
-    registerMap->add_register("fpga/sst_offload_hdr_eth_destination_mac",    "-", 1, "RW", REG_FORMAT_STRING,  1);
-    registerMap->add_register("fpga/sst_offload_hdr_ip_destination_address", "-", 1, "RW", REG_FORMAT_STRING,  1);
-    registerMap->add_register("fpga/sst_offload_hdr_udp_destination_port",   "-", 1, "RW", REG_FORMAT_UINT16,  1);
-
-    registerMap->add_register("fpga/sdp_info_station_id",                    "-", 1, "RW", REG_FORMAT_UINT32, 1);
-    registerMap->add_register("fpga/sdp_info_observation_id",                "-", 1, "RW", REG_FORMAT_UINT32, 1);
-    registerMap->add_register("fpga/sdp_info_nyquist_sampling_zone_index",   "-", 1, "RW", REG_FORMAT_UINT32, 1);
-    registerMap->add_register("fpga/sdp_info_antenna_band_index",            "-", 1, "RO", REG_FORMAT_UINT32, 1);
-    registerMap->add_register("fpga/sdp_info_f_adc",                         "-", 1, "RO", REG_FORMAT_UINT32, 1);
-    registerMap->add_register("fpga/sdp_info_fsub_type",                     "-", 1, "RO", REG_FORMAT_UINT32, 1);
-    registerMap->add_register("fpga/sdp_info_block_period",                  "-", 1, "RO", REG_FORMAT_UINT32, 1);
+    registerMap->add_register("fpga/weights",                              "-", 1, weights_span, "RW", REG_FORMAT_INT16, 33);
+
+    registerMap->add_register("fpga/processing_enable",                      "-", 1, 1, "RW", REG_FORMAT_BOOLEAN, 1);
+    registerMap->add_register("fpga/sst_offload_selector",                   "-", 1, 1, "RW", REG_FORMAT_BOOLEAN, 1);
+    registerMap->add_register("fpga/sst_offload_enable",                     "-", 1, 1, "RW", REG_FORMAT_BOOLEAN, 1);
+    registerMap->add_register("fpga/sst_offload_hdr_eth_destination_mac",    "-", 1, 1, "RW", REG_FORMAT_STRING,  1);
+    registerMap->add_register("fpga/sst_offload_hdr_ip_destination_address", "-", 1, 1, "RW", REG_FORMAT_STRING,  1);
+    registerMap->add_register("fpga/sst_offload_hdr_udp_destination_port",   "-", 1, 1, "RW", REG_FORMAT_UINT16,  1);
+
+    registerMap->add_register("fpga/sdp_info_station_id",                    "-", 1, 1, "RW", REG_FORMAT_UINT32, 1);
+    registerMap->add_register("fpga/sdp_info_observation_id",                "-", 1, 1, "RW", REG_FORMAT_UINT32, 1);
+    registerMap->add_register("fpga/sdp_info_nyquist_sampling_zone_index",   "-", 1, 1, "RW", REG_FORMAT_UINT32, 1);
+    registerMap->add_register("fpga/sdp_info_antenna_band_index",            "-", 1, 1, "RO", REG_FORMAT_UINT32, 1);
+    registerMap->add_register("fpga/sdp_info_f_adc",                         "-", 1, 1, "RO", REG_FORMAT_UINT32, 1);
+    registerMap->add_register("fpga/sdp_info_fsub_type",                     "-", 1, 1, "RO", REG_FORMAT_UINT32, 1);
+    registerMap->add_register("fpga/sdp_info_block_period",                  "-", 1, 1, "RO", REG_FORMAT_UINT32, 1);
+
+    registerMap->add_register("fpga/wg_enable",                              "-", 1, 12, "RW", REG_FORMAT_BOOLEAN, 1);
+    registerMap->add_register("fpga/wg_amplitude",                           "-", 1, 12, "RW", REG_FORMAT_FLOAT, 1);
+    registerMap->add_register("fpga/wg_phase",                               "-", 1, 12, "RW", REG_FORMAT_FLOAT, 1);
+    registerMap->add_register("fpga/wg_frequency",                           "-", 1, 12, "RW", REG_FORMAT_FLOAT, 1);
 
     registerMap->print_screen();
 
@@ -171,7 +176,7 @@ Periph_fpga::~Periph_fpga()
     if (registerMap != NULL) delete registerMap;
 }
 
-bool Periph_fpga::Read(const string addr_str, uint32_t *data_ptr)
+bool Periph_fpga::Read(const string addr_str, uint32_t *data_ptr, bool use_mask_shift=true)
 {
     bool ret;
     if (!Enabled) {
@@ -181,27 +186,24 @@ bool Periph_fpga::Read(const string addr_str, uint32_t *data_ptr)
     if (!mmap->find_register(addr_str)) {
         return false;
     }
-    
+
     uint32_t addr = mmap->getAddr((addr_str));
 
     mmap->getReadPermission((addr_str));
 
     uint32_t nvalues = mmap->getSpan((addr_str));
-    uint32_t mask = mmap->getMask((addr_str));
-    uint32_t shift = mmap->getShift((addr_str));
     bool isfifo = mmap->type_isfifo((addr_str));
 
     ret = ucp->readRegister(addr, nvalues, data_ptr, isfifo);
-    if (ret && (shift != 0 || mask != 0xffffffff)) {
+    if (use_mask_shift) {
         for (uint32_t i=0; i<nvalues; i++) {
-            data_ptr[i] &= mask;
-            data_ptr[i] = data_ptr[i] >> shift;
+            data_ptr[i] = mask_shift(addr_str, data_ptr[i]);
         }
     }
     return ret;
 }
 
-bool Periph_fpga::Write(const string addr_str, const uint32_t nvalues, uint32_t *data_ptr)
+bool Periph_fpga::Write(const string addr_str, const uint32_t nvalues, uint32_t *data_ptr, bool use_shift_mask=true)
 {
     if (!Enabled) {
         return false;
@@ -212,21 +214,47 @@ bool Periph_fpga::Write(const string addr_str, const uint32_t nvalues, uint32_t
     }
     uint32_t addr = mmap->getValidAddr((addr_str), 1);
     uint32_t span = mmap->getSpan((addr_str));
+    cout << "addr=" << addr_str << " span=" << to_string(span) << endl;
     mmap->getWritePermission((addr_str));
 
-    uint32_t shift = mmap->getShift((addr_str));
-    uint32_t mask = mmap->getMask((addr_str));
     bool isfifo = mmap->type_isfifo((addr_str));
-
-    if (shift != 0 || mask != 0xffffffff) {
+    if (use_shift_mask) {
         for (uint32_t i=0; i<span; i++) {
-            data_ptr[i] = data_ptr[i] << shift;
-            data_ptr[i] &= mask;
+            data_ptr[i] = shift_mask(addr_str, data_ptr[i]);
         }
     }
     return ucp->writeRegister(addr, span, data_ptr, isfifo);
 }
 
+// for reading
+uint32_t Periph_fpga::mask_shift(const string addr_str, uint32_t data)
+{
+    uint32_t shift = mmap->getShift((addr_str));
+    uint32_t mask = mmap->getMask((addr_str));
+    uint32_t _data = data;
+
+    if (shift != 0 || mask != 0xffffffff) {
+        _data &= mask;
+        _data = _data >> shift;
+    }
+    return _data;
+}
+
+// for writing
+uint32_t Periph_fpga::shift_mask(const string addr_str, uint32_t data)
+{
+    uint32_t shift = mmap->getShift((addr_str));
+    uint32_t mask = mmap->getMask((addr_str));
+    uint32_t _data = data;
+
+    if (shift != 0 || mask != 0xffffffff) {
+        _data = _data << shift;
+        _data &= mask;
+    }
+    return _data;
+}
+
+
 bool Periph_fpga::read_fpga_status(TermOutput& termout, int format)
 {
     if (my_current_status == "online") {
@@ -254,8 +282,6 @@ bool Periph_fpga::read_fpga_enable_mask(TermOutput& termout, int format)
     return true;
 }
 
-
-
 /*
 """Peripheral system_info
    Register map:
@@ -360,17 +386,12 @@ bool Periph_fpga::read(TermOutput& termout, const string addr,
         else if (addr == "fpga/enable_mask") {
             retval = read_fpga_enable_mask(termout, format);
         }
-        else if (addr == "fpga/scrap_RW") {
-            retval = read_fpga_scrap_RW(termout, format);
-        }
-        else if (addr == "fpga/scrap_R") {
-            retval = read_fpga_scrap_R(termout, format);
+        else if (addr == "fpga/scrap") {
+            retval = read_fpga_scrap(termout, format, R_MEM);
         }
-        else if (addr == "fpga/weights_RW") {
-            retval = read_fpga_weights_RW(termout, format);
-        }
-        else if (addr == "fpga/weights_R") {
-            retval = read_fpga_weights_R(termout, format);
+        else if (addr == "fpga/weights") {
+            // retval = read_fpga_weights(termout, format);
+            retval = read_fpga_weights(termout, format, R_MEM);
         }
         else if (addr == "fpga/sst_offload_selector") {
             retval = read_sst_offload_selector(termout, format);
@@ -411,6 +432,18 @@ bool Periph_fpga::read(TermOutput& termout, const string addr,
         else if (addr == "fpga/sdp_info_block_period") {
             retval = read_sdp_info_block_period(termout, format);
         }
+        else if (addr == "fpga/wg_enable") {
+            retval = read_wg_enable(termout, format);
+        }
+        else if (addr == "fpga/wg_amplitude") {
+            retval = read_wg_amplitude(termout, format);
+        }
+        else if (addr == "fpga/wg_phase") {
+            retval = read_wg_phase(termout, format);
+        }
+        else if (addr == "fpga/wg_frequency") {
+            retval = read_wg_frequency(termout, format);
+        }
 
         else {
             throw runtime_error("address " + addr + " not found!");
@@ -467,11 +500,11 @@ bool Periph_fpga::write(TermOutput& termout, const string addr, const string typ
         else if (addr == "fpga/enable_mask") {
             retval = write_fpga_enable_mask(data);
         }
-        else if (addr == "fpga/scrap_W") {
-            retval = write_fpga_scrap_RW(data_ptr, nvalues);
+        else if (addr == "fpga/scrap") {
+            retval = write_fpga_scrap(data_ptr, nvalues);
         }
-        else if (addr == "fpga/weights_W") {
-            retval = write_fpga_weights_RW(data_ptr, nvalues);
+        else if (addr == "fpga/weights") {
+            retval = write_fpga_weights(data_ptr, nvalues);
         }
         else if (addr == "fpga/sst_offload_selector") {
             retval = write_sst_offload_selector(data_ptr, nvalues);
@@ -480,11 +513,9 @@ bool Periph_fpga::write(TermOutput& termout, const string addr, const string typ
             retval = write_sst_offload_enable(data_ptr, nvalues);
         }
         else if (addr == "fpga/sst_offload_hdr_eth_destination_mac") {
-            //retval = write_sst_offload_hdr_eth_destination_mac(data_ptr, nvalues);
             retval = write_sst_offload_hdr_eth_destination_mac(data, nvalues);
         }
         else if (addr == "fpga/sst_offload_hdr_ip_destination_address") {
-            //retval = write_sst_offload_hdr_ip_destination_address(data_ptr, nvalues);
             retval = write_sst_offload_hdr_ip_destination_address(data, nvalues);
         }
         else if (addr == "fpga/sst_offload_hdr_udp_destination_port") {
@@ -502,6 +533,18 @@ bool Periph_fpga::write(TermOutput& termout, const string addr, const string typ
         else if (addr == "fpga/sdp_info_nyquist_sampling_zone_index") {
             retval = write_sdp_info_nyquist_sampling_zone_index(data_ptr, nvalues);
         }
+        else if (addr == "fpga/wg_enable") {
+            retval = write_wg_enable(data_ptr, nvalues);
+        }
+        else if (addr == "fpga/wg_amplitude") {
+            retval = write_wg_amplitude(data_ptr, nvalues);
+        }
+        else if (addr == "fpga/wg_phase") {
+            retval = write_wg_phase(data_ptr, nvalues);
+        }
+        else if (addr == "fpga/wg_frequency") {
+            retval = write_wg_frequency(data_ptr, nvalues);
+        }
         else {
             throw runtime_error("address " + addr + " not found!");
         }
@@ -529,6 +572,14 @@ bool Periph_fpga::monitor(TermOutput& termout, uint seconds)
         read_firmware_version(termout, REG_FORMAT_STRING, R_UCP);
         termout.clear();
     }
+    if ((seconds % registerMap->getUpdateInterval("fpga/scrap")) == 0) {
+        read_fpga_scrap(termout, REG_FORMAT_UINT32, R_UCP);
+        termout.clear();
+    }
+    if ((seconds % registerMap->getUpdateInterval("fpga/weights")) == 0) {
+        read_fpga_weights(termout, REG_FORMAT_INT16, R_UCP);
+        termout.clear();
+    }
     return true;
 }
 
@@ -647,7 +698,7 @@ string Periph_fpga::read_design_name()
 {
     uint32_t data[20];
     memset((void *)data, 0, sizeof(data));
-    if (Read("mm/0/PIO_SYSTEM_INFO/design_name", data)) {
+    if (Read("mm/0/PIO_SYSTEM_INFO/0/design_name", data)) {
         char *str_ptr = (char *)data;
         string name = string(str_ptr);
         //if (data != NULL) delete[] data;
@@ -660,7 +711,7 @@ string Periph_fpga::read_design_note()
 {
     uint32_t data[20];
     memset((void *)data, 0, sizeof(data));
-    if (Read("mm/0/PIO_SYSTEM_INFO/design_note", data)) {
+    if (Read("mm/0/PIO_SYSTEM_INFO/0/design_note", data)) {
         char *str_ptr = (char *)data;
         string note = string(str_ptr);
         //if (data != NULL) delete[] data;
@@ -677,7 +728,7 @@ bool Periph_fpga::read_hardware_version(TermOutput& termout, int format, int mod
         uint32_t data[20];
         uint hw_version_nr;
         memset((void *)data, 0, sizeof(data));
-        retval = Read("mm/0/PIO_SYSTEM_INFO/info_hw_version", data);
+        retval = Read("mm/0/PIO_SYSTEM_INFO/0/info_hw_version", data);
         if (retval == false) { return false; }
         hw_version_nr = data[0];
         if (hw_version_nr == 1) {
@@ -705,26 +756,26 @@ bool Periph_fpga::read_firmware_version(TermOutput& termout, int format, int mod
         uint32_t data[20];
 
         memset((void *)data, 0, sizeof(data));
-        retval = Read("mm/0/PIO_SYSTEM_INFO/design_name", data);
+        retval = Read("mm/0/PIO_SYSTEM_INFO/0/design_name", data);
         if (retval == false) { return retval; }
         char *str_ptr = (char *)data;
         string design_name = string(str_ptr);
 
         memset((void *)data, 0, sizeof(data));
-        retval = Read("mm/0/PIO_SYSTEM_INFO/stamp_date", data);
+        retval = Read("mm/0/PIO_SYSTEM_INFO/0/stamp_date", data);
         if (retval == false) { return retval; }
         string date = to_string(data[0]);
 
         memset((void *)data, 0, sizeof(data));
-        retval = Read("mm/0/PIO_SYSTEM_INFO/stamp_time", data);
+        retval = Read("mm/0/PIO_SYSTEM_INFO/0/stamp_time", data);
         if (retval == false) { return retval; }
         string time = to_string(data[0]);
 
         memset((void *)data, 0, sizeof(data));
-        retval = Read("mm/0/PIO_SYSTEM_INFO/stamp_commit", data);
+        retval = Read("mm/0/PIO_SYSTEM_INFO/0/stamp_commit", data);
         if (retval == false) { return retval; }
         string revision = to_string(data[0]);
-    
+
         version = date.substr(0, 2) + "-" + date.substr(2, 2) + "-" + date.substr(4, 2)
                 + "T"
                 + time.substr(0, 2) + "." + time.substr(2, 2) + "." + time.substr(4, 2)
@@ -743,7 +794,7 @@ bool Periph_fpga::read_stamps(TermOutput& termout, int format)
 {
     uint32_t data[20];
     memset((void *)data, 0, sizeof(data));
-    bool retval = Read("mm/0/PIO_SYSTEM_INFO/stamp_date", data);
+    bool retval = Read("mm/0/PIO_SYSTEM_INFO/0/stamp_date", data);
 
     termout.datatype = format;
     return retval;
@@ -757,7 +808,7 @@ bool Periph_fpga::read_fpga_temperature(TermOutput& termout, int format, int mod
         // cout << "read from UCP" << endl;
         uint32_t data[20];
         memset((void *)data, 0, sizeof(data));
-        retval = Read("mm/0/REG_FPGA_TEMP_SENS/temp", data);
+        retval = Read("mm/0/REG_FPGA_TEMP_SENS/0/temp", data);
         if (retval == false) { return false; }
         // ADC to engineering
         // see the constants: https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_alttemp_sense.pdf
@@ -772,22 +823,29 @@ bool Periph_fpga::read_fpga_temperature(TermOutput& termout, int format, int mod
     return retval;
 }
 
-bool Periph_fpga::read_fpga_scrap_R(TermOutput& termout, int format)
+bool Periph_fpga::read_fpga_scrap(TermOutput& termout, int format, int mode)
 {
     bool retval = true;
-
-    uint32_t nvalues = mmap->getSpan("mm/0/RAM_SCRAP/data");
     uint32_t *ptr = (uint32_t *)termout.val;
-    retval = Read("mm/0/RAM_SCRAP/data", ptr);
-    termout.nof_vals = nvalues;
+    if (mode == R_UCP) {
+        uint32_t nvalues = mmap->getSpan("mm/0/RAM_SCRAP/0/data");
+        retval = Read("mm/0/RAM_SCRAP/0/data", ptr);
+        termout.nof_vals = nvalues;
+    }
+    else {
+        for (uint i=0; i<Scrap_RW_copy.size(); i++) {
+            ptr[i] = Scrap_RW_copy[i];
+            termout.nof_vals = Scrap_RW_copy.size();
+        }
+    }
     termout.datatype = format;
     return retval;
 }
 
-bool Periph_fpga::write_fpga_scrap_RW(uint32_t *data, uint nvalues)
+bool Periph_fpga::write_fpga_scrap(uint32_t *data, uint nvalues)
 {
     cout << "Periph_fpga::write_fpga_scrap " << nvalues << " values" << endl;
-    uint32_t nvalues_chk = mmap->getSpan("mm/0/RAM_SCRAP/data");
+    uint32_t nvalues_chk = mmap->getSpan("mm/0/RAM_SCRAP/0/data");
     if (nvalues > nvalues_chk) {
         nvalues = nvalues_chk;
     }
@@ -797,53 +855,46 @@ bool Periph_fpga::write_fpga_scrap_RW(uint32_t *data, uint nvalues)
         cout << data[i] << " ";
     }
     cout << endl;
-    bool retval = Write("mm/0/RAM_SCRAP/data", nvalues, data);
-    return retval;
-}
-
-bool Periph_fpga::read_fpga_scrap_RW(TermOutput& termout, int format)
-{
-    bool retval = true;
-
-    uint32_t *ptr = (uint32_t *)termout.val;
-    for (uint i=0; i<Scrap_RW_copy.size(); i++) {
-        ptr[i] = Scrap_RW_copy[i];
-    }
-    termout.nof_vals = Scrap_RW_copy.size();
-    termout.datatype = format;
+    bool retval = Write("mm/0/RAM_SCRAP/0/data", nvalues, data);
     return retval;
 }
 
-bool Periph_fpga::read_fpga_weights_R(TermOutput& termout, int format)
+bool Periph_fpga::read_fpga_weights(TermOutput& termout, int format, int mode)
 {
     bool retval = true;
-    uint32_t nvalues_scrap = mmap->getSpan("mm/0/RAM_SCRAP/data");
-    uint nblocks = 48; // 11712/244=48
-
-    uint32_t *data_scrap = new uint32_t[nvalues_scrap];
-    short *ptr = (short *)termout.val;
+    int16_t *ptr = (int16_t *)termout.val;
+    if (mode == R_UCP) {
+        uint32_t nvalues_scrap = mmap->getSpan("mm/0/RAM_SCRAP/0/data");
+        uint nblocks = 48; // 11712/244=48
 
-    for (uint i=0; i<nblocks; i++) {
-        retval = Read("mm/0/RAM_SCRAP/data", data_scrap);
+        uint32_t *data_scrap = new uint32_t[nvalues_scrap];
+        for (uint i=0; i<nblocks; i++) {
+            retval = Read("mm/0/RAM_SCRAP/0/data", data_scrap);
 
-        for (uint j=0; j<nvalues_scrap; j+=2) {
-            uint32_t ds = data_scrap[j];
-            *ptr++ = (short)(ds & 0xffff);
-            *ptr++ = (short)(ds >> 16);
+            for (uint j=0; j<nvalues_scrap; j+=2) {
+                uint32_t ds = data_scrap[j];
+                *ptr++ = (int16_t)(ds & 0xffff);
+                *ptr++ = (int16_t)(ds >> 16);
+            }
         }
+        termout.nof_vals = registerMap->getDataSize("fpga/weights_R");
+        delete[] data_scrap;
+    }
+    else {
+        for (uint i=0; i<Weights_RW_copy.size(); i++) {
+            ptr[i] = Weights_RW_copy[i];
+        }
+        termout.nof_vals = Weights_RW_copy.size();
     }
-
-    termout.nof_vals = registerMap->getSpan("fpga/weights_R");
     termout.datatype = format;
-    delete[] data_scrap;
     return retval;
 }
 
-bool Periph_fpga::write_fpga_weights_RW(const uint32_t *data, uint nvalues)
+bool Periph_fpga::write_fpga_weights(const uint32_t *data, uint nvalues)
 {
     bool retval = false;
-    uint32_t nvalues_scrap = mmap->getSpan("mm/0/RAM_SCRAP/data");
-    uint32_t nvalues_weights = registerMap->getSpan("fpga/weights_R");
+    uint32_t nvalues_scrap = mmap->getSpan("mm/0/RAM_SCRAP/0/data");
+    uint32_t nvalues_weights = registerMap->getDataSize("fpga/weights_R");
     uint nblocks = 48; // 11712/244=48
     if (nvalues > nvalues_weights) {
         nvalues = nvalues_weights;
@@ -872,35 +923,20 @@ bool Periph_fpga::write_fpga_weights_RW(const uint32_t *data, uint nvalues)
             si++;
             data_scrap[j] = ds;
         }
-        retval = Write("mm/0/RAM_SCRAP/data", nvalues_scrap, data_scrap);
+        retval = Write("mm/0/RAM_SCRAP/0/data", nvalues_scrap, data_scrap);
     }
 
     delete[] data_scrap;
     return retval;
 }
 
-bool Periph_fpga::read_fpga_weights_RW(TermOutput& termout, int format)
-{
-    bool retval = true;
-
-    short *ptr = (short *)termout.val;
-    for (uint i=0; i<Weights_RW_copy.size(); i++) {
-        ptr[i] = Weights_RW_copy[i];
-    }
-    termout.nof_vals = Weights_RW_copy.size();
-    termout.datatype = format;
-    return retval;
-}
-
-
-
 bool Periph_fpga::read_sst_offload_selector(TermOutput& termout, int format)
 {
     bool retval = true;
 
     uint32_t data[20];
     memset((void *)data, 0, sizeof(data));
-    retval = Read("mm/0/REG_DP_SELECTOR/input_select", data);
+    retval = Read("mm/0/REG_DP_SELECTOR/0/input_select", data);
 
     bool select = (bool)data[0];
 
@@ -913,7 +949,7 @@ bool Periph_fpga::read_sst_offload_selector(TermOutput& termout, int format)
 
 bool Periph_fpga::write_sst_offload_selector(uint32_t *data, uint32_t nvalues)
 {
-    bool retval = Write("mm/0/REG_DP_SELECTOR/input_select", nvalues, data);
+    bool retval = Write("mm/0/REG_DP_SELECTOR/0/input_select", nvalues, data);
     return retval;
 }
 
@@ -923,7 +959,7 @@ bool Periph_fpga::read_sst_offload_enable(TermOutput& termout, int format)
 
     uint32_t data[20];
     memset((void *)data, 0, sizeof(data));
-    retval = Read("mm/0/REG_STAT_ENABLE_SST/enable", data);
+    retval = Read("mm/0/REG_STAT_ENABLE_SST/0/enable", data);
 
     bool select = (bool)data[0];
 
@@ -937,7 +973,7 @@ bool Periph_fpga::read_sst_offload_enable(TermOutput& termout, int format)
 bool Periph_fpga::write_sst_offload_enable(uint32_t *data, uint32_t nvalues)
 {
     cout << "sst_offload_enable data=" << data[0] << " nvlues=" << nvalues << endl;
-    return Write("mm/0/REG_STAT_ENABLE_SST/enable", nvalues, data);
+    return Write("mm/0/REG_STAT_ENABLE_SST/0/enable", nvalues, data);
 }
 
 
@@ -947,7 +983,7 @@ bool Periph_fpga::read_sst_offload_hdr_eth_destination_mac(TermOutput& termout,
 
     uint32_t data[20];
     memset((void *)data, 0, sizeof(data));
-    retval = Read("mm/0/REG_STAT_HDR_DAT_SST/eth_destination_mac", data);
+    retval = Read("mm/0/REG_STAT_HDR_DAT_SST/0/eth_destination_mac", data);
 
     uint64_t mac = (uint64_t)data[1] << 32 | data[0];
 
@@ -977,14 +1013,14 @@ bool Periph_fpga::write_sst_offload_hdr_eth_destination_mac(const char *data, ui
     string ds(data);
     stringstream ss(ds);
     ss >> setbase(16) >> m0 >> sep >> m1 >> sep >> m2 >> sep >> m3 >> sep >> m4 >> sep >> m5;
-    if (ss.good()) {
-        mac[1] = (m0 << 8) + (m1 << 0);
-        mac[0] = (m2 << 24) + (m3 << 16) + (m4 << 8) + m5;
-        // cout << "mac=" << mac[1] << ", " << mac[0] << endl;
-        return Write("mm/0/REG_STAT_HDR_DAT_SST/eth_destination_mac", nvalues, mac);
-    }
-    cout << "parse error in write_sst_offload_hdr_eth_destination_mac (" << ds << ")" << endl;
-    return false;
+    if (ss.fail() || ss.bad()) {
+        cout << "parse error in write_sst_offload_hdr_eth_destination_mac (" << ds << ")" << endl;
+        return false;
+    }
+    mac[1] = (m0 << 8) + (m1 << 0);
+    mac[0] = (m2 << 24) + (m3 << 16) + (m4 << 8) + m5;
+    // cout << "mac=" << mac[1] << ", " << mac[0] << endl;
+    return Write("mm/0/REG_STAT_HDR_DAT_SST/0/eth_destination_mac", nvalues, mac);
 }
 
 bool Periph_fpga::read_sst_offload_hdr_ip_destination_address(TermOutput& termout, int format)
@@ -993,7 +1029,7 @@ bool Periph_fpga::read_sst_offload_hdr_ip_destination_address(TermOutput& termou
 
     uint32_t data[20];
     memset((void *)data, 0, sizeof(data));
-    retval = Read("mm/0/REG_STAT_HDR_DAT_SST/ip_destination_address", data);
+    retval = Read("mm/0/REG_STAT_HDR_DAT_SST/0/ip_destination_address", data);
 
     stringstream ip_ss;
     for (int i=3; i>=0; i--) {
@@ -1018,18 +1054,26 @@ bool Periph_fpga::write_sst_offload_hdr_ip_destination_address(const char *data,
     uint ip0, ip1, ip2, ip3;
     uint32_t ip[1] = {0};
     string ds(data);
+    cout << "write_ip=[" << ds << "]" << endl;
     stringstream ss(ds);
-    ss >> setbase(10) >> ip0 >> sep >> ip1 >> sep >> ip2 >> sep >> ip3;
-    if (ss.good()) {
-        ip[0] += (ip0 & 0xff) << 24;
-        ip[0] += (ip1 & 0xff) << 16;
-        ip[0] += (ip2 & 0xff) << 8;
-        ip[0] += ip3 & 0xff;
-        // cout << "ip=" << hex << ip[0] << endl;
-        return Write("mm/0/REG_STAT_HDR_DAT_SST/ip_destination_address", nvalues, ip);
-    }
-    cout << "parse error in write_sst_offload_hdr_ip_destination_address (" << ds << ")" << endl;
-    return false;
+    ss >> setbase(10) >> ip0;
+    ss >> sep;
+    ss >> setbase(10) >> ip1;
+    ss >> sep;
+    ss >> setbase(10) >> ip2;
+    ss >> sep;
+    ss >> setbase(10) >> ip3;
+    cout << "ip0=" << to_string(ip0) << " ip1=" << to_string(ip1) << " ip2=" << to_string(ip2) << " ip3=" << to_string(ip3) << endl;
+    if (ss.fail() || ss.bad()) {
+        cout << "parse error in write_sst_offload_hdr_ip_destination_address (" << ds << ")" << endl;
+        return false;
+    }
+    ip[0] += (ip0 & 0xff) << 24;
+    ip[0] += (ip1 & 0xff) << 16;
+    ip[0] += (ip2 & 0xff) << 8;
+    ip[0] += ip3 & 0xff;
+    cout << "ip=" << hex << ip[0] << endl;
+    return Write("mm/0/REG_STAT_HDR_DAT_SST/0/ip_destination_address", nvalues, ip);
 }
 
 bool Periph_fpga::read_sst_offload_hdr_udp_destination_port(TermOutput& termout, int format)
@@ -1038,7 +1082,7 @@ bool Periph_fpga::read_sst_offload_hdr_udp_destination_port(TermOutput& termout,
 
     uint32_t data[20];
     memset((void *)data, 0, sizeof(data));
-    retval = Read("mm/0/REG_STAT_HDR_DAT_SST/udp_destination_port", data);
+    retval = Read("mm/0/REG_STAT_HDR_DAT_SST/0/udp_destination_port", data);
     int port = (int)data[0];
 
     int *_ptr = (int *)termout.val;
@@ -1051,7 +1095,7 @@ bool Periph_fpga::read_sst_offload_hdr_udp_destination_port(TermOutput& termout,
 
 bool Periph_fpga::write_sst_offload_hdr_udp_destination_port(uint32_t *data, uint32_t nvalues)
 {
-    return Write("mm/0/REG_STAT_HDR_DAT_SST/udp_destination_port", nvalues, data);
+    return Write("mm/0/REG_STAT_HDR_DAT_SST/0/udp_destination_port", nvalues, data);
 }
 
 
@@ -1061,7 +1105,7 @@ bool Periph_fpga::read_processing_enable(TermOutput& termout, int format)
 
     uint32_t data[20];
     memset((void *)data, 0, sizeof(data));
-    retval = Read("mm/0/REG_BSN_SOURCE_V2/dp_on", data);
+    retval = Read("mm/0/REG_BSN_SOURCE_V2/0/dp_on", data);
     bool dp_on = (bool)data[0];
 
     bool *_ptr = (bool *)termout.val;
@@ -1087,11 +1131,11 @@ bool Periph_fpga::write_processing_enable(uint32_t *data, uint32_t nvalues)
     bool processing_enable = (bool)data[0];
     if (processing_enable) {
         cout << "turn on bsn" << endl;
-        reg[0] = 0;
-        if (Write("mm/0/REG_BSN_SOURCE_V2/dp_on", 1, reg) == false) {
-            cout << "Write error (mm/0/REG_BSN_SOURCE_V2/dp_on) 0" << endl;
-            return false;
-        }
+        // reg[0] = 0;
+        // if (Write("mm/0/REG_BSN_SOURCE_V2/0/dp_on", 1, reg) == false) {
+        //     cout << "Write error (mm/0/REG_BSN_SOURCE_V2/0/dp_on) 0" << endl;
+        //     return false;
+        // }
 
         struct timeval now;
         uint64_t bsn;
@@ -1107,30 +1151,30 @@ bool Periph_fpga::write_processing_enable(uint32_t *data, uint32_t nvalues)
         }
         reg[0] = (uint32_t)(bsn & 0xffffffff);
         reg[1] = (uint32_t)((bsn >> 32) & 0xffffffff);
-        if (Write("mm/0/REG_BSN_SOURCE_V2/bsn_init", 2, reg) == false) {
-            cout << "Write error (mm/0/REG_BSN_SOURCE_V2/bsn_init)" << endl;
+        if (Write("mm/0/REG_BSN_SOURCE_V2/0/bsn_init", 2, reg) == false) {
+            cout << "Write error (mm/0/REG_BSN_SOURCE_V2/0/bsn_init)" << endl;
             return false;
         }
         reg[0] = offset;
-        if (Write("mm/0/REG_BSN_SOURCE_V2/bsn_time_offset", 1, reg) == false) {
-            cout << "Write error (mm/0/REG_BSN_SOURCE_V2/bsn_time_offset)" << endl;
+        if (Write("mm/0/REG_BSN_SOURCE_V2/0/bsn_time_offset", 1, reg) == false) {
+            cout << "Write error (mm/0/REG_BSN_SOURCE_V2/0/bsn_time_offset)" << endl;
             return false;
         }
-        reg[0] = 1;
-        if (Write("mm/0/REG_BSN_SOURCE_V2/dp_on_pps", 1, reg) == false) {
-            cout << "Write error (mm/0/REG_BSN_SOURCE_V2/dp_on_pps)" << endl;
+        reg[0] = shift_mask("mm/0/REG_BSN_SOURCE_V2/0/dp_on", 0) | shift_mask("mm/0/REG_BSN_SOURCE_V2/0/dp_on_pps", 1);
+        if (Write("mm/0/REG_BSN_SOURCE_V2/0/dp_on", 1, reg, false) == false) {
+            cout << "Write error (mm/0/REG_BSN_SOURCE_V2/0/dp_on_pps)" << endl;
             return false;
         }
-        reg[0] = 1;
-        if (Write("mm/0/REG_BSN_SOURCE_V2/dp_on", 1, reg) == false) {
-            cout << "Write error (mm/0/REG_BSN_SOURCE_V2/dp_on) 1" << endl;
+        reg[0] = shift_mask("mm/0/REG_BSN_SOURCE_V2/0/dp_on", 1) | shift_mask("mm/0/REG_BSN_SOURCE_V2/0/dp_on_pps", 1);
+        if (Write("mm/0/REG_BSN_SOURCE_V2/0/dp_on", 1, reg, false) == false) {
+            cout << "Write error (mm/0/REG_BSN_SOURCE_V2/0/dp_on) 1" << endl;
             return false;
         }
     }
     else {
         reg[0] = 0;
-        if (Write("mm/0/REG_BSN_SOURCE_V2/dp_on", 1, reg) == false) {
-            cout << "Write error (mm/0/REG_BSN_SOURCE_V2/dp_on) 0" << endl;
+        if (Write("mm/0/REG_BSN_SOURCE_V2/0/dp_on", 1, reg) == false) {
+            cout << "Write error (mm/0/REG_BSN_SOURCE_V2/0/dp_on) 0" << endl;
             return false;
         }
     }
@@ -1141,7 +1185,7 @@ bool Periph_fpga::read_sdp_info_station_id(TermOutput& termout, int format) {
     bool retval = true;
     uint32_t data[20];
     memset((void *)data, 0, sizeof(data));
-    retval = Read("mm/0/REG_SDP_INFO/station_id", data);
+    retval = Read("mm/0/REG_SDP_INFO/0/station_id", data);
 
     uint32_t station_id = (uint32_t)data[0];
 
@@ -1153,7 +1197,7 @@ bool Periph_fpga::read_sdp_info_station_id(TermOutput& termout, int format) {
 }
 
 bool Periph_fpga::write_sdp_info_station_id(uint32_t *data, uint32_t nvalues) {
-    bool retval = Write("mm/0/REG_SDP_INFO/station_id", nvalues, data);
+    bool retval = Write("mm/0/REG_SDP_INFO/0/station_id", nvalues, data);
     return retval;
 }
 
@@ -1161,7 +1205,7 @@ bool Periph_fpga::read_sdp_info_observation_id(TermOutput& termout, int format)
     bool retval = true;
     uint32_t data[20];
     memset((void *)data, 0, sizeof(data));
-    retval = Read("mm/0/REG_SDP_INFO/observation_id", data);
+    retval = Read("mm/0/REG_SDP_INFO/0/observation_id", data);
 
     uint32_t observation_id = (uint32_t)data[0];
 
@@ -1173,7 +1217,7 @@ bool Periph_fpga::read_sdp_info_observation_id(TermOutput& termout, int format)
 }
 
 bool Periph_fpga::write_sdp_info_observation_id(uint32_t *data, uint32_t nvalues) {
-    bool retval = Write("mm/0/REG_SDP_INFO/observation_id", nvalues, data);
+    bool retval = Write("mm/0/REG_SDP_INFO/0/observation_id", nvalues, data);
     return retval;
 }
 
@@ -1181,7 +1225,7 @@ bool Periph_fpga::read_sdp_info_nyquist_sampling_zone_index(TermOutput& termout,
     bool retval = true;
     uint32_t data[20];
     memset((void *)data, 0, sizeof(data));
-    retval = Read("mm/0/REG_SDP_INFO/nyquist_zone_index", data);
+    retval = Read("mm/0/REG_SDP_INFO/0/nyquist_zone_index", data);
 
     uint32_t nyquist_zone_index = (uint32_t)data[0];
 
@@ -1193,7 +1237,7 @@ bool Periph_fpga::read_sdp_info_nyquist_sampling_zone_index(TermOutput& termout,
 }
 
 bool Periph_fpga::write_sdp_info_nyquist_sampling_zone_index(uint32_t *data, uint32_t nvalues) {
-    bool retval = Write("mm/0/REG_SDP_INFO/nyquist_zone_index", nvalues, data);
+    bool retval = Write("mm/0/REG_SDP_INFO/0/nyquist_zone_index", nvalues, data);
     return retval;
 }
 
@@ -1201,7 +1245,7 @@ bool Periph_fpga::read_sdp_info_antenna_band_index(TermOutput& termout, int form
     bool retval = true;
     uint32_t data[20];
     memset((void *)data, 0, sizeof(data));
-    retval = Read("mm/0/REG_SDP_INFO/antenna_band_index", data);
+    retval = Read("mm/0/REG_SDP_INFO/0/antenna_band_index", data);
 
     uint32_t antenna_band_index = (uint32_t)data[0];
 
@@ -1216,7 +1260,7 @@ bool Periph_fpga::read_sdp_info_f_adc(TermOutput& termout, int format) {
     bool retval = true;
     uint32_t data[20];
     memset((void *)data, 0, sizeof(data));
-    retval = Read("mm/0/REG_SDP_INFO/f_adc", data);
+    retval = Read("mm/0/REG_SDP_INFO/0/f_adc", data);
 
     uint32_t f_adc = (uint32_t)data[0];
 
@@ -1231,7 +1275,7 @@ bool Periph_fpga::read_sdp_info_fsub_type(TermOutput& termout, int format) {
     bool retval = true;
     uint32_t data[20];
     memset((void *)data, 0, sizeof(data));
-    retval = Read("mm/0/REG_SDP_INFO/fsub_type", data);
+    retval = Read("mm/0/REG_SDP_INFO/0/fsub_type", data);
 
     uint32_t fsub_type = (uint32_t)data[0];
 
@@ -1246,7 +1290,7 @@ bool Periph_fpga::read_sdp_info_block_period(TermOutput& termout, int format) {
     bool retval = true;
     uint32_t data[20];
     memset((void *)data, 0, sizeof(data));
-    retval = Read("mm/0/REG_SDP_INFO/block_period", data);
+    retval = Read("mm/0/REG_SDP_INFO/0/block_period", data);
 
     uint32_t block_period = (uint32_t)data[0];
 
@@ -1257,10 +1301,239 @@ bool Periph_fpga::read_sdp_info_block_period(TermOutput& termout, int format) {
     return retval;
 }
 
+// Waveform generator functions "_wg_"
+/*
+When FPGA_wg_enable_RW is set False, then disable the WG via mode = c_mode_off = 0.
+When FPGA_wg_enable_RW is set True, then enable the WG via mode = c_mode_calc = 1. Once enabled, the
+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
+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.
+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.
+*/
+bool Periph_fpga::read_wg_enable(TermOutput& termout, int format) {
+    bool retval = true;
+    uint32_t data[20];
+    memset((void *)data, 0, sizeof(data));
+    string regname;
+    for (uint i=0; i< C_S_pn; i++) {
+        regname = "mm/0/REG_WG/" + to_string(i) + "/mode";
+        retval = Read(regname, &data[i]);
+    }
+
+    bool enabled;
+    bool *_ptr = (bool *)termout.val ;
+    for (uint i=0; i< C_S_pn; i++) {
+        enabled = (bool)data[i];
+        *_ptr = enabled;
+        _ptr++;
+    }
+
+    termout.nof_vals = C_S_pn;
+    termout.datatype = format;
+    return retval;
+}
+
+bool Periph_fpga::write_wg_enable(uint32_t *data, uint32_t nvalues) {
+    bool retval = true;
+    uint32_t *reg = new uint32_t[4];
+    uint64_t scheduled_bsn;
+    bool wg_enable;
+
+    string regname1;
+    string regname2;
+
+    // turn off waveform
+    for (uint i=0; i< C_S_pn; i++) {
+        wg_enable = (bool)data[i];
+        if (wg_enable == false) {
+            regname1 = "mm/0/REG_WG/" + to_string(i) + "/mode";
+            regname2 = "mm/0/REG_WG/" + to_string(i) + "/nof_samples";
+            reg[0] = shift_mask(regname1, C_WG_MODE_OFF) | shift_mask(regname2, 1024);  // TODO: make constant
+            retval = Write(regname1, 1, reg, false);
+        }
+    }
+    // turn on waveform
+    for (uint i=0; i< C_S_pn; i++) {
+        wg_enable = (bool)data[i];
+        if (wg_enable == true) {
+            regname1 = "mm/0/REG_WG/" + to_string(i) + "/mode";
+            regname2 = "mm/0/REG_WG/" + to_string(i) + "/nof_samples";
+            reg[0] = shift_mask(regname1, C_WG_MODE_CALC) | shift_mask(regname2, 1024);  // TODO: make constant
+            retval = Write(regname1, 1, reg, false);
+        }
+    }
+    // get bsn and add latency
+    wg_enable = (bool)data[0];
+    if (wg_enable == true) {
+        regname1 = "mm/0/REG_BSN_SCHEDULER/0/scheduled_bsn";
+        retval = Read(regname1, reg);
+        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);
+    }
+    // write sheduled bsn
+    for (uint i=0; i< C_S_pn; i++) {
+        wg_enable = (bool)data[i];
+        if (wg_enable == true) {
+            regname1 = "mm/0/REG_BSN_SCHEDULER/" + to_string(i) + "/scheduled_bsn";
+            retval = Write(regname1, 1, reg);
+        }
+    }
+    delete[] reg;
+    return retval;
+}
+
+/*
+ampl = FPGA_wg_amplitude_RW * c_ampl_unit
+  where c_ampl_unit = 2^16.
+  MP converts ampl into FPGA_wg_amplitude_R.
+*/
+bool Periph_fpga::read_wg_amplitude(TermOutput& termout, int format) {
+    bool retval = true;
+    uint32_t data[20];
+    memset((void *)data, 0, sizeof(data));
+    string regname;
+    for (uint i=0; i< C_S_pn; i++) {
+        regname = "mm/0/REG_WG/" + to_string(i) + "/ampl";
+        retval = Read(regname, &data[i]);
+    }
+
+    float ampl;
+    float *_ptr = (float *)termout.val ;
+    for (uint i=0; i< C_S_pn; i++) {
+        ampl = (float)data[i] / C_WG_AMPL_UNIT;
+        *_ptr = ampl;
+        _ptr++;
+    }
+
+    termout.nof_vals = C_S_pn;
+    termout.datatype = format;
+    return retval;
+}
+
+bool Periph_fpga::write_wg_amplitude(uint32_t *data, uint32_t nvalues) {
+    bool retval = true;
+    uint32_t *reg = new uint32_t[2];
+
+    float ampl;
+    string regname;
+    for (uint i=0; i< C_S_pn; i++) {
+        regname = "mm/0/REG_WG/" + to_string(i) + "/ampl";
+        ampl = (float)data[i] * C_WG_AMPL_UNIT;
+        reg[0] = (uint32_t)ampl;
+        retval = Write(regname, 1, reg);
+    }
+    delete[] reg;
+    return retval;
+}
+
+
+/*
+phase = FPGA_wg_phase_RW * c_phase_unit
+  where c_phase_unit = 2^16 / 360.
+  MP converts phase into FPGA_wg_phase_R.
+*/
+bool Periph_fpga::read_wg_phase(TermOutput& termout, int format) {
+    bool retval = true;
+    uint32_t data[20];
+    memset((void *)data, 0, sizeof(data));
+    string regname;
+    for (uint i=0; i< C_S_pn; i++) {
+        regname = "mm/0/REG_WG/" + to_string(i) + "/phase";
+        retval = Read(regname, &data[i]);
+    }
+
+    float phase;
+    float *_ptr = (float *)termout.val ;
+    for (uint i=0; i< C_S_pn; i++) {
+        phase = ((float)data[i]) / C_WG_PHASE_UNIT;
+        *_ptr = phase;
+        _ptr++;
+    }
+
+    termout.nof_vals = C_S_pn;
+    termout.datatype = format;
+    return retval;
+}
+
+bool Periph_fpga::write_wg_phase (uint32_t *data, uint32_t nvalues) {
+    bool retval = true;
+    uint32_t *reg = new uint32_t[2];
+
+    float phase;
+    string regname;
+    for (uint i=0; i< C_S_pn; i++) {
+        regname = "mm/0/REG_WG/" + to_string(i) + "/phase";
+        phase = ((float)data[i]) * C_WG_PHASE_UNIT;
+        reg[0] = (uint32_t)phase;
+        retval = Write(regname, 1, reg);
+    }
+    delete[] reg;
+    return retval;
+}
+
+/*
+freq = FPGA_wg_frequency_RW / f_adc
+freq = freq % 1  # to wrap freq in [0, 1> interval
+freq = freq * c_freq_unit
+  where f_adc = 200e6 and c_freq_unit = 2^31.
+  MP converts freq into FPGA_wg_frequency_R.
+*/
+bool Periph_fpga::read_wg_frequency(TermOutput& termout, int format) {
+    bool retval = true;
+    uint32_t data[20];
+    memset((void *)data, 0, sizeof(data));
+    string regname;
+    for (uint i=0; i< C_S_pn; i++) {
+        regname = "mm/0/REG_WG/" + to_string(i) + "/freq";
+        retval = Read(regname, &data[i]);
+    }
+
+    float freq;
+    float *_ptr = (float *)termout.val ;
+    for (uint i=0; i< C_S_pn; i++) {
+        freq = ((float)data[i] / C_WG_FREQ_UNIT) * C_F_adc;
+        *_ptr = freq;
+        _ptr++;
+    }
+
+    termout.nof_vals = C_S_pn;
+    termout.datatype = format;
+    return retval;
+}
+
+bool Periph_fpga::write_wg_frequency(uint32_t *data, uint32_t nvalues) {
+    bool retval = true;
+    uint32_t *reg = new uint32_t[2];
+    
+    float freq, intpart;
+    string regname;
+    for (uint i=0; i< C_S_pn; i++) {
+        regname = "mm/0/REG_WG/" + to_string(i) + "/freq";
+        freq = (float)data[i] / C_F_adc;
+        freq = modf(freq, &intpart);
+        freq = freq * C_WG_FREQ_UNIT;
+        reg[0] = (uint32_t)freq;
+        retval = Write(regname, 1, reg);
+    }
+    delete[] reg;
+    return retval;
+}
+
+
 bool Periph_fpga::write_wdi_override(TermOutput& termout)
 {
     uint32_t data = 0xB007FAC7;
-    return Write("mm/0/PIO_WDI/wdi_override", 1, &data);
+    return Write("mm/0/PIO_WDI/0/wdi_override", 1, &data);
 }
 
 CMMap Periph_fpga::read_reg_map()
diff --git a/src/periph/fpga.h b/src/periph/fpga.h
index f464940f9b13021bba403658c707172c958303b6..08e6891c3e7cf37296dd252e36614a3433dadb7a 100644
--- a/src/periph/fpga.h
+++ b/src/periph/fpga.h
@@ -67,8 +67,10 @@ private:
            Flash_user_sector_end, Flash_pages_per_sector,
            Flash_fact_sector_start, Flash_fact_sector_end, Flash_select;
 
-  bool Read(const std::string addr_str, uint32_t *data_ptr);
-  bool Write(const std::string addr_str, const uint32_t nvalues, uint32_t *data_ptr);
+  bool Read(const std::string addr_str, uint32_t *data_ptr, bool use_mask_shift);
+  bool Write(const std::string addr_str, const uint32_t nvalues, uint32_t *data_ptr, bool use_shift_mask);
+  uint32_t mask_shift(const std::string addr_str, uint32_t data);
+  uint32_t shift_mask(const std::string addr_str, uint32_t data);
 
   bool flash_erase_sector(uint32_t sector);
   bool flash_erase();
@@ -90,13 +92,11 @@ private:
 
   bool read_fpga_temperature(TermOutput& termout, int format, int mode);
 
-  bool read_fpga_scrap_R(TermOutput& termout, int format);
-  bool read_fpga_scrap_RW(TermOutput& termout, int format);
-  bool write_fpga_scrap_RW(uint32_t *data, uint len);
+  bool read_fpga_scrap(TermOutput& termout, int format, int mode);
+  bool write_fpga_scrap(uint32_t *data, uint len);
 
-  bool read_fpga_weights_R(TermOutput& termout, int format);
-  bool read_fpga_weights_RW(TermOutput& termout, int format);
-  bool write_fpga_weights_RW(const uint32_t *data, uint nvalues);
+  bool read_fpga_weights(TermOutput& termout, int format, int mode);
+  bool write_fpga_weights(const uint32_t *data, uint nvalues);
 
   bool read_sst_offload_selector(TermOutput& termout, int format);
   bool write_sst_offload_selector(uint32_t *data, uint32_t nvalues);
@@ -125,6 +125,16 @@ private:
   bool read_sdp_info_antenna_band_index(TermOutput& termout, int format);
   bool read_sdp_info_f_adc(TermOutput& termout, int format);
   bool read_sdp_info_fsub_type(TermOutput& termout, int format);
+  bool read_wg_enable(TermOutput& termout, int format);
+
+  bool write_wg_enable(uint32_t *data, uint32_t nvalues);
+  bool read_wg_amplitude(TermOutput& termout, int format);
+  bool write_wg_amplitude(uint32_t *data, uint32_t nvalues);
+  bool read_wg_phase(TermOutput& termout, int format);
+  bool write_wg_phase (uint32_t *data, uint32_t nvalues);
+  bool write_wg_frequency(uint32_t *data, uint32_t nvalues);
+  bool read_wg_frequency(TermOutput& termout, int format);
+
   bool read_sdp_info_block_period(TermOutput& termout, int format);
 
   bool write_wdi_override(TermOutput& termout);
diff --git a/src/registers.cpp b/src/registers.cpp
index a829b94f602999912b931fad2f26d001c67deaec..218a4bd2ec0398ff15c097dba4aacc0d50bc9d7f 100644
--- a/src/registers.cpp
+++ b/src/registers.cpp
@@ -37,25 +37,28 @@ using namespace std;
 //
 // CMMap used for holding fpga mm register information
 //
-bool CMMap::add_register(const string name, const uint32_t base, 
-                               const uint32_t span, const uint32_t mask, 
-                               const uint32_t shift, const string access,
-                               const string type, const uint32_t instance, const uint32_t format) 
+CMMap::CMMap() {}
+CMMap::~CMMap() { reg.clear(); }
+
+bool CMMap::add_register(const string name, const uint32_t base, const uint32_t n_mm_ports,
+                         const uint32_t span, const uint32_t mask,
+                         const uint32_t shift, const string access,
+                         const string type, const uint32_t peripheral_span, const uint32_t mm_port_span)
 {
     cout << "CMMap::add_register: " << name << endl;
     if (find_register(name)) {
         cerr << "CMMap::add_register: " << name << " already exist!" << endl;
         return false;
     }
-    register_info r={base, span, mask, shift, access, type, instance, format};
+    register_info r = {base, n_mm_ports, span, mask, shift, access, type, mm_port_span, peripheral_span};
     reg.insert(reg.end(), pair<string, register_info>(name, r));
     return true;
 }
 
-bool CMMap::update_register(const string name, const uint32_t base, 
-                                  const uint32_t span, const uint32_t mask, 
-                                  const uint32_t shift, const string access,
-                                  const string type, const uint32_t instance, const uint32_t format) 
+bool CMMap::update_register(const string name, const uint32_t base, const uint32_t n_mm_ports,
+                            const uint32_t span, const uint32_t mask,
+                            const uint32_t shift, const string access,
+                            const string type, const uint32_t peripheral_span, const uint32_t mm_port_span)
 {
     cout << "CMMap::update_register: " << name << endl;
     if (!find_register(name)) {
@@ -68,8 +71,9 @@ bool CMMap::update_register(const string name, const uint32_t base,
     reg[name].mask = mask;
     reg[name].span = span;
     reg[name].base = base;
-    reg[name].instance = instance;
-    reg[name].format = format;
+    reg[name].n_mm_ports = n_mm_ports;
+    reg[name].mm_port_span = mm_port_span;
+    reg[name].peripheral_span = peripheral_span;
     return true;
 }
 
@@ -83,21 +87,9 @@ bool CMMap::find_register(string name)
     return ret;
 }
 
-#define MAX_NOF_INSTANCES 1024
-
-uint CMMap::findLastInstance(string shortname)
-{
-    int i;
-    for (i=0; i<MAX_NOF_INSTANCES; i++) {
-        auto ii = reg.find("mm/" + to_string(i) + "/" + shortname);
-        if (ii != reg.end()) {
-            break;
-        }
-    }
-    return i; 
-}
+// #define MAX_NOF_INSTANCES 1024
 
-void CMMap::print(ostringstream& strs, string prefix) 
+void CMMap::print(ostringstream& strs, string prefix)
 {
     for (auto m : reg) {
         strs << prefix << " register[" << m.first << "]"
@@ -107,23 +99,24 @@ void CMMap::print(ostringstream& strs, string prefix)
              << " shift="    << dec << m.second.shift
              << " access="   << m.second.access
              << " type="     << m.second.type
-             << " instance=" << m.second.instance
-             << " format="   << m.second.format << endl;
+             << endl;
     }
 }
 
-void CMMap::print_screen(void) 
+void CMMap::print_screen(void)
 {
     for (auto m : reg) {
         cout << " register[" << m.first << "]"
-                  << " base=0x"   << hex << m.second.base
-                  << " size="     << dec << m.second.span 
-                  << " mask=0x"   << hex << m.second.mask 
-                  << " shift="    << dec << m.second.shift 
-                  << " access="   << m.second.access 
-                  << " type="     << m.second.type 
-                  << " instance=" << m.second.instance 
-                  << " format="   << m.second.format << endl;
+                  << ", base=0x"          << hex << m.second.base
+                  << ", n_ports="         << dec << m.second.n_mm_ports
+                  << ", size="            << dec << m.second.span
+                  << ", mask=0x"          << hex << m.second.mask
+                  << ", shift="           << dec << m.second.shift
+                  << ", access="          << m.second.access
+                  << ", type="            << m.second.type
+                  << ", mm_port_span="    << m.second.mm_port_span
+                  << ", peripheral_span=" << m.second.peripheral_span
+                  << endl;
     }
 }
 
@@ -156,7 +149,7 @@ vector<string> CMMap::getRegnames_full(string prefix)
     return regnames;
 }
 
-uint32_t CMMap::getAddr(const string name) 
+uint32_t CMMap::getAddr(const string name)
 {
     if (!find_register(name)) {
         throw runtime_error("Register[" + name + "] not existing!");
@@ -165,8 +158,8 @@ uint32_t CMMap::getAddr(const string name)
     return addr;
 }
 
-uint32_t CMMap::getValidAddr(const string name, 
-                                   const uint32_t size) 
+uint32_t CMMap::getValidAddr(const string name,
+                                   const uint32_t size)
 {
     if (!find_register(name)) {
         throw runtime_error("Register[" + name + "] not existing!");
@@ -181,31 +174,31 @@ uint32_t CMMap::getValidAddr(const string name,
     return addr;
 }
 
-bool CMMap::getReadPermission(const string name) 
+bool CMMap::getReadPermission(const string name)
 {
     string perm = getPerm(name);
     if (perm == "RO" || perm == "RW") {
         return true;
-    } 
+    }
     else {
         throw runtime_error("Register[" + name + "] getReadPermission() fail!");
     }
     return false;
 }
 
-bool CMMap::getWritePermission(const string name) 
+bool CMMap::getWritePermission(const string name)
 {
     string perm = getPerm(name);
     if (perm == "WO" || perm == "RW") {
         return true;
-    } 
+    }
     else {
         throw runtime_error("Register[" + name + "] getWritePermission() fail!");
     }
     return false;
 }
 
-void CMMap::setAllPermission_NA(void) 
+void CMMap::setAllPermission_NA(void)
 {
     cerr << "CMMap::setAllPermission_NA()" << endl;
     for (auto &m : reg) {
@@ -216,19 +209,25 @@ void CMMap::setAllPermission_NA(void)
 //
 // CPointMap used for assigning opc-ua points
 //
-bool CPointMap::add_register(const string name, const string relname, const uint32_t span, const string access, const uint32_t format, const uint32_t interval) 
+CPointMap::CPointMap() {}
+
+CPointMap::~CPointMap() { reg.clear(); }
+
+bool CPointMap::add_register(const string name, const string relname, const uint32_t n_nodes, const uint32_t n_data,
+                             const string access, const uint32_t format, const uint32_t interval)
 {
     cout << "CPointMap::add_register: " << name << endl;
     if (find_register(name)) {
         cerr << "CPointMap::add_register: " << name << " already exist!" << endl;
         return false;
     }
-    register_info r={relname, span, access, format, interval};
+    register_info r={relname, n_nodes, n_data, access, format, interval};
     reg.insert(reg.end(), pair<string, register_info>(name, r));
     return true;
 }
 
-bool CPointMap::update_register(const string name, const string relname, const uint32_t span, const string access, const uint32_t format, const uint32_t interval)
+bool CPointMap::update_register(const string name, const string relname, const uint32_t n_nodes, const uint32_t n_data,
+                                const string access, const uint32_t format, const uint32_t interval)
 {
     cout << "CPointMap::update_register: " << name << endl;
     if (!find_register(name)) {
@@ -236,7 +235,8 @@ bool CPointMap::update_register(const string name, const string relname, const u
         return false;
     }
     reg[name].relname = relname;
-    reg[name].span = span;
+    reg[name].n_nodes = n_nodes;
+    reg[name].n_data = n_data;
     reg[name].access = access;
     reg[name].format = format;
     reg[name].update_interval = interval;
@@ -253,24 +253,26 @@ bool CPointMap::find_register(string name)
     return ret;
 }
 
-void CPointMap::print(ostringstream& strs, string prefix) 
+void CPointMap::print(ostringstream& strs, string prefix)
 {
     for (auto m : reg) {
         strs << prefix << " register[" << m.first << "]"
              << " relname="  << m.second.relname
-             << " size="     << dec << m.second.span
+             << " n_nodes="  << dec << m.second.n_nodes
+             << " n_data="   << dec << m.second.n_data
              << " access="   << m.second.access
              << " format="   << m.second.format << endl;
     }
 }
 
-void CPointMap::print_screen(void) 
+void CPointMap::print_screen(void)
 {
     for (auto m : reg) {
         cout << " register[" << m.first << "]"
                   << " relname="  << m.second.relname
-                  << " size="     << dec << m.second.span 
-                  << " access="   << m.second.access 
+                  << " n_nodes="  << dec << m.second.n_nodes
+                  << " n_data="   << dec << m.second.n_data
+                  << " access="   << m.second.access
                   << " format="   << m.second.format << endl;
     }
 }
@@ -284,31 +286,31 @@ vector<string> CPointMap::getRegnames(string prefix)
     return regnames;
 }
 
-bool CPointMap::getReadPermission(const string name) 
+bool CPointMap::getReadPermission(const string name)
 {
     string perm = getPerm(name);
     if (perm == "RO" || perm == "RW") {
         return true;
-    } 
+    }
     else {
         throw runtime_error("Register[" + name + "] getReadPermission() fail!");
     }
     return false;
 }
 
-bool CPointMap::getWritePermission(const string name) 
+bool CPointMap::getWritePermission(const string name)
 {
     string perm = getPerm(name);
     if (perm == "WO" || perm == "RW") {
         return true;
-    } 
+    }
     else {
         throw runtime_error("Register[" + name + "] getWritePermission() fail!");
     }
     return false;
 }
 
-void CPointMap::setAllPermission_NA(void) 
+void CPointMap::setAllPermission_NA(void)
 {
     cerr << "CPointMap::setAllPermission_NA()" << endl;
     for (auto &m : reg) {
diff --git a/src/registers.h b/src/registers.h
index 04b3960e04b46e78fd5c0a3668d527e31653049a..0c34e4a2f05024b6a96ef16999695b61dc8f37ec 100644
--- a/src/registers.h
+++ b/src/registers.h
@@ -45,94 +45,99 @@
 #define REG_FORMAT_FLOAT    6
 #define REG_FORMAT_BOOLEAN  7
 
-
-class CPointMap {
+class CMMap {
 private:
 
   typedef struct {
-    std::string relname;
+    uint32_t base;
+    uint32_t n_mm_ports;
     uint32_t span;
+    uint32_t mask;
+    uint32_t shift;
     std::string access;
-    uint32_t format;
-    uint32_t  update_interval;
+    std::string type;
+    uint32_t mm_port_span;
+    uint32_t peripheral_span;
   } register_info;
 
   std::map <std::string, register_info> reg;
 
- public:
-   CPointMap() {};
-   ~CPointMap() { reg.clear(); };
+public:
+   CMMap();
+   ~CMMap();
+   bool add_register(const std::string name, const uint32_t base, const uint32_t n_mm_ports, const uint32_t span,
+                     const uint32_t mask, const uint32_t shift, const std::string access,
+                     const std::string type, const uint32_t peripheral_span, const uint32_t mm_port_span);
+   bool update_register(const std::string name, const uint32_t base, const uint32_t n_mm_ports, const uint32_t span,
+                     const uint32_t mask, const uint32_t shift, const std::string access,
+                     const std::string type, const uint32_t peripheral_span, const uint32_t mm_port_span);
 
-   bool add_register   (const std::string name, const std::string relname, const uint32_t span, const std::string access, const uint32_t format, const uint32_t interval); 
-   bool update_register(const std::string name, const std::string relname, const uint32_t span, const std::string access, const uint32_t format, const uint32_t interval); 
    bool find_register(std::string name);
    void print(std::ostringstream& strs, std::string prefix);
    void print_screen(void);
-   
-   uint32_t getUpdateInterval(const std::string name) { return reg[name].update_interval; }
-   std::string getRelativeName(const std::string name) {return reg[name].relname; }
+
+   uint32_t getBaseAddr(const std::string name) { return reg[name].base; }
    uint32_t getSpan(const std::string name) { return reg[name].span; }
    std::string getPerm(const std::string name) { return reg[name].access; }
-   uint32_t getFormat(const std::string name) { return reg[name].format; }
-   bool getReadPermission(const std::string name);
-   bool getWritePermission(const std::string name);
-   void setPermission_NA(const std::string name) { reg[name].access = "NA"; }
-   void setAllPermission_NA(void);
+   uint32_t getMask(const std::string name) { return reg[name].mask; }
+   uint32_t getShift(const std::string name) { return reg[name].shift; }
+   std::string getType(const std::string name) { return reg[name].type; }
+   uint32_t getNPorts(const std::string name) { return reg[name].n_mm_ports; }
+   uint32_t getPortSpan(const std::string name) { return reg[name].mm_port_span; }
+   uint32_t getPeripheralSpan(const std::string name) { return reg[name].peripheral_span; }
+
+   bool type_isfifo(const std::string name) { return (reg[name].type == "FIFO"); }
+   uint32_t getAddr(const std::string name);
+   uint32_t getValidAddr(const std::string name,
+                         const uint32_t size);
+   bool     getReadPermission(const std::string name);
+   bool     getWritePermission(const std::string name);
+   void     setPermission_NA(const std::string name) { reg[name].access = "NA"; }
+   void     setAllPermission_NA(void);
 
    std::vector<std::string> getRegnames(std::string prefix);
+   std::vector<std::string> getRegnames_full(std::string prefix);
 };
 
 
-class CMMap {
+class CPointMap {
 private:
 
   typedef struct {
-    uint32_t base;
-    uint32_t span;
-    uint32_t mask;
-    uint32_t shift;
+    std::string relname;
+    uint32_t n_nodes;
+    uint32_t n_data;
     std::string access;
-    std::string type;
-    uint32_t instance;
     uint32_t format;
+    uint32_t  update_interval;
   } register_info;
 
   std::map <std::string, register_info> reg;
 
-public:
-   CMMap() {};
-   ~CMMap() { reg.clear(); };
+ public:
+   CPointMap();
+   ~CPointMap();
 
-   bool add_register(const std::string name, const uint32_t base, const uint32_t span, 
-                     const uint32_t mask, const uint32_t shift, const std::string access,
-                     const std::string type, const uint32_t instance, const uint32_t format); 
-   bool update_register(const std::string name, const uint32_t base, const uint32_t span, 
-                     const uint32_t mask, const uint32_t shift, const std::string access,
-                     const std::string type, const uint32_t instance, const uint32_t format); 
+   bool add_register   (const std::string name, const std::string relname, const uint32_t n_nodes, const uint32_t n_data,
+                        const std::string access, const uint32_t format, const uint32_t interval);
+   bool update_register(const std::string name, const std::string relname, const uint32_t n_nodes, const uint32_t n_data,
+                        const std::string access, const uint32_t format, const uint32_t interval);
    bool find_register(std::string name);
    void print(std::ostringstream& strs, std::string prefix);
    void print_screen(void);
-   
-   uint32_t getBaseAddr(const std::string name) { return reg[name].base; }
-   uint32_t getSpan(const std::string name) { return reg[name].span; }
+
+   uint32_t getUpdateInterval(const std::string name) { return reg[name].update_interval; }
+   std::string getRelativeName(const std::string name) {return reg[name].relname; }
+   uint32_t getNodesSize(const std::string name) { return reg[name].n_nodes; }
+   uint32_t getDataSize(const std::string name) { return reg[name].n_data; }
    std::string getPerm(const std::string name) { return reg[name].access; }
-   uint32_t getMask(const std::string name) { return reg[name].mask; }
-   uint32_t getShift(const std::string name) { return reg[name].shift; }
-   std::string getType(const std::string name) { return reg[name].type; }
-   uint32_t getInstance(const std::string name) { return reg[name].instance; }
    uint32_t getFormat(const std::string name) { return reg[name].format; }
-   uint findLastInstance(const std::string shortname);
-   bool type_isfifo(const std::string name) { return (reg[name].type == "FIFO"); }
-   uint32_t getAddr(const std::string name); 
-   uint32_t getValidAddr(const std::string name, 
-                         const uint32_t size);
-   bool     getReadPermission(const std::string name);
-   bool     getWritePermission(const std::string name);
-   void     setPermission_NA(const std::string name) { reg[name].access = "NA"; }
-   void     setAllPermission_NA(void);
+   bool getReadPermission(const std::string name);
+   bool getWritePermission(const std::string name);
+   void setPermission_NA(const std::string name) { reg[name].access = "NA"; }
+   void setAllPermission_NA(void);
 
    std::vector<std::string> getRegnames(std::string prefix);
-   std::vector<std::string> getRegnames_full(std::string prefix);
 };
 
 #endif // __REGISTERMAP_H__
diff --git a/src/tools/mmap.cpp b/src/tools/mmap.cpp
index 81266459b4896ea31c07ef6e80232868f91a418f..b1a5a0dc25bac253a15051c314cdafa6e6cc3d57 100644
--- a/src/tools/mmap.cpp
+++ b/src/tools/mmap.cpp
@@ -23,7 +23,7 @@
 * Purpose:
 * . opc-ua to ucp translator
 * Description:
-* . 
+* .
 * *********************************************************************** */
 
 #include <string>
@@ -46,117 +46,57 @@ typedef struct {
     string   radix;
     uint32_t mm_mask;
     uint32_t user_mask;
-    uint32_t span;   
-    uint32_t shift;   
+    uint32_t span;
+    uint32_t shift;
+    uint32_t peripheral_span;
+    uint32_t mm_port_span;
 } mm_info_t;
 
-
 void mmap_add_register(CMMap& regmap, mm_info_t mm_info)
 {
-    /*
-    TODO: 1) From mmap n_peripherals en n_mm_ports are not handled the way it should be.
-          2) If portname and field_name are the same increase span adjust mask (array ?)
-    */
-    
-    bool update = false;
+    bool update;
+    uint32_t addr;
     string full_name;
-    full_name = "mm/0/" + mm_info.port_name + "/" + mm_info.field_name;
-    
-    if (regmap.find_register(full_name)) {
-        mm_info.base_addr = regmap.getBaseAddr(full_name);
-        mm_info.span += regmap.getSpan(full_name);
-        update = true;
-    }
-
-
-    if (update) {
-        // regmap.update_register(full_name, "-", mm_info.base_addr, mm_info.span, mm_info.mm_mask, mm_info.shift, mm_info.acces_mode, mm_info.port_type, 0, REG_FORMAT_STRING);
-        regmap.update_register(full_name, mm_info.base_addr, mm_info.span, mm_info.mm_mask, mm_info.shift, mm_info.acces_mode, mm_info.port_type, 0, REG_FORMAT_STRING);
+    for (uint i=0; i<mm_info.n_peripherals; i++) {
+        for (uint j=0; j<mm_info.n_ports; j++) {
+            update = false;
+            full_name = "mm/" + to_string(i) + "/" + mm_info.port_name + "/" + to_string(j) + "/" + mm_info.field_name;
+
+            if (regmap.find_register(full_name)) {
+                mm_info.base_addr = regmap.getBaseAddr(full_name);
+                mm_info.span += regmap.getSpan(full_name);
+                update = true;
+            }
+            addr = mm_info.base_addr + (i * mm_info.peripheral_span) + (j * mm_info.mm_port_span);
+
+            if (update) {
+                regmap.update_register(full_name,
+                                       addr,
+                                       mm_info.n_ports,
+                                       mm_info.span,
+                                       mm_info.mm_mask,
+                                       mm_info.shift,
+                                       mm_info.acces_mode,
+                                       mm_info.port_type,
+                                       mm_info.peripheral_span,
+                                       mm_info.mm_port_span);
+            }
+            else {
+                regmap.add_register(full_name,
+                                    addr,
+                                    mm_info.n_ports,
+                                    mm_info.span,
+                                    mm_info.mm_mask,
+                                    mm_info.shift,
+                                    mm_info.acces_mode,
+                                    mm_info.port_type,
+                                    mm_info.peripheral_span,
+                                    mm_info.mm_port_span);
+            }
+        }
     }
-    else {
-        // regmap.add_register(full_name, "-", mm_info.base_addr, mm_info.span, mm_info.mm_mask, mm_info.shift, mm_info.acces_mode, mm_info.port_type, 0, REG_FORMAT_STRING);
-        regmap.add_register(full_name, mm_info.base_addr, mm_info.span, mm_info.mm_mask, mm_info.shift, mm_info.acces_mode, mm_info.port_type, 0, REG_FORMAT_STRING);
-    }        
-
-    // if (nof_instances >= 1) {
-    //     for (int i=0; i<nof_instances; i++) {
-    //         // add full name register
-    //         regmap.add_register("mm/"+to_string(i)+"/"+qsysname+"/"+fieldname, base, span, mask, shift, perm, type, i, REG_FORMAT_STRING);
-    //     }
-    // } 
-    // else {
-    //     uint update_base, update_span, update_instance;
-
-    //     update_instance = regmap.findLastInstance(qsysname);
-    //     string full_qsysname = "mm/"+to_string(update_instance)+"/"+qsysname+"/"+fieldname;
-
-    //     update_base = regmap.getBaseAddr(full_qsysname);
-    //     update_span = regmap.getSpan(full_qsysname);
-    //     update_span += span;
-
-    //     if (update_base < base) {
-    //         // already have a base which is lower
-    //         regmap.update_register(full_qsysname, update_base, update_span, 0xffffffff, 0, "RW", type, update_instance, REG_FORMAT_STRING);
-    //     } else {
-    //         // this will be the new base which is lower
-    //         regmap.update_register(full_qsysname, base, update_span, 0xffffffff, 0, "RW", type, update_instance, REG_FORMAT_STRING);
-    //     }
-    // }
 }
 
-/* Voorbeeld van een ingepakte mmap
-
-fpga_name = unb2b_minimal
-number_of_columns = 11
-ROM_SYSTEM_INFO 1 1 RAM data 0x00004000 32768 RO char8 31:0 7:0
-PIO_SYSTEM_INFO 1 1 REG info 0x00000000 1 RO uint32 31:0 -
-- - - - gn_index 0x00000000 1 RO uint32 7:0 -
-- - - - hw_version 0x00000000 1 RO uint32 9:8 -
-- - - - cs_sim 0x00000000 1 RO uint32 10:10 -
-- - - - fw_version_major 0x00000000 1 RO uint32 19:16 -
-- - - - fw_version_minor 0x00000000 1 RO uint32 23:20 -
-- - - - rom_version 0x00000000 1 RO uint32 26:24 -
-- - - - technology 0x00000000 1 RO uint32 31:27 -
-- - - - use_phy 0x00000001 1 RO uint32 7:0 -
-- - - - design_name 0x00000002 52 RO char8 31:0 7:0
-- - - - stamp_date 0x0000000f 1 RO uint32 31:0 -
-- - - - stamp_time 0x00000010 1 RO uint32 31:0 -
-- - - - stamp_commit 0x00000011 3 RO uint32 31:0 -
-- - - - design_note 0x00000014 52 RO char8 31:0 7:0
-PIO_WDI 1 1 REG wdi_override 0x000000e0 1 WO uint32 31:0 -
-REG_FPGA_TEMP_SENS 1 1 REG temp 0x000000c8 1 RO uint32 31:0 -
-REG_FPGA_VOLTAGE_SENS 1 1 REG voltages 0x00000030 6 RO uint32 31:0 -
-RAM_SCRAP 1 1 RAM data 0x00000e00 512 RW uint32 31:0 -
-AVS_ETH_0_TSE 1 1 REG status 0x00000400 1024 RO uint32 31:0 -
-AVS_ETH_0_REG 1 1 REG status 0x00000020 12 RO uint32 31:0 -
-AVS_ETH_0_RAM 1 1 RAM data 0x00000800 1024 RW uint32 31:0 -
-PIO_PPS 1 1 REG capture_cnt 0x000000e4 1 RO uint32 29:0 -
-- - - - stable 0x000000e4 1 RO uint32 30:30 -
-- - - - toggle 0x000000e4 1 RO uint32 31:31 -
-- - - - expected_cnt 0x000000e5 1 RW uint32 27:0 -
-- - - - edge 0x000000e5 1 RW uint32 31:31 -
-- - - - offset_cnt 0x000000e6 1 RO uint32 27:0 -
-REG_EPCS 1 1 REG addr 0x000000d0 1 WO uint32 23:0 -
-- - - - rden 0x000000d1 1 WO uint32 0:0 -
-- - - - read_bit 0x000000d2 1 WO uint32 0:0 -
-- - - - write_bit 0x000000d3 1 WO uint32 0:0 -
-- - - - sector_erase 0x000000d4 1 WO uint32 0:0 -
-- - - - busy 0x000000d5 1 RO uint32 0:0 -
-- - - - unprotect 0x000000d6 1 WO uint32 31:0 -
-REG_DPMM_CTRL 1 1 REG rd_usedw 0x000000ee 1 RO uint32 31:0 -
-REG_DPMM_DATA 1 1 FIFO data 0x000000ec 1 RO uint32 31:0 -
-REG_MMDP_CTRL 1 1 REG wr_usedw 0x000000ea 1 RO uint32 31:0 -
-- - - - wr_availw 0x000000eb 1 RO uint32 31:0 -
-REG_MMDP_DATA 1 1 FIFO data 0x000000e8 1 WO uint32 31:0 -
-REG_REMU 1 1 REG reconfigure 0x000000d8 1 WO uint32 31:0 -
-- - - - param 0x000000d9 1 WO uint32 2:0 -
-- - - - read_param 0x000000da 1 WO uint32 0:0 -
-- - - - write_param 0x000000db 1 WO uint32 0:0 -
-- - - - data_out 0x000000dc 1 RO uint32 23:0 -
-- - - - data_in 0x000000dd 1 WO uint32 23:0 -
-- - - - busy 0x000000de 1 RO uint32 0:0 -
-*/
-
 CMMap mmap_to_regmap(istringstream& iss)
 {
     CMMap regmap;
@@ -166,14 +106,15 @@ CMMap mmap_to_regmap(istringstream& iss)
     mm_info_t last_mm_info;
 
     unsigned long long start_addr44;
-    
+
     int mm_mask_hi, mm_mask_lo;
     int user_mask_hi, user_mask_lo;
-   
+
     uint32_t mask;
     char line[250];
     string val_str;
     bool same_mask;
+    // char sep;
 
     iss.getline(line, sizeof(line));
     iss.getline(line, sizeof(line));
@@ -181,20 +122,24 @@ CMMap mmap_to_regmap(istringstream& iss)
         same_mask = false;
         mm_info = last_mm_info;
         stringstream strs(line);
-        
+
         strs >> val_str;
         if (val_str != "-") {
             mm_info.port_name = val_str;
+            mm_info.peripheral_span = 1;
+            mm_info.mm_port_span = 1;
+            mm_info.n_peripherals = 1;
+            mm_info.n_ports = 1;
         }
 
         strs >> val_str;
-        mm_info.n_peripherals = 0;
+        // mm_info.n_peripherals = 1;
         if (val_str != "-") {
             mm_info.n_peripherals = stoi(val_str);
         }
 
         strs >> val_str;
-        mm_info.n_ports = 0;
+        // mm_info.n_ports = 1;
         if (val_str != "-") {
             mm_info.n_ports = stoi(val_str);
         }
@@ -230,6 +175,10 @@ CMMap mmap_to_regmap(istringstream& iss)
             mm_info.radix = val_str;
         }
 
+        /* Code to remove sscanf */
+        // strs >> mm_mask_hi;
+        // strs >> sep;
+        // strs >> mm_mask_lo;
         strs >> val_str;
         sscanf(val_str.c_str(), "%d:%d", &mm_mask_hi, &mm_mask_lo);
         mask = 0;
@@ -240,6 +189,24 @@ CMMap mmap_to_regmap(istringstream& iss)
             mm_info.mm_mask = mask;
         }
         mm_info.shift = mm_mask_lo;
+        
+        /* Code to remove sscanf */ 
+        // if (strs.peek() != "-") {
+        //     sep = strs.get()
+        //     mm_info.user_mask = mm_info.mm_mask;
+        //     mm_info.span = mm_info.n_fields;
+        // }
+        // else {
+        //     strs >> user_mask_hi;
+        //     strs >> sep;
+        //     strs >> user_mask_lo;
+        //     mask = 0;
+        //     for (int i=mm_mask_lo; i<=mm_mask_hi; i++) {
+        //         mask |= (1<<i);
+        //     }
+        //     mm_info.user_mask = mask;
+        //     mm_info.span = (uint)(((user_mask_hi - user_mask_lo + 1) * mm_info.n_fields) / (mm_mask_hi - mm_mask_lo + 1));
+        // }
         strs >> val_str;
         if (val_str != "-") {
             sscanf(val_str.c_str(), "%d:%d", &user_mask_hi, &user_mask_lo);
@@ -252,12 +219,27 @@ CMMap mmap_to_regmap(istringstream& iss)
         }
         else {
             mm_info.user_mask = mm_info.mm_mask;
-            mm_info.span = mm_info.n_fields; 
+            mm_info.span = mm_info.n_fields;
+        }
+
+        strs >> val_str;
+        if (val_str != "-") {
+            if (mm_info.n_peripherals > 1 || mm_info.n_ports > 1) {
+                mm_info.peripheral_span = stoi(val_str);
+            }
+        }
+
+        strs >> val_str;
+        if (val_str != "-") {
+            if (mm_info.n_peripherals > 1 || mm_info.n_ports > 1) {
+                mm_info.mm_port_span = stoi(val_str);
+            }
         }
 
         if (strs.fail() || strs.bad()) {
             cerr << "import_mmap_file: invalid" << endl;
-        } 
+            cout << "import_mmap_file: invalid" << endl;
+        }
         else {
             last_mm_info = mm_info;
             mmap_add_register(regmap, mm_info);
@@ -266,6 +248,6 @@ CMMap mmap_to_regmap(istringstream& iss)
 
     cout << "regmap:" << endl;
     regmap.print_screen();
-    
+
     return regmap;
 }
diff --git a/src/tools/util.h b/src/tools/util.h
index e1a497b586b7936923f33b580f92b62bc4231b13..f9fa23005ebca23230de19f1674799f6c5b0898d 100644
--- a/src/tools/util.h
+++ b/src/tools/util.h
@@ -96,7 +96,7 @@ public:
     }
 
     void clearStr(uint val_nr) {
-        std::memset((void *)strdata[val_nr].val, 0, sizeof(strdata[val_nr].val));
+        std::memset((void *)strdata[val_nr].val, 0, MAX_VAL_SIZE);
     }
     
     void clearInt(uint val_nr) {
diff --git a/src/tr.cpp b/src/tr.cpp
index ebed5bcf042e4a842b52fead0b08a37cb11cb966..73bfe541adc292c0470c34866c462bb6a209dfaf 100644
--- a/src/tr.cpp
+++ b/src/tr.cpp
@@ -48,11 +48,11 @@ TranslatorMap::TranslatorMap()
 {
     translatorMap = new CPointMap();
 
-    translatorMap->add_register("TR_reload_W",           "-", 1, "RW", REG_FORMAT_BOOLEAN,1);
-    translatorMap->add_register("TR_software_version_R", "-", 1, "RO", REG_FORMAT_STRING, 1);
-    translatorMap->add_register("TR_busy_R",             "-", 1, "RO", REG_FORMAT_BOOLEAN,1);
-    translatorMap->add_register("TR_tod_R",              "-", 1, "RO", REG_FORMAT_UINT32, 1);
-    translatorMap->add_register("TR_uptime_R",           "-", 1, "RO", REG_FORMAT_UINT32, 1);
+    translatorMap->add_register("TR_reload_RW",          "-", 1, 1, "RW", REG_FORMAT_BOOLEAN,1);
+    translatorMap->add_register("TR_software_version_R", "-", 1, 1, "RO", REG_FORMAT_STRING, 1);
+    translatorMap->add_register("TR_busy_R",             "-", 1, 1, "RO", REG_FORMAT_BOOLEAN,1);
+    translatorMap->add_register("TR_tod_R",              "-", 1, 1, "RO", REG_FORMAT_UINT32, 1);
+    translatorMap->add_register("TR_uptime_R",           "-", 1, 1, "RO", REG_FORMAT_UINT32, 1);
 }
 
 
@@ -79,7 +79,7 @@ bool TranslatorMap::translator(TermOutput& termout, const char cmd, const string
     }
 
     int format = (int)translatorMap->getFormat(addr);
-    termout.nof_vals = translatorMap->getSpan(addr);
+    termout.nof_vals = translatorMap->getDataSize(addr);
     termout.datatype = format;
 
     retval = true;