diff --git a/src/constants.h b/src/constants.h
index 1ab897de269ba69b276b4447e1e4ad790dbc1ac9..3f399ebe91f1c9ae671afa385c7c478d7e667cb6 100644
--- a/src/constants.h
+++ b/src/constants.h
@@ -29,6 +29,7 @@
 #ifndef CONSTANTS_H
 #define CONSTANTS_H
 
+#define C_N_pn 16
 #define C_S_pn 12
 #define C_W_adc 14
 #define C_F_adc 200E6
@@ -41,4 +42,7 @@
 
 #define C_BSN_LATENCY 20000  // 1 period = 5.12us, 20000 = +/- 100ms
 
+#define C_Q_fft 2
+#define C_N_sub 512
+
 #endif
diff --git a/src/fpga.cpp b/src/fpga.cpp
index 45bf172179c165e37c8ce04e7194c243136e388a..3e18f3a11860460f2432af7dce3393d9ceefdc7b 100644
--- a/src/fpga.cpp
+++ b/src/fpga.cpp
@@ -61,8 +61,8 @@ Fpga::Fpga(list<class Node*>& nodelist)
     pointMap->add_register("FPGA_version_R",                                 "fpga/name",                                   nodes.size(), 1, "RO", REG_FORMAT_STRING);
     pointMap->add_register("FPGA_firmware_version_R",                        "fpga/firmware_version",                       nodes.size(), 1, "RO", REG_FORMAT_STRING);
     pointMap->add_register("FPGA_hardware_version_R",                        "fpga/hardware_version",                       nodes.size(), 1, "RO", REG_FORMAT_STRING);
-    pointMap->add_register("FPGA_sst_offload_selector_R",                    "fpga/sst_offload_selector",                   nodes.size(), 1, "RO", REG_FORMAT_BOOLEAN);
-    pointMap->add_register("FPGA_sst_offload_selector_RW",                   "fpga/sst_offload_selector",                   nodes.size(), 1, "RW", REG_FORMAT_BOOLEAN);
+    pointMap->add_register("FPGA_sst_offload_weighted_subbands_R",           "fpga/sst_offload_weighted_subbands",          nodes.size(), 1, "RO", REG_FORMAT_BOOLEAN);
+    pointMap->add_register("FPGA_sst_offload_weighted_subbands_RW",          "fpga/sst_offload_weighted_subbands",          nodes.size(), 1, "RW", REG_FORMAT_BOOLEAN);
     pointMap->add_register("FPGA_sst_offload_enable_R",                      "fpga/sst_offload_enable",                     nodes.size(), 1, "RO", REG_FORMAT_BOOLEAN);
     pointMap->add_register("FPGA_sst_offload_enable_RW",                     "fpga/sst_offload_enable",                     nodes.size(), 1, "RW", REG_FORMAT_BOOLEAN);
     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);
@@ -106,6 +106,9 @@ Fpga::Fpga(list<class Node*>& nodelist)
     pointMap->add_register("FPGA_signal_input_samples_delay_R",              "fpga/signal_input_samples_delay",             nodes.size(), C_S_pn, "RO", REG_FORMAT_UINT32);
     pointMap->add_register("FPGA_signal_input_samples_delay_RW",             "fpga/signal_input_samples_delay",             nodes.size(), C_S_pn, "RW", REG_FORMAT_UINT32);
     
+    pointMap->add_register("FPGA_subband_weights_R",                         "fpga/subband_weights",                        nodes.size(), C_S_pn*C_N_sub, "RO", REG_FORMAT_UINT32);
+    pointMap->add_register("FPGA_subband_weights_RW",                        "fpga/subband_weights",                        nodes.size(), C_S_pn*C_N_sub, "RW", REG_FORMAT_UINT32);
+
     uint32_t scrap_span = 0;
     uint32_t scrap_span_next = 0;
     uint32_t scrap_span_prev = 0;
