diff --git a/README.md b/README.md
index b811fa3dbeb7eb07e3f741e6a86a656055b3e9b5..9dc7c53a6fe28374b864a5b103c053a3326d51db 100644
--- a/README.md
+++ b/README.md
@@ -166,6 +166,8 @@ Next change the version in the following places:
 
 # Release Notes
 
+* 0.30.2 Add XST/SST settings to Observation specifications
+         Fixed dimensionality of xst.FPGA_subband_select_R(W)
 * 0.30.1 Remove deprecated FPGA_beamlet_output_nof_beamlets
          Fix prometheus metric for counting calibrations
          Removed ALARM and DISABLED states
diff --git a/tangostationcontrol/VERSION b/tangostationcontrol/VERSION
index 1a44cad74d6555dd4d4557871257966853237a86..0f72177373685866f1681484947dc95375e4d750 100644
--- a/tangostationcontrol/VERSION
+++ b/tangostationcontrol/VERSION
@@ -1 +1 @@
-0.30.1
+0.30.2
diff --git a/tangostationcontrol/integration_test/default/devices/test_device_observation_field.py b/tangostationcontrol/integration_test/default/devices/test_device_observation_field.py
index 40c06aab247df55a7a145591cde251e1d4fff946..11f915d7ff4486dec16f13f8c68acabb95ee1e6c 100644
--- a/tangostationcontrol/integration_test/default/devices/test_device_observation_field.py
+++ b/tangostationcontrol/integration_test/default/devices/test_device_observation_field.py
@@ -111,6 +111,8 @@ class TestDeviceObservationField(AbstractTestBases.TestDeviceBase):
         self.recv_proxy = self.setup_proxy("STAT/RECVH/H0", defaults=True)
         self.sdpfirmware_proxy = self.setup_proxy("STAT/SDPFirmware/HBA0")
         self.sdp_proxy = self.setup_proxy("STAT/SDP/HBA0")
+        self.sst_proxy = self.setup_proxy("STAT/SST/HBA0")
+        self.xst_proxy = self.setup_proxy("STAT/XST/HBA0")
         self.antennafield_proxy = self.setup_proxy(
             self.antennafield_name, cb=self.antennafield_configure
         )
diff --git a/tangostationcontrol/integration_test/default/devices/test_observation_client.py b/tangostationcontrol/integration_test/default/devices/test_observation_client.py
index 3b46b8319110f5acc9404af44e3f5e1765e21ad1..58576f3c24f14ef26f98535e77465f5e894b3656 100644
--- a/tangostationcontrol/integration_test/default/devices/test_observation_client.py
+++ b/tangostationcontrol/integration_test/default/devices/test_observation_client.py
@@ -36,6 +36,8 @@ class TestObservation(base.IntegrationTestCase):
             "STAT/DigitalBeam/HBA0",
             "STAT/TileBeam/HBA0",
             "STAT/AFH/HBA0",
+            "STAT/SST/HBA0",
+            "STAT/XST/HBA0",
         ]:
             proxy = TestDeviceProxy(device)
             proxy.off()
diff --git a/tangostationcontrol/tangostationcontrol/common/constants.py b/tangostationcontrol/tangostationcontrol/common/constants.py
index 0331b8ee0057f8f95dceab1fb68462d71d5994a0..45684b65576b69da4972bdc098bfcfe1e3a70451 100644
--- a/tangostationcontrol/tangostationcontrol/common/constants.py
+++ b/tangostationcontrol/tangostationcontrol/common/constants.py
@@ -66,7 +66,7 @@ CLK_200_MHZ = 200_000_000
 CLK_160_MHZ = 160_000_000
 
 # Maximum number of subbands for which we collect XSTs simultaneously
-MAX_PARALLEL_SUBBANDS = 8
+MAX_PARALLEL_SUBBANDS = 7
 # Expected block for XST's
 BLOCK_LENGTH = 12
 # Complex values are (real, imag).
diff --git a/tangostationcontrol/tangostationcontrol/configuration/__init__.py b/tangostationcontrol/tangostationcontrol/configuration/__init__.py
index b567fc35750358442fa60da4e845980744541f72..8b7cbce6a59b3e648cd50e82697dff0f8cb21fb7 100644
--- a/tangostationcontrol/tangostationcontrol/configuration/__init__.py
+++ b/tangostationcontrol/tangostationcontrol/configuration/__init__.py
@@ -8,6 +8,8 @@ from .observation_settings import ObservationSettings
 from .observation_field_settings import ObservationFieldSettings
 from .pointing import Pointing
 from .sap import Sap
