Skip to content
Snippets Groups Projects
Select Git revision
  • fc87ff1d93a1277d4e132a50d73f2514e547f602
  • master default protected
  • Work_Gijs protected
3 results

I2C_serial_pi3.py

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    fpga_map.cpp 42.99 KiB
    /* *************************************************************************
    * 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:
    * . class with fpga registers available for opc-ua server
    * *********************************************************************** */
    
    // You need to compile with _REENTRANT defined since this uses threads
    #ifndef _REENTRANT
    #define _REENTRANT 1
    #endif
    
    #include <cstdio>
    #include <stdexcept>
    #include <iostream>
    #include <sstream>
    #include <exception>
    #include <unistd.h>
    
    #include <thread>
    #include <chrono>
    
    #include "sdptr.h"
    #include "constants.h"
    #include "fpga_map.h"
    #include "tools/loguru.h"
    #include "periph/fpga.h"
    
    using namespace std;
    
    // Everything addressed with FPGA_...
    
    extern int debug;
    extern Serverdat SD;
    
    FpgaMap::FpgaMap()
    {
        nFilterbanks = (uint32_t)SD.n_filterbanks;
        nBeamsets = (uint32_t)SD.n_beamsets;
        nFpgas = (uint32_t)SD.n_fpgas;
    
        pointMap = new CPointMap();
    
        // Add all opc-ua points:
        //                      opc-ua name,                                        intern cmdID,                                       n_nodes, n_data, permision, data_format
        pointMap->add_register("FPGA_ucp_block_comm_R",                             UCP_BLOCK,                              nFpgas, 1, "RO", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_ucp_block_comm_RW",                            UCP_BLOCK,                              nFpgas, 1, "RW", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_ucp_status_R",                                 UCP_STATUS,                             nFpgas, 6, "RO", REG_FORMAT_INT64);
        pointMap->add_register("FPGA_ucp_status_reset_WO",                          UCP_STATUS,                             nFpgas, 1, "WO", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_temp_R",                                       TEMP,                                   nFpgas, 1, "RO", REG_FORMAT_DOUBLE);
        pointMap->add_register("FPGA_firmware_version_R",                           FIRMWARE_VERSION,                       nFpgas, 1, "RO", REG_FORMAT_STRING);
        pointMap->add_register("FPGA_hardware_version_R",                           HARDWARE_VERSION,                       nFpgas, 1, "RO", REG_FORMAT_STRING);
        pointMap->add_register("FPGA_global_node_index_R",                          GLOBAL_NODE_INDEX,                      nFpgas, 1, "RO", REG_FORMAT_UINT32);
    
        pointMap->add_register("FPGA_sst_offload_weighted_subbands_R",              SST_OFFLOAD_WEIGHTED_SUBBANDS,          nFpgas, 1, "RO", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_sst_offload_weighted_subbands_RW",             SST_OFFLOAD_WEIGHTED_SUBBANDS,          nFpgas, 1, "RW", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_sst_offload_enable_R",                         SST_OFFLOAD_ENABLE,                     nFpgas, 1, "RO", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_sst_offload_enable_RW",                        SST_OFFLOAD_ENABLE,                     nFpgas, 1, "RW", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_sst_offload_hdr_eth_destination_mac_R",        SST_OFFLOAD_HDR_ETH_DESTINATION_MAC,    nFpgas, 1, "RO", REG_FORMAT_STRING);
        pointMap->add_register("FPGA_sst_offload_hdr_eth_destination_mac_RW",       SST_OFFLOAD_HDR_ETH_DESTINATION_MAC,    nFpgas, 1, "RW", REG_FORMAT_STRING);
        pointMap->add_register("FPGA_sst_offload_hdr_ip_destination_address_R",     SST_OFFLOAD_HDR_IP_DESTINATION_ADDRESS, nFpgas, 1, "RO", REG_FORMAT_STRING);
        pointMap->add_register("FPGA_sst_offload_hdr_ip_destination_address_RW",    SST_OFFLOAD_HDR_IP_DESTINATION_ADDRESS, nFpgas, 1, "RW", REG_FORMAT_STRING);
        pointMap->add_register("FPGA_sst_offload_hdr_udp_destination_port_R",       SST_OFFLOAD_HDR_UDP_DESTINATION_PORT,   nFpgas, 1, "RO", REG_FORMAT_UINT16);
        pointMap->add_register("FPGA_sst_offload_hdr_udp_destination_port_RW",      SST_OFFLOAD_HDR_UDP_DESTINATION_PORT,   nFpgas, 1, "RW", REG_FORMAT_UINT16);
        pointMap->add_register("FPGA_sst_offload_nof_packets_R",                    SST_OFFLOAD_NOF_PACKETS,                nFpgas, 1, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_sst_offload_nof_valid_R",                      SST_OFFLOAD_NOF_VALID,                  nFpgas, 1, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_sst_offload_bsn_R",                            SST_OFFLOAD_BSN,                        nFpgas, 1, "RO", REG_FORMAT_INT64);
    
        pointMap->add_register("FPGA_bst_offload_enable_R",                         BST_OFFLOAD_ENABLE,                     nFpgas, nBeamsets, "RO", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_bst_offload_enable_RW",                        BST_OFFLOAD_ENABLE,                     nFpgas, nBeamsets, "RW", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_bst_offload_hdr_eth_destination_mac_R",        BST_OFFLOAD_HDR_ETH_DESTINATION_MAC,    nFpgas, nBeamsets, "RO", REG_FORMAT_STRING);
        pointMap->add_register("FPGA_bst_offload_hdr_eth_destination_mac_RW",       BST_OFFLOAD_HDR_ETH_DESTINATION_MAC,    nFpgas, nBeamsets, "RW", REG_FORMAT_STRING);
        pointMap->add_register("FPGA_bst_offload_hdr_ip_destination_address_R",     BST_OFFLOAD_HDR_IP_DESTINATION_ADDRESS, nFpgas, nBeamsets, "RO", REG_FORMAT_STRING);
        pointMap->add_register("FPGA_bst_offload_hdr_ip_destination_address_RW",    BST_OFFLOAD_HDR_IP_DESTINATION_ADDRESS, nFpgas, nBeamsets, "RW", REG_FORMAT_STRING);
        pointMap->add_register("FPGA_bst_offload_hdr_udp_destination_port_R",       BST_OFFLOAD_HDR_UDP_DESTINATION_PORT,   nFpgas, nBeamsets, "RO", REG_FORMAT_UINT16);
        pointMap->add_register("FPGA_bst_offload_hdr_udp_destination_port_RW",      BST_OFFLOAD_HDR_UDP_DESTINATION_PORT,   nFpgas, nBeamsets, "RW", REG_FORMAT_UINT16);
        pointMap->add_register("FPGA_bst_offload_nof_packets_R",                    BST_OFFLOAD_NOF_PACKETS,                nFpgas, nBeamsets, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_bst_offload_nof_valid_R",                      BST_OFFLOAD_NOF_VALID,                  nFpgas, nBeamsets, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_bst_offload_bsn_R",                            BST_OFFLOAD_BSN,                        nFpgas, nBeamsets, "RO", REG_FORMAT_INT64);
    
        pointMap->add_register("FPGA_xst_subband_select_R",                         XST_SUBBAND_SELECT,                      nFpgas, 1+C_N_crosslets_max, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_xst_subband_select_RW",                        XST_SUBBAND_SELECT,                      nFpgas, 1+C_N_crosslets_max, "RW", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_xst_integration_interval_R",                   XST_INTEGRATION_INTERVAL,                nFpgas, 1, "RO", REG_FORMAT_DOUBLE);
        pointMap->add_register("FPGA_xst_integration_interval_RW",                  XST_INTEGRATION_INTERVAL,                nFpgas, 1, "RW", REG_FORMAT_DOUBLE);
        pointMap->add_register("FPGA_xst_processing_enable_R",                      XST_PROCESSING_ENABLE,                   nFpgas, 1, "RO", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_xst_processing_enable_RW",                     XST_PROCESSING_ENABLE,                   nFpgas, 1, "RW", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_xst_offload_enable_R",                         XST_OFFLOAD_ENABLE,                      nFpgas, 1, "RO", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_xst_offload_enable_RW",                        XST_OFFLOAD_ENABLE,                      nFpgas, 1, "RW", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_xst_offload_nof_crosslets_R",                  XST_OFFLOAD_NOF_CROSSLETS,               nFpgas, 1, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_xst_offload_nof_crosslets_RW",                 XST_OFFLOAD_NOF_CROSSLETS,               nFpgas, 1, "RW", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_xst_offload_hdr_eth_destination_mac_R",        XST_OFFLOAD_HDR_ETH_DESTINATION_MAC,     nFpgas, 1, "RO", REG_FORMAT_STRING);
        pointMap->add_register("FPGA_xst_offload_hdr_eth_destination_mac_RW",       XST_OFFLOAD_HDR_ETH_DESTINATION_MAC,     nFpgas, 1, "RW", REG_FORMAT_STRING);
        pointMap->add_register("FPGA_xst_offload_hdr_ip_destination_address_R",     XST_OFFLOAD_HDR_IP_DESTINATION_ADDRESS,  nFpgas, 1, "RO", REG_FORMAT_STRING);
        pointMap->add_register("FPGA_xst_offload_hdr_ip_destination_address_RW",    XST_OFFLOAD_HDR_IP_DESTINATION_ADDRESS,  nFpgas, 1, "RW", REG_FORMAT_STRING);
        pointMap->add_register("FPGA_xst_offload_hdr_udp_destination_port_R",       XST_OFFLOAD_HDR_UDP_DESTINATION_PORT,    nFpgas, 1, "RO", REG_FORMAT_UINT16);
        pointMap->add_register("FPGA_xst_offload_hdr_udp_destination_port_RW",      XST_OFFLOAD_HDR_UDP_DESTINATION_PORT,    nFpgas, 1, "RW", REG_FORMAT_UINT16);
        pointMap->add_register("FPGA_xst_input_bsn_at_sync_R",                      XST_INPUT_SYNC_AT_BSN,                   nFpgas, 1, "RO", REG_FORMAT_INT64);
        pointMap->add_register("FPGA_xst_output_sync_bsn_R",                        XST_OUTPUT_SYNC_BSN,                     nFpgas, 1, "RO", REG_FORMAT_INT64);
        pointMap->add_register("FPGA_xst_offload_nof_packets_R",                    XST_OFFLOAD_NOF_PACKETS,                 nFpgas, 1, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_xst_offload_nof_valid_R",                      XST_OFFLOAD_NOF_VALID,                   nFpgas, 1, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_xst_offload_bsn_R",                            XST_OFFLOAD_BSN,                         nFpgas, 1, "RO", REG_FORMAT_INT64);
        pointMap->add_register("FPGA_xst_ring_nof_transport_hops_R",                XST_RING_NOF_TRANSPORT_HOPS,             nFpgas, 1, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_xst_ring_nof_transport_hops_RW",               XST_RING_NOF_TRANSPORT_HOPS,             nFpgas, 1, "RW", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_xst_ring_rx_clear_total_counts_R",             XST_RING_RX_CLEAR_TOTAL_COUNTS,          nFpgas, 1, "RO", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_xst_ring_rx_clear_total_counts_RW",            XST_RING_RX_CLEAR_TOTAL_COUNTS,          nFpgas, 1, "RW", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_xst_rx_align_stream_enable_R",                 XST_RX_ALIGN_STREAM_ENABLE,              nFpgas, C_P_sq, "RO", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_xst_rx_align_stream_enable_RW",                XST_RX_ALIGN_STREAM_ENABLE,              nFpgas, C_P_sq, "RW", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_xst_rx_align_nof_replaced_packets_R",          XST_RX_ALIGN_NOF_REPLACED_PACKETS,       nFpgas, C_P_sq, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_xst_ring_rx_total_nof_packets_received_R",     XST_RING_RX_TOTAL_NOF_PACKETS_RECEIVED,  nFpgas, 1, "RO", REG_FORMAT_UINT64);
        pointMap->add_register("FPGA_xst_ring_rx_total_nof_packets_discarded_R",    XST_RING_RX_TOTAL_NOF_PACKETS_DISCARDED, nFpgas, 1, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_xst_ring_rx_total_nof_sync_received_R",        XST_RING_RX_TOTAL_NOF_SYNC_RECEIVED,     nFpgas, 1, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_xst_ring_rx_total_nof_sync_discarded_R",       XST_RING_RX_TOTAL_NOF_SYNC_DISCARDED,    nFpgas, 1, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_xst_ring_rx_bsn_R",                            XST_RING_RX_BSN,                         nFpgas, nFpgas, "RO", REG_FORMAT_INT64);
        pointMap->add_register("FPGA_xst_ring_rx_nof_packets_R",                    XST_RING_RX_NOF_PACKETS,                 nFpgas, nFpgas, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_xst_ring_rx_nof_valid_R",                      XST_RING_RX_NOF_VALID,                   nFpgas, nFpgas, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_xst_ring_rx_latency_R",                        XST_RING_RX_LATENCY,                     nFpgas, nFpgas, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_xst_rx_align_bsn_R",                           XST_RX_ALIGN_BSN,                        nFpgas, C_P_sq, "RO", REG_FORMAT_INT64);
        pointMap->add_register("FPGA_xst_rx_align_nof_packets_R",                   XST_RX_ALIGN_NOF_PACKETS,                nFpgas, C_P_sq, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_xst_rx_align_nof_valid_R",                     XST_RX_ALIGN_NOF_VALID,                  nFpgas, C_P_sq, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_xst_rx_align_latency_R",                       XST_RX_ALIGN_LATENCY,                    nFpgas, C_P_sq, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_xst_aligned_bsn_R",                            XST_ALIGNED_BSN,                         nFpgas, 1, "RO", REG_FORMAT_INT64);
        pointMap->add_register("FPGA_xst_aligned_nof_packets_R",                    XST_ALIGNED_NOF_PACKETS,                 nFpgas, 1, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_xst_aligned_nof_valid_R",                      XST_ALIGNED_NOF_VALID,                   nFpgas, 1, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_xst_aligned_latency_R",                        XST_ALIGNED_LATENCY,                     nFpgas, 1, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_xst_ring_tx_bsn_R",                            XST_RING_TX_BSN,                         nFpgas, nFpgas, "RO", REG_FORMAT_INT64);
        pointMap->add_register("FPGA_xst_ring_tx_nof_packets_R",                    XST_RING_TX_NOF_PACKETS,                 nFpgas, nFpgas, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_xst_ring_tx_nof_valid_R",                      XST_RING_TX_NOF_VALID,                   nFpgas, nFpgas, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_xst_ring_tx_latency_R",                        XST_RING_TX_LATENCY,                     nFpgas, nFpgas, "RO", REG_FORMAT_INT32);
    
        pointMap->add_register("FPGA_beamlet_output_enable_R",                      BEAMLET_OUTPUT_ENABLE,                     nFpgas, nBeamsets, "RO", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_beamlet_output_enable_RW",                     BEAMLET_OUTPUT_ENABLE,                     nFpgas, nBeamsets, "RW", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_beamlet_output_scale_R",                       BEAMLET_OUTPUT_SCALE,                      nFpgas, nBeamsets, "RO", REG_FORMAT_DOUBLE);
        pointMap->add_register("FPGA_beamlet_output_scale_RW",                      BEAMLET_OUTPUT_SCALE,                      nFpgas, nBeamsets, "RW", REG_FORMAT_DOUBLE);
        // pointMap->add_register("FPGA_beamlet_output_nof_beamlets_R",                BEAMLET_OUTPUT_NOF_BEAMLETS,               nFpgas, 1, "RO", REG_FORMAT_UINT32);  // not implemented in sdpfw
        // pointMap->add_register("FPGA_beamlet_output_nof_beamlets_RW",               BEAMLET_OUTPUT_NOF_BEAMLETS,               nFpgas, 1, "RW", REG_FORMAT_UINT32);  // not implemented in sdpfw
        pointMap->add_register("FPGA_beamlet_output_hdr_eth_destination_mac_R",     BEAMLET_OUTPUT_HDR_ETH_DESTINATION_MAC,    nFpgas, nBeamsets, "RO", REG_FORMAT_STRING);
        pointMap->add_register("FPGA_beamlet_output_hdr_eth_destination_mac_RW",    BEAMLET_OUTPUT_HDR_ETH_DESTINATION_MAC,    nFpgas, nBeamsets, "RW", REG_FORMAT_STRING);
        pointMap->add_register("FPGA_beamlet_output_hdr_ip_destination_address_R",  BEAMLET_OUTPUT_HDR_IP_DESTINATION_ADDRESS, nFpgas, nBeamsets, "RO", REG_FORMAT_STRING);
        pointMap->add_register("FPGA_beamlet_output_hdr_ip_destination_address_RW", BEAMLET_OUTPUT_HDR_IP_DESTINATION_ADDRESS, nFpgas, nBeamsets, "RW", REG_FORMAT_STRING);
        pointMap->add_register("FPGA_beamlet_output_hdr_udp_destination_port_R",    BEAMLET_OUTPUT_HDR_UDP_DESTINATION_PORT,   nFpgas, nBeamsets, "RO", REG_FORMAT_UINT16);
        pointMap->add_register("FPGA_beamlet_output_hdr_udp_destination_port_RW",   BEAMLET_OUTPUT_HDR_UDP_DESTINATION_PORT,   nFpgas, nBeamsets, "RW", REG_FORMAT_UINT16);
        pointMap->add_register("FPGA_beamlet_output_hdr_eth_source_mac_R",          BEAMLET_OUTPUT_HDR_ETH_SOURCE_MAC,         nFpgas, 1, "RO", REG_FORMAT_STRING);
        pointMap->add_register("FPGA_beamlet_output_hdr_eth_source_mac_RW",         BEAMLET_OUTPUT_HDR_ETH_SOURCE_MAC,         nFpgas, 1, "RW", REG_FORMAT_STRING);
        pointMap->add_register("FPGA_beamlet_output_hdr_ip_source_address_R",       BEAMLET_OUTPUT_HDR_IP_SOURCE_ADDRESS,      nFpgas, 1, "RO", REG_FORMAT_STRING);
        pointMap->add_register("FPGA_beamlet_output_hdr_ip_source_address_RW",      BEAMLET_OUTPUT_HDR_IP_SOURCE_ADDRESS,      nFpgas, 1, "RW", REG_FORMAT_STRING);
        pointMap->add_register("FPGA_beamlet_output_hdr_udp_source_port_R",         BEAMLET_OUTPUT_HDR_UDP_SOURCE_PORT,        nFpgas, 1, "RO", REG_FORMAT_UINT16);
        pointMap->add_register("FPGA_beamlet_output_hdr_udp_source_port_RW",        BEAMLET_OUTPUT_HDR_UDP_SOURCE_PORT,        nFpgas, 1, "RW", REG_FORMAT_UINT16);
        pointMap->add_register("FPGA_beamlet_subband_select_R",                     BEAMLET_SUBBAND_SELECT,                    nFpgas, C_A_pn*C_N_pol*nBeamsets*C_S_sub_bf, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_beamlet_subband_select_RW",                    BEAMLET_SUBBAND_SELECT,                    nFpgas, C_A_pn*C_N_pol*nBeamsets*C_S_sub_bf, "RW", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_beamlet_output_nof_packets_R",                 BEAMLET_OUTPUT_NOF_PACKETS,                nFpgas, nBeamsets, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_beamlet_output_nof_valid_R",                   BEAMLET_OUTPUT_NOF_VALID,                  nFpgas, nBeamsets, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_beamlet_output_bsn_R",                         BEAMLET_OUTPUT_BSN,                        nFpgas, nBeamsets, "RO", REG_FORMAT_INT64);
        pointMap->add_register("FPGA_beamlet_output_ready_R",                       BEAMLET_OUTPUT_READY,                      nFpgas, nBeamsets, "RO", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_beamlet_output_xon_R",                         BEAMLET_OUTPUT_XON,                        nFpgas, nBeamsets, "RO", REG_FORMAT_BOOLEAN);
    
        pointMap->add_register("FPGA_processing_enable_R",                          PROCESSING_ENABLE,                      nFpgas, 1, "RO", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_processing_enable_RW",                         PROCESSING_ENABLE,                      nFpgas, 1, "RW", REG_FORMAT_BOOLEAN);
    
        pointMap->add_register("FPGA_sdp_info_station_id_R",                        SDP_INFO_STATION_ID,                    nFpgas, 1, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_sdp_info_station_id_RW",                       SDP_INFO_STATION_ID,                    nFpgas, 1, "RW", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_sdp_info_observation_id_R",                    SDP_INFO_OBSERVATION_ID,                nFpgas, 1, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_sdp_info_observation_id_RW",                   SDP_INFO_OBSERVATION_ID,                nFpgas, 1, "RW", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_sdp_info_nyquist_sampling_zone_index_R",       SDP_INFO_NYQUIST_SAMPLING_ZONE_INDEX,   nFpgas, 1, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_sdp_info_nyquist_sampling_zone_index_RW",      SDP_INFO_NYQUIST_SAMPLING_ZONE_INDEX,   nFpgas, 1, "RW", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_sdp_info_antenna_band_index_R",                SDP_INFO_ANTENNA_BAND_INDEX,            nFpgas, 1, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_sdp_info_antenna_band_index_RW",               SDP_INFO_ANTENNA_BAND_INDEX,            nFpgas, 1, "RW", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_sdp_info_f_adc_R",                             SDP_INFO_F_ADC,                         nFpgas, 1, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_sdp_info_fsub_type_R",                         SDP_INFO_FSUB_TYPE,                     nFpgas, 1, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_sdp_info_block_period_R",                      SDP_INFO_BLOCK_PERIOD,                  nFpgas, 1, "RO", REG_FORMAT_UINT32);
    
        pointMap->add_register("FPGA_wg_enable_R",                                  WG_ENABLE,                              nFpgas, C_S_pn, "RO", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_wg_enable_RW",                                 WG_ENABLE,                              nFpgas, C_S_pn, "RW", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_wg_amplitude_R",                               WG_AMPLITUDE,                           nFpgas, C_S_pn, "RO", REG_FORMAT_DOUBLE);
        pointMap->add_register("FPGA_wg_amplitude_RW",                              WG_AMPLITUDE,                           nFpgas, C_S_pn, "RW", REG_FORMAT_DOUBLE);
        pointMap->add_register("FPGA_wg_phase_R",                                   WG_PHASE,                               nFpgas, C_S_pn, "RO", REG_FORMAT_DOUBLE);
        pointMap->add_register("FPGA_wg_phase_RW",                                  WG_PHASE,                               nFpgas, C_S_pn, "RW", REG_FORMAT_DOUBLE);
        pointMap->add_register("FPGA_wg_frequency_R",                               WG_FREQUENCY,                           nFpgas, C_S_pn, "RO", REG_FORMAT_DOUBLE);
        pointMap->add_register("FPGA_wg_frequency_RW",                              WG_FREQUENCY,                           nFpgas, C_S_pn, "RW", REG_FORMAT_DOUBLE);
    
        pointMap->add_register("FPGA_signal_input_bsn_R",                           SIGNAL_INPUT_BSN,                       nFpgas, 1, "RO", REG_FORMAT_INT64);
        pointMap->add_register("FPGA_signal_input_nof_blocks_R",                    SIGNAL_INPUT_NOF_BLOCKS,                nFpgas, 1, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_signal_input_nof_samples_R",                   SIGNAL_INPUT_NOF_SAMPLES,               nFpgas, 1, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_jesd204b_csr_rbd_count_R",                     JESD204B_CSR_RBD_COUNT,                 nFpgas, C_S_pn, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_jesd204b_csr_dev_syncn_R",                     JESD204B_CSR_DEV_SYNCN,                 nFpgas, C_S_pn, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_jesd204b_rx_err0_R",                           JESD204B_RX_ERR0,                       nFpgas, C_S_pn, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_jesd204b_rx_err1_R",                           JESD204B_RX_ERR1,                       nFpgas, C_S_pn, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_jesd_ctrl_R",                                  JESD_CTRL,                              nFpgas, 1, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_jesd_ctrl_RW",                                 JESD_CTRL,                              nFpgas, 1, "RW", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_signal_input_mean_R",                          SIGNAL_INPUT_MEAN,                      nFpgas, C_S_pn, "RO", REG_FORMAT_DOUBLE);
        pointMap->add_register("FPGA_signal_input_rms_R",                           SIGNAL_INPUT_RMS,                       nFpgas, C_S_pn, "RO", REG_FORMAT_DOUBLE);
        pointMap->add_register("FPGA_signal_input_std_R",                           SIGNAL_INPUT_STD,                       nFpgas, C_S_pn, "RO", REG_FORMAT_DOUBLE);
        pointMap->add_register("FPGA_signal_input_samples_delay_R",                 SIGNAL_INPUT_SAMPLES_DELAY,             nFpgas, C_S_pn, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_signal_input_samples_delay_RW",                SIGNAL_INPUT_SAMPLES_DELAY,             nFpgas, C_S_pn, "RW", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_subband_weights_R",                            SUBBAND_WEIGHTS,                        nFpgas, nFilterbanks*C_S_pn*C_N_sub, "RO", REG_FORMAT_UINT32);  // cint16
        pointMap->add_register("FPGA_subband_weights_RW",                           SUBBAND_WEIGHTS,                        nFpgas, nFilterbanks*C_S_pn*C_N_sub, "RW", REG_FORMAT_UINT32);  // cint16
        pointMap->add_register("FPGA_subband_fir_filter_coefficients_R",            SUBBAND_FIR_FILTER_COEFFICIENTS,        nFpgas, nFilterbanks*C_N_tap*C_N_fft, "RO", REG_FORMAT_INT16);
        pointMap->add_register("FPGA_subband_fir_filter_coefficients_RW",           SUBBAND_FIR_FILTER_COEFFICIENTS,        nFpgas, nFilterbanks*C_N_tap*C_N_fft, "RW", REG_FORMAT_INT16);
        pointMap->add_register("FPGA_scrap_R",                                      SCRAP,                                  nFpgas, C_N_scrap, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_scrap_RW",                                     SCRAP,                                  nFpgas, C_N_scrap, "RW", REG_FORMAT_UINT32);
        // Beam Former Weights
        // FPGA_bf_weights_R and FPGA_bf_weights_RW => raw data
        pointMap->add_register("FPGA_bf_weights_R",                                 BF_WEIGHTS,                             nFpgas, nBeamsets*C_N_pol_bf*C_A_pn*C_N_pol*C_S_sub_bf, "RO", REG_FORMAT_UINT32);  // cint16
        pointMap->add_register("FPGA_bf_weights_RW",                                BF_WEIGHTS,                             nFpgas, nBeamsets*C_N_pol_bf*C_A_pn*C_N_pol*C_S_sub_bf, "RW", REG_FORMAT_UINT32);  // cint16
        pointMap->add_register("FPGA_bf_weights_xx_yy_R",                           BF_WEIGHTS_XX_YY,                       nFpgas,            C_A_pn*C_N_pol*nBeamsets*C_S_sub_bf, "RO", REG_FORMAT_UINT32);  // cint16
        pointMap->add_register("FPGA_bf_weights_xx_yy_RW",                          BF_WEIGHTS_XX_YY,                       nFpgas,            C_A_pn*C_N_pol*nBeamsets*C_S_sub_bf, "RW", REG_FORMAT_UINT32);  // cint16
        pointMap->add_register("FPGA_bf_weights_xy_yx_R",                           BF_WEIGHTS_XY_YX,                       nFpgas,            C_A_pn*C_N_pol*nBeamsets*C_S_sub_bf, "RO", REG_FORMAT_UINT32);  // cint16
        pointMap->add_register("FPGA_bf_weights_xy_yx_RW",                          BF_WEIGHTS_XY_YX,                       nFpgas,            C_A_pn*C_N_pol*nBeamsets*C_S_sub_bf, "RW", REG_FORMAT_UINT32);  // cint16
        pointMap->add_register("FPGA_bf_weights_xx_xy_yx_yy_R",                     BF_WEIGHTS_XX_XY_YX_YY,                 nFpgas, C_N_pol_bf*C_A_pn*C_N_pol*nBeamsets*C_S_sub_bf, "RO", REG_FORMAT_UINT32);  // cint16
        pointMap->add_register("FPGA_bf_weights_xx_xy_yx_yy_RW",                    BF_WEIGHTS_XX_XY_YX_YY,                 nFpgas, C_N_pol_bf*C_A_pn*C_N_pol*nBeamsets*C_S_sub_bf, "RW", REG_FORMAT_UINT32);  // cint16
        pointMap->add_register("FPGA_bf_weights_xx_R",                              BF_WEIGHTS_XX,                          nFpgas,            C_A_pn*        nBeamsets*C_S_sub_bf, "RO", REG_FORMAT_UINT32);  // cint16
        pointMap->add_register("FPGA_bf_weights_xx_RW",                             BF_WEIGHTS_XX,                          nFpgas,            C_A_pn*        nBeamsets*C_S_sub_bf, "RW", REG_FORMAT_UINT32);  // cint16
        pointMap->add_register("FPGA_bf_weights_xy_R",                              BF_WEIGHTS_XY,                          nFpgas,            C_A_pn*        nBeamsets*C_S_sub_bf, "RO", REG_FORMAT_UINT32);  // cint16
        pointMap->add_register("FPGA_bf_weights_xy_RW",                             BF_WEIGHTS_XY,                          nFpgas,            C_A_pn*        nBeamsets*C_S_sub_bf, "RW", REG_FORMAT_UINT32);  // cint16
        pointMap->add_register("FPGA_bf_weights_yx_R",                              BF_WEIGHTS_YX,                          nFpgas,            C_A_pn*        nBeamsets*C_S_sub_bf, "RO", REG_FORMAT_UINT32);  // cint16
        pointMap->add_register("FPGA_bf_weights_yx_RW",                             BF_WEIGHTS_YX,                          nFpgas,            C_A_pn*        nBeamsets*C_S_sub_bf, "RW", REG_FORMAT_UINT32);  // cint16
        pointMap->add_register("FPGA_bf_weights_yy_R",                              BF_WEIGHTS_YY,                          nFpgas,            C_A_pn*        nBeamsets*C_S_sub_bf, "RO", REG_FORMAT_UINT32);  // cint16
        pointMap->add_register("FPGA_bf_weights_yy_RW",                             BF_WEIGHTS_YY,                          nFpgas,            C_A_pn*        nBeamsets*C_S_sub_bf, "RW", REG_FORMAT_UINT32);  // cint16
        pointMap->add_register("FPGA_bf_ring_nof_transport_hops_R",                 BF_RING_NOF_TRANSPORT_HOPS,             nFpgas, nBeamsets, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_bf_ring_nof_transport_hops_RW",                BF_RING_NOF_TRANSPORT_HOPS,             nFpgas, nBeamsets, "RW", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_bf_ring_rx_clear_total_counts_R",              BF_RING_RX_CLEAR_TOTAL_COUNTS,          nFpgas, nBeamsets, "RO", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_bf_ring_rx_clear_total_counts_RW",             BF_RING_RX_CLEAR_TOTAL_COUNTS,          nFpgas, nBeamsets, "RW", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_bf_rx_align_stream_enable_R",                  BF_RX_ALIGN_STREAM_ENABLE,              nFpgas, nBeamsets*C_P_sum, "RO", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_bf_rx_align_stream_enable_RW",                 BF_RX_ALIGN_STREAM_ENABLE,              nFpgas, nBeamsets*C_P_sum, "RW", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_bf_rx_align_nof_replaced_packets_R",           BF_RX_ALIGN_NOF_REPLACED_PACKETS,       nFpgas, nBeamsets*C_P_sum, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_bf_ring_rx_total_nof_packets_received_R",      BF_RING_RX_TOTAL_NOF_PACKETS_RECEIVED,  nFpgas, nBeamsets, "RO", REG_FORMAT_UINT64);
        pointMap->add_register("FPGA_bf_ring_rx_total_nof_packets_discarded_R",     BF_RING_RX_TOTAL_NOF_PACKETS_DISCARDED, nFpgas, nBeamsets, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_bf_ring_rx_total_nof_sync_received_R",         BF_RING_RX_TOTAL_NOF_SYNC_RECEIVED,     nFpgas, nBeamsets, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_bf_ring_rx_total_nof_sync_discarded_R",        BF_RING_RX_TOTAL_NOF_SYNC_DISCARDED,    nFpgas, nBeamsets, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_bf_ring_rx_bsn_R",                             BF_RING_RX_BSN,                         nFpgas, nBeamsets, "RO", REG_FORMAT_INT64);
        pointMap->add_register("FPGA_bf_ring_rx_nof_packets_R",                     BF_RING_RX_NOF_PACKETS,                 nFpgas, nBeamsets, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_bf_ring_rx_nof_valid_R",                       BF_RING_RX_NOF_VALID,                   nFpgas, nBeamsets, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_bf_ring_rx_latency_R",                         BF_RING_RX_LATENCY,                     nFpgas, nBeamsets, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_bf_rx_align_bsn_R",                            BF_RX_ALIGN_BSN,                        nFpgas, nBeamsets*C_P_sum, "RO", REG_FORMAT_INT64);
        pointMap->add_register("FPGA_bf_rx_align_nof_packets_R",                    BF_RX_ALIGN_NOF_PACKETS,                nFpgas, nBeamsets*C_P_sum, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_bf_rx_align_nof_valid_R",                      BF_RX_ALIGN_NOF_VALID,                  nFpgas, nBeamsets*C_P_sum, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_bf_rx_align_latency_R",                        BF_RX_ALIGN_LATENCY,                    nFpgas, nBeamsets*C_P_sum, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_bf_aligned_bsn_R",                             BF_ALIGNED_BSN,                         nFpgas, nBeamsets, "RO", REG_FORMAT_INT64);
        pointMap->add_register("FPGA_bf_aligned_nof_packets_R",                     BF_ALIGNED_NOF_PACKETS,                 nFpgas, nBeamsets, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_bf_aligned_nof_valid_R",                       BF_ALIGNED_NOF_VALID,                   nFpgas, nBeamsets, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_bf_aligned_latency_R",                         BF_ALIGNED_LATENCY,                     nFpgas, nBeamsets, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_bf_ring_tx_bsn_R",                             BF_RING_TX_BSN,                         nFpgas, nBeamsets, "RO", REG_FORMAT_INT64);
        pointMap->add_register("FPGA_bf_ring_tx_nof_packets_R",                     BF_RING_TX_NOF_PACKETS,                 nFpgas, nBeamsets, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_bf_ring_tx_nof_valid_R",                       BF_RING_TX_NOF_VALID,                   nFpgas, nBeamsets, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_bf_ring_tx_latency_R",                         BF_RING_TX_LATENCY,                     nFpgas, nBeamsets, "RO", REG_FORMAT_INT32);
    
        pointMap->add_register("FPGA_signal_input_data_buffer_R",                   SIGNAL_INPUT_DATA_BUFFER,               nFpgas, C_S_pn*C_V_si_db, "RO", REG_FORMAT_INT16);
        pointMap->add_register("FPGA_signal_input_histogram_R",                     SIGNAL_INPUT_HISTOGRAM,                 nFpgas, C_S_pn*C_V_si_histogram, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_subband_spectral_inversion_R",                 SUBBAND_SPECTRAL_INVERSION,             nFpgas, 1, "RO", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_subband_spectral_inversion_RW",                SUBBAND_SPECTRAL_INVERSION,             nFpgas, 1, "RW", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_pps_expected_cnt_R",                           PPS_EXPECTED_CNT,                       nFpgas, 1, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_pps_expected_cnt_RW",                          PPS_EXPECTED_CNT,                       nFpgas, 1, "RW", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_pps_present_R",                                PPS_PRESENT,                            nFpgas, 1, "RO", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_pps_capture_cnt_R",                            PPS_CAPTURE_CNT,                        nFpgas, 1, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_monitor_pps_offset_time_R",                    MONITOR_PPS_OFFSET_TIME,                nFpgas, 1, "RO", REG_FORMAT_DOUBLE);
        pointMap->add_register("FPGA_time_since_last_pps_R",                        TIME_SINCE_LAST_PPS,                    nFpgas, 1, "RO", REG_FORMAT_DOUBLE);
    
        pointMap->add_register("FPGA_boot_image_R",                                 BOOT_IMAGE,                             nFpgas, 1, "RO", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_boot_image_RW",                                BOOT_IMAGE,                             nFpgas, 1, "RW", REG_FORMAT_INT32);
        pointMap->add_register("FPGA_flash_addr_R",                                 FLASH_ADDR,                             nFpgas, 1, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_flash_addr_RW",                                FLASH_ADDR,                             nFpgas, 1, "RW", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_flash_protect_R",                              FLASH_PROTECT,                          nFpgas, 1, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_flash_protect_RW",                             FLASH_PROTECT,                          nFpgas, 1, "RW", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_flash_erase_R",                                FLASH_ERASE_SECTOR,                     nFpgas, 1, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_flash_erase_RW",                               FLASH_ERASE_SECTOR,                     nFpgas, 1, "RW", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_flash_pages_R",                                FLASH_PAGES,                            nFpgas, 16384, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_flash_pages_RW",                               FLASH_PAGES,                            nFpgas, 16384, "RW", REG_FORMAT_UINT32);
    
        pointMap->add_register("FPGA_ring_node_offset_R",                           RING_NODE_OFFSET,                       nFpgas, 1, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_ring_node_offset_RW",                          RING_NODE_OFFSET,                       nFpgas, 1, "RW", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_ring_nof_nodes_R",                             RING_NOF_NODES,                         nFpgas, 1, "RO", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_ring_nof_nodes_RW",                            RING_NOF_NODES,                         nFpgas, 1, "RW", REG_FORMAT_UINT32);
        pointMap->add_register("FPGA_ring_use_cable_to_next_rn_R",                  RING_USE_CABLE_TO_NEXT_RN,              nFpgas, 1, "RO", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_ring_use_cable_to_next_rn_RW",                 RING_USE_CABLE_TO_NEXT_RN,              nFpgas, 1, "RW", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_ring_use_cable_to_previous_rn_R",              RING_USE_CABLE_TO_PREVIOUS_RN,          nFpgas, 1, "RO", REG_FORMAT_BOOLEAN);
        pointMap->add_register("FPGA_ring_use_cable_to_previous_rn_RW",             RING_USE_CABLE_TO_PREVIOUS_RN,          nFpgas, 1, "RW", REG_FORMAT_BOOLEAN);
    }
    
    FpgaMap::~FpgaMap()
    {
        if (pointMap != NULL) { delete pointMap; pointMap = NULL; }
        for (auto node : FPGA) { delete node; node = NULL; }
    }
    
    void FpgaMap::add_nodes(void)
    {
        for (auto nc : SD.node_config) {
            Node *node = new Node(nc.ipaddr, nc.udp_port, nc.board_nr, nc.fpga_nr, nFilterbanks, nBeamsets);
            FPGA.push_back(node);
            // add global node nr to nodes
            nodes.push_back(nc.gn);
        }
    }
    
    Node * FpgaMap::select_node(const int nr)
    {
        for (auto node : FPGA) {
            if (node->GetGlobalNr() == (uint)nr) {
                return node;
            }
        }
        throw runtime_error("select_node: not found");
    }
    
    vector<bool> FpgaMap::get_all_masked_nodes(void)
    {
        vector<bool> masked;
        for (auto node : FPGA) {
            masked.push_back(node->isMasked());
        }
        return masked;
    }
    
    vector<bool> FpgaMap::get_all_offline_nodes(void)
    {
        vector<bool> online;
        for (auto node : FPGA) {
            online.push_back(!node->isOnline());
        }
        return online;
    }
    
    void FpgaMap::set_all_masked_nodes(std::vector<bool> masked)
    {
        for (uint idx = 0; idx<nFpgas; idx++) {
            auto node = select_node(nodes[idx]);
            node->setMasked(masked[idx]);
        }
    }
    
    vector<double> FpgaMap::get_all_monitor_pps_offset_times(void)
    {
        vector<double> monitor_pps_offset_times;
        for (auto node : FPGA) {
            monitor_pps_offset_times.push_back(node->monitorPpsOffsetTime());
        }
        return monitor_pps_offset_times;
    }
    
    vector<struct timespec> FpgaMap::get_all_monitor_start_times(void)
    {
        vector<struct timespec> monitor_start_time;
        for (auto node : FPGA) {
            monitor_start_time.push_back(node->monitorStartTime());
        }
        return monitor_start_time;
    }
    
    CPointMap * FpgaMap::get_pointMap(void)
    {
        return pointMap;
    }
    
    bool FpgaMap::monitor(void)
    {
        for (uint idx=0; idx<nFpgas; idx++) {
            auto node = select_node(nodes[idx]);
            node->monitor();
        }
        return true;
    }
    
    /* read and write are called by the ua_server */
    bool FpgaMap::read(char *data, const string& pointname)
    {
        return point(data, 'R', pointname);
    }
    
    bool FpgaMap::write(char *data, const string& pointname)
    {
        return point(data, 'W', pointname);
    }
    
    /* point() is only called by read() and write() and is used send/receive the single opc-ua request to/from all the nodes.
      data: char buffer for send/receive data, buffer size is calculated in ua_server.cpp
      cmd: ['R' | 'W'] read or write action.
      pointname: opcua pointname
    1) Check if read/write can be done on the requested pointname.
    2) convert pointname to a cmd_id, cmd_id is a numeric id for the pointname without the access part.
    3) The start pointer in the single data buffer for each node is calculated.
    4) cmd is executed on all online nodes or all nodes if it is an intern point.
    5) wait for status response from all nodes and return
    */
    bool FpgaMap::point(char *data, const char cmd, const string& pointname)
    {
        char _cmd = cmd;
    
        // check if pointname exists and can be read or writen
        if (_cmd == 'R' && !pointMap->canRead(pointname)) { return false; }
        else if (_cmd == 'W' && !pointMap->canWrite(pointname)) { return false; }
    
        if (_cmd == 'R' && pointname.rfind("_RW") != string::npos) {
            LOG_F(DEBUG, "Read from cache");
            _cmd = 'r';
        }
    
        uint32_t cmd_id = pointMap->getCommandId(pointname);
    
        uint32_t format = pointMap->getFormat(pointname);
        size_t n_values = pointMap->getDataSize(pointname);
        size_t n_nodes = pointMap->getNodesSize(pointname);
        size_t data_size_bytes = n_values * reg_format_size_in_bytes(format);
    
        // map with node status
        //  1 = send request
        // -1 = not online
        //  2 = received response
        map <int, int> node_status;
    
        // loop over all nodes and execute requested command
        for (uint idx = 0; idx<n_nodes; idx++) {
            node_status.insert(node_status.end(), pair<int, int>(idx, 0));
            auto node = select_node(nodes[idx]);
    
            // if node online or an intern point exec_cmd.
            if (node->isOnline() || cmd_id < MAX_ID_INTERN_POINT) {
                uint32_t didx = 0;
                didx = idx * data_size_bytes;
                node->exec_cmd(_cmd, cmd_id, &(data[didx]), n_values, format);
                node_status[idx] = 1;
            } else {
                node_status[idx] = -1;
            }
        }
    
        // try to get all reply data, delete fpga from map if done
        bool done = false;
        while (!done) {
            done = true;
            for (uint idx = 0; idx<n_nodes; idx++) {
                int state = node_status[idx];
                if (state == 1) {
                    done = false;
                    auto node = select_node(nodes[idx]);
                    int stat = node->exec_reply(cmd_id);
                    // if stat = 0, still waiting for response
                    if (stat == 1) {          // valid data
                        node_status[idx] = 2;
                    }
                    else if (stat == -1) {    // no valid data
                        node_status[idx] = -1;
                    }
                }
            }
            // to avoid 100% load while looping (waiting for reply)
            this_thread::sleep_for(chrono::microseconds(2));
        }
    
        // make no response string
        string no_response = "";
        for (uint idx = 0; idx<n_nodes; idx++) {
            auto node = select_node(nodes[idx]);
            int state = node_status[idx];
            if (state == -1) {
                // If no response from the fpga (-1) add fpga number to the string
                if (no_response == "") {
                    no_response = "No response from node(s): " + to_string(node->GetGlobalNr());
                } else {
                    no_response += ", " + to_string(node->GetGlobalNr());
                }
            }
        }
        // if no_response string is not empty log string
        if (no_response != "") { LOG_F(INFO, "%s", no_response.c_str()); }
    
        return true;
    }