diff --git a/docker-compose/tango-prometheus-exporter/lofar2-policy.json b/docker-compose/tango-prometheus-exporter/lofar2-policy.json
index 01d574dc8517357935174f080d4df1fcd030271d..313d9a05c9f170d9bbf1e01216d02715d5b3548c 100644
--- a/docker-compose/tango-prometheus-exporter/lofar2-policy.json
+++ b/docker-compose/tango-prometheus-exporter/lofar2-policy.json
@@ -92,6 +92,9 @@
             ]
         },
         "stat/sdpfirmware/*": {
+            "exclude": [
+                "FPGA_scrap_*"
+            ],
             "include": [
                 "TR_fpga_mask_RW"
             ]
@@ -101,7 +104,6 @@
                 "FPGA_subband_weights_*",
                 "FPGA_signal_input_samples_delay_*",
                 "FPGA_jesd204b_*",
-                "FPGA_scrap_*",
                 "FPGA_wg_amplitude_*",
                 "FPGA_wg_frequency_*",
                 "FPGA_wg_phase_*",
diff --git a/tangostationcontrol/integration_test/default/devices/test_device_antennafield.py b/tangostationcontrol/integration_test/default/devices/test_device_antennafield.py
index 1dd6c9e23a1d1bf62f26443f516909d7932ba734..74a59f50724330cce2ac45d3cc14bbbaebc7559e 100644
--- a/tangostationcontrol/integration_test/default/devices/test_device_antennafield.py
+++ b/tangostationcontrol/integration_test/default/devices/test_device_antennafield.py
@@ -43,7 +43,7 @@ class TestAntennaFieldDevice(AbstractTestBases.TestDeviceBase):
 
         # configure the frequencies, which allows access
         # to the calibration attributes and commands
-        self.sdp_proxy.clock_RW = CLK_200_MHZ
+        self.sdpfirmware_proxy.clock_RW = CLK_200_MHZ
         self.recv_proxy.RCU_band_select_RW = [[1] * N_rcu_inp] * N_rcu
 
     def restore_antennafield(self):
@@ -369,7 +369,7 @@ class TestAntennaFieldDevice(AbstractTestBases.TestDeviceBase):
 
                 # test whether clock propagated correctly
                 numpy.testing.assert_equal(
-                    band.clock, self.sdp_proxy.clock_RW, err_msg=f"{band.name}"
+                    band.clock, self.sdpfirmware_proxy.clock_RW, err_msg=f"{band.name}"
                 )
 
                 # test whether nyquist zone propagated correctly (for both polarisations!)
diff --git a/tangostationcontrol/integration_test/default/devices/test_device_beamlet.py b/tangostationcontrol/integration_test/default/devices/test_device_beamlet.py
index 1eecddd87c21c609726862679ee8f7cc1593a73e..213e6a2c6d9c063947d815158b247e7c7920e760 100644
--- a/tangostationcontrol/integration_test/default/devices/test_device_beamlet.py
+++ b/tangostationcontrol/integration_test/default/devices/test_device_beamlet.py
@@ -27,6 +27,7 @@ class TestDeviceBeamlet(AbstractTestBases.TestDeviceBase):
     def test_device_read_all_attributes(self):
         # We need to connect to SDP first to read some of our attributes
         self.sdp_proxy = self.setup_sdp()
+        self.sdpfirmware_proxy = self.setup_sdpfirmware()
 
         super().test_device_read_all_attributes()
 
@@ -40,13 +41,25 @@ class TestDeviceBeamlet(AbstractTestBases.TestDeviceBase):
         # setup the frequencies as expected in the test
         sdp_proxy.antenna_type_RW = [[antenna_type] * S_pn] * N_pn
         sdp_proxy.nyquist_zone_RW = [[2] * S_pn] * N_pn
-        sdp_proxy.clock_RW = clock
 
         return sdp_proxy
 
+    def setup_sdpfirmware(self, antenna_type="HBA", clock=CLK_200_MHZ):
+        # setup SDP, on which this device depends
+        sdpfirmware_proxy = TestDeviceProxy("STAT/SDPFirmware/HBA")
+        sdpfirmware_proxy.off()
+        sdpfirmware_proxy.boot()
+        sdpfirmware_proxy.set_defaults()
+
+        # setup the frequencies as expected in the test
+        sdpfirmware_proxy.clock_RW = clock
+
+        return sdpfirmware_proxy
+
     def test_pointing_to_zenith(self):
         # Setup configuration
         sdp_proxy = self.setup_sdp()
+        sdpfirmware_proxy = self.setup_sdpfirmware()
 
         self.proxy.initialise()
         self.proxy.on()
@@ -70,6 +83,7 @@ class TestDeviceBeamlet(AbstractTestBases.TestDeviceBase):
     def test_subband_select_change(self):
         # Setup configuration
         sdp_proxy = self.setup_sdp()
+        sdpfirmware_proxy = self.setup_sdpfirmware()
 
         # Change subband
         self.proxy.off()
@@ -97,6 +111,7 @@ class TestDeviceBeamlet(AbstractTestBases.TestDeviceBase):
     def test_sdp_clock_change(self):
         # Setup configuration
         sdp_proxy = self.setup_sdp()
+        sdpfirmware_proxy = self.setup_sdpfirmware()
 
         self.proxy.initialise()
         self.proxy.subband_select_RW = numpy.array(
@@ -108,15 +123,15 @@ class TestDeviceBeamlet(AbstractTestBases.TestDeviceBase):
         # any non-zero delay should result in different weights for different clocks
         delays = numpy.array([[[2.5e-9] * N_pn] * A_pn] * N_beamlets_ctrl)
 
-        sdp_proxy.clock_RW = CLK_200_MHZ
+        sdpfirmware_proxy.clock_RW = CLK_200_MHZ
         time.sleep(1)  # wait for beamlet device to process change event
         calculated_bf_weights_200 = self.proxy.calculate_bf_weights(delays.flatten())
 
-        sdp_proxy.clock_RW = CLK_160_MHZ
+        sdpfirmware_proxy.clock_RW = CLK_160_MHZ
         time.sleep(1)  # wait for beamlet device to process change event
         calculated_bf_weights_160 = self.proxy.calculate_bf_weights(delays.flatten())
 
-        sdp_proxy.clock_RW = CLK_200_MHZ
+        sdpfirmware_proxy.clock_RW = CLK_200_MHZ
         time.sleep(1)  # wait for beamlet device to process change event
         calculated_bf_weights_200_v2 = self.proxy.calculate_bf_weights(delays.flatten())
 
@@ -136,7 +151,7 @@ class TestDeviceBeamlet(AbstractTestBases.TestDeviceBase):
             (calculated_bf_weights_200_v2 != calculated_bf_weights_200_v3).all()
         )
 
-        sdp_proxy.clock_RW = CLK_160_MHZ
+        sdpfirmware_proxy.clock_RW = CLK_160_MHZ
         time.sleep(1)  # wait for beamlet device to process change event
         calculated_bf_weights_160_v2 = self.proxy.calculate_bf_weights(delays.flatten())
         self.assertTrue(
diff --git a/tangostationcontrol/integration_test/default/devices/test_device_calibration.py b/tangostationcontrol/integration_test/default/devices/test_device_calibration.py
index e664942be6a2ee6ef484289c3d0c4b81bed2d7b2..f6f835992e03356d1c431912fd908eb510cc8f5e 100644
--- a/tangostationcontrol/integration_test/default/devices/test_device_calibration.py
+++ b/tangostationcontrol/integration_test/default/devices/test_device_calibration.py
@@ -88,7 +88,7 @@ class TestCalibrationDevice(AbstractTestBases.TestDeviceBase):
 
         # configure the frequencies, which allows access
         # to the calibration attributes and commands
-        self.sdp_proxy.clock_RW = CLK_200_MHZ
+        self.sdpfirmware_proxy.clock_RW = CLK_200_MHZ
         self.recv_proxy.RCU_band_select_RW = [[1] * N_rcu_inp] * N_rcu
 
     def restore_antennafield(self):
diff --git a/tangostationcontrol/integration_test/default/devices/test_device_digitalbeam.py b/tangostationcontrol/integration_test/default/devices/test_device_digitalbeam.py
index 42974a60e8198ec4bf558b8b497f753862532479..248c06aa1bfdf2c228a6189c6f19ccce2ce89fd7 100644
--- a/tangostationcontrol/integration_test/default/devices/test_device_digitalbeam.py
+++ b/tangostationcontrol/integration_test/default/devices/test_device_digitalbeam.py
@@ -126,7 +126,7 @@ class TestDeviceDigitalBeam(AbstractTestBases.TestDeviceBase):
         self.beamlet_proxy.on()
 
         # Set first (default) clock configuration
-        self.sdp_proxy.clock_RW = CLK_200_MHZ
+        self.sdpfirmware_proxy.clock_RW = CLK_200_MHZ
         time.sleep(1)
 
         self.proxy.initialise()
@@ -148,7 +148,7 @@ class TestDeviceDigitalBeam(AbstractTestBases.TestDeviceBase):
         self.beamlet_proxy.on()
 
         # Change clock configuration
-        self.sdp_proxy.clock_RW = CLK_160_MHZ
+        self.sdpfirmware_proxy.clock_RW = CLK_160_MHZ
         time.sleep(1)
 
         FPGA_bf_weights_pp_clock160 = self.beamlet_proxy.FPGA_bf_weights_pp_RW.flatten()
diff --git a/tangostationcontrol/tangostationcontrol/common/calibration.py b/tangostationcontrol/tangostationcontrol/common/calibration.py
index b6f759887ca3f165d928421d7604ab570527410f..1c98b7dbce3e5a4584dae2bfd5b4151af03741ba 100644
--- a/tangostationcontrol/tangostationcontrol/common/calibration.py
+++ b/tangostationcontrol/tangostationcontrol/common/calibration.py
@@ -207,7 +207,9 @@ def dB_to_factor(dB: numpy.ndarray) -> numpy.ndarray:
 
 
 # SDP input delay calibration
-def calibrate_input_samples_delay(antenna_field: DeviceProxy, sdp: DeviceProxy):
+def calibrate_input_samples_delay(
+    antenna_field: DeviceProxy, sdpfirmware: DeviceProxy, sdp: DeviceProxy
+):
     # Mapping [antenna] -> [fpga][input]
     antenna_to_sdp_mapping = antenna_field.Antenna_to_SDP_Mapping_R
 
@@ -220,7 +222,7 @@ def calibrate_input_samples_delay(antenna_field: DeviceProxy, sdp: DeviceProxy):
     signal_delay_seconds = antenna_field.Antenna_Cables_Delay_R
 
     # compute the required compensation
-    clock = sdp.clock_RW
+    clock = sdpfirmware.clock_RW
     input_samples_delay, _ = delay_compensation(signal_delay_seconds, clock)
 
     # read-modify-write on [fpga][(input, polarisation)]
diff --git a/tangostationcontrol/tangostationcontrol/devices/antennafield.py b/tangostationcontrol/tangostationcontrol/devices/antennafield.py
index fda4e626fb9f5fa3bdbf7add121dbf4cc10815ac..e919715b6ce9d16b765990cc2742ce5f801551ca 100644
--- a/tangostationcontrol/tangostationcontrol/devices/antennafield.py
+++ b/tangostationcontrol/tangostationcontrol/devices/antennafield.py
@@ -695,7 +695,7 @@ class AntennaField(LOFARDevice):
         rcu_band_select = self.read_attribute("RCU_band_select_RW")
 
         # fetch settings from SDP
-        clock = self.sdp_proxy.clock_RW
+        clock = self.sdpfirmware_proxy.clock_RW
 
         def lookup_band(rcu_band):
             try:
@@ -738,7 +738,7 @@ class AntennaField(LOFARDevice):
         )(value)
 
         # apply settings on SDP
-        self.sdp_proxy.clock_RW = bands[value[0]].clock
+        self.sdpfirmware_proxy.clock_RW = bands[value[0]].clock
 
         # read-modify-write on [fpga][(input, polarisation)]
         sdp_nyquist_zone = numpy.full((N_pn, A_pn * N_pol), None)
diff --git a/tangostationcontrol/tangostationcontrol/devices/calibration.py b/tangostationcontrol/tangostationcontrol/devices/calibration.py
index 115facc8fbf2f0441f1b9605a768996babbe42f4..5b4360808e1fcc0c8cbe56c4a0084e26b49ca092 100644
--- a/tangostationcontrol/tangostationcontrol/devices/calibration.py
+++ b/tangostationcontrol/tangostationcontrol/devices/calibration.py
@@ -137,7 +137,7 @@ class Calibration(LOFARDevice):
         """Calibrate RECV for our antennas.
 
         Run whenever the following changes:
-            sdp.clock_RW
+            sdpfirmware.clock_RW
             antennafield.RCU_band_select_RW
         """
 
@@ -161,7 +161,7 @@ class Calibration(LOFARDevice):
         """Calibrate SDP for our antennas.
 
         Run whenever the following changes:
-            sdp.clock_RW
+            sdpfirmware.clock_RW
             antennafield.RCU_band_select_RW
         """
 
@@ -189,7 +189,7 @@ class Calibration(LOFARDevice):
 
         sdp_proxy = self.sdp_proxies[sdp_device]
 
-        calibrate_input_samples_delay(ant_proxy, sdp_proxy)
+        calibrate_input_samples_delay(ant_proxy, sdpfirmware_proxy, sdp_proxy)
 
         self._calibration_manager.calibrate_subband_weights(ant_proxy, sdp_proxy)
 
@@ -236,7 +236,7 @@ class Calibration(LOFARDevice):
                     ),
                 )
             )
-        for prx in self.sdp_proxies.values():
+        for prx in self.sdpfirmware_proxies.values():
             self.event_subscriptions.append(
                 (
                     prx,
diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/firmware.py b/tangostationcontrol/tangostationcontrol/devices/sdp/firmware.py
index 4783e0c0111ab2a589b6390c04af57d3f5b460ae..6250fb9eef5345a7eefd0b6bcbfb8c71f4daec22 100644
--- a/tangostationcontrol/tangostationcontrol/devices/sdp/firmware.py
+++ b/tangostationcontrol/tangostationcontrol/devices/sdp/firmware.py
@@ -14,7 +14,13 @@ from tango import AttrWriteType
 from tango.server import device_property, attribute
 
 # Additional import
-from tangostationcontrol.common.constants import N_pn
+from tangostationcontrol.common.constants import (
+    N_pn,
+    CLK_200_MHZ,
+    CLK_160_MHZ,
+    N_subbands,
+    DEFAULT_POLLING_PERIOD,
+)
 from tangostationcontrol.common.entrypoint import entry
 from tangostationcontrol.common.lofar_logging import device_logging_to_python
 
@@ -38,6 +44,9 @@ class SDPFirmware(OPCUADevice):
     TR_fpga_mask_RW_default = device_property(
         dtype="DevVarBooleanArray", mandatory=False, default_value=[True] * N_pn
     )
+    clock_RW_default = device_property(
+        dtype="DevULong", mandatory=False, default_value=CLK_200_MHZ
+    )
 
     TRANSLATOR_DEFAULT_SETTINGS = ["TR_fpga_mask_RW"]
 
@@ -45,6 +54,11 @@ class SDPFirmware(OPCUADevice):
     # Attributes
     # ----------
 
+    # The SDP Firmware device offers all monitoring & control points
+    # available in the Board Support Package (BSP) that is supported
+    # by both the user and factory images.
+
+    # Translator
     TR_fpga_mask_R = AttributeWrapper(
         comms_annotation=["TR_fpga_mask_R"], datatype=bool, dims=(N_pn,)
     )
@@ -57,6 +71,37 @@ class SDPFirmware(OPCUADevice):
     TR_fpga_communication_error_R = AttributeWrapper(
         comms_annotation=["TR_fpga_communication_error_R"], datatype=bool, dims=(N_pn,)
     )
+    TR_sdp_config_first_fpga_nr_R = AttributeWrapper(
+        comms_annotation=["TR_sdp_config_first_fpga_nr_R"], datatype=numpy.uint32
+    )
+    TR_sdp_config_nof_beamsets_R = AttributeWrapper(
+        comms_annotation=["TR_sdp_config_nof_beamsets_R"], datatype=numpy.uint32
+    )
+    TR_sdp_config_nof_fpgas_R = AttributeWrapper(
+        comms_annotation=["TR_sdp_config_nof_fpgas_R"], datatype=numpy.uint32
+    )
+    TR_software_version_R = AttributeWrapper(
+        comms_annotation=["TR_software_version_R"], datatype=str
+    )
+    TR_start_time_R = AttributeWrapper(
+        comms_annotation=["TR_start_time_R"], datatype=numpy.int64
+    )
+    TR_tod_R = AttributeWrapper(
+        doc="Time-of-day of SDPTR",
+        comms_annotation=["TR_tod_R"],
+        datatype=numpy.int64,
+        dims=(2,),
+    )  # struct of (time_t, int64)
+    TR_tod_sync_status_R = AttributeWrapper(
+        doc="Time-of-day synchronisation status with PTP/NTP (True=synchronised)",
+        comms_annotation=["TR_tod_sync_status_R"],
+        datatype=bool,
+    )
+    TR_tod_pps_delta_R = AttributeWrapper(
+        comms_annotation=["TR_tod_pps_delta_R"], datatype=numpy.double
+    )
+
+    # Firmware & flash
     FPGA_boot_image_R = AttributeWrapper(
         comms_annotation=["FPGA_boot_image_R"],
         datatype=numpy.int32,
@@ -69,9 +114,74 @@ class SDPFirmware(OPCUADevice):
         dims=(N_pn,),
         access=AttrWriteType.READ_WRITE,
     )
+    FPGA_flash_protect_R = AttributeWrapper(
+        comms_annotation=["FPGA_flash_protect_R"],
+        datatype=numpy.uint32,
+        dims=(N_pn,),
+        doc="Protect (0) or unprotect (1) writing the factory image",
+    )
+    FPGA_flash_protect_RW = AttributeWrapper(
+        comms_annotation=["FPGA_flash_protect_RW"],
+        datatype=numpy.uint32,
+        dims=(N_pn,),
+        access=AttrWriteType.READ_WRITE,
+        doc="Protect (0) or unprotect (1) writing the factory image",
+    )
+    FPGA_scrap_R = AttributeWrapper(
+        comms_annotation=["FPGA_scrap_R"],
+        datatype=numpy.int32,
+        dims=(N_pn, N_subbands),
+        doc="FPGA scratch memory",
+    )
+    FPGA_scrap_RW = AttributeWrapper(
+        comms_annotation=["FPGA_scrap_RW"],
+        datatype=numpy.int32,
+        dims=(N_pn, N_subbands),
+        access=AttrWriteType.READ_WRITE,
+        doc="FPGA scratch memory",
+    )
+
+    # Configuration
     FPGA_firmware_version_R = AttributeWrapper(
         comms_annotation=["FPGA_firmware_version_R"], datatype=str, dims=(N_pn,)
     )
+    FPGA_hardware_version_R = AttributeWrapper(
+        comms_annotation=["FPGA_hardware_version_R"], datatype=str, dims=(N_pn,)
+    )
+    FPGA_global_node_index_R = AttributeWrapper(
+        comms_annotation=["FPGA_global_node_index_R"],
+        datatype=numpy.uint32,
+        dims=(N_pn,),
+    )
+
+    # PPS
+    FPGA_pps_present_R = AttributeWrapper(
+        comms_annotation=["FPGA_pps_present_R"], datatype=bool, dims=(N_pn,)
+    )
+    FPGA_pps_capture_cnt_R = AttributeWrapper(
+        comms_annotation=["FPGA_pps_capture_cnt_R"], datatype=numpy.uint32, dims=(N_pn,)
+    )
+    FPGA_pps_expected_cnt_R = AttributeWrapper(
+        comms_annotation=["FPGA_pps_expected_cnt_R"],
+        datatype=numpy.uint32,
+        dims=(N_pn,),
+    )
+    FPGA_pps_expected_cnt_RW = AttributeWrapper(
+        comms_annotation=["FPGA_pps_expected_cnt_RW"],
+        datatype=numpy.uint32,
+        dims=(N_pn,),
+        access=AttrWriteType.READ_WRITE,
+    )
+    FPGA_time_since_last_pps_R = AttributeWrapper(
+        comms_annotation=["FPGA_time_since_last_pps_R"],
+        datatype=numpy.float_,
+        dims=(N_pn,),
+    )
+
+    # Monitoring
+    FPGA_temp_R = AttributeWrapper(
+        comms_annotation=["FPGA_temp_R"], datatype=numpy.float_, dims=(N_pn,)
+    )
 
     @attribute(
         access=AttrWriteType.READ,
@@ -80,6 +190,38 @@ class SDPFirmware(OPCUADevice):
     def SDP_device_R(self):
         return self.control.child(DeviceTypes.SDP).dev_name()
 
+    clock_RW = attribute(
+        doc="Configured sampling clock (Hz)",
+        unit="Hz",
+        dtype=numpy.uint32,
+        access=AttrWriteType.READ_WRITE,
+        fisallowed="is_attribute_access_allowed",
+        polling_period=DEFAULT_POLLING_PERIOD,
+        abs_change=1,
+    )
+
+    def read_clock_RW(self):
+        # We can only return a single value, so we assume the FPGA is configured coherently.
+        # Which is something that is to be checked by an independent monitoring system anyway.
+        mask = self.read_attribute(
+            "TR_fpga_mask_RW",
+        )
+        clocks = self.read_attribute("FPGA_pps_expected_cnt_RW")
+        clocks_in_mask = [clock for idx, clock in enumerate(clocks) if mask[idx]]
+
+        # We return first setting within the mask.
+        # If there are no FPGAs selected at all, just return a sane default.
+        return (
+            numpy.uint32(clocks_in_mask[0]) if clocks_in_mask else self.clock_RW_default
+        )
+
+    def write_clock_RW(self, clock):
+        if clock not in (CLK_160_MHZ, CLK_200_MHZ):
+            raise ValueError(f"Unsupported clock frequency: {clock}")
+
+        # Tell all FPGAs to use this clock
+        self.proxy.FPGA_pps_expected_cnt_RW = [clock] * N_pn
+
     # ----------
     # Summarising Attributes
     # ----------
diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py b/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py
index c18dfc89da979924844b92c5622d030d355847cd..dff46058d014385a80bb428f462a65994fd57e08 100644
--- a/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py
+++ b/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py
@@ -17,7 +17,6 @@ from tangostationcontrol.common.constants import (
     S_pn,
     N_pn,
     CLK_200_MHZ,
-    CLK_160_MHZ,
     N_subband_res,
     N_subbands,
     DEFAULT_SUBBAND,
@@ -105,39 +104,10 @@ class SDP(OPCUADevice):
         default_value=[[0] * S_pn * N_subbands] * N_pn,
     )
 
-    clock_RW_default = device_property(
-        dtype="DevULong", mandatory=False, default_value=CLK_200_MHZ
-    )
-
     # ----------
     # Attributes
     # ----------
 
-    FPGA_global_node_index_R = AttributeWrapper(
-        comms_annotation=["FPGA_global_node_index_R"],
-        datatype=numpy.uint32,
-        dims=(N_pn,),
-    )
-    FPGA_hardware_version_R = AttributeWrapper(
-        comms_annotation=["FPGA_hardware_version_R"], datatype=str, dims=(N_pn,)
-    )
-    FPGA_pps_present_R = AttributeWrapper(
-        comms_annotation=["FPGA_pps_present_R"], datatype=bool, dims=(N_pn,)
-    )
-    FPGA_pps_capture_cnt_R = AttributeWrapper(
-        comms_annotation=["FPGA_pps_capture_cnt_R"], datatype=numpy.uint32, dims=(N_pn,)
-    )
-    FPGA_pps_expected_cnt_R = AttributeWrapper(
-        comms_annotation=["FPGA_pps_expected_cnt_R"],
-        datatype=numpy.uint32,
-        dims=(N_pn,),
-    )
-    FPGA_pps_expected_cnt_RW = AttributeWrapper(
-        comms_annotation=["FPGA_pps_expected_cnt_RW"],
-        datatype=numpy.uint32,
-        dims=(N_pn,),
-        access=AttrWriteType.READ_WRITE,
-    )
     FPGA_processing_enable_R = AttributeWrapper(
         comms_annotation=["FPGA_processing_enable_R"], datatype=bool, dims=(N_pn,)
     )
@@ -189,15 +159,6 @@ class SDP(OPCUADevice):
         dims=(N_pn,),
         access=AttrWriteType.READ_WRITE,
     )
-    FPGA_scrap_R = AttributeWrapper(
-        comms_annotation=["FPGA_scrap_R"], datatype=numpy.int32, dims=(N_pn, N_subbands)
-    )
-    FPGA_scrap_RW = AttributeWrapper(
-        comms_annotation=["FPGA_scrap_RW"],
-        datatype=numpy.int32,
-        dims=(N_pn, N_subbands),
-        access=AttrWriteType.READ_WRITE,
-    )
     FPGA_sdp_info_antenna_band_index_R = AttributeWrapper(
         comms_annotation=["FPGA_sdp_info_antenna_band_index_R"],
         datatype=numpy.uint32,
@@ -288,14 +249,6 @@ class SDP(OPCUADevice):
         dims=(N_pn, S_pn, N_subbands),
         access=AttrWriteType.READ_WRITE,
     )
-    FPGA_time_since_last_pps_R = AttributeWrapper(
-        comms_annotation=["FPGA_time_since_last_pps_R"],
-        datatype=numpy.float_,
-        dims=(N_pn,),
-    )
-    FPGA_temp_R = AttributeWrapper(
-        comms_annotation=["FPGA_temp_R"], datatype=numpy.float_, dims=(N_pn,)
-    )
 
     FPGA_wg_amplitude_R = AttributeWrapper(
         comms_annotation=["FPGA_wg_amplitude_R"],
@@ -337,27 +290,6 @@ class SDP(OPCUADevice):
         dims=(N_pn, S_pn),
         access=AttrWriteType.READ_WRITE,
     )
-    TR_sdp_config_first_fpga_nr_R = AttributeWrapper(
-        comms_annotation=["TR_sdp_config_first_fpga_nr_R"], datatype=numpy.uint32
-    )
-    TR_sdp_config_nof_beamsets_R = AttributeWrapper(
-        comms_annotation=["TR_sdp_config_nof_beamsets_R"], datatype=numpy.uint32
-    )
-    TR_sdp_config_nof_fpgas_R = AttributeWrapper(
-        comms_annotation=["TR_sdp_config_nof_fpgas_R"], datatype=numpy.uint32
-    )
-    TR_software_version_R = AttributeWrapper(
-        comms_annotation=["TR_software_version_R"], datatype=str
-    )
-    TR_start_time_R = AttributeWrapper(
-        comms_annotation=["TR_start_time_R"], datatype=numpy.int64
-    )
-    TR_tod_R = AttributeWrapper(
-        comms_annotation=["TR_tod_R"], datatype=numpy.int64, dims=(2,)
-    )  # struct of (time_t, int64)
-    TR_tod_pps_delta_R = AttributeWrapper(
-        comms_annotation=["TR_tod_pps_delta_R"], datatype=numpy.double
-    )
 
     # OPC-UA MP only points for AIT
     FPGA_signal_input_mean_R = AttributeWrapper(
@@ -446,15 +378,6 @@ class SDP(OPCUADevice):
         polling_period=DEFAULT_POLLING_PERIOD,
         abs_change=1,
     )
-    clock_RW = attribute(
-        doc="Configured sampling clock (Hz)",
-        unit="Hz",
-        dtype=numpy.uint32,
-        access=AttrWriteType.READ_WRITE,
-        fisallowed="is_attribute_access_allowed",
-        polling_period=DEFAULT_POLLING_PERIOD,
-        abs_change=1,
-    )
     subband_frequency_R = attribute(
         doc="Frequency of each subband for each input",
         unit="Hz",
@@ -537,31 +460,9 @@ class SDP(OPCUADevice):
         # to make sure the subbands are ascending in frequency
         self.proxy.FPGA_spectral_inversion_RW = self._nyquist_zone % 2
 
-    def read_clock_RW(self):
-        # We can only return a single value, so we assume the FPGA is configured coherently.
-        # Which is something that is to be checked by an independent monitoring system anyway.
-        mask = self.control.read_parent_attribute(
-            "TR_fpga_mask_RW",
-        )
-        clocks = self.read_attribute("FPGA_pps_expected_cnt_RW")
-        clocks_in_mask = [clock for idx, clock in enumerate(clocks) if mask[idx]]
-
-        # We return first setting within the mask.
-        # If there are no FPGAs selected at all, just return a sane default.
-        return (
-            numpy.uint32(clocks_in_mask[0]) if clocks_in_mask else self.clock_RW_default
-        )
-
-    def write_clock_RW(self, clock):
-        if clock not in (CLK_160_MHZ, CLK_200_MHZ):
-            raise ValueError(f"Unsupported clock frequency: {clock}")
-
-        # Tell all FPGAs to use this clock
-        self.proxy.FPGA_pps_expected_cnt_RW = [clock] * N_pn
-
     @TimeIt()
     def read_subband_frequency_R(self):
-        clock = self.read_attribute("clock_RW")  # scalar
+        clock = self.control.read_parent_attribute("clock_RW")  # scalar
         nyquist_zone = numpy.array(
             self.read_attribute("nyquist_zone_RW")
         )  # N_pn x S_pn