+from .sst import SST
+from .xst import XST
 
 __all__ = [
     "ObservationSettings",
@@ -17,4 +19,6 @@ __all__ = [
     "HBA",
     "Dithering",
     "REGISTRY",
+    "SST",
+    "XST",
 ]
diff --git a/tangostationcontrol/tangostationcontrol/configuration/_json_parser.py b/tangostationcontrol/tangostationcontrol/configuration/_json_parser.py
index 92daf15a46e8bc444263c2380936c7f072ab56b3..c3327ca36041acd21319a748648b4eb9a2366cca 100644
--- a/tangostationcontrol/tangostationcontrol/configuration/_json_parser.py
+++ b/tangostationcontrol/tangostationcontrol/configuration/_json_parser.py
@@ -14,6 +14,8 @@ def _from_json_hook_t(primary: Type):
         ObservationFieldSettings,
         HBA,
         Dithering,
+        SST,
+        XST,
     )
 
     def actual_hook(json_dct):
@@ -21,6 +23,8 @@ def _from_json_hook_t(primary: Type):
         primary_ex = None
         # Order is critical, must match inheritance, deepest layers first
         for t in [
+            SST,
+            XST,
             Pointing,
             Sap,
             HBA,
diff --git a/tangostationcontrol/tangostationcontrol/configuration/_schemas.py b/tangostationcontrol/tangostationcontrol/configuration/_schemas.py
index 6a6678e0876fca671519552d76a20f5ee61e352e..ebfa2d0f057f29ec1398e9ee727824a842f604a6 100644
--- a/tangostationcontrol/tangostationcontrol/configuration/_schemas.py
+++ b/tangostationcontrol/tangostationcontrol/configuration/_schemas.py
@@ -14,8 +14,12 @@ from referencing.jsonschema import SchemaRegistry as _SchemaRegistry
 
 
 def _schemas():
-    for schema in files(__package__).joinpath("schemas").iterdir():
-        contents = json.loads(schema.read_text(encoding="utf-8"))
+    for schema in files(__package__).joinpath("schemas").glob("*.json"):
+        try:
+            contents = json.loads(schema.read_text(encoding="utf-8"))
+        except json.decoder.JSONDecodeError as ex:
+            raise ValueError(f"Error decoding JSON schema {schema}") from ex
+
         yield Resource.from_contents(contents)
 
 
diff --git a/tangostationcontrol/tangostationcontrol/configuration/configuration_base.py b/tangostationcontrol/tangostationcontrol/configuration/configuration_base.py
index a8e94dc8a140765fe32b7463d6f6e8a5c7e64ea8..18c06e82f66645867dd724622cb9ec96aaf8aaf9 100644
--- a/tangostationcontrol/tangostationcontrol/configuration/configuration_base.py
+++ b/tangostationcontrol/tangostationcontrol/configuration/configuration_base.py
@@ -33,6 +33,8 @@ class _ConfigurationBase(ABC):
         """Class name to json schema file conversion name"""
         cls_name = cls_name.replace("HBA", "hba")
         cls_name = cls_name.replace("LBA", "lba")
+        cls_name = cls_name.replace("SST", "sst")
+        cls_name = cls_name.replace("XST", "xst")
         return re.sub(r"(?<!^)(?=[A-Z])", "-", cls_name).lower()
 
     @classmethod
@@ -53,7 +55,11 @@ class _ConfigurationBase(ABC):
         pass
 
     def __str__(self):
-        return json.dumps(dict(self), ensure_ascii=False)
+        try:
+            return json.dumps(dict(self), ensure_ascii=False)
+        except TypeError:
+            # This happens if we want to dump a type that cannot be represented in JSON
+            return str(dict(self))
 
     def __repr__(self):
         return self.__str__()
@@ -76,10 +82,14 @@ class _ConfigurationBase(ABC):
 
     @classmethod
     def from_json(cls: Type[T], data: str) -> T:
-        s = json.loads(data, object_hook=_from_json_hook_t(cls))
+        try:
+            s = json.loads(data, object_hook=_from_json_hook_t(cls))
+        except json.decoder.JSONDecodeError as ex:
+            raise ValueError(f"Error decoding JSON {data}") from ex
+
         if not isinstance(s, cls):
             raise ValidationError(
                 f"Unexpected type: expected <{cls.__class__.__name__}>, got "
-                f"<{type(s).__name__}>"
+                f"<{type(s).__name__}>: {s}"
             )
         return s
diff --git a/tangostationcontrol/tangostationcontrol/configuration/hba.py b/tangostationcontrol/tangostationcontrol/configuration/hba.py
index ecd65aecf06c074edf124a194fc0ba7d2f5c91eb..274fd9c126458c1b3af3b881ee5aee40506cf3ec 100644
--- a/tangostationcontrol/tangostationcontrol/configuration/hba.py
+++ b/tangostationcontrol/tangostationcontrol/configuration/hba.py
@@ -9,7 +9,7 @@ class HBA(_ConfigurationBase):
     def __init__(
         self,
         tile_beam: Pointing,
-        DAB_filter: bool | None,
+        DAB_filter: bool | None = None,
         element_selection: str | None = "ALL",
     ):
         self.tile_beam = tile_beam
diff --git a/tangostationcontrol/tangostationcontrol/configuration/observation_field_settings.py b/tangostationcontrol/tangostationcontrol/configuration/observation_field_settings.py
index d862468ac193d8184bbdf12b1b29b7e6a10e86c7..51349377d9859aa8ecba6c33ecc6f0ed8b442766 100644
--- a/tangostationcontrol/tangostationcontrol/configuration/observation_field_settings.py
+++ b/tangostationcontrol/tangostationcontrol/configuration/observation_field_settings.py
@@ -8,6 +8,8 @@ from tangostationcontrol.configuration.configuration_base import _ConfigurationB
 from tangostationcontrol.configuration.dithering import Dithering
 from tangostationcontrol.configuration.hba import HBA
 from tangostationcontrol.configuration.sap import Sap
+from tangostationcontrol.configuration.sst import SST
+from tangostationcontrol.configuration.xst import XST
 
 
 class ObservationFieldSettings(_ConfigurationBase):
@@ -24,6 +26,8 @@ class ObservationFieldSettings(_ConfigurationBase):
         first_beamlet: int = 0,
         lead_time: float | None = None,
         dithering: Dithering | None = None,
+        SST: SST | None = None,
+        XST: XST | None = None,
     ):
         self.observation_id = observation_id
         self.start_time = self._parse_and_convert_datetime(start_time)
