Skip to content
Snippets Groups Projects
Commit cb1dbe66 authored by Jan David Mol's avatar Jan David Mol
Browse files

L2SS-1006: Move Antenna_Type as a property of AntennaField instead of SDP

parent f37b0999
No related branches found
No related tags found
1 merge request!451Draft: Move configuration about to implement calibration
...@@ -147,6 +147,9 @@ ...@@ -147,6 +147,9 @@
"AntennaField": { "AntennaField": {
"STAT/AntennaField/1": { "STAT/AntennaField/1": {
"properties": { "properties": {
"Antenna_Type": [
"HBA"
],
"RECV_devices": [ "RECV_devices": [
"STAT/RECV/1" "STAT/RECV/1"
], ],
......
...@@ -172,6 +172,9 @@ ...@@ -172,6 +172,9 @@
"AntennaField": { "AntennaField": {
"STAT/AntennaField/2": { "STAT/AntennaField/2": {
"properties": { "properties": {
"Antenna_Type": [
"HBA"
],
"RECV_devices": [ "RECV_devices": [
"STAT/RECV/1" "STAT/RECV/1"
], ],
...@@ -229,6 +232,9 @@ ...@@ -229,6 +232,9 @@
}, },
"STAT/AntennaField/1": { "STAT/AntennaField/1": {
"properties": { "properties": {
"Antenna_Type": [
"LBA"
],
"RECV_devices": [ "RECV_devices": [
"STAT/RECV/1" "STAT/RECV/1"
], ],
...@@ -344,9 +350,6 @@ ...@@ -344,9 +350,6 @@
"SDP": { "SDP": {
"STAT/SDP/1": { "STAT/SDP/1": {
"properties": { "properties": {
"AntennaType": [
"LBA"
],
"OPC_Server_Name": [ "OPC_Server_Name": [
"10.99.0.250" "10.99.0.250"
], ],
......
...@@ -117,6 +117,13 @@ class AntennaField(lofar_device): ...@@ -117,6 +117,13 @@ class AntennaField(lofar_device):
# ----- Antenna properties # ----- Antenna properties
Antenna_Type = device_property(
doc="Type of antenna in this field (LBA or HBA)",
dtype='DevString',
mandatory=False,
default_value = "LBA"
)
Antenna_Needs_Power = device_property( Antenna_Needs_Power = device_property(
doc="Whether to provide power to each antenna (False for noise sources)", doc="Whether to provide power to each antenna (False for noise sources)",
dtype='DevVarBooleanArray', dtype='DevVarBooleanArray',
...@@ -225,6 +232,9 @@ class AntennaField(lofar_device): ...@@ -225,6 +232,9 @@ class AntennaField(lofar_device):
default_value = [] default_value = []
) )
Antenna_Type_R = attribute(doc='The type of antenna in this field (LBA or HBA).',
dtype=str)
Antenna_Names_R = attribute(access=AttrWriteType.READ, Antenna_Names_R = attribute(access=AttrWriteType.READ,
dtype=(str,), max_dim_x=MAX_NUMBER_OF_HBAT) dtype=(str,), max_dim_x=MAX_NUMBER_OF_HBAT)
Antenna_Quality_R = attribute(doc='The quality of each antenna. 0=OK, 1=SUSPICIOUS, 2=BROKEN, 3=BEYOND_REPAIR.', Antenna_Quality_R = attribute(doc='The quality of each antenna. 0=OK, 1=SUSPICIOUS, 2=BROKEN, 3=BEYOND_REPAIR.',
...@@ -289,6 +299,9 @@ class AntennaField(lofar_device): ...@@ -289,6 +299,9 @@ class AntennaField(lofar_device):
doc='Number of Antennas in this field', doc='Number of Antennas in this field',
dtype=numpy.int32) dtype=numpy.int32)
def read_Antenna_Type_R(self):
return self.Antenna_Type
def read_Antenna_Names_R(self): def read_Antenna_Names_R(self):
return self.Antenna_Names return self.Antenna_Names
...@@ -451,6 +464,10 @@ class AntennaField(lofar_device): ...@@ -451,6 +464,10 @@ class AntennaField(lofar_device):
def _prepare_hardware(self): def _prepare_hardware(self):
usage_mask = self.read_attribute('Antenna_Usage_Mask_R') usage_mask = self.read_attribute('Antenna_Usage_Mask_R')
# -----------------------------------------------------------
# Configure RECV
# -----------------------------------------------------------
# Disable controlling the tiles that fall outside the mask # Disable controlling the tiles that fall outside the mask
# WARN: Needed in configure_for_initialise but Tango does not allow to write attributes in INIT state # WARN: Needed in configure_for_initialise but Tango does not allow to write attributes in INIT state
self.proxy.write_attribute('ANT_mask_RW', self.read_attribute('Antenna_Usage_Mask_R')) self.proxy.write_attribute('ANT_mask_RW', self.read_attribute('Antenna_Usage_Mask_R'))
...@@ -458,9 +475,31 @@ class AntennaField(lofar_device): ...@@ -458,9 +475,31 @@ class AntennaField(lofar_device):
# Turn on power to antennas that need it (and due to the ANT_mask, that we're using) # Turn on power to antennas that need it (and due to the ANT_mask, that we're using)
self.proxy.write_attribute('RCU_PWR_ANT_on_RW', self.Antenna_Needs_Power) self.proxy.write_attribute('RCU_PWR_ANT_on_RW', self.Antenna_Needs_Power)
# -----------------------------------------------------------
# Configure SDP
# -----------------------------------------------------------
self.configure_sdp()
# -------- # --------
# Commands # Commands
# -------- # --------
@command()
def configure_sdp(self):
""" Configure SDP to process our antennas. """
# upload which antenna type we're using
# read-modify-write on [fpga][(input, polarisation)]
sdp_antenna_type = self.sdp_proxy.antenna_type_RW
for fpga_nr, input_nr in self.read_attribute("Antenna_to_SDP_Mapping_R"):
# set for x polarisation
sdp_antenna_type[fpga_nr, input_nr * 2 + 0] = self.Antenna_Type
# set for y polarisation
sdp_antenna_type[fpga_nr, input_nr * 2 + 1] = self.Antenna_Type
self.sdp_proxy.antenna_type_RW = sdp_antenna_type
@command(dtype_in=DevVarFloatArray, dtype_out=DevVarLongArray) @command(dtype_in=DevVarFloatArray, dtype_out=DevVarLongArray)
def calculate_HBAT_bf_delay_steps(self, delays: numpy.ndarray): def calculate_HBAT_bf_delay_steps(self, delays: numpy.ndarray):
num_tiles = self.read_nr_antennas_R() num_tiles = self.read_nr_antennas_R()
......
...@@ -32,13 +32,6 @@ class SDP(opcua_device): ...@@ -32,13 +32,6 @@ class SDP(opcua_device):
# Device Properties # Device Properties
# ----------------- # -----------------
AntennaType = device_property(
doc='Antenna type (LBA or HBA) we control',
dtype='DevString',
mandatory=False,
default_value = "HBA"
)
TR_fpga_mask_RW_default = device_property( TR_fpga_mask_RW_default = device_property(
dtype='DevVarBooleanArray', dtype='DevVarBooleanArray',
mandatory=False, mandatory=False,
...@@ -186,8 +179,9 @@ class SDP(opcua_device): ...@@ -186,8 +179,9 @@ class SDP(opcua_device):
FPGA_bst_offload_bsn_R = attribute_wrapper(comms_annotation=["FPGA_bst_offload_bsn_R"], datatype=numpy.int64, dims=(N_pn, N_beamsets_ctrl)) FPGA_bst_offload_bsn_R = attribute_wrapper(comms_annotation=["FPGA_bst_offload_bsn_R"], datatype=numpy.int64, dims=(N_pn, N_beamsets_ctrl))
antenna_type_R = attribute(doc='Type of antenna (LBA or HBA) attached to the FPGAs', antenna_type_RW = attribute(doc='Type of antenna (LBA or HBA) attached to each input of the FPGAs',
dtype=str, fget=lambda self: self.AntennaType) dtype=(str,), max_dim_y=N_pn, max_dim_x=S_pn,
access=AttrWriteType.READ_WRITE, fisallowed="is_attribute_access_allowed")
nyquist_zone_R = attribute(doc='Nyquist zone of the input frequencies', nyquist_zone_R = attribute(doc='Nyquist zone of the input frequencies',
dtype=numpy.uint32, fisallowed="is_attribute_access_allowed", dtype=numpy.uint32, fisallowed="is_attribute_access_allowed",
polling_period=1000, abs_change=1) polling_period=1000, abs_change=1)
...@@ -195,6 +189,19 @@ class SDP(opcua_device): ...@@ -195,6 +189,19 @@ class SDP(opcua_device):
dtype=numpy.uint32, access=AttrWriteType.READ_WRITE, fisallowed="is_attribute_access_allowed", dtype=numpy.uint32, access=AttrWriteType.READ_WRITE, fisallowed="is_attribute_access_allowed",
polling_period=1000, abs_change=1) polling_period=1000, abs_change=1)
def read_antenna_type_RW(self):
return self._antenna_type
def write_antenna_type_RW(self, value):
if value.shape != (self.N_pn, self.S_pn):
raise ValueError(f"Dimension mismatch. Expected ({self.N_pn}, {self.S_pn}), got {value.shape}.")
for val in value.flatten():
if val not in ["LBA", "HBA"]:
raise ValueError(f"Unsupported antenna type: {val}. Must be one of [LBA, HBA].")
self._antenna_type = value
def _nyquist_zone(self, clock): def _nyquist_zone(self, clock):
""" Return the Nyquist zone for the given clock (in Hz). """ Return the Nyquist zone for the given clock (in Hz).
...@@ -212,7 +219,8 @@ class SDP(opcua_device): ...@@ -212,7 +219,8 @@ class SDP(opcua_device):
} }
try: try:
return nyquist_zones[(self.AntennaType), clock // 1000000] # support only one AntennaType for now. TODO: expose nyquist zones as an array
return nyquist_zones[(self._antenna_type[0][0], clock // 1000000)]
except KeyError: except KeyError:
raise ValueError(f"Could not determine Nyquist zone for antenna type {self.AntennaType} with clock {clock} Hz") raise ValueError(f"Could not determine Nyquist zone for antenna type {self.AntennaType} with clock {clock} Hz")
...@@ -274,6 +282,14 @@ class SDP(opcua_device): ...@@ -274,6 +282,14 @@ class SDP(opcua_device):
# overloaded functions # overloaded functions
# -------- # --------
def configure_for_initialise(self):
super().configure_for_initialise()
# Store which type of antenna is connected to each input.
#
# We need to be told this by AntennaField, through configure_for_antennafield.
self._antenna_type = numpy.array([["???"] * self.S_pn] * self.N_pn, dtype=str)
def _prepare_hardware(self): def _prepare_hardware(self):
# FPGAs that are actually reachable and we care about # FPGAs that are actually reachable and we care about
wait_for = ~(self.read_attribute("TR_fpga_communication_error_R")) & self.read_attribute("TR_fpga_mask_R") wait_for = ~(self.read_attribute("TR_fpga_communication_error_R")) & self.read_attribute("TR_fpga_mask_R")
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment