From 8c5a7b597b57a3dcd612f1d0bb95474acc797e2c Mon Sep 17 00:00:00 2001
From: Jan David Mol <mol@astron.nl>
Date: Wed, 16 Feb 2022 10:56:47 +0100
Subject: [PATCH] L2SS-624: Updated boot procedure in jupyter notebook test
 script

---
 jupyter-notebooks/test_template.ipynb         | 17 +-----
 .../tangostationcontrol/devices/apsct.py      | 25 ++++++++-
 .../tangostationcontrol/devices/apspu.py      | 22 ++++++++
 .../devices/lofar_device.py                   |  2 +-
 .../tangostationcontrol/devices/recv.py       | 26 +++++++++
 .../tangostationcontrol/devices/sdp/sdp.py    |  1 +
 .../tangostationcontrol/devices/sdp/sst.py    | 10 ++++
 .../devices/sdp/statistics.py                 |  4 ++
 .../tangostationcontrol/devices/sdp/xst.py    | 10 ++++
 .../tangostationcontrol/devices/unb2.py       | 56 ++++++++++++++++---
 10 files changed, 149 insertions(+), 24 deletions(-)

diff --git a/jupyter-notebooks/test_template.ipynb b/jupyter-notebooks/test_template.ipynb
index 9d3553517..136e4965f 100644
--- a/jupyter-notebooks/test_template.ipynb
+++ b/jupyter-notebooks/test_template.ipynb
@@ -119,24 +119,11 @@
    "id": "7532d05e",
    "metadata": {},
    "source": [
-    "### Hot reboot\n",
+    "### Reboot\n",
     "\n",
     "Makes sure the software and hardware are all in a known state."
    ]
   },
-  {
-   "cell_type": "code",
-   "execution_count": 1,
-   "id": "c7a3effa",
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "# Restart boot device\n",
-    "boot.off()\n",
-    "boot.initialise()\n",
-    "boot.on()"
-   ]
-  },
   {
    "cell_type": "code",
    "execution_count": 2,
@@ -145,7 +132,7 @@
    "outputs": [],
    "source": [
     "# Reboot the station\n",
-    "boot.boot()"
+    "boot.reboot()"
    ]
   },
   {
diff --git a/tangostationcontrol/tangostationcontrol/devices/apsct.py b/tangostationcontrol/tangostationcontrol/devices/apsct.py
index f75707676..20b161e97 100644
--- a/tangostationcontrol/tangostationcontrol/devices/apsct.py
+++ b/tangostationcontrol/tangostationcontrol/devices/apsct.py
@@ -79,7 +79,30 @@ class APSCT(opcua_device):
 
     def read_APSCT_error_R(self):
         return ((self.proxy.APSCTTR_I2C_error_R > 0)
-               | self.alarm_val("APSCT_PCB_ID_R"))
+               | self.alarm_val("APSCT_PCB_ID_R")
+               | ~self.proxy.APSCT_INPUT_10MHz_good_R
+               | (~self.proxy.APSCT_INPUT_PPS_good_R & ~self.proxy.ASPCT_PPS_ignore_R)
+               | (~self.proxy.APSCT_PLL_160MHz_locked_R & ~self.proxy.APSCT_PLL_200MHz_locked_R)
+               | (self.proxy.APSCT_PLL_200MHz_locked_R & self.proxy.APSCT_PLL_200MHz_error_R)
+               | (self.proxy.APSCT_PLL_160MHz_locked_R & self.proxy.APSCT_PLL_160MHz_error_R)
+               )
+
+    APSCT_TEMP_error_R            = attribute(dtype=bool)
+    APSCT_VOUT_error_R            = attribute(dtype=bool)
+
+    def read_APSCT_TEMP_error_R(self):
+        return (self.alarm_val("APSCT_TEMP_R"))
+
+    def read_APSCT_VOUT_error_R(self):
+        return ( self.alarm_val("APSCT_PWR_PPSDIST_3V3_R")
+               | self.alarm_val("APSCT_PWR_CLKDIST1_3V3_R")
+               | self.alarm_val("APSCT_PWR_CLKDIST2_3V3_R")
+               | self.alarm_val("APSCT_PWR_CTRL_3V3_R")
+               | self.alarm_val("APSCT_PWR_INPUT_3V3_R")
+               | (self.proxy.APSCT_PWR_PLL_160MHz_on_R & self.alarm_val("APSCT_PWR_PLL_160MHz_3V3_R"))
+               | (self.proxy.APSCT_PWR_PLL_200MHz_on_R & self.alarm_val("APSCT_PWR_PLL_200MHz_3V3_R"))
+               | ~self.proxy.APSCT_PWR_on_R
+               )
 
     # --------
     # overloaded functions