@@ -36,6 +40,8 @@ class ObservationFieldSettings(_ConfigurationBase):
         self.first_beamlet = first_beamlet
         self.lead_time = lead_time
         self.dithering = dithering
+        self.SST = SST
+        self.XST = XST
 
     @staticmethod
     def _parse_and_convert_datetime(time: str | datetime | None):
@@ -68,6 +74,10 @@ class ObservationFieldSettings(_ConfigurationBase):
             yield "lead_time", self.lead_time
         if self.dithering is not None:
             yield "dithering", dict(self.dithering)
+        if self.SST is not None:
+            yield "SST", dict(self.SST)
+        if self.XST is not None:
+            yield "SST", dict(self.XST)
 
     @staticmethod
     def to_object(json_dct) -> "ObservationFieldSettings":
@@ -83,4 +93,6 @@ class ObservationFieldSettings(_ConfigurationBase):
             json_dct.get("first_beamlet", 0),
             json_dct.get("lead_time"),
             json_dct.get("dithering"),
+            json_dct.get("SST"),
+            json_dct.get("XST"),
         )
diff --git a/tangostationcontrol/tangostationcontrol/configuration/schemas/observation-field-settings.json b/tangostationcontrol/tangostationcontrol/configuration/schemas/observation-field-settings.json
index 98d90868c0f863a5b4f355211d3eb7f12e531ea4..bfa84e83d2291edec23c2e00f5e1f42c7d53a6cf 100644
--- a/tangostationcontrol/tangostationcontrol/configuration/schemas/observation-field-settings.json
+++ b/tangostationcontrol/tangostationcontrol/configuration/schemas/observation-field-settings.json
@@ -82,6 +82,12 @@
     },
     "HBA": {
       "$ref": "hba"
+    },
+    "sst": {
+      "$ref": "sst"
+    },
+    "xst": {
+      "$ref": "xst"
     }
   }
 }
diff --git a/tangostationcontrol/tangostationcontrol/configuration/schemas/sst.json b/tangostationcontrol/tangostationcontrol/configuration/schemas/sst.json
new file mode 100644
index 0000000000000000000000000000000000000000..7cd50724c6c30e7917216929a08033756b24b20c
--- /dev/null
+++ b/tangostationcontrol/tangostationcontrol/configuration/schemas/sst.json
@@ -0,0 +1,14 @@
+{
+  "$schema": "http://json-schema.org/draft-07/schema",
+  "$id": "sst",
+  "type": "object",
+  "required": [
+    "subbands_calibrated"
+  ],
+  "properties": {
+    "subbands_calibrated": {
+      "type": "boolean",
+      "default": true
+    }
+  }
+}
diff --git a/tangostationcontrol/tangostationcontrol/configuration/schemas/xst.json b/tangostationcontrol/tangostationcontrol/configuration/schemas/xst.json
new file mode 100644
index 0000000000000000000000000000000000000000..27cf2ec7849e36aa84b53a56e60a9bae3224126d
--- /dev/null
+++ b/tangostationcontrol/tangostationcontrol/configuration/schemas/xst.json
@@ -0,0 +1,33 @@
+{
+  "$schema": "http://json-schema.org/draft-07/schema",
+  "$id": "xst",
+  "type": "object",
+  "required": [
+    "subbands",
+    "integration_interval"
+  ],
+  "properties": {
+    "subbands": {
+      "type": "array",
+      "minItems": 0,
+      "maxItems": 7,
+      "items": {
+        "type": "number",
+        "minimum": 0,
+        "maximum": 488
+      }
+    },
+    "subbands_step": {
+      "type": "number",
+      "default": 0,
+      "minimum": 0,
+      "maximum": 488
+    },
+    "integration_interval": {
+      "type": "number",
+      "default": 1.0,
+      "minimum": 0.1,
+      "maximum": 10.7
+    }
+  }
+}
diff --git a/tangostationcontrol/tangostationcontrol/configuration/sst.py b/tangostationcontrol/tangostationcontrol/configuration/sst.py
new file mode 100644
index 0000000000000000000000000000000000000000..cfd1237df19286d03c1628ea082e6475e3def73f
--- /dev/null
+++ b/tangostationcontrol/tangostationcontrol/configuration/sst.py
@@ -0,0 +1,21 @@
+# Copyright (C) 2024 ASTRON (Netherlands Institute for Radio Astronomy)
+# SPDX-License-Identifier: Apache-2.0
+
+from tangostationcontrol.configuration.configuration_base import _ConfigurationBase
+
+
+class SST(_ConfigurationBase):
+    def __init__(
+        self,
+        subbands_calibrated: bool,
+    ):
+        self.subbands_calibrated = subbands_calibrated
+
+    def __iter__(self):
+        yield "subbands_calibrated", self.subbands_calibrated
+
+    @staticmethod
+    def to_object(json_dct) -> "SST":
+        return SST(
+            json_dct["subbands_calibrated"],
+        )
diff --git a/tangostationcontrol/tangostationcontrol/configuration/xst.py b/tangostationcontrol/tangostationcontrol/configuration/xst.py
new file mode 100644
index 0000000000000000000000000000000000000000..7d14bccef81fb47b82e1872a53428a17c4f91a64
--- /dev/null
+++ b/tangostationcontrol/tangostationcontrol/configuration/xst.py
@@ -0,0 +1,33 @@
+# Copyright (C) 2024 ASTRON (Netherlands Institute for Radio Astronomy)
+# SPDX-License-Identifier: Apache-2.0
+
+from typing import List
+
+from tangostationcontrol.configuration.configuration_base import _ConfigurationBase
+
+
+class XST(_ConfigurationBase):
+    def __init__(
+        self,
+        integration_interval: float,
+        subbands: List[int],
+        subbands_step: int | None = None,
+    ):
+        self.subbands = subbands
+        self.subbands_step = subbands_step
+        self.integration_interval = integration_interval
+
+    def __iter__(self):
+        yield "integration_interval", self.integration_interval
+        yield "subbands", self.subbands
+
+        if self.subbands_step is not None:
+            yield "subbands_step", self.subbands_step
+
+    @staticmethod
+    def to_object(json_dct) -> "XST":
+        return XST(
+            json_dct["integration_interval"],
+            json_dct["subbands"],
+            json_dct.get("subbands_step"),
+        )
diff --git a/tangostationcontrol/tangostationcontrol/devices/observation_field.py b/tangostationcontrol/tangostationcontrol/devices/observation_field.py
index df970322aa075ff9522aa8d8fccac13217ea6ba5..870f14b9685b42209cc531d0fec3ac01debe9b1a 100644
--- a/tangostationcontrol/tangostationcontrol/devices/observation_field.py
+++ b/tangostationcontrol/tangostationcontrol/devices/observation_field.py
@@ -6,7 +6,7 @@ from datetime import datetime
 import logging
 from itertools import chain
 from time import time
-from typing import Optional
+from typing import Optional, List
 
 import numpy
 from jsonschema.exceptions import ValidationError
@@ -18,8 +18,10 @@ from tangostationcontrol.common.constants import (
     DEFAULT_METRICS_POLLING_PERIOD,
     DEFAULT_POLLING_PERIOD,
     MAX_ANTENNA,
+    MAX_PARALLEL_SUBBANDS,
     N_beamlets_ctrl,
     N_elements,
+    N_pn,
     N_point_prop,
     N_pol,
 )
@@ -254,6 +256,52 @@ class ObservationField(LOFARDevice):
         except AttributeError:
             return "ALL"
 
+    @attribute(
+        doc="",
+        dtype=bool,
+        fisallowed="is_attribute_access_allowed",
+    )
+    def SST_subbands_calibrated_R(self):
+        try:
+            return self._observation_field_settings.SST.subbands_calibrated
+        except AttributeError:
+            return True
+
+    @attribute(
+        doc="The indices of the subbands to emit every integration interval.",
+        dtype=(numpy.uint32,),
+        max_dim_x=MAX_PARALLEL_SUBBANDS,
+    )
+    def XST_subbands_R(self):
+        try:
+            return numpy.array(
+                self._observation_field_settings.XST.subbands,
+                dtype=numpy.uint32,
+            )
+        except AttributeError:
+            return numpy.array([], dtype=numpy.uint32)
+
+    @attribute(
+        doc="The subband indices are increased with this index every interval, causing different subbands to be emitted.",
+        dtype=numpy.uint32,
+    )
+    def XST_subbands_step_R(self):
+        try:
+            return self._observation_field_settings.XST.subbands_step
+        except AttributeError:
+            return 0
+
+    @attribute(
+        doc="",
+        dtype=numpy.float64,
+        fisallowed="is_attribute_access_allowed",
+    )
+    def XST_integration_interval_R(self):
+        try:
+            return self._observation_field_settings.XST.integration_interval
+        except AttributeError:
+            return 1.0
+
     observation_field_settings_RW = attribute(
         dtype=str, access=AttrWriteType.READ_WRITE
     )
@@ -372,6 +420,14 @@ class ObservationField(LOFARDevice):
                 f"{util.get_ds_inst_name()}/TileBeam/{antennafield}"
             )
 
+        self.sst_proxy = create_device_proxy(
+            f"{util.get_ds_inst_name()}/SST/{antennafield}"
+        )
+
+        self.xst_proxy = create_device_proxy(
+            f"{util.get_ds_inst_name()}/XST/{antennafield}"
+        )
+
     @log_exceptions()
     def _start_observation(self):
         """Configure the station for this observation and antenna field."""
@@ -438,6 +494,31 @@ class ObservationField(LOFARDevice):
                 element_selection
             )
 
+        # Configure SST
+        subbands_calibrated = self.read_attribute("SST_subbands_calibrated_R")
+        self.sst_proxy.FPGA_sst_offload_weighted_subbands_RW = [
+            subbands_calibrated
+        ] * N_pn
+
+        # Toggle statistics to activate new settings
+        self.sst_proxy.power_hardware_off()
+        self.sst_proxy.power_hardware_on()
+
+        # Configure XST
+        subbands = self.read_attribute("XST_subbands_R")
+        subbands_step = self.read_attribute("XST_subbands_step_R")
+        integration_interval = self.read_attribute("XST_integration_interval_R")
+
+        self.xst_proxy.FPGA_xst_subband_select_RW = self._apply_xst_subband_select(
+            subbands.tolist(),
+            subbands_step,
+        )
+        self.xst_proxy.FPGA_xst_integration_interval_RW = [integration_interval] * N_pn
+
+        # Toggle statistics to activate new settings
+        self.xst_proxy.power_hardware_off()
+        self.xst_proxy.power_hardware_on()
+
     @log_exceptions()
     def _stop_observation(self):
         """Tear down station resources we used."""
@@ -470,6 +551,21 @@ class ObservationField(LOFARDevice):
         """Return whether this observation should control a TileBeam device."""
         return self._observation_field_settings.antenna_field.startswith("HBA")
 
+    def _apply_xst_subband_select(
+        self, subbands: List[int], subbands_step: int
+    ) -> numpy.ndarray:
+
+        if len(subbands) > MAX_PARALLEL_SUBBANDS:
+            raise ValueError(
+                f"Requested more than {MAX_PARALLEL_SUBBANDS} subbands for the XSTs: {subbands}"
+            )
+
+        return numpy.array(
+            [[subbands_step] + subbands + [0] * (MAX_PARALLEL_SUBBANDS - len(subbands))]
+            * N_pn,
+            dtype=numpy.uint32,
+        )
+
     def _apply_antennafield_settings(self, filter_name: str):
         """Retrieve the RCU band from filter name, returning the correct format for
         AntennaField device
diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/bst.py b/tangostationcontrol/tangostationcontrol/devices/sdp/bst.py
index 1e9215d5d9b8939b200de775827ed8152965e6f7..256b082b895ad7f840992c183297f8ed4dafe758 100644
--- a/tangostationcontrol/tangostationcontrol/devices/sdp/bst.py
+++ b/tangostationcontrol/tangostationcontrol/devices/sdp/bst.py
@@ -195,6 +195,14 @@ class BST(Statistics):
     # Overloaded functions
     # --------
 
+    def _power_hardware_on(self):
+        self.proxy.write_attribute(
+            "FPGA_bst_offload_enable_RW", self.FPGA_bst_offload_enable_RW_default
+        )
+
+    def _power_hardware_off(self):
+        self.proxy.write_attribute("FPGA_bst_offload_enable_RW", [False] * N_pn)
+
     # --------
     # Commands
     # --------
diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/sst.py b/tangostationcontrol/tangostationcontrol/devices/sdp/sst.py
index 73cd1ea4a298c19c8fe918adc1a5a730ae119eab..63d05a5cb838eaacba01c79118ba62ac93ebacf8 100644
--- a/tangostationcontrol/tangostationcontrol/devices/sdp/sst.py
+++ b/tangostationcontrol/tangostationcontrol/devices/sdp/sst.py
@@ -222,6 +222,14 @@ class SST(Statistics):
     # Overloaded functions
     # --------
 
+    def _power_hardware_on(self):
+        self.proxy.write_attribute(
+            "FPGA_sst_offload_enable_RW", self.FPGA_sst_offload_enable_RW_default
+        )
+
+    def _power_hardware_off(self):
+        self.proxy.write_attribute("FPGA_sst_offload_enable_RW", [False] * N_pn)
+
     # --------
     # Commands
     # --------
diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/xst.py b/tangostationcontrol/tangostationcontrol/devices/sdp/xst.py
index 94e55aa3a7ad74da5c6d98d98c333ebc9e72319c..45d7cbe3c510f47f809ce5c874c570296261fc83 100644
--- a/tangostationcontrol/tangostationcontrol/devices/sdp/xst.py
+++ b/tangostationcontrol/tangostationcontrol/devices/sdp/xst.py
@@ -58,7 +58,7 @@ class XST(Statistics):
         first_signal_index = self.control.read_parent_attribute(
             "first_signal_input_index_R"
         )
-        return XSTCollector(nr_signal_inputs, first_signal_index)
+        return XSTCollector(nr_signal_inputs, first_signal_index, MAX_PARALLEL_SUBBANDS)
 
     # -----------------
     # Device Properties
@@ -210,17 +210,19 @@ class XST(Statistics):
         dims=(N_pn,),
     )
     FPGA_xst_subband_select_RW = AttributeWrapper(
+        doc="Which subbands to emit XSTs for. The first element is the step size, allowing different subbands to be emitted every interval.",
         comms_id=OPCUAConnection,
         comms_annotation=["FPGA_xst_subband_select_RW"],
         datatype=numpy.uint32,
-        dims=(MAX_PARALLEL_SUBBANDS, N_pn),
+        dims=(N_pn, MAX_PARALLEL_SUBBANDS + 1),
         access=AttrWriteType.READ_WRITE,
     )
     FPGA_xst_subband_select_R = AttributeWrapper(
+        doc="Which subbands to emit XSTs for. The first element is the step size, allowing different subbands to be emitted every interval.",
         comms_id=OPCUAConnection,
         comms_annotation=["FPGA_xst_subband_select_R"],
         datatype=numpy.uint32,
-        dims=(MAX_PARALLEL_SUBBANDS, N_pn),
+        dims=(N_pn, MAX_PARALLEL_SUBBANDS + 1),
     )
     FPGA_xst_start_time_RW = AttributeWrapper(
         doc="Start generating XSTs at this timestamp, or as soon as possible. Use this to synchronise the XSTs from different FPGAs.",
@@ -689,31 +691,6 @@ class XST(Statistics):
         fget=lambda self: self.read_xst_N_phase_R(6),
     )
 
-    xst_7_real_R = attribute(
-        max_dim_x=MAX_INPUTS,
-        max_dim_y=MAX_INPUTS,
-        dtype=((numpy.float32,),),
-        fget=lambda self: self.read_xst_N_real_R(7),
-    )
-    xst_7_imag_R = attribute(
-        max_dim_x=MAX_INPUTS,
-        max_dim_y=MAX_INPUTS,
-        dtype=((numpy.float32,),),
-        fget=lambda self: self.read_xst_N_imag_R(7),
-    )
-    xst_7_power_R = attribute(
-        max_dim_x=MAX_INPUTS,
-        max_dim_y=MAX_INPUTS,
-        dtype=((numpy.float32,),),
-        fget=lambda self: self.read_xst_N_power_R(7),
-    )
-    xst_7_phase_R = attribute(
-        max_dim_x=MAX_INPUTS,
-        max_dim_y=MAX_INPUTS,
-        dtype=((numpy.float32,),),
-        fget=lambda self: self.read_xst_N_phase_R(7),
-    )
-
     def read_xst_N_real_R(self, subband_idx):
         return numpy.real(self.statistics_client.collector.xst_values([subband_idx])[0])
 
@@ -745,6 +722,18 @@ class XST(Statistics):
     # Overloaded functions
     # --------
 
+    def _power_hardware_on(self):
+        self.proxy.write_attribute(
+            "FPGA_xst_processing_enable_RW", self.FPGA_xst_processing_enable_RW_default
+        )
+        self.proxy.write_attribute(
+            "FPGA_xst_offload_enable_RW", self.FPGA_xst_offload_enable_RW_default
+        )
+
+    def _power_hardware_off(self):
+        self.proxy.write_attribute("FPGA_xst_offload_enable_RW", [False] * N_pn)
+        self.proxy.write_attribute("FPGA_xst_processing_enable_RW", [False] * N_pn)
+
     # --------
     # Commands
     # --------
diff --git a/tangostationcontrol/tangostationcontrol/observation/observation_controller.py b/tangostationcontrol/tangostationcontrol/observation/observation_controller.py
index 4c8f74c666219a34e4bec125696dd4b0fb1edf70..a062cf0b0a92f568f5cbb0dbba12af7fa3560210 100644
--- a/tangostationcontrol/tangostationcontrol/observation/observation_controller.py
+++ b/tangostationcontrol/tangostationcontrol/observation/observation_controller.py
@@ -8,7 +8,6 @@ from typing import Callable, Type
 from tango import DevFailed, Util, Database
 from tangostationcontrol.configuration import ObservationSettings
 from tangostationcontrol.observation.observation import Observation
-from tangostationcontrol.devices.observation_field import ObservationField
 
 logger = logging.getLogger()
 
@@ -133,6 +132,10 @@ class ObservationController(dict[int, Observation]):
     @staticmethod
     def _destroy_all_observation_field_devices():
         """Prevent any lingering observation field devices, remove all from database"""
+
+        # import here to avoid circular imports
+        from tangostationcontrol.devices.observation_field import ObservationField
+
         db = Database()
         devices = db.get_device_exported_for_class(ObservationField.__name__)
         for device in devices:
diff --git a/tangostationcontrol/tangostationcontrol/test/dummy_observation_settings.py b/tangostationcontrol/tangostationcontrol/test/dummy_observation_settings.py
index ab8a8c626cda8c8f734d39727be2c95a4b9b94c3..b0b1a2f29487e1443f1c066d556a8b890541ff0e 100644
--- a/tangostationcontrol/tangostationcontrol/test/dummy_observation_settings.py
+++ b/tangostationcontrol/tangostationcontrol/test/dummy_observation_settings.py
@@ -9,6 +9,8 @@ from tangostationcontrol.configuration import (
     Pointing,
     Sap,
     HBA,
+    SST,
+    XST,
 )
 
 SETTINGS_TWO_FIELDS = ObservationSettings(
@@ -60,6 +62,10 @@ SETTINGS_HBA_IMMEDIATE = ObservationSettings(
                 element_selection="GENERIC_201512",
             ),
             dithering=Dithering(enabled=True, power=-10, frequency=123000000),
+            SST=SST(subbands_calibrated=False),
+            XST=XST(
+                subbands=[1, 2, 3, 4, 5], subbands_step=5, integration_interval=1.0
+            ),
         ),
     ],
 )
diff --git a/tangostationcontrol/test/configuration/test_observation_field_settings.py b/tangostationcontrol/test/configuration/test_observation_field_settings.py
index 90b8aae33e9acbd09e51916fc13545b4076597d5..38f374851f32973f4030fd6839eeda97f272dfdc 100644
--- a/tangostationcontrol/test/configuration/test_observation_field_settings.py
+++ b/tangostationcontrol/test/configuration/test_observation_field_settings.py
@@ -5,19 +5,32 @@ import json
 
 from jsonschema.exceptions import ValidationError
 
-from tangostationcontrol.configuration import Pointing, ObservationFieldSettings, Sap
+from tangostationcontrol.configuration import (
+    Pointing,
+    ObservationFieldSettings,
+    Sap,
+    XST,
+)
 
 from test import base
 
 
 class TestObservationFieldSettings(base.TestCase):
-    def test_from_json(self):
-        sut = ObservationFieldSettings.from_json(
+    def test_xst_from_json_simple(self):
+        json_str = '{ "subbands": [1, 2, 3], "integration_interval": 1.0 }'
+        sut = XST.from_json(json_str)
+
+        # check whether converting back to JSON does not throw
+        _ = sut.to_json()
+
+    def test_from_json_simple(self):
+        json_str = (
             '{"observation_id": 3, "stop_time": "2012-04-23T18:25:43", '
             '"antenna_field": "HBA", '
             '"antenna_set": "ALL", "filter": "HBA_110_190",'
             '"SAPs": [{"subbands": [3, 2, 1], "pointing": {"angle1":1.2, "angle2": 2.1, "direction_type":"LMN"}}]}'
         )
+        sut = ObservationFieldSettings.from_json(json_str)
 
         self.assertEqual(sut.observation_id, 3)
         self.assertEqual(sut.stop_time, "2012-04-23T18:25:43")
@@ -25,18 +38,27 @@ class TestObservationFieldSettings(base.TestCase):
         self.assertEqual(sut.filter, "HBA_110_190")
         self.assertEqual(len(sut.SAPs), 1)
 
-        sut = ObservationFieldSettings.from_json(
+        # check whether converting back to JSON does not throw
+        _ = sut.to_json()
+
+    def test_from_json_hba(self):
+        json_str = (
             '{"observation_id": 3, "stop_time": "2012-04-23T18:25:43", '
             '"antenna_field": "HBA", '
             '"antenna_set": "ALL", "filter": "HBA_110_190",'
             '"SAPs": [{"subbands": [3, 2, 1], "pointing": {"angle1":1.2, "angle2": 2.1, "direction_type":"LMN"}}],'
             '"HBA": { "tile_beam": {"angle1":2.2, "angle2": 3.1, "direction_type":"MOON"} } }'
         )
+        sut = ObservationFieldSettings.from_json(json_str)
 
         self.assertEqual(sut.HBA.tile_beam.angle1, 2.2)
         self.assertEqual(sut.HBA.tile_beam.angle2, 3.1)
         self.assertEqual(sut.HBA.tile_beam.direction_type, "MOON")
 
+        # check whether converting back to JSON does not throw
+        _ = sut.to_json()
+
+    def test_from_json_first_beamlet(self):
         sut = ObservationFieldSettings.from_json(
             '{"observation_id": 3, "stop_time": "2012-04-23T18:25:43", '
             '"antenna_field": "HBA", '
@@ -47,6 +69,22 @@ class TestObservationFieldSettings(base.TestCase):
 
         self.assertEqual(sut.first_beamlet, 2)
 
+        # check whether converting back to JSON does not throw
+        _ = sut.to_json()
+
+    def test_from_json_statistics(self):
+        sut = ObservationFieldSettings.from_json(
+            '{"observation_id": 3, "stop_time": "2012-04-23T18:25:43", '
+            '"antenna_field": "HBA", '
+            '"antenna_set": "ALL", "filter": "HBA_110_190",'
+            '"SAPs": [{"subbands": [3, 2, 1], "pointing": {"angle1":1.2, "angle2": 2.1, "direction_type":"LMN"}}],'
+            '"HBA": {"tile_beam": {"angle1":1.2, "angle2": 2.1, "direction_type":"LMN"}},'
+            '"XST": { "subbands": [1, 2, 3], "integration_interval": 1.0 }}'
+        )
+
+        # check whether converting back to JSON does not throw
+        _ = sut.to_json()
+
     def test_from_json_type_missmatch(self):
         for json_str in [
             # observation_id