diff --git a/src/periph/fpga.cpp b/src/periph/fpga.cpp
index 68d6545f4f7058c543ebd2b3ea2f3f3ddc7199e7..6c8906488fc561fdcbab9cbc706efed0f6a0923f 100644
--- a/src/periph/fpga.cpp
+++ b/src/periph/fpga.cpp
@@ -111,7 +111,7 @@ Periph_fpga::Periph_fpga(string ipaddr, string expected_design_name, uint expect
     registerMap->add_register("fpga/weights",                              "-", 1, weights_span, "RW", REG_FORMAT_INT16);
 
     registerMap->add_register("fpga/processing_enable",                      "-", 1, 1, "RW", REG_FORMAT_BOOLEAN);
-    registerMap->add_register("fpga/sst_offload_selector",                   "-", 1, 1, "RW", REG_FORMAT_BOOLEAN);
+    registerMap->add_register("fpga/sst_offload_weighted_subbands",          "-", 1, 1, "RW", REG_FORMAT_BOOLEAN);
     registerMap->add_register("fpga/sst_offload_enable",                     "-", 1, 1, "RW", REG_FORMAT_BOOLEAN);
     registerMap->add_register("fpga/sst_offload_hdr_eth_destination_mac",    "-", 1, 1, "RW", REG_FORMAT_STRING);
     registerMap->add_register("fpga/sst_offload_hdr_ip_destination_address", "-", 1, 1, "RW", REG_FORMAT_STRING);
@@ -143,6 +143,8 @@ Periph_fpga::Periph_fpga(string ipaddr, string expected_design_name, uint expect
     
     registerMap->add_register("fpga/signal_input_samples_delay",             "-", 1, 12, "RW", REG_FORMAT_UINT32);
 
+    registerMap->add_register("fpga/subband_weights",                        "-", 1, 12*512, "RW", REG_FORMAT_UINT32);
+
     registerMap->print_screen();
 
     // Test FPGA by reading system info:
@@ -213,7 +215,7 @@ bool Periph_fpga::Read(const string addr_str, uint32_t *data_ptr, bool use_mask_
     return ret;
 }
 
-bool Periph_fpga::Write(const string addr_str, const uint32_t nvalues, uint32_t *data_ptr, bool use_shift_mask=true)
+bool Periph_fpga::Write(const string addr_str, uint32_t *data_ptr, bool use_shift_mask=true)
 {
     if (!Enabled) {
         return false;
@@ -402,8 +404,8 @@ bool Periph_fpga::read(TermOutput& termout, const string addr,
         else if (addr == "fpga/weights") {
             retval = read_fpga_weights(termout, format);
         }
-        else if (addr == "fpga/sst_offload_selector") {
-            retval = read_sst_offload_selector(termout, format);
+        else if (addr == "fpga/sst_offload_weighted_subbands") {
+            retval = read_sst_offload_weighted_subbands(termout, format);
         }
         else if (addr == "fpga/sst_offload_enable") {
             retval = read_sst_offload_enable(termout, format);
@@ -480,6 +482,9 @@ bool Periph_fpga::read(TermOutput& termout, const string addr,
         else if (addr == "fpga/signal_input_samples_delay") {
             retval = read_signal_input_samples_delay(termout, format);
         }
+        else if (addr == "fpga/subband_weights") {
+            retval = read_subband_weights(termout, format);
+        }
         else {
             throw runtime_error("address " + addr + " not found!");
         }
@@ -498,7 +503,7 @@ bool Periph_fpga::write(TermOutput& termout, const string addr, const string typ
     uint32_t *data_ptr = (uint32_t *)data;
 
     if (type == "mm") {
-        retval = Write(addr, nvalues, data_ptr);
+        retval = Write(addr, data_ptr);
     }
     else { // "fpga/..."
     //    if (addr == "fpga/rbf") {
@@ -523,65 +528,68 @@ bool Periph_fpga::write(TermOutput& termout, const string addr, const string typ
             retval = flash_pages(data_ptr, nvalues);
         }
         else if (addr == "fpga/flash_page") {
-            retval = flash_page(data_ptr, nvalues);
+            retval = flash_page(data_ptr);
         }
         else if (addr == "fpga/flash_prot") {
             retval = flash_prot(data_ptr);
         }
         else if (addr == "fpga/epcs_mmdp_data") {
             // write to FIFO
-            retval = Write("mm/0/REG_MMDP_DATA/data", nvalues, data_ptr);
+            retval = Write("mm/0/REG_MMDP_DATA/data", data_ptr);
         }
         else if (addr == "fpga/enable_mask") {
             retval = write_fpga_enable_mask(data);
         }
         else if (addr == "fpga/scrap") {
-            retval = write_fpga_scrap(data_ptr, nvalues);
+            retval = write_fpga_scrap(data_ptr);
         }
         else if (addr == "fpga/weights") {
-            retval = write_fpga_weights(data_ptr, nvalues);
+            retval = write_fpga_weights(data_ptr);
         }
-        else if (addr == "fpga/sst_offload_selector") {
-            retval = write_sst_offload_selector(data_ptr, nvalues);
+        else if (addr == "fpga/sst_offload_weighted_subbands") {
+            retval = write_sst_offload_weighted_subbands(data_ptr);
         }
         else if (addr == "fpga/sst_offload_enable") {
-            retval = write_sst_offload_enable(data_ptr, nvalues);
+            retval = write_sst_offload_enable(data_ptr);
         }
         else if (addr == "fpga/sst_offload_hdr_eth_destination_mac") {
-            retval = write_sst_offload_hdr_eth_destination_mac(data, nvalues);
+            retval = write_sst_offload_hdr_eth_destination_mac(data);
         }
         else if (addr == "fpga/sst_offload_hdr_ip_destination_address") {
-            retval = write_sst_offload_hdr_ip_destination_address(data, nvalues);
+            retval = write_sst_offload_hdr_ip_destination_address(data);
         }
         else if (addr == "fpga/sst_offload_hdr_udp_destination_port") {
-            retval = write_sst_offload_hdr_udp_destination_port(data_ptr, nvalues);
+            retval = write_sst_offload_hdr_udp_destination_port(data_ptr);
         }
         else if (addr == "fpga/processing_enable") {
-            retval = write_processing_enable(data_ptr, nvalues);
+            retval = write_processing_enable(data_ptr);
         }
         else if (addr == "fpga/sdp_info_station_id") {
-            retval = write_sdp_info_station_id(data_ptr, nvalues);
+            retval = write_sdp_info_station_id(data_ptr);
         }
         else if (addr == "fpga/sdp_info_observation_id") {
-            retval = write_sdp_info_observation_id(data_ptr, nvalues);
+            retval = write_sdp_info_observation_id(data_ptr);
         }
         else if (addr == "fpga/sdp_info_nyquist_sampling_zone_index") {
-            retval = write_sdp_info_nyquist_sampling_zone_index(data_ptr, nvalues);
+            retval = write_sdp_info_nyquist_sampling_zone_index(data_ptr);
         }
         else if (addr == "fpga/wg_enable") {
-            retval = write_wg_enable(data_ptr, nvalues);
+            retval = write_wg_enable(data_ptr);
         }
         else if (addr == "fpga/wg_amplitude") {
-            retval = write_wg_amplitude(data_ptr, nvalues);
+            retval = write_wg_amplitude(data_ptr);
         }
         else if (addr == "fpga/wg_phase") {
-            retval = write_wg_phase(data_ptr, nvalues);
+            retval = write_wg_phase(data_ptr);
         }
         else if (addr == "fpga/wg_frequency") {
-            retval = write_wg_frequency(data_ptr, nvalues);
+            retval = write_wg_frequency(data_ptr);
         }
         else if (addr == "fpga/signal_input_samples_delay") {
-            retval = write_signal_input_samples_delay(data_ptr, nvalues);
+            retval = write_signal_input_samples_delay(data_ptr);
+        }
+        else if (addr == "fpga/subband_weights") {
+            retval = write_subband_weights(data_ptr);
         }
         else {
             throw runtime_error("address " + addr + " not found!");
@@ -619,29 +627,29 @@ bool Periph_fpga::flash_prot(uint32_t *data)
     uint32_t passphrase_unprotect = 0xBEDA221E;
 
     if (*data == 0) { // unprotect
-        retval = Write("mm/0/REG_EPCS/unprotect", 1, &passphrase_unprotect);
+        retval = Write("mm/0/REG_EPCS/unprotect", &passphrase_unprotect);
     }
     else { // protect
-        retval = Write("mm/0/REG_EPCS/unprotect", 1, &passphrase_protect);
+        retval = Write("mm/0/REG_EPCS/unprotect", &passphrase_protect);
     }
     return retval;
 }
 
-bool Periph_fpga::flash_page(uint32_t *data, const uint len)
+bool Periph_fpga::flash_page(uint32_t *data)
 {
     bool retval = false;
 
     wait_while_epcs_busy(1);
     // write address
     uint32_t addr = Flash_page_start * Flash_page_size_bytes;
-    retval = Write("mm/0/REG_EPCS/addr", 1, &addr);
+    retval = Write("mm/0/REG_EPCS/addr", &addr);
 
     // write to FIFO
-    retval = Write("mm/0/REG_MMDP_DATA/data", len, data);
+    retval = Write("mm/0/REG_MMDP_DATA/data", data);
 
     // write_write
     uint32_t d = 1;
-    retval = Write("mm/0/REG_EPCS/write", 1, &d);
+    retval = Write("mm/0/REG_EPCS/write", &d);
 
     return retval;
 }
@@ -655,7 +663,7 @@ bool Periph_fpga::flash_pages(uint32_t *data, const uint len)
     cout << "Periph_fpga::flash_pages nof_pages=" << nof_pages << endl;
 
     for (uint p=0; p<nof_pages; p++) {
-        retval = flash_page(&data[(p*page_size_words)], page_size_words);
+        retval = flash_page(&data[(p*page_size_words)]);
         Flash_page_start++;
     }
     return retval;
@@ -694,10 +702,10 @@ bool Periph_fpga::flash_erase_sector(uint32_t sector)
     for (uint i=0; i<s_list.size(); i++) {
         s = sector * 0x40000 + s_list[i];
         // write address
-        retval = Write("mm/0/REG_EPCS/addr", 1, &s);
+        retval = Write("mm/0/REG_EPCS/addr", &s);
         // sector erase
         d = 1;
-        retval = Write("mm/0/REG_EPCS/sector_erase", 1, &d);
+        retval = Write("mm/0/REG_EPCS/sector_erase", &d);
         wait_while_epcs_busy(50000);
     }
     return retval;
@@ -853,19 +861,15 @@ bool Periph_fpga::read_fpga_scrap(TermOutput& termout, int format)
     return retval;
 }
 
-bool Periph_fpga::write_fpga_scrap(uint32_t *data, uint nvalues)
+bool Periph_fpga::write_fpga_scrap(uint32_t *data)
 {
+    uint32_t nvalues = mmap->getSpan("mm/0/RAM_SCRAP/0/data");
     cout << "Periph_fpga::write_fpga_scrap " << nvalues << " values" << endl;
-    uint32_t nvalues_chk = mmap->getSpan("mm/0/RAM_SCRAP/0/data");
-    if (nvalues > nvalues_chk) {
-        nvalues = nvalues_chk;
-    }
-
     for (uint i=0; i<nvalues; i++) {
         cout << data[i] << " ";
     }
     cout << endl;
-    bool retval = Write("mm/0/RAM_SCRAP/0/data", nvalues, data);
+    bool retval = Write("mm/0/RAM_SCRAP/0/data", data);
     return retval;
 }
 
@@ -873,14 +877,14 @@ bool Periph_fpga::read_fpga_weights(TermOutput& termout, int format)
 {
     bool retval = true;
     int16_t *ptr = (int16_t *)termout.val;
-    uint32_t nvalues_scrap = mmap->getSpan("mm/0/RAM_SCRAP/0/data");
+    uint32_t nvalues = mmap->getSpan("mm/0/RAM_SCRAP/0/data");
     uint nblocks = 48; // 11712/244=48
 
-    uint32_t *data_scrap = new uint32_t[nvalues_scrap];
+    uint32_t *data_scrap = new uint32_t[nvalues];
     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) {
+        for (uint j=0; j<nvalues; j+=2) {
             uint32_t ds = data_scrap[j];
             *ptr++ = (int16_t)(ds & 0xffff);
             *ptr++ = (int16_t)(ds >> 16);
@@ -892,15 +896,12 @@ bool Periph_fpga::read_fpga_weights(TermOutput& termout, int format)
     return retval;
 }
 
-bool Periph_fpga::write_fpga_weights(const uint32_t *data, uint nvalues)
+bool Periph_fpga::write_fpga_weights(const uint32_t *data)
 {
     bool retval = false;
     uint32_t nvalues_scrap = mmap->getSpan("mm/0/RAM_SCRAP/0/data");
-    uint32_t nvalues_weights = registerMap->getDataSize("fpga/weights_R");
+    uint32_t nvalues = registerMap->getDataSize("fpga/weights_R");
     uint nblocks = 48; // 11712/244=48
-    if (nvalues > nvalues_weights) {
-        nvalues = nvalues_weights;
-    }
 
     uint32_t *data_scrap = new uint32_t[nvalues_scrap];
 
@@ -922,14 +923,14 @@ bool Periph_fpga::write_fpga_weights(const uint32_t *data, uint nvalues)
             si++;
             data_scrap[j] = ds;
         }
-        retval = Write("mm/0/RAM_SCRAP/0/data", nvalues_scrap, data_scrap);
+        retval = Write("mm/0/RAM_SCRAP/0/data", data_scrap);
     }
 
     delete[] data_scrap;
     return retval;
 }
 
-bool Periph_fpga::read_sst_offload_selector(TermOutput& termout, int format)
+bool Periph_fpga::read_sst_offload_weighted_subbands(TermOutput& termout, int format)
 {
     bool retval = true;
 
@@ -946,9 +947,9 @@ bool Periph_fpga::read_sst_offload_selector(TermOutput& termout, int format)
     return retval;
 }
 
-bool Periph_fpga::write_sst_offload_selector(uint32_t *data, uint32_t nvalues)
+bool Periph_fpga::write_sst_offload_weighted_subbands(uint32_t *data)
 {
-    bool retval = Write("mm/0/REG_DP_SELECTOR/0/input_select", nvalues, data);
+    bool retval = Write("mm/0/REG_DP_SELECTOR/0/input_select", data);
     return retval;
 }
 
@@ -969,10 +970,9 @@ bool Periph_fpga::read_sst_offload_enable(TermOutput& termout, int format)
     return retval;
 }
 
-bool Periph_fpga::write_sst_offload_enable(uint32_t *data, uint32_t nvalues)
+bool Periph_fpga::write_sst_offload_enable(uint32_t *data)
 {
-    cout << "sst_offload_enable data=" << data[0] << " nvlues=" << nvalues << endl;
-    return Write("mm/0/REG_STAT_ENABLE_SST/0/enable", nvalues, data);
+    return Write("mm/0/REG_STAT_ENABLE_SST/0/enable", data);
 }
 
 
@@ -1001,10 +1001,8 @@ bool Periph_fpga::read_sst_offload_hdr_eth_destination_mac(TermOutput& termout,
     return retval;
 }
 
-bool Periph_fpga::write_sst_offload_hdr_eth_destination_mac(const char *data, uint32_t nvalues)
+bool Periph_fpga::write_sst_offload_hdr_eth_destination_mac(const char *data)
 {
-    if (nvalues == 0) return true;
-
     // cout << "data=" << string(data) << endl;
     char sep;
     uint32_t m0, m1, m2, m3, m4, m5;
@@ -1019,7 +1017,7 @@ bool Periph_fpga::write_sst_offload_hdr_eth_destination_mac(const char *data, ui
     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);
+    return Write("mm/0/REG_STAT_HDR_DAT_SST/0/eth_destination_mac", mac);
 }
 
 bool Periph_fpga::read_sst_offload_hdr_ip_destination_address(TermOutput& termout, int format)
@@ -1045,10 +1043,8 @@ bool Periph_fpga::read_sst_offload_hdr_ip_destination_address(TermOutput& termou
     return retval;
 }
 
-bool Periph_fpga::write_sst_offload_hdr_ip_destination_address(const char *data, uint32_t nvalues)
+bool Periph_fpga::write_sst_offload_hdr_ip_destination_address(const char *data)
 {
-    if (nvalues == 0) return true;
-
     char sep;
     uint ip0, ip1, ip2, ip3;
     uint32_t ip[1] = {0};
@@ -1072,7 +1068,7 @@ bool Periph_fpga::write_sst_offload_hdr_ip_destination_address(const char *data,
     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);
+    return Write("mm/0/REG_STAT_HDR_DAT_SST/0/ip_destination_address", ip);
 }
 
 bool Periph_fpga::read_sst_offload_hdr_udp_destination_port(TermOutput& termout, int format)
@@ -1092,9 +1088,9 @@ bool Periph_fpga::read_sst_offload_hdr_udp_destination_port(TermOutput& termout,
     return retval;
 }
 
-bool Periph_fpga::write_sst_offload_hdr_udp_destination_port(uint32_t *data, uint32_t nvalues)
+bool Periph_fpga::write_sst_offload_hdr_udp_destination_port(uint32_t *data)
 {
-    return Write("mm/0/REG_STAT_HDR_DAT_SST/0/udp_destination_port", nvalues, data);
+    return Write("mm/0/REG_STAT_HDR_DAT_SST/0/udp_destination_port", data);
 }
 
 
@@ -1115,7 +1111,7 @@ bool Periph_fpga::read_processing_enable(TermOutput& termout, int format)
     return retval;
 }
 
-bool Periph_fpga::write_processing_enable(uint32_t *data, uint32_t nvalues)
+bool Periph_fpga::write_processing_enable(uint32_t *data)
 {
     // write dp_on 0
     // write bsn_init [calc val for next sec]
@@ -1123,7 +1119,6 @@ bool Periph_fpga::write_processing_enable(uint32_t *data, uint32_t nvalues)
     // write dp_on_pps 1
     // write dp_on 1
 
-    cout << "processing_enable data=" << data[0] << " nvalues=" << nvalues << endl;
     uint32_t *reg = new uint32_t[2];
     reg[0] = 0;
     reg[1] = 0;
@@ -1131,7 +1126,7 @@ bool Periph_fpga::write_processing_enable(uint32_t *data, uint32_t nvalues)
     if (processing_enable) {
         cout << "turn on bsn" << endl;
         // reg[0] = 0;
-        // if (Write("mm/0/REG_BSN_SOURCE_V2/0/dp_on", 1, reg) == false) {
+        // if (Write("mm/0/REG_BSN_SOURCE_V2/0/dp_on", reg) == false) {
         //     cout << "Write error (mm/0/REG_BSN_SOURCE_V2/0/dp_on) 0" << endl;
         //     return false;
         // }
@@ -1150,29 +1145,29 @@ 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/0/bsn_init", 2, reg) == false) {
+        if (Write("mm/0/REG_BSN_SOURCE_V2/0/bsn_init", 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/0/bsn_time_offset", 1, reg) == false) {
+        if (Write("mm/0/REG_BSN_SOURCE_V2/0/bsn_time_offset", reg) == false) {
             cout << "Write error (mm/0/REG_BSN_SOURCE_V2/0/bsn_time_offset)" << endl;
             return false;
         }
         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) {
+        if (Write("mm/0/REG_BSN_SOURCE_V2/0/dp_on", reg, false) == false) {
             cout << "Write error (mm/0/REG_BSN_SOURCE_V2/0/dp_on_pps)" << endl;
             return false;
         }
         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) {
+        if (Write("mm/0/REG_BSN_SOURCE_V2/0/dp_on", 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/0/dp_on", 1, reg) == false) {
+        if (Write("mm/0/REG_BSN_SOURCE_V2/0/dp_on", reg) == false) {
             cout << "Write error (mm/0/REG_BSN_SOURCE_V2/0/dp_on) 0" << endl;
             return false;
         }
@@ -1195,8 +1190,8 @@ bool Periph_fpga::read_sdp_info_station_id(TermOutput& termout, int format) {
     return retval;
 }
 
-bool Periph_fpga::write_sdp_info_station_id(uint32_t *data, uint32_t nvalues) {
-    bool retval = Write("mm/0/REG_SDP_INFO/0/station_id", nvalues, data);
+bool Periph_fpga::write_sdp_info_station_id(uint32_t *data) {
+    bool retval = Write("mm/0/REG_SDP_INFO/0/station_id", data);
     return retval;
 }
 
@@ -1215,8 +1210,8 @@ bool Periph_fpga::read_sdp_info_observation_id(TermOutput& termout, int format)
     return retval;
 }
 
-bool Periph_fpga::write_sdp_info_observation_id(uint32_t *data, uint32_t nvalues) {
-    bool retval = Write("mm/0/REG_SDP_INFO/0/observation_id", nvalues, data);
+bool Periph_fpga::write_sdp_info_observation_id(uint32_t *data) {
+    bool retval = Write("mm/0/REG_SDP_INFO/0/observation_id", data);
     return retval;
 }
 
@@ -1235,8 +1230,8 @@ bool Periph_fpga::read_sdp_info_nyquist_sampling_zone_index(TermOutput& termout,
     return retval;
 }
 
-bool Periph_fpga::write_sdp_info_nyquist_sampling_zone_index(uint32_t *data, uint32_t nvalues) {
-    bool retval = Write("mm/0/REG_SDP_INFO/0/nyquist_zone_index", nvalues, data);
+bool Periph_fpga::write_sdp_info_nyquist_sampling_zone_index(uint32_t *data) {
+    bool retval = Write("mm/0/REG_SDP_INFO/0/nyquist_zone_index", data);
     return retval;
 }
 
@@ -1338,7 +1333,7 @@ bool Periph_fpga::read_wg_enable(TermOutput& termout, int format) {
     return retval;
 }
 
-bool Periph_fpga::write_wg_enable(uint32_t *data, uint32_t nvalues) {
+bool Periph_fpga::write_wg_enable(uint32_t *data) {
     bool retval = true;
     uint32_t *reg = new uint32_t[4];
     uint64_t scheduled_bsn;
@@ -1354,7 +1349,7 @@ bool Periph_fpga::write_wg_enable(uint32_t *data, uint32_t nvalues) {
             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);
+            retval = Write(regname1, reg, false);
         }
     }
     // turn on waveform
@@ -1364,7 +1359,7 @@ bool Periph_fpga::write_wg_enable(uint32_t *data, uint32_t nvalues) {
             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);
+            retval = Write(regname1, reg, false);
         }
     }
     // get bsn and add latency
@@ -1384,7 +1379,7 @@ bool Periph_fpga::write_wg_enable(uint32_t *data, uint32_t nvalues) {
         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);
+            retval = Write(regname1, reg);
         }
     }
     delete[] reg;
@@ -1419,7 +1414,7 @@ bool Periph_fpga::read_wg_amplitude(TermOutput& termout, int format) {
     return retval;
 }
 
-bool Periph_fpga::write_wg_amplitude(uint32_t *data, uint32_t nvalues) {
+bool Periph_fpga::write_wg_amplitude(uint32_t *data) {
     bool retval = true;
     uint32_t *reg = new uint32_t[2];
 
@@ -1430,7 +1425,7 @@ bool Periph_fpga::write_wg_amplitude(uint32_t *data, uint32_t nvalues) {
         regname = "mm/0/REG_WG/" + to_string(i) + "/ampl";
         ampl = (*_ptr) * C_WG_AMPL_UNIT;
         reg[0] = (uint32_t)ampl;
-        retval = Write(regname, 1, reg);
+        retval = Write(regname, reg);
         _ptr++;
     }
     delete[] reg;
@@ -1466,7 +1461,7 @@ bool Periph_fpga::read_wg_phase(TermOutput& termout, int format) {
     return retval;
 }
 
-bool Periph_fpga::write_wg_phase (uint32_t *data, uint32_t nvalues) {
+bool Periph_fpga::write_wg_phase (uint32_t *data) {
     bool retval = true;
     uint32_t *reg = new uint32_t[2];
 
@@ -1477,7 +1472,7 @@ bool Periph_fpga::write_wg_phase (uint32_t *data, uint32_t nvalues) {
         regname = "mm/0/REG_WG/" + to_string(i) + "/phase";
         phase = (*_ptr) * C_WG_PHASE_UNIT;
         reg[0] = (uint32_t)phase;
-        retval = Write(regname, 1, reg);
+        retval = Write(regname, reg);
         _ptr++;
     }
     delete[] reg;
@@ -1514,7 +1509,7 @@ bool Periph_fpga::read_wg_frequency(TermOutput& termout, int format) {
     return retval;
 }
 
-bool Periph_fpga::write_wg_frequency(uint32_t *data, uint32_t nvalues) {
+bool Periph_fpga::write_wg_frequency(uint32_t *data) {
     bool retval = true;
     uint32_t *reg = new uint32_t[2];
     
@@ -1527,7 +1522,7 @@ bool Periph_fpga::write_wg_frequency(uint32_t *data, uint32_t nvalues) {
         freq = modf(freq, &intpart);
         freq = freq * C_WG_FREQ_UNIT;
         reg[0] = (uint32_t)freq;
-        retval = Write(regname, 1, reg);
+        retval = Write(regname, reg);
         _ptr++;
     }
     delete[] reg;
@@ -1730,7 +1725,7 @@ bool Periph_fpga::read_jesd204b_csr_rx_err1(TermOutput& termout, int format, int
     return retval;
 }
 
-bool Periph_fpga::write_signal_input_samples_delay(uint32_t *data, uint32_t nvalues) {
+bool Periph_fpga::write_signal_input_samples_delay(uint32_t *data) {
     bool retval = true;
     uint32_t *reg = new uint32_t[2];
     uint32_t min_sample_delay = 0;
@@ -1746,7 +1741,7 @@ bool Periph_fpga::write_signal_input_samples_delay(uint32_t *data, uint32_t nval
         } else {
             regname = "mm/0/REG_DP_SHIFTRAM/" + to_string(i) + "/shift";
             reg[0] = (uint32_t)sample_delay;
-            retval = Write(regname, 1, reg);
+            retval = Write(regname, reg);
             _ptr++;
         }
     }
@@ -1771,10 +1766,45 @@ bool Periph_fpga::read_signal_input_samples_delay(TermOutput& termout, int forma
     return retval;
 }
 
+bool Periph_fpga::write_subband_weights(uint32_t *data) {
+    bool retval = true;
+    string regname;
+    uint32_t span;
+    uint32_t data_ptr;
+    uint32_t n_regs = (int32_t)(C_S_pn / C_Q_fft);
+
+    for (uint i=0; i<n_regs; i++) {
+        regname = "mm/0/RAM_EQUALIZER_GAINS/" + to_string(i) + "/data";
+        span = mmap->getSpan((regname));
+        data_ptr = i * span;
+        retval = Write(regname, &data[data_ptr]);
+    }
+    return retval;
+}
+
+bool Periph_fpga::read_subband_weights(TermOutput& termout, int format) {
+    bool retval = true;
+    uint32_t *_ptr = (uint32_t *)termout.val;
+
+    string regname;
+    uint32_t span;
+    uint32_t n_regs = (int32_t)(C_S_pn / C_Q_fft);
+
+    for (uint i=0; i<n_regs; i++) {
+        regname = "mm/0/RAM_EQUALIZER_GAINS/" + to_string(i) + "/data";
+        span = mmap->getSpan((regname));
+        retval = Read(regname, _ptr);
+        _ptr += span;
+    }
+    termout.nof_vals = C_S_pn * C_N_sub;
+    termout.datatype = format;
+    return retval;
+}
+
 bool Periph_fpga::write_wdi_override(TermOutput& termout)
 {
     uint32_t data = 0xB007FAC7;
-    return Write("mm/0/PIO_WDI/0/wdi_override", 1, &data);
+    return Write("mm/0/PIO_WDI/0/wdi_override", &data);
 }
 
 CMMap Periph_fpga::read_reg_map()
diff --git a/src/periph/fpga.h b/src/periph/fpga.h
index 4308d93ee430f277916681776bdfabd86f978040..7d743148ef034cb99b35d7b5b0487b4bc9627fca 100644
--- a/src/periph/fpga.h
+++ b/src/periph/fpga.h
@@ -73,14 +73,14 @@ private:
            Flash_fact_sector_start, Flash_fact_sector_end, Flash_select;
 
   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);
+  bool Write(const std::string addr_str, 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();
   bool flash_pages(uint32_t *data, const uint len);
-  bool flash_page(uint32_t *data, const uint len);
+  bool flash_page(uint32_t *data);
   bool flash_prot(uint32_t *data);
   bool wait_while_epcs_busy(uint sleeptime);
   std::string read_design_name();
@@ -98,46 +98,46 @@ private:
   bool read_fpga_temperature(TermOutput& termout, int format);
 
   bool read_fpga_scrap(TermOutput& termout, int format);
-  bool write_fpga_scrap(uint32_t *data, uint len);
+  bool write_fpga_scrap(uint32_t *data);
 
   bool read_fpga_weights(TermOutput& termout, int format);
-  bool write_fpga_weights(const uint32_t *data, uint nvalues);
+  bool write_fpga_weights(const uint32_t *data);
 
-  bool read_sst_offload_selector(TermOutput& termout, int format);
-  bool write_sst_offload_selector(uint32_t *data, uint32_t nvalues);
+  bool read_sst_offload_weighted_subbands(TermOutput& termout, int format);
+  bool write_sst_offload_weighted_subbands(uint32_t *data);
 
   bool read_sst_offload_enable(TermOutput& termout, int format);
-  bool write_sst_offload_enable(uint32_t *data, uint32_t nvalues);
+  bool write_sst_offload_enable(uint32_t *data);
 
   bool read_sst_offload_hdr_eth_destination_mac(TermOutput& termout, int format);
-  bool write_sst_offload_hdr_eth_destination_mac(const char *data, uint32_t nvalues);
+  bool write_sst_offload_hdr_eth_destination_mac(const char *data);
 
   bool read_sst_offload_hdr_ip_destination_address(TermOutput& termout, int format);
-  bool write_sst_offload_hdr_ip_destination_address(const char *data, uint32_t nvalues);
+  bool write_sst_offload_hdr_ip_destination_address(const char *data);
 
   bool read_sst_offload_hdr_udp_destination_port(TermOutput& termout, int format);
-  bool write_sst_offload_hdr_udp_destination_port(uint32_t *data, uint32_t nvalues);
+  bool write_sst_offload_hdr_udp_destination_port(uint32_t *data);
 
   bool read_processing_enable(TermOutput& termout, int format);
-  bool write_processing_enable(uint32_t *data, uint32_t nvalues);
+  bool write_processing_enable(uint32_t *data);
 
   bool read_sdp_info_station_id(TermOutput& termout, int format);
-  bool write_sdp_info_station_id(uint32_t *data, uint32_t nvalues);
+  bool write_sdp_info_station_id(uint32_t *data);
   bool read_sdp_info_observation_id(TermOutput& termout, int format);
-  bool write_sdp_info_observation_id(uint32_t *data, uint32_t nvalues);
+  bool write_sdp_info_observation_id(uint32_t *data);
   bool read_sdp_info_nyquist_sampling_zone_index(TermOutput& termout, int format);
-  bool write_sdp_info_nyquist_sampling_zone_index(uint32_t *data, uint32_t nvalues);
+  bool write_sdp_info_nyquist_sampling_zone_index(uint32_t *data);
   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 write_wg_enable(uint32_t *data);
   bool read_wg_amplitude(TermOutput& termout, int format);
-  bool write_wg_amplitude(uint32_t *data, uint32_t nvalues);
+  bool write_wg_amplitude(uint32_t *data);
   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 write_wg_phase (uint32_t *data);
+  bool write_wg_frequency(uint32_t *data);
   bool read_wg_frequency(TermOutput& termout, int format);
 
   bool read_bsn_monitor_input_sync_timeout(TermOutput& termout, int format, int mode);
@@ -151,9 +151,11 @@ private:
   bool read_jesd204b_csr_rx_err0(TermOutput& termout, int format, int mode);
   bool read_jesd204b_csr_rx_err1(TermOutput& termout, int format, int mode);
   
-  bool write_signal_input_samples_delay(uint32_t *data, uint32_t nvalues);
+  bool write_signal_input_samples_delay(uint32_t *data);
   bool read_signal_input_samples_delay(TermOutput& termout, int format);
 
+  bool write_subband_weights(uint32_t *data);
+  bool read_subband_weights(TermOutput& termout, int format);
 
   bool read_sdp_info_block_period(TermOutput& termout, int format);