diff --git a/tangostationcontrol/tangostationcontrol/devices/apspu.py b/tangostationcontrol/tangostationcontrol/devices/apspu.py
index 44b58c25e..d014a0eae 100644
--- a/tangostationcontrol/tangostationcontrol/devices/apspu.py
+++ b/tangostationcontrol/tangostationcontrol/devices/apspu.py
@@ -72,6 +72,28 @@ class APSPU(opcua_device):
                | self.alarm_val("APSPU_FAN2_RPM_R") 
                | self.alarm_val("APSPU_FAN3_RPM_R"))
 
+    APSPU_IOUT_error_R          = attribute(dtype=bool)
+    APSPU_TEMP_error_R          = attribute(dtype=bool)
+    APSPU_VOUT_error_R          = attribute(dtype=bool)
+
+    def read_APSPU_IOUT_error_R(self):
+        return ( self.alarm_val("APSPU_LBA_IOUT_R")
+               | self.alarm_val("APSPU_RCU2A_IOUT_R")
+               | self.alarm_val("APSPU_RCU2D_IOUT_R")
+               )
+
+    def read_APSPU_TEMP_error_R(self):
+        return ( self.alarm_val("APSPU_LBA_TEMP_R")
+               | self.alarm_val("APSPU_RCU2A_TEMP_R")
+               | self.alarm_val("APSPU_RCU2D_TEMP_R")
+               )
+
+    def read_APSPU_VOUT_error_R(self):
+        return ( self.alarm_val("APSPU_LBA_VOUT_R")
+               | self.alarm_val("APSPU_RCU2A_VOUT_R")
+               | self.alarm_val("APSPU_RCU2D_VOUT_R")
+               )
+
     # --------
     # overloaded functions
     # --------
diff --git a/tangostationcontrol/tangostationcontrol/devices/lofar_device.py b/tangostationcontrol/tangostationcontrol/devices/lofar_device.py
index 9d68a5dec..745fa641d 100644
--- a/tangostationcontrol/tangostationcontrol/devices/lofar_device.py
+++ b/tangostationcontrol/tangostationcontrol/devices/lofar_device.py
@@ -266,7 +266,7 @@ class lofar_device(Device, metaclass=DeviceMeta):
         # This is just the command version of _initialise_hardware().
         self._initialise_hardware()
 
-    def _boot_device(self, initialise_hardware=True):
+    def _boot(self, initialise_hardware=True):
         # setup connections
         self.Initialise()
 
diff --git a/tangostationcontrol/tangostationcontrol/devices/recv.py b/tangostationcontrol/tangostationcontrol/devices/recv.py
index 965f27648..238764ae2 100644
--- a/tangostationcontrol/tangostationcontrol/devices/recv.py
+++ b/tangostationcontrol/tangostationcontrol/devices/recv.py
@@ -186,6 +186,32 @@ class RECV(opcua_device):
                  ~self.proxy.RCU_ADC_locked_R
                )
 
+    RECV_IOUT_error_R          = attribute(dtype=(bool,), max_dim_x=32)
+    RECV_TEMP_error_R          = attribute(dtype=(bool,), max_dim_x=32)
+    RECV_VOUT_error_R          = attribute(dtype=(bool,), max_dim_x=32)
+
+    def read_RECV_IOUT_error_R(self):
+        return self.proxy.ANT_mask_RW & (
+                 self.alarm_val("RCU_PWR_ANT_IOUT_R")
+               ).any(axis=1)
+
+    def read_RECV_TEMP_error_R(self):
+        return self.proxy.RCU_mask_RW & (
+                 self.alarm_val("RCU_TEMP_R")
+               )
+
+    def read_RECV_VOUT_error_R(self):
+        return (self.proxy.ANT_mask_RW & (
+                 self.alarm_val("RCU_PWR_ANT_VIN_R")
+               | self.alarm_val("RCU_PWR_ANT_VOUT_R")
+               ).any(axis=1) | (self.proxy.RCU_mask_RW & (
+                 self.alarm_val("RCU_PWR_1V8_R")
+               | self.alarm_val("RCU_PWR_2V5_R")
+               | self.alarm_val("RCU_PWR_3V3_R")
+               | ~self.proxy.RCU_PWR_DIGITAL_on_R
+               | ~self.proxy.RCU_PWR_good_R
+               )))
+
     # --------
     # overloaded functions
     # --------
diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py b/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py
index 275d8fe8a..2337b0142 100644
--- a/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py
+++ b/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py
@@ -214,6 +214,7 @@ class SDP(opcua_device):
     def read_FPGA_error_R(self):
         return self.proxy.TR_fpga_mask_RW & (
                  self.proxy.TR_fpga_communication_error_R
+               | self.alarm_val(self.proxy.FPGA_jesd204b_csr_dev_syncn_R).any(axis=1)
                )
 
     def read_FPGA_processing_error_R(self):
diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/sst.py b/tangostationcontrol/tangostationcontrol/devices/sdp/sst.py
index 889f38ba2..f541f8108 100644
--- a/tangostationcontrol/tangostationcontrol/devices/sdp/sst.py
+++ b/tangostationcontrol/tangostationcontrol/devices/sdp/sst.py
@@ -104,6 +104,16 @@ class SST(Statistics):
     # whether the subband data was calibrated by the SDP (that is, were subband weights applied)
     subbands_calibrated_R   = attribute_wrapper(comms_id=StatisticsClient, comms_annotation={"type": "statistics", "parameter": "subbands_calibrated"}, dims=(SSTCollector.MAX_INPUTS,), datatype=numpy.bool_)
 
+    # ----------
+    # Summarising Attributes
+    # ----------
+    FPGA_processing_error_R      = attribute(dtype=(bool,), max_dim_x=16)
+
+    def read_FPGA_processing_error_R(self):
+        return self.sdp_proxy.TR_fpga_mask_RW & (
+                 ~self.proxy.FPGA_sst_offload_enable_R
+               )
+
     # --------
     # Overloaded functions
     # --------
diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/statistics.py b/tangostationcontrol/tangostationcontrol/devices/sdp/statistics.py
index 21286acd4..0e96366bc 100644
--- a/tangostationcontrol/tangostationcontrol/devices/sdp/statistics.py
+++ b/tangostationcontrol/tangostationcontrol/devices/sdp/statistics.py
@@ -13,6 +13,7 @@
 
 # PyTango imports
 from tango.server import device_property
+from tango import DeviceProxy
 
 # Additional import
 import asyncio
@@ -123,6 +124,9 @@ class Statistics(opcua_device):
         future = asyncio.run_coroutine_threadsafe(self._connect_statistics(), self.statistics_client.event_loop)
         _ = future.result()
 
+        # proxy the SDP device in case we need the FPGA mask
+        self.sdp_proxy = DeviceProxy("STAT/SDP/1")
+
     async def _connect_statistics(self):
         # map an access helper class
         for i in self.attr_list():
diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/xst.py b/tangostationcontrol/tangostationcontrol/devices/sdp/xst.py
index 3b0f59d24..89da8dddc 100644
--- a/tangostationcontrol/tangostationcontrol/devices/sdp/xst.py
+++ b/tangostationcontrol/tangostationcontrol/devices/sdp/xst.py
@@ -144,6 +144,16 @@ class XST(Statistics):
     def read_xst_phase_R(self):
         return numpy.angle(self.statistics_client.collector.xst_values())
 
+    # ----------
+    # Summarising Attributes
+    # ----------
+    FPGA_processing_error_R      = attribute(dtype=(bool,), max_dim_x=16)
+
+    def read_FPGA_processing_error_R(self):
+        return self.sdp_proxy.TR_fpga_mask_RW & (
+                 ~self.proxy.FPGA_xst_offload_enable_R
+               )
+
     # --------
     # Overloaded functions
     # --------
diff --git a/tangostationcontrol/tangostationcontrol/devices/unb2.py b/tangostationcontrol/tangostationcontrol/devices/unb2.py
index de7f73658..d172c8ddc 100644
--- a/tangostationcontrol/tangostationcontrol/devices/unb2.py
+++ b/tangostationcontrol/tangostationcontrol/devices/unb2.py
@@ -123,24 +123,66 @@ class UNB2(opcua_device):
     # Summarising Attributes
     # ----------
     UNB2_error_R                  = attribute(dtype=(bool,), max_dim_x=2)
-    UNB2_FPGA_error_R             = attribute(dtype=((bool,),), max_dim_x=4, max_dim_y=2)
-    UNB2_QSFP_error_R             = attribute(dtype=((bool,),), max_dim_x=24, max_dim_y=2)
 
     def read_UNB2_error_R(self):
         return self.proxy.UNB2_mask_RW & (
                  (self.proxy.UNB2TR_I2C_bus_error_R > 0)
                | self.alarm_val("UNB2_PCB_ID_R")
+               | (self.proxy.UNB2TR_I2C_bus_DDR4_error_R > 0).any(axis=1)
+               | (self.proxy.UNB2TR_I2C_bus_FPGA_PS_error_R > 0).any(axis=1)
+               | (self.proxy.UNB2TR_I2C_bus_QSFP_error_R > 0).any(axis=1)
                )
 
-    def read_UNB2_FPGA_error_R(self):
+    UNB2_IOUT_error_R          = attribute(dtype=(bool,), max_dim_x=2)
+    UNB2_TEMP_error_R          = attribute(dtype=(bool,), max_dim_x=2)
+    UNB2_VOUT_error_R          = attribute(dtype=(bool,), max_dim_x=2)
+
+    def read_UNB2_IOUT_error_R(self):
+        return self.proxy.UNB2_mask_RW & (
+                 self.alarm_val("UNB2_DC_DC_48V_12V_IOUT_R")
+               | self.alarm_val("UNB2_FPGA_POL_CORE_IOUT_R").any(axis=1)
+               | self.alarm_val("UNB2_FPGA_POL_ERAM_IOUT_R").any(axis=1)
+               | self.alarm_val("UNB2_FPGA_POL_HGXB_IOUT_R").any(axis=1)
+               | self.alarm_val("UNB2_FPGA_POL_PGM_IOUT_R").any(axis=1)
+               | self.alarm_val("UNB2_FPGA_POL_RXGXB_IOUT_R").any(axis=1)
+               | self.alarm_val("UNB2_FPGA_POL_TXGXB_IOUT_R").any(axis=1)
+               | self.alarm_val("UNB2_POL_CLOCK_IOUT_R")
+               | self.alarm_val("UNB2_POL_QSFP_N01_IOUT_R")
+               | self.alarm_val("UNB2_POL_QSFP_N23_IOUT_R")
+               | self.alarm_val("UNB2_POL_SWITCH_1V2_IOUT_R")
+               | self.alarm_val("UNB2_POL_SWITCH_PHY_IOUT_R")
+               )
+
+    def read_UNB2_TEMP_error_R(self):
         return self.proxy.UNB2_mask_RW & (
-                 (self.proxy.UNB2TR_I2C_bus_DDR4_error_R > 0)
-               | (self.proxy.UNB2TR_I2C_bus_FPGA_PS_error_R > 0)
+                 self.alarm_val("UNB2_DC_DC_48V_12V_TEMP_R")
+               | self.alarm_val("UNB2_FPGA_POL_CORE_TEMP_R").any(axis=1)
+               | self.alarm_val("UNB2_FPGA_POL_ERAM_TEMP_R").any(axis=1)
+               | self.alarm_val("UNB2_FPGA_POL_HGXB_TEMP_R").any(axis=1)
+               | self.alarm_val("UNB2_FPGA_POL_PGM_TEMP_R").any(axis=1)
+               | self.alarm_val("UNB2_FPGA_POL_RXGXB_TEMP_R").any(axis=1)
+               | self.alarm_val("UNB2_FPGA_POL_TXGXB_TEMP_R").any(axis=1)
+               | self.alarm_val("UNB2_POL_CLOCK_TEMP_R")
+               | self.alarm_val("UNB2_POL_QSFP_N01_TEMP_R")
+               | self.alarm_val("UNB2_POL_QSFP_N23_TEMP_R")
+               | self.alarm_val("UNB2_POL_SWITCH_1V2_TEMP_R")
+               | self.alarm_val("UNB2_POL_SWITCH_PHY_TEMP_R")
                )
 
-    def read_UNB2_QSFP_error_R(self):
+    def read_UNB2_VOUT_error_R(self):
         return self.proxy.UNB2_mask_RW & (
-                 (self.proxy.UNB2TR_I2C_bus_QSFP_error_R > 0)
+                 self.alarm_val("UNB2_DC_DC_48V_12V_VOUT_R")
+               | self.alarm_val("UNB2_FPGA_POL_CORE_VOUT_R").any(axis=1)
+               | self.alarm_val("UNB2_FPGA_POL_ERAM_VOUT_R").any(axis=1)
+               | self.alarm_val("UNB2_FPGA_POL_HGXB_VOUT_R").any(axis=1)
+               | self.alarm_val("UNB2_FPGA_POL_PGM_VOUT_R").any(axis=1)
+               | self.alarm_val("UNB2_FPGA_POL_RXGXB_VOUT_R").any(axis=1)
+               | self.alarm_val("UNB2_FPGA_POL_TXGXB_VOUT_R").any(axis=1)
+               | self.alarm_val("UNB2_POL_CLOCK_VOUT_R")
+               | self.alarm_val("UNB2_POL_QSFP_N01_VOUT_R")
+               | self.alarm_val("UNB2_POL_QSFP_N23_VOUT_R")
+               | self.alarm_val("UNB2_POL_SWITCH_1V2_VOUT_R")
+               | self.alarm_val("UNB2_POL_SWITCH_PHY_VOUT_R")
                )
 
     # --------
-- 
GitLab