From dccaed0112e41a6f4c5d3996c90d5ef2730ce919 Mon Sep 17 00:00:00 2001
From: Arno Schoenmakers <schoenmakers@astron.nl>
Date: Tue, 27 Jan 2009 15:09:26 +0000
Subject: [PATCH] Bug 1319: Moved MAC/Test/Station to StationTest

---
 .gitattributes                      |   45 +
 StationTest/Makefile.am             |   23 +
 StationTest/README.txt              |  303 +++++++
 StationTest/bootstrap               |    3 +
 StationTest/configure.in            |   12 +
 StationTest/gold/Makefile.am        |    9 +
 StationTest/gold/prbs_dir_test.gold |   68 ++
 StationTest/gold/rsp_version.gold   |    4 +
 StationTest/gold/tbb_version.gold   |   11 +
 StationTest/gold/xst.m              |   29 +
 StationTest/gold/xst_160.gold       |  Bin 0 -> 16384 bytes
 StationTest/gold/xst_200_even.gold  |  Bin 0 -> 16384 bytes
 StationTest/gold/xst_200_odd.gold   |  Bin 0 -> 16384 bytes
 StationTest/i2c_spu.py              |   64 ++
 StationTest/i2c_td.py               |   54 ++
 StationTest/modules/Makefile.am     |    9 +
 StationTest/modules/cli.py          |   14 +
 StationTest/modules/mep.py          |  366 ++++++++
 StationTest/modules/rsp.py          | 1280 +++++++++++++++++++++++++++
 StationTest/modules/smbus.py        |  281 ++++++
 StationTest/modules/testcase.py     |   72 ++
 StationTest/modules/testlog.py      |   69 ++
 StationTest/prbs_dir_test.py        |  114 +++
 StationTest/prbs_test.py            |  103 +++
 StationTest/rmfiles.sh              |    7 +
 StationTest/rsp_version.sh          |   16 +
 StationTest/rsp_xc_160.sh           |   11 +
 StationTest/rsp_xc_200.sh           |   11 +
 StationTest/station_production.py   |  191 ++++
 StationTest/subrack_production.py   |  170 ++++
 StationTest/subracktest.sh          |   29 +
 StationTest/tbb_prbs_tester.sh      |   48 +
 StationTest/tbb_version.sh          |   16 +
 StationTest/tc/Makefile.am          |   15 +
 StationTest/tc/bist.py              |  146 +++
 StationTest/tc/empty.py             |    2 +
 StationTest/tc/hba_client.py        |  167 ++++
 StationTest/tc/hba_server.py        |  337 +++++++
 StationTest/tc/prsg.py              |  150 ++++
 StationTest/tc/rad_lanemode.py      |   35 +
 StationTest/tc/rad_latency.py       |   21 +
 StationTest/tc/serdes.py            |  187 ++++
 StationTest/tc/spustat.py           |  102 +++
 StationTest/tc/status.py            |   57 ++
 StationTest/tc/sync_delay.py        |   37 +
 StationTest/tc/tdstat.py            |   95 ++
 StationTest/verify.py               |  188 ++++
 StationTest/xc_160_setup.sh         |   24 +
 StationTest/xc_160_verify.sh        |   25 +
 StationTest/xc_200_setup.sh         |   24 +
 StationTest/xc_200_verify.sh        |   31 +
 51 files changed, 5075 insertions(+)
 create mode 100644 StationTest/Makefile.am
 create mode 100644 StationTest/README.txt
 create mode 100755 StationTest/bootstrap
 create mode 100644 StationTest/configure.in
 create mode 100644 StationTest/gold/Makefile.am
 create mode 100644 StationTest/gold/prbs_dir_test.gold
 create mode 100644 StationTest/gold/rsp_version.gold
 create mode 100644 StationTest/gold/tbb_version.gold
 create mode 100644 StationTest/gold/xst.m
 create mode 100644 StationTest/gold/xst_160.gold
 create mode 100644 StationTest/gold/xst_200_even.gold
 create mode 100644 StationTest/gold/xst_200_odd.gold
 create mode 100644 StationTest/i2c_spu.py
 create mode 100644 StationTest/i2c_td.py
 create mode 100644 StationTest/modules/Makefile.am
 create mode 100644 StationTest/modules/cli.py
 create mode 100644 StationTest/modules/mep.py
 create mode 100644 StationTest/modules/rsp.py
 create mode 100644 StationTest/modules/smbus.py
 create mode 100644 StationTest/modules/testcase.py
 create mode 100644 StationTest/modules/testlog.py
 create mode 100644 StationTest/prbs_dir_test.py
 create mode 100644 StationTest/prbs_test.py
 create mode 100644 StationTest/rmfiles.sh
 create mode 100644 StationTest/rsp_version.sh
 create mode 100644 StationTest/rsp_xc_160.sh
 create mode 100644 StationTest/rsp_xc_200.sh
 create mode 100644 StationTest/station_production.py
 create mode 100644 StationTest/subrack_production.py
 create mode 100644 StationTest/subracktest.sh
 create mode 100644 StationTest/tbb_prbs_tester.sh
 create mode 100644 StationTest/tbb_version.sh
 create mode 100644 StationTest/tc/Makefile.am
 create mode 100644 StationTest/tc/bist.py
 create mode 100644 StationTest/tc/empty.py
 create mode 100644 StationTest/tc/hba_client.py
 create mode 100644 StationTest/tc/hba_server.py
 create mode 100644 StationTest/tc/prsg.py
 create mode 100644 StationTest/tc/rad_lanemode.py
 create mode 100644 StationTest/tc/rad_latency.py
 create mode 100644 StationTest/tc/serdes.py
 create mode 100644 StationTest/tc/spustat.py
 create mode 100644 StationTest/tc/status.py
 create mode 100644 StationTest/tc/sync_delay.py
 create mode 100644 StationTest/tc/tdstat.py
 create mode 100644 StationTest/verify.py
 create mode 100644 StationTest/xc_160_setup.sh
 create mode 100644 StationTest/xc_160_verify.sh
 create mode 100644 StationTest/xc_200_setup.sh
 create mode 100644 StationTest/xc_200_verify.sh

diff --git a/.gitattributes b/.gitattributes
index f4f68e0047e..90e8ece855f 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1149,6 +1149,51 @@ SHM/Components/WebInterface/testing/djstart/playpen/urls.py -text
 SHM/apache_config/httpd.conf -text
 SHM/apache_config/sites-enabled/001-shmprod -text
 SHM/apache_config/sites-enabled/002-shmdev -text
+StationTest/README.txt -text
+StationTest/bootstrap -text
+StationTest/gold/prbs_dir_test.gold -text
+StationTest/gold/rsp_version.gold -text
+StationTest/gold/tbb_version.gold -text
+StationTest/gold/xst.m -text
+StationTest/gold/xst_160.gold -text
+StationTest/gold/xst_200_even.gold -text
+StationTest/gold/xst_200_odd.gold -text
+StationTest/i2c_spu.py -text
+StationTest/i2c_td.py -text
+StationTest/modules/cli.py -text
+StationTest/modules/mep.py -text
+StationTest/modules/rsp.py -text
+StationTest/modules/smbus.py -text
+StationTest/modules/testcase.py -text
+StationTest/modules/testlog.py -text
+StationTest/prbs_dir_test.py -text
+StationTest/prbs_test.py -text
+StationTest/rmfiles.sh -text
+StationTest/rsp_version.sh -text
+StationTest/rsp_xc_160.sh -text
+StationTest/rsp_xc_200.sh -text
+StationTest/station_production.py -text
+StationTest/subrack_production.py -text
+StationTest/subracktest.sh -text
+StationTest/tbb_prbs_tester.sh -text
+StationTest/tbb_version.sh -text
+StationTest/tc/bist.py -text
+StationTest/tc/empty.py -text
+StationTest/tc/hba_client.py -text
+StationTest/tc/hba_server.py -text
+StationTest/tc/prsg.py -text
+StationTest/tc/rad_lanemode.py -text
+StationTest/tc/rad_latency.py -text
+StationTest/tc/serdes.py -text
+StationTest/tc/spustat.py -text
+StationTest/tc/status.py -text
+StationTest/tc/sync_delay.py -text
+StationTest/tc/tdstat.py -text
+StationTest/verify.py -text
+StationTest/xc_160_setup.sh -text
+StationTest/xc_160_verify.sh -text
+StationTest/xc_200_setup.sh -text
+StationTest/xc_200_verify.sh -text
 SubSystems/CEPCU_MAC/lofarconf.in -text
 SubSystems/LCU_MAC/lofarconf.in -text
 SubSystems/MCU_MAC/lofarconf.in -text
diff --git a/StationTest/Makefile.am b/StationTest/Makefile.am
new file mode 100644
index 00000000000..4c094293917
--- /dev/null
+++ b/StationTest/Makefile.am
@@ -0,0 +1,23 @@
+SUBDIRS = modules gold tc
+
+testdir		 =  $(prefix)/stationtest
+test_SCRIPTS = 	README.txt \
+				i2c_spu.py \
+				i2c_td.py \
+				prbs_dir_test.py \
+				prbs_test.py \
+				rmfiles.sh \
+				rsp_version.sh \
+				rsp_xc_160.sh \
+				rsp_xc_200.sh \
+				subrack_production.py \
+				subracktest.sh \
+				tbb_prbs_tester.sh \
+				tbb_version.sh \
+				verify.py \
+				xc_160_setup.sh \
+				xc_160_verify.sh \
+				xc_200_setup.sh \
+				xc_200_verify.sh 
+
+include $(top_srcdir)/Makefile.common
diff --git a/StationTest/README.txt b/StationTest/README.txt
new file mode 100644
index 00000000000..fd5eb2f8951
--- /dev/null
+++ b/StationTest/README.txt
@@ -0,0 +1,303 @@
+#
+# Test scripts for LOFAR station regression, production and operation tests.
+#
+#  2 sep 2008  Eric Kooistra  First working test environment.
+# 31 oct 2008  Eric kooistra  More readme info.
+#                             Added subrack_production.py, smbus.py, spustat.py,
+#                             tdstat.py, hba_client.py, hba_server.py
+#
+
+################################################################################
+1) Introduction
+
+a) Purpose
+This test suite uses scripts that call rsptcl and tbbctl to control a LOFAR
+station. Most scripts are written in Python. The test suite offers modules
+written in Python that allow easy access to rspctl and tbbctl, and that offer
+pass/fail handling and logging. The test scripts allow focussing on a typical
+function or interface of the station, therefore they can be used for:
+
+- regression tests (e.g. functional coverage tests)
+- production tests (e.g. chip interface, board interface tests)
+- stress tests (e.g. many HBA write, read accesses)
+- operation sanity tests
+
+b) Why Python?
+For tool interfacing TCL is the common script language, that is why the VHDL
+developent using Modelsim uses TCL scripts. The problem with the remote station
+TCL scripts is that they run under Windows using WinPCap to interface with the
+Ethernet card. TCL is platform independent, but there is no easy equivalent for
+WinPCAP under Linux. Hence it is not straigthforward to run the TCL testcases
+environment also under Linux on the LCU.
+Instead of using something like WinPCap the low level register access functions
+--readblock and --writeblock were added to rspctl . This allows controlling the
+RSP board via scripts.
+Python was choosen as test script language, because it is a popular script
+language and adopted at various levels within the LOFAR software development,
+including operations. Based on my experience in translating TCL scripts into
+Python equivalents I think that Python is a more natural and nicer language than
+TCL.
+
+
+################################################################################
+2) Test setup
+
+a) Directory structure
+  ./ : README.txt, Python scripts, bash scripts. Run from this directory.
+  modules/ : Python modules
+  gold/ : Golden result files for corresponding scripts, 'diff *.log *.gold'
+          should yield no difference for the test to pass
+  tc/ : Testcase scripts to be used with verify.py
+  
+b) This test suite uses different types of test scripting:
+
+  - Testcase Python scripts in tc/ called via verify.py
+    . e.g.: tc/status.py, tc/bist.py, tc/prsg.py
+    . verify.py offers argument parsing, test result logging
+    . Resembles TCL testcase structure used for gateware development tests
+    . Most scripts in tc/ are direct (manual) translations of the TCL test
+      scripts that were used for the gateware (VHDL) development, see
+      LOFAR-ASTRON-MEM-186. The Python / rspctl test scripts run rather slow,
+      about a factor 2 slower than a comparable TCL / C test script.
+  - Stand alone Python scripts
+    . e.g.: python i2c_spy.py
+    . suitable for simple tests without argument passing
+  - BASH shell scripts
+    . e.g.: ./rsp_version.sh
+  
+  All these individual test scripts can be combined:
+  . e.g. for production test, regression test
+  . e.g. subracktest.sh
+   
+c) Environment setting
+
+  The scripts run from ./ The search path needs to be set:
+    export PYTHONPATH=./modules
+  or absolute path
+    export PYTHONPATH=/home/lofartest/ptest/modules
+  or to add the path
+    export PYTHONPATH=$PYTHONPATH:./modules
+  or on older systems
+    PYTHONPATH=$PYTHONPATH:./modules
+    export PYTHONPATH
+      
+  If rspctl is called then there must be a directory ../log/ for rspctl.log.
+  This ../log/ can be a symbolic link.
+  
+
+d) RSPDriver.conf
+
+To allow the 'rspctl --readblock' and 'rspctl --writeblock' low level access
+commands the RSP driver in /opt/lofar/etc/ must have:
+
+  RSPDriver.READ_RAW_DATA = 1
+  RSPDriver.WRITE_RAW_DATA = 1
+
+For tests that access the SPU or TDS, the RSP driver regular accesses via TDSH
+must be stopped via:
+
+  RSPDriver.READWRITE_TDSSTATUS=0
+
+
+################################################################################
+3) Test modules:
+
+cli.py      - Command line interface access
+verify.py   - Run one or more test scripts after parsing the arguments from the
+              command line
+testcase.py - Testcase pass/fail control, timing and logging for testcases that
+              run with verify.py
+testlog.py  - Similar to testcase.py, provides pass/fail control, timing and
+              logging for standalone test scripts like subrack_production.py
+mep.py      - MEP interface for RSP board access via 'rspctl --readblock/
+              rspctl --writeblock'
+rsp.py      - RSP board register access functions
+smbus.py    - SMBus (I2C) access functions
+
+
+Remarks:
+
+a) To see all script options (both general and test case specific) do:
+  
+  python verify.py --help
+
+   Remarks:
+   - via --brd a test can be ran for one RSP or multiple
+   - via --fpga a test can be ran on the BP, AP0, AP1, AP2, and/or AP3 in any
+     combination
+   - via --pol a test can be ran on RCU x and/or RCU y of the AP.
+   - There are 2 RCU per AP and 4 AP per RSP. In a station the RCUs are
+     numbered starting from 0. Hence e.g. RCU[64] = (rsp8, blp0, x) and
+     RCU[65] = (rsp8, blp0, y).
+  
+b) Classes:
+   - mep.py defines class MepMessage
+   - testcase.py defines class Testcase
+   - testlog.py defines class Testlog
+  The other modules cli.py, rsp.py and smbus.py define plain functions. Classes
+  are a nice way of grouping constants and functions to an object, for mep.py
+  the object it the message string that can be manipulated and access through
+  the class functions. Similar smbus.py could have been written as a class to
+  with the protocol_list and protocol_result as objects. I do not know what is
+  the best approach and why. With smbus.py as a plain set of functions it is 
+  also clear that the functions belong together, because they are called using
+  the module name as prefix.
+   
+c) The 'rspctl --readblock' and 'rspctl --writeblock' are quite slow, due to:
+   - the double buffering in the RSP driver
+   - maybe rspctl excepts only one access per pps interval
+   - the hex translations in mep.py to adhere to the format ot rspctl
+  For scripts that only use these low level peek and poke rsptcl commands it
+  would be a great improvement to have a dedicated driver program that takes 
+  care of these low level commands. This may be a driver program or some C
+  functions that can be used directly in Python. The scripts can then remain as
+  they are, only a different mep.py module needs to be added.
+   
+d) Some scripts also use higher level rspctl commands, e.g. to set the RCU in
+   PSRG mode.
+   
+e) Typically all RSP access goes via functions in rsp.py and smbus.py. Hence in
+   a test script it should never be necessary to call the low level rspctl
+   commands directly.
+   
+f) I tried to follow the Python documentation rules. For example to read the
+   documentation in the module rsp.py do:
+
+   python
+   >>> import rsp
+   >>> dir(rsp)
+   >>> print rsp.__doc__
+   >>> print rsp.write_mem.__doc__
+
+g) When command line options are needed I use the Python option parser. For the
+   test scripts all command line options need to be defined in testcase.py.
+   There are some general test script options (e.g. --brd) but there are also
+   test script specific options (e.g. --pid). The general testcase options are
+   passed on via the Testcase class, the specific options are passed on as
+   directly and all get prefix 'arg_' in verify.py to easily recognize them.
+   
+h) For logging I followed the logging approach that was used for the RSP test
+   environment written in TCL. Python also has modules for logging thay may be
+   useful in future.
+   
+   
+################################################################################
+4) Test scripts in tc/
+
+a) The testcases in tc/ are ran using verify.py. The test results are reported
+   to the screen and also stored in tc/ in a *.log file with the same name. The
+   ammount of logging depends on the verbosity level set by option -v.
+   
+   To run a testcase with verify.py in ./ do:
+
+  python verify.py --brd rsp0 --fp blp0 --te tc/prsg.py -v 21
+  
+   To run a testcase for one subrack with 4 RSP do:
+ 
+  python verify.py --brd rsp0,rsp1,rsp2,rsp3 --rep 1 -v 21 --te tc/serdes.py
+
+   To run a testcase for a station with three subracks, so 12 RSP do:
+
+  python verify.py --brd rsp0,rsp1,rsp2,rsp3,rsp4,rsp5,rsp6,rsp7,rsp8,rsp9,
+                         rsp10,rsp11 --te tc/serdes.py
+   
+  Remarks:
+  - The default option parameter values are defined in verify.py
+  - For options with multiple parameters the parameters must form one continuous
+    string seperated by commas's. 
+  
+b) The following test scripts are available in tc/, they are more or less plain,
+   manual translations from TCL test cases:
+
+  - empty.py   = empty, can be used to try verify.py
+  - prsg.py    = TC 5.10, capture RCU PSRG data
+  - serdes.py  = TC 3.8, serdes ring test
+  - status.py  = TC 11.1, read RSP status register
+  - spustat.py = TC 9.6, read SPU sensor status <=> 'rspctl --spustat'
+  - tdstat.py  = TC 9.1, read TD sensor status <=> 'rspctl --tdstat' 
+  - hba_client = TC 5.42, read or write to a HBA client register at the RCU
+  - hba_server = TC 5.43, read or write to a HBA server register at the tile
+
+c) 'rspctl --readblock' and 'rspctl --writeblock'
+
+  If available high level rspctl options are used to set up things, e.g. like
+  the PRSG on an RCU. For other low level board control use the direct access
+  '--readblock' and '--writeblock' options of rspctl. The modules mep.py and
+  rsp.py provide easy interfacing with theses options.
+  
+d) For help on the testcase usage and options do:
+
+  python verify.py --help
+
+e) To delete temporary files do:
+
+  ./rmfiles.sh
+  
+f) Verbosity level (-v)
+  The testcases all adhere to the following verbosity level convention:
+   
+  -v  0 : show PASSED or FAILED
+  -v  1 : show testcase title
+  -v  2 : show testcase time
+  -v 11 : show '... went wrong' for each step or section in a testcase, plus
+          some more info like expected result and read result
+  -v 21 : show '... went OK' for each step or section in a testcase
+  -v 22 : show rspctl commands
+  -v 23 : show rspctl command return results
+	   
+g) Pass/fail
+  Default a testcase run using verify.py/testcase.py (or using testlog.py) gets
+  pass/fail status 'RUNONLY'. This is useful for test scripts that are
+  utilities. If the testcase checks for expected results then it one of the it 
+  should first initialized the tc result to 'PASSED'. Subsequently each step in
+  the testcase that fails should also set the tc result to 'FAILED'. Once the
+  tc status is 'FAILED' it can not change anymore.
+   
+h) Test scripts and the RSP driver
+  The test scripts use rspctl. Some test scripts do not affect the functional
+  behaviour of the RSP driver, however many scripts do. Due to the slow and 
+  asynchronlous behaviour of teh test scripts it is often handy to disable the
+  external sync (pps). The scripts also enable the external sync again, but 
+  if that does not recover normal rspctl behaviour then it may be necessary to
+  do a 'rspctl --rspclear' or restart the RSP driver via swlevel 1, swlevel 2.
+   
+   
+################################################################################
+5) More examples
+
+a) HBA client access
+  To read the speed register of HBA client on RCU[65] do:
+   
+  python verify.py --brd rsp8 --fp blp0 --rep 1 -v 21 --te tc/hba_client.py
+                      --client_access r --client_reg speed --data 1
+
+  The test will only signal pass if the --data value equals the read speed
+  value, hence for read the --data option is used as expected result.
+
+b) HBA server access
+  To read the delay settings for polarization X and Y of HBA server 2 on the 
+  HBA tile of RCU[64]=X (power via X) and RCU[65]=Y (control via Y) do:
+  
+ python verify.py --brd rsp8 --fp blp0 --rep 1 -v 21 --te tc/hba_server.py
+                  --server 2 --server_access uc --server_function gw
+		  --server_reg delay_x --data 50,51
+
+
+################################################################################
+6) Standalone test scripts
+
+a) Subrack production tests
+
+The Python script subrack_production.py runs the subrack production test, it 
+requires a batch nr and a serial nr that will be used to name the log file.
+
+  python subrack_production.py --help
+  python subrack_production.py -b 3 -s 2
+
+This subrack_production.py replaces subracktest.sh.
+
+b) Various
+
+  i2c_spu.py = uses 'rspctl --spustat' to verify SPU sensor status
+  i2c_td.py  = uses 'rspctl --spustat' to verify TDS sensor status
+
diff --git a/StationTest/bootstrap b/StationTest/bootstrap
new file mode 100755
index 00000000000..06f18cde1db
--- /dev/null
+++ b/StationTest/bootstrap
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+../../../autoconf_share/bootstrap ../../../autoconf_share
diff --git a/StationTest/configure.in b/StationTest/configure.in
new file mode 100644
index 00000000000..4fcf2bda263
--- /dev/null
+++ b/StationTest/configure.in
@@ -0,0 +1,12 @@
+AC_INIT(README.txt)
+AM_CONFIG_HEADER(config.h)
+AM_INIT_AUTOMAKE(Station, 1.0, no-define)
+
+AC_PROG_LIBTOOL
+
+AC_OUTPUT(
+	Makefile
+	gold/Makefile
+	modules/Makefile
+	tc/Makefile
+)
diff --git a/StationTest/gold/Makefile.am b/StationTest/gold/Makefile.am
new file mode 100644
index 00000000000..46aa24695c7
--- /dev/null
+++ b/StationTest/gold/Makefile.am
@@ -0,0 +1,9 @@
+testdir		 =  $(prefix)/stationtest/gold
+test_SCRIPTS = 	prbs_dir_test.gold \
+				rsp_version.gold \
+				tbb_version.gold \
+				xst_160.gold \
+				xst_200_even.gold \
+				xst_200_odd.gold
+
+include $(top_srcdir)/Makefile.common
diff --git a/StationTest/gold/prbs_dir_test.gold b/StationTest/gold/prbs_dir_test.gold
new file mode 100644
index 00000000000..99aaecba653
--- /dev/null
+++ b/StationTest/gold/prbs_dir_test.gold
@@ -0,0 +1,68 @@
+
+ 
+ PRSB test 
+ 
+Frame nr 0 Station 1  RSP 0  RCU 0  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 0  RCU 1  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 0  RCU 2  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 0  RCU 3  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 0  RCU 4  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 0  RCU 5  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 0  RCU 6  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 0  RCU 7  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 1  RCU 8  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 1  RCU 9  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 1  RCU 10  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 1  RCU 11  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 1  RCU 12  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 1  RCU 13  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 1  RCU 14  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 1  RCU 15  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 2  RCU 16  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 2  RCU 17  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 2  RCU 18  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 2  RCU 19  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 2  RCU 20  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 2  RCU 21  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 2  RCU 22  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 2  RCU 23  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 3  RCU 24  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 3  RCU 25  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 3  RCU 26  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 3  RCU 27  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 3  RCU 28  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 3  RCU 29  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 3  RCU 30  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
+Frame nr 0 Station 1  RSP 3  RCU 31  Sample rate 200 MHz
+Samples checked : 10239 PRBS errors: 0
diff --git a/StationTest/gold/rsp_version.gold b/StationTest/gold/rsp_version.gold
new file mode 100644
index 00000000000..71915568991
--- /dev/null
+++ b/StationTest/gold/rsp_version.gold
@@ -0,0 +1,4 @@
+RSP[ 0] RSP version = 4, BP version = 4.13, AP version = 4.13
+RSP[ 1] RSP version = 4, BP version = 4.13, AP version = 4.13
+RSP[ 2] RSP version = 4, BP version = 4.13, AP version = 4.13
+RSP[ 3] RSP version = 4, BP version = 4.13, AP version = 4.13
diff --git a/StationTest/gold/tbb_version.gold b/StationTest/gold/tbb_version.gold
new file mode 100644
index 00000000000..6d3133946f0
--- /dev/null
+++ b/StationTest/gold/tbb_version.gold
@@ -0,0 +1,11 @@
+
+== TBB ====================================== ID and version information ====
+
+TBBDriver software version 2.00
+
+TBB  ID  Software   Board    TP0      MP0      MP1      MP2      MP3
+---  --  --------  -------  -------  -------  -------  -------  -------
+  0   0   V  2.0    V 0.2    V 1.6    V 1.6    V 1.6    V 1.6    V 1.6
+  1   2   V  2.0    V 0.2    V 1.6    V 1.6    V 1.6    V 1.6    V 1.6
+
+== normal termination of tbbctl ==============================================
diff --git a/StationTest/gold/xst.m b/StationTest/gold/xst.m
new file mode 100644
index 00000000000..c6eee9a6097
--- /dev/null
+++ b/StationTest/gold/xst.m
@@ -0,0 +1,29 @@
+%
+% Utility to examine XST data
+%
+
+%cd C:\svnroot\LOFAR\trunk\MAC\Test\Station\gold
+close all
+% golden XST data
+fid = fopen('xst_160.gold','r')
+data_gold = fread(fid,'double')
+fclose(fid)
+corr_gold = reshape(data_gold(1:2:end) + i * data_gold(2:2:end), [32,32])
+figure(1)
+imagesc(abs(corr_gold))
+colorbar
+figure(2)
+imagesc(angle(corr_gold))
+colorbar
+
+% new XST data
+fid = fopen('xst.dat','r')
+data = fread(fid,'double')
+fclose(fid)
+corr = reshape(data(1:2:end) + i * data(2:2:end), [32,32])
+figure(3)
+imagesc(abs(corr))
+colorbar
+figure(4)
+imagesc(angle(corr))
+colorbar
diff --git a/StationTest/gold/xst_160.gold b/StationTest/gold/xst_160.gold
new file mode 100644
index 0000000000000000000000000000000000000000..028a0359218d24ffea62e82480cd199f9fa46172
GIT binary patch
literal 16384
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

literal 0
HcmV?d00001

diff --git a/StationTest/gold/xst_200_even.gold b/StationTest/gold/xst_200_even.gold
new file mode 100644
index 0000000000000000000000000000000000000000..0b0b7fe23fded1d1acea55d98510d328fd959f7e
GIT binary patch
literal 16384
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

literal 0
HcmV?d00001

diff --git a/StationTest/gold/xst_200_odd.gold b/StationTest/gold/xst_200_odd.gold
new file mode 100644
index 0000000000000000000000000000000000000000..5c689fb51c1a8c0819e177233ae009a03c0304ab
GIT binary patch
literal 16384
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

literal 0
HcmV?d00001

diff --git a/StationTest/i2c_spu.py b/StationTest/i2c_spu.py
new file mode 100644
index 00000000000..78293b5328c
--- /dev/null
+++ b/StationTest/i2c_spu.py
@@ -0,0 +1,64 @@
+"""Testcase for RSP - SPU I2C interface, read SPU sensor information
+"""
+
+################################################################################
+# User imports
+import cli
+
+print ''
+print 'Read SPU sensor information to verify the RSP - SPU I2C interface'
+print ''
+
+################################################################################
+# Command line
+
+appLev = False
+cli.command('rm -f spustat.log',appLev)
+cli.command('rspctl --spustat > spustat.log',appLev)
+
+################################################################################
+# Verify result
+
+f=open('spustat.log','r')
+f.readline()                # skip title line
+data_str = f.readline()     # keep measured data line
+f.close()
+
+data_str = data_str.replace(' ','')    # remove spaces
+data_str = data_str.strip()            # remove \n
+data = data_str.split('|')             # make a list of strings
+
+volt_5v  = float(data[1])
+volt_8v  = float(data[2])
+volt_48v = float(data[3])
+volt_3v3 = float(data[4])
+temp_pcb = int(data[5])
+
+print '5   V = %5.2f V' % volt_5v
+print '8   V = %5.2f V' % volt_8v
+print '48  V = %5.2f V' % volt_48v
+print '3.3 V = %5.2f V' % volt_3v3
+print 'Temp  = %d degrees C' % temp_pcb
+print ''
+
+tc_result = 1
+if volt_5v  < 4.5 or volt_5v  > 5.5:
+  print 'Value %f for 5 V is wrong' % volt_5v
+  tc_result = 0
+if volt_8v  < 7.0 or volt_8v  > 8.5:
+  print 'Value %f for 8 V is wrong' % volt_8v
+  tc_result = 0
+if volt_48v < 44  or volt_48v > 49:
+  print 'Value %f for 48 V is wrong' % volt_48v
+  tc_result = 0
+if volt_3v3 < 3.0 or volt_3v3  > 4.0:
+  print 'Value %f for 3.3 V is wrong' % volt_3v3
+  tc_result = 0
+if temp_pcb < 10  or temp_pcb > 40:
+  print 'Value %f for PCB temperature is wrong' % temp_pcb
+  tc_result = 0
+  
+if tc_result == 0:
+  print 'RSP --> SPU I2C interface test went wrong'
+else:
+  print 'RSP --> SPU I2C interface test went OK'
diff --git a/StationTest/i2c_td.py b/StationTest/i2c_td.py
new file mode 100644
index 00000000000..01b5d631baf
--- /dev/null
+++ b/StationTest/i2c_td.py
@@ -0,0 +1,54 @@
+"""Testcase for RSP - TD I2C interface, read TD sensor information
+"""
+
+################################################################################
+# User imports
+import cli
+
+print ''
+print 'Read TD sensor information to verify the RSP - TD I2C interface'
+print ''
+
+################################################################################
+# Command line
+
+appLev = False
+cli.command('rm -f tdstat.log',appLev)
+cli.command('rspctl --tdstat > tdstat.log',appLev)
+
+################################################################################
+# Verify result
+
+f=open('tdstat.log','r')
+f.readline()                # skip title line
+data_str = f.readline()     # keep measured data line
+f.close()
+
+data_str = data_str.replace(' ','')    # remove spaces
+data_str = data_str.strip()            # remove \n
+data = data_str.split('|')             # make a list of strings
+
+volt_3v3 = float(data[6])
+volt_5v  = float(data[7])
+temp_pcb = int(data[8])
+
+print '3.3 V = %5.2f V' % volt_3v3
+print '5   V = %5.2f V' % volt_5v
+print 'Temp  = %d degrees C' % temp_pcb
+print ''
+
+tc_result = 1
+if volt_3v3 < 3.0 and volt_5v  > 4.0:
+  print 'Value %f for 3.3 V is wrong' % volt_3v3
+  tc_result = 0
+if volt_5v  < 4.5 and volt_5v  > 5.5:
+  print 'Value %f for 5 V is wrong' % volt_5v
+  tc_result = 0
+if temp_pcb < 10  and temp_pcb > 40:
+  print 'Value %f for PCB temperature is wrong' % temp_pcb
+  tc_result = 0
+  
+if tc_result == 0:
+  print 'RSP --> TD I2C interface test went wrong'
+else:
+  print 'RSP --> TD I2C interface test went OK'
diff --git a/StationTest/modules/Makefile.am b/StationTest/modules/Makefile.am
new file mode 100644
index 00000000000..0d289bbe166
--- /dev/null
+++ b/StationTest/modules/Makefile.am
@@ -0,0 +1,9 @@
+testdir		 =	$(prefix)/stationtest/modules
+test_SCRIPTS = 	cli.py \
+				mep.py \
+				rsp.py \
+				smbus.py \
+				testcase.py \
+				testlog.py
+
+include $(top_srcdir)/Makefile.common
diff --git a/StationTest/modules/cli.py b/StationTest/modules/cli.py
new file mode 100644
index 00000000000..9cb9861031b
--- /dev/null
+++ b/StationTest/modules/cli.py
@@ -0,0 +1,14 @@
+"""Command line interface access
+"""
+
+################################################################################
+# System imports
+import commands
+
+################################################################################
+# Functions
+
+def command(arg, p=False):
+  if p:
+    print arg
+  return commands.getoutput(arg)
diff --git a/StationTest/modules/mep.py b/StationTest/modules/mep.py
new file mode 100644
index 00000000000..92a3fb5ca8a
--- /dev/null
+++ b/StationTest/modules/mep.py
@@ -0,0 +1,366 @@
+"""MEP interface for RSP board access via rspctl --readblock/--writeblock
+
+  See also MepMessage.tcl.
+
+  class MepMessage:
+    def swap2(self, h)
+    def swap3(self, h)
+    def swap4(self, h)
+    def packAddr(self, blpId, pid, regId)
+    def clearPayload(self)
+    def appendPayload(self, hexString)
+    def lenPayload(self)
+    def getPayload(self, offset, nof)
+    def packPayload(self, data, width)
+    def extractPayload(self, readData)
+    def unpackPayload(self, width, sign='+')
+    def setOffset(self, offset=0)
+    def incrOffset(self, offset=1)
+    def readUnsigned(self, width):
+    def readSigned(self, width):
+"""
+
+class MepMessage:
+  c_blpid = {'blp0' : 1,
+             'blp1' : 2,
+             'blp2' : 4,
+             'blp3' : 8}
+             
+  c_pid = {'rsr'   :1,
+           'rsu'   :2,
+           'diag'  :3,
+           'ss'    :4,
+           'bf'    :5,
+           'bst'   :6,
+           'sst'   :7,
+           'rcuh'  :8,
+           'cr'    :9,
+           'xst'   :10,
+           'cdo'   :11,
+           'bs'    :12,
+           'serdes':13,
+           'tdsh'  :14,
+           'tbbi'  :15,
+           'cep'   :16,
+           'lcu'   :17,
+           'rad'   :18}
+   
+  c_regid = {('rsr','status') :     0,
+             ('rsr','version') :    1,
+             ('rsr','timestamp') :  2,
+             ('rsu','flash') :      1,
+             ('rsu','erase') :      2,
+             ('rsu','reconfig') :   3,
+             ('rsu','sysctrl') :    4,
+             ('rsu','unprotect') :  5,
+             ('tdsh','protocol') :  0,
+             ('tdsh','result') :    1,
+             ('diag','setx') :      0,
+             ('diag','sety') :      1,
+             ('diag','wavex') :     2,
+             ('diag','wavey') :     3,
+             ('diag','bypass') :    4,
+             ('diag','result') :    5,
+             ('diag','selftest') :  6,
+             ('bs','psync') :       0,
+             ('ss','settings') :    0,
+             ('bf','coefxr') :      0,
+             ('bf','coefxi') :      1,
+             ('bf','coefyr') :      2,
+             ('bf','coefyi') :      3,
+             ('sst','power') :      0,
+             ('bst','power0') :     0,
+             ('bst','power1') :     1,
+             ('bst','power2') :     2,
+             ('bst','power3') :     3,
+             ('xst','r0') :         0,
+             ('xst','r1') :         1,
+             ('xst','r2') :         2,
+             ('xst','r3') :         3,
+             ('xst','r4') :         4,
+             ('xst','r5') :         5,
+             ('xst','r6') :         6,
+             ('xst','r7') :         7,
+             ('xst','r8') :         8,
+             ('xst','r9') :         9,
+             ('xst','r10') :        10,
+             ('xst','r11') :        11,
+             ('xst','r12') :        12,
+             ('xst','r13') :        13,
+             ('xst','r14') :        14,
+             ('xst','r15') :        15,
+             ('xst','r16') :        16,
+             ('xst','r17') :        17,
+             ('xst','r18') :        18,
+             ('xst','r19') :        19,
+             ('xst','r20') :        20,
+             ('xst','r21') :        21,
+             ('xst','r22') :        22,
+             ('xst','r23') :        23,
+             ('xst','r24') :        24,
+             ('xst','r25') :        25,
+             ('xst','r26') :        26,
+             ('xst','r27') :        27,
+             ('xst','r28') :        28,
+             ('xst','r29') :        29,
+             ('xst','r30') :        30,
+             ('xst','r31') :        31,
+             ('rcuh','settings') :  0,
+             ('rcuh','protocolx') : 1,
+             ('rcuh','resultx') :   2,
+             ('rcuh','protocoly') : 3,
+             ('rcuh','resulty') :   4,
+             ('cr','softrst') :     0,
+             ('cr','softsync') :    1,
+             ('cr','syncoff') :     2,
+             ('cr','syncdelay') :   3,
+             ('cdo','settings') :   0,
+             ('cdo','iphdr') :      1,
+             ('serdes','hdr') :     0,
+             ('serdes','data') :    1,
+             ('cep','hdr') :        0,
+             ('cep','data') :       1,
+             ('lcu','hdr') :        0,
+             ('lcu','data') :       1,
+             ('rad','settings') :   0,
+             ('rad','latency') :    1,
+             ('tbbi','settingsx') : 0,
+             ('tbbi','settingsy') : 1,
+             ('tbbi','selmemx') :   2,
+             ('tbbi','selmemy') :   3}
+     
+  c_hw = 2         # 2 hex digits per byte
+
+  hexAddr = ''     # rspctl --readblock/writeblock ADDR field as string of hex digits
+  hexPayload = ''  # payload string of hex digits
+  offset = 0       # offset for read hexPayload in nof bytes
+     
+  def swap2(self, h):
+    """Byte swap hex string of two bytes
+    """
+    return h[2:4] + h[0:2]
+    
+  def swap3(self, h):
+    """Byte swap hex string of three bytes
+    """
+    return h[4:6] + h[2:4] + h[0:2]
+    
+  def swap4(self, h):
+    """Byte swap hex string of four bytes
+    """
+    return h[6:8] + h[4:6] + h[2:4] + h[0:2]
+    
+  def packAddr(self, blpId, pid, regId):
+    """Construct string of hex digits for rspctl --readblock/writeblock ADDR field
+    
+    Input:
+    - blpId = list of 'rsp' for BP and/or one or more 'blp#' for AP# to address
+    - pid   = process ID
+    - regId = register ID of the process
+    Output:
+    - self.hexAddr
+    Return: void
+    Example:
+      p=mep.MepMessage()
+      p.packAddr(['rsp', 'blp0', 'blp1'], 'diag', 'bypass')
+    """
+    ap = 0
+    bp = 0
+    for i in blpId:
+      if i=='rsp':
+        bp = 1
+      else:
+        ap += self.c_blpid[i]
+    self.hexAddr = '%02x%02x%02x%02x' % (ap, bp, self.c_pid[pid], self.c_regid[(pid,regId)])
+    
+  def clearPayload(self):
+    """Clear hex payload string
+    """
+    self.hexPayload = ''
+  
+  def appendPayload(self, hexString):
+    """Append hex string to the hex payload string
+    """
+    self.hexPayload += hexString
+    
+  def lenPayload(self):
+    """Return length of the hex payload string in nof bytes
+    """
+    return len(self.hexPayload)/self.c_hw
+    
+  def getPayload(self, offset, nof):
+    """Return hex payload string
+    
+    Input:
+    - offset = Offset in nof bytes
+    - nof    = Nof bytes to get
+    Return:
+    - hex string
+    """
+    return self.hexPayload[offset * self.c_hw : (offset + nof) * self.c_hw]
+    
+  def packPayload(self, data, width, append=False):
+    """Pack data list into hex payload string
+    
+    Input:
+    - data   = list of numbers
+    - width  = nof bytes per number
+    - append = when false clear hexPayload first, when true append the data
+    Output:
+    - self.hexPayload
+    Return: void
+    Example:
+      p=mep.MepMessage()
+      p.packPayload([3,-400,50],2)
+    """
+    if append == False:
+      self.clearPayload()
+    if width==1:
+      for i in data:
+        self.appendPayload(('%02x' % i)[-2:])   # pad 0 for single hex digit, strip sign extension of negative long
+    elif width==2:
+      for i in data:
+        self.appendPayload(self.swap2(('%04x' % i)[-4:]))
+    else: # width==4:
+      for i in data:
+        self.appendPayload(self.swap4(('%08x' % i)))
+    
+  def extractPayload(self, readData, append=False):
+    """Extract hex payload string from rspctl read data
+    Input:
+    - readData = echo from rspctl command
+    - append   = when false clear hexPayload first, when true append the read data
+    Output:
+    - self.hexPayload
+    Return: void
+    """
+    if append == False:
+      self.clearPayload()
+    j = 1
+    for i in range(len(readData)):
+      if readData[i] == '\n':
+        j = 0                               # found new line
+      elif readData[i] != ':' and j == 5:
+        j = -1                              # check data start of ':' at pos 5
+      elif j > 5 and j < 55:
+        if readData[i] != ' ':              # read the data
+          self.appendPayload(readData[i])
+      if j >= 0:
+        j += 1
+
+  def unpackPayload(self, width, sign='+'):
+    """Unpack data list from hex payload string
+    
+    Input:
+    - self.hexPayload
+    - width = nof bytes per number
+    - sign = '+' for unsigned word list, '-' for signed word list
+    Return:
+    - list of numbers
+    Example:
+      p=mep.MepMessage()
+      p.packPayload([3,-400,50],2)
+      p.unpackPayload(2, '-'):
+    """
+    umax = [0, 256, 65536, 0, 4294967296L]  # sign convert constant
+    data = []
+    if sign=='+':  # unsigned
+      for i in range(0, self.lenPayload(), width):
+        d = self.getPayload(i, width)
+        if width==2:
+          d = self.swap2(d)
+        elif width==4:
+          d = self.swap4(d)
+        d = int(d,16)
+        data.append(d)
+    else:          # signed
+      for i in range(0, self.lenPayload(), width):
+        d = self.getPayload(i, width)
+        if width==2:
+          d = self.swap2(d)
+        elif width==4:
+          d = self.swap4(d)
+        if int(d[0],16)<8:
+          d = int(d,16)
+        else:
+          d = int(d,16)-umax[width]
+        data.append(d)
+    return data
+
+  def setOffset(self, offset=0):
+    """Set offset for read access in payload octets
+    
+    Input:
+    - offset      = offset as nof bytes
+    Output:
+    - self.offset = offset as nof bytes
+    Return: void
+    """ 
+    self.offset = offset
+    
+  def incrOffset(self, offset=1):
+    """Increment offset for read access in payload octets
+    
+    Input:
+    - offset      = offset increment in nof bytes
+    Output:
+    - self.offset = offset incremented by offset nof bytes
+    Return: void
+    """ 
+    self.offset += offset
+    
+  def readUnsigned(self, width):
+    """Read unsigned word from the hex payload string and increment offset
+    
+    Input:
+    - self.hexPayload
+    - width = nof bytes per number
+    - self.offset
+    Return:
+    - unsigned
+    Example:
+      p=mep.MepMessage()
+      p.packPayload([3,-400,50],2)
+      p.setOffset(2)
+      p.readUnsigned(payload, 2)
+    """
+    d = self.getPayload(self.offset, width)
+    self.incrOffset(width)
+    if width==2:
+      d = self.swap2(d)
+    elif width==3:
+      d = self.swap3(d)
+    elif width==4:
+      d = self.swap4(d)
+    return int(d,16)
+
+  def readSigned(self, width):
+    """Read signed from the hex payload string and increment offset
+    
+    Input:
+    - self.hexPayload
+    - width = nof bytes per number
+    - self.offset
+    Return:
+    - signed
+    Example:
+      p=mep.MepMessage()
+      p.packPayload([3,-400,50],2)
+      p.setOffset(1)
+      p.readSigned(payload, 2)
+    """
+    umax = [0, 256, 65536, 0, 4294967296L]  # sign convert constant
+    d = self.getPayload(self.offset, width)
+    self.incrOffset(width)
+    if width==2:
+      d = self.swap2(d)
+    elif width==3:
+      d = self.swap3(d)
+    elif width==4:
+      d = self.swap4(d)
+    if int(d[0],16)<8:
+      d = int(d,16)
+    else:
+      d = int(d,16)-umax[width]
+    return d
+
diff --git a/StationTest/modules/rsp.py b/StationTest/modules/rsp.py
new file mode 100644
index 00000000000..a17f8cd8201
--- /dev/null
+++ b/StationTest/modules/rsp.py
@@ -0,0 +1,1280 @@
+"""RSP board register access functions
+
+  def rspctl(tc, arg)
+
+  def i2bb(s)
+  def i2bbbb(s)
+  def calculate_next_sequence_value(in_word, seq='PRSG', width=12)
+  def reorder(data, index)
+  
+  def write_mem(tc, msg, pid, regid, data, blpId=['blp0'], rspId=['rsp0'], width=2, offset=0, bc=0)
+  def read_mem(tc, msg, pid, regid, nof, blpId=['blp0'], rspId=['rsp0'], sign='+', width=2, offset=0)
+  
+  def write_cr_syncoff(tc, msg, blpId=['blp0'], rspId=['rsp0'])
+  def write_cr_syncon(tc, msg, blpId=['blp0'], rspId=['rsp0'])
+  def write_cr_sync_delay(tc, msg, syncdelay=0, syncedge=0, blpId=['blp0'], rspId=['rsp0'])
+  def read_cr_sync_delay(tc, msg, blpId=['blp0'], rspId=['rsp0'], applev=21)
+
+  def write_diag_bypass(tc, msg, bypass, blpId=['blp0'], rspId=['rsp0'], applev=21)
+  def read_diag_bypass(tc, msg, blpId=['blp0'], rspId=['rsp0'], applev=21)
+  def write_diag_selftest(tc, msg, selftest, blpId=['blp0'], rspId=['rsp0'], applev=21)
+  def read_diag_result_buffer(tc, msg, nof, width, blpId=['blp0'], rspId=['rsp0'])
+  
+  def write_rd_smbh_protocol_list(tc, msg, smbh, protocol_list,  polId=['x', 'y'], blpId=['blp0'], rspId=['rsp0'])
+  def overwrite_rd_smbh_protocol_results(tc, msg, smbh, polId=['x', 'y'], blpId=['blp0'], rspId=['rsp0'])
+
+  def write_rsu_altsync(tc, msg, rspId=['rsp0'])
+  
+  def overwrite_rsr(tc, msg, procid='all', value=255, rspId=['rsp0'])
+  def read_rsr(tc, msg, procid='all', rspId=['rsp0'], applev=21)
+  
+  def write_rad_settings(tc, msg, settings, rspId=['rsp0'], applev=21)
+  def read_rad_settings(tc, msg, rspId=['rsp0'], applev=21)
+  def read_rad_latency(tc, msg, rspId=['rsp0'], applev=21)
+  
+  def write_ss(tc, msg, ss_map, blpId=['blp0'], rspId=['rsp0'])
+  def read_ss(tc, msg, nof, blpId=['blp0'], rspId=['rsp0'])
+"""
+
+################################################################################
+# System imports
+import math
+
+# User imports
+import cli
+import mep
+import smbus
+
+
+################################################################################
+# Constansts (from constants.tcl)
+
+# From common(pkg).vhd
+c_complex                   = 2       # factor 2 accounting for Re part and Im part of complex number
+c_cpx                       = c_complex
+c_phs                       = c_complex
+c_pol                       = 2       # factor 2 accounting for X and Y polarization
+c_pol_phs                   = c_pol * c_phs
+
+c_long                      = 4
+
+c_rcu_version               = 1  # ctrlreg[23:20] = "0001" in RCU i2cslave(rtl).vhd
+
+c_ext_clk_freq              = 200000000
+c_rcu_clk_freq              = c_ext_clk_freq
+
+c_nof_bp                    = 1
+c_nof_ap                    = 4
+c_nof_blp_per_ap            = 1
+c_nof_blp                   = c_nof_ap * c_nof_blp_per_ap
+
+c_nof_subbands              = 512
+c_slice_size                = c_cpx * c_nof_subbands
+
+c_nof_lanes                 = 4
+c_nof_beamlets              = 248
+c_nof_beamlets_per_lane     = c_nof_beamlets / c_nof_lanes
+c_nof_antennas              = 96
+c_nof_crosslets_per_antenna = 1
+c_nof_crosslets             = c_nof_antennas * c_nof_crosslets_per_antenna
+c_nof_crosslets_per_lane    = c_nof_crosslets / c_nof_lanes
+c_nof_reflets               = c_nof_crosslets_per_antenna
+c_nof_reflets_ap            = c_nof_crosslets_per_antenna * c_nof_ap
+c_nof_beamlets_ap           = c_nof_reflets_ap + c_nof_beamlets
+c_nof_let_types             = 2
+
+c_rcu_dat_w                 = 12
+c_rcu_dat_mask              = 2**c_rcu_dat_w - 1
+c_blp_out_dat_w             = 18
+c_ring_data_dat_w           = c_blp_out_dat_w+2        # = 20
+
+c_diag_reg_wave_dat_w        = 18
+c_diag_reg_wave_size_small_w = 11
+c_diag_reg_res_word_w        =  4
+c_diag_reg_res_size          =  c_nof_beamlets_ap*c_pol_phs
+
+c_bf_reg_coef_w              = 16
+c_beam_data_dat_w            = 24
+
+c_ring_dat_w                 = 14
+
+c_tdsh_protocol_adr_w        = 11
+c_tdsh_result_adr_w          = 10
+c_rcuh_protocol_adr_w        =  9
+c_rcuh_result_adr_w          =  9
+
+c_rad_nof_rx                 =  1+c_nof_let_types*c_nof_lanes   # = 9
+
+c_ei_status_rsp_tvolt_offset =  0
+c_ei_status_rsp_tvolt_size   =  9
+c_ei_status_rsp_clk_offset   =  c_ei_status_rsp_tvolt_offset +                 c_ei_status_rsp_tvolt_size
+c_ei_status_rsp_clk_size     =  1
+c_ei_status_rsp_offset       =  0  # = c_ei_status_rsp_tvolt_offset
+c_ei_status_rsp_size         = 12  # = c_ei_status_rsp_tvolt_size + c_ei_status_rsp_clk_size rounded to factor of 4
+c_ei_status_eth_offset       =  c_ei_status_rsp_offset       +                 c_ei_status_rsp_size
+c_ei_status_eth_size         = 12
+c_ei_status_mep_offset       =  c_ei_status_eth_offset       +                 c_ei_status_eth_size
+c_ei_status_mep_size         =  4
+c_ei_status_diag_offset      =  c_ei_status_mep_offset       +                 c_ei_status_mep_size
+c_ei_status_diag_size        = 24
+c_ei_status_bs_offset        =  c_ei_status_diag_offset      +                 c_ei_status_diag_size
+c_ei_status_bs_size          = 16  # For each AP
+c_ei_status_rcuh_offset      =  c_ei_status_bs_offset        + c_nof_blp     * c_ei_status_bs_size
+c_ei_status_rcuh_size        = 12  # For each AP
+c_ei_status_rsu_offset       =  c_ei_status_rcuh_offset      + c_nof_blp     * c_ei_status_rcuh_size
+c_ei_status_rsu_size         =  4
+c_ei_status_ado_offset       =  c_ei_status_rsu_offset       +                 c_ei_status_rsu_size
+c_ei_status_ado_size         =  8
+c_ei_status_rad_offset       =  c_ei_status_ado_offset       + c_nof_blp     * c_ei_status_ado_size
+c_ei_status_rad_size         =  4
+c_ei_status_rsr_offset       =  0  # = c_ei_status_rsp_tvolt_offset
+c_ei_status_rsr_size         =  c_ei_status_rad_offset       + c_rad_nof_rx  * c_ei_status_rad_size
+
+c_ei_eth_err_noerr           = 0
+c_ei_eth_err_preamblevalue   = 1
+c_ei_eth_err_framedelimiter  = 2
+c_ei_eth_err_preamblelength  = 3
+c_ei_eth_err_headerlength    = 4
+c_ei_eth_err_crc             = 5
+c_ei_eth_err_oddnibblelength = 6
+c_ei_eth_err_framelength     = 7
+
+c_ei_mep_err_noerr           = 0
+c_ei_mep_err_type            = 1
+c_ei_mep_err_addr_blp        = 2
+c_ei_mep_err_pid             = 3
+c_ei_mep_err_regid           = 4
+c_ei_mep_err_offset          = 5
+c_ei_mep_err_size            = 6
+c_ei_mep_err_ringcrc         = 7
+c_ei_mep_err_timeout         = 8
+
+################################################################################
+# Derived constants (from constants.tcl)
+
+# - Calculate ADO scale factor based on word widths in ado(rtl).vhd and nof samples per sync interval for 200 MHz
+dat_in_w    = c_rcu_dat_w
+nof_acc_w   = math.ceil(math.log(c_rcu_clk_freq)/math.log(2))
+result_w    = 32
+acc_w       = dat_in_w + nof_acc_w
+c_ado_scale = int(round(pow(2, acc_w - result_w)))
+
+# RSR status
+c_rsr_ok        = 0
+c_rsr_error     = 1
+c_rsr_undefined = 2
+
+c_cp_bp              = 1
+c_cp_statusRdy       = 0
+c_cp_statusVersion0  = 1
+c_cp_statusFpgaType  = 2
+c_cp_statusImageType = 3
+c_cp_statusTrigLo    = 4
+c_cp_statusTrigHi    = 6
+c_cp_statusVersion1  = 7
+c_cp_version_w       = 2
+c_cp_trig_w          = c_cp_statusTrigHi-c_cp_statusTrigLo+1
+c_cp_trig_mask       = (1 << c_cp_trig_w) - 1
+c_cp_trig_ButtonRst  = 0
+c_cp_trig_TempRst    = 1
+c_cp_trig_UserRst    = 2
+c_cp_trig_WdRst      = 4
+
+# From diag(pkg).vhd
+c_diag_dev_ri           = 0
+c_diag_dev_rcux         = 1
+c_diag_dev_rcuy         = 2
+c_diag_dev_lcu          = 3
+c_diag_dev_cep          = 4
+c_diag_dev_serdes       = 5
+
+c_diag_mode_no_tst          =  0
+c_diag_mode_loop_local      =  1
+c_diag_mode_loop_line       =  2
+c_diag_mode_loop_remote     =  3
+c_diag_mode_tx              =  4
+c_diag_mode_rx              =  5
+c_diag_mode_tx_rx           =  6
+# RI specific modes
+c_diag_mode_bus             =  c_diag_mode_tx_rx
+c_diag_mode_lane_all        =  7
+c_diag_mode_lane_single     =  8
+# Serdes specific loopback mode variants
+c_diag_mode_loop_sys_diag   =  9
+c_diag_mode_loop_par_diag   =  c_diag_mode_loop_local
+c_diag_mode_loop_serial     = 10
+c_diag_mode_loop_metal_line =  c_diag_mode_loop_line
+c_diag_mode_loop_par_line   = 11
+
+c_diag_duration_debug   = 0
+c_diag_duration_quick   = 1
+c_diag_duration_normal  = 2
+c_diag_duration_extra   = 3
+
+c_diag_res_ok           = 0
+c_diag_res_none         = 1
+c_diag_res_sync_timeout = 2
+c_diag_res_data_timeout = 3
+c_diag_res_word_err     = 4
+c_diag_res_illegal      = 5
+
+# RCU I2C bus
+c_rcuh_i2c_addr_rcu     = 1
+c_rcuh_i2c_addr_hba     = 2
+
+# I2C handler time resolution
+c_msec                  = int(round(200e6 * 1e-3))
+
+# HBA control
+#
+#   In the client the registers are stored in order: SPEED, TBM, LED, DUMMY, VREF, STAT.
+#   - TBM = measured bit time
+#   - STAT = bit 0 contains the comparator state: 0 is high line input level, 1 for low line input level
+#   Reading 2 bytes from the SPEED register yields SPEED and TBM. Similar reading 2 bytes from VREF yields
+#   VREF and STAT. In fact note that reading 6 bytes from SPEED yields them all.
+#
+#   In the server the measured bit time is also stored after YDELAY, so via get word from c_hba_sreg_ydelay
+#   one gets ydelay and the measured bit time.
+c_hba_nof_servers     =  16       # HBA nof servers
+
+c_hba_cmd_request     =   0       # HBA client REQUEST register
+c_hba_cmd_response    =   1       # HBA client RESPONSE register
+c_hba_cmd_led         =   2       # HBA client LED register
+c_hba_cmd_vref        = 124       # HBA client VREF register (v10)
+c_hba_cmd_speed       = 127       # HBA client SPEED register (old)
+#c_hba_cmd_speed       = 125       # HBA client SPEED register (v10)
+c_hba_cmd_version     = 126       # HBA client VERSION register
+c_hba_reg_request_sz  =  38       # register size in octets
+c_hba_reg_response_sz =   4
+c_hba_reg_led_sz      =   1
+c_hba_reg_vref_sz     =   1
+c_hba_reg_speed_sz    =   1
+c_hba_reg_version_sz  =   1
+
+c_hba_f_set_byte      =   2       # HBA server function codes
+c_hba_f_get_byte      =   3
+c_hba_f_set_word      =   4
+c_hba_f_get_word      =   5
+c_hba_bc_server       =   0       # HBA server broadcast address
+c_hba_sreg_xdelay     =   0       # HBA server xdelay register address
+c_hba_sreg_ydelay     =   1       # HBA server ydelay register address
+c_hba_sreg_version    = 254       # HBA server version register address
+c_hba_sreg_address    = 255       # HBA server address register address
+
+# - Modem time (modem speed = 40 = 10 kbps, modem prescaler = 1): 
+#   . Broadcast request: 38 msec seems minimum for set_word broadcast 16 servers
+#   . Unicast request  : 11 msec seems minimum for set_word or get word
+# - For modem prescaler = 2 the uc_wait = 20 just works at modem speed = 40 = 5.5 kbps,
+#   hence to be safe double the wait times.
+# - Use hba_gap_wait as minimal wait after every I2C access to the client, before issueing a new I2C access
+hba_prescaler  =  1
+hba_prescaler  =  2
+hba_bc_wait    = 40*hba_prescaler      # used with PROTOCOL_C_WAIT and WG_WAIT
+hba_uc_wait    = 16*hba_prescaler      # used with PROTOCOL_C_WAIT and WG_WAIT
+hba_gap_wait   =  2                    # used with PROTOCOL_C_WAIT and WG_WAIT
+hba_bc_i2c     = 40       # used with WG_WAIT, I2C signalling time +30 is enough at 200 M
+hba_uc_i2c     = 25       # used with WG_WAIT, I2C signalling time +20 is enough at 200 M
+hba_reg_i2c    =  5       # used with WG_WAIT, I2C signalling time  +4 is enough at 50 kbps and 327 us comma per byte,
+                          # so addr, cmd, 4 bytes = 6 bytes * 9 = 54 bits @ 50 kbps = 1.1 ms, 6 bytes * 327 us = 1.9 ms
+
+c_hba_vref_default  = 0xEC  # Reference default mid level setting
+c_hba_speed_default = 40
+ 
+# TDS timing distribution clock board
+c_tds_clksel_10MHz_sma    = 1
+c_tds_clksel_10MHz_infini = 1 * (not c_tds_clksel_10MHz_sma)
+c_tds_clksel_160MHz       = 0
+c_tds_clksel_200MHz       = 1 * (not c_tds_clksel_160MHz)
+c_tds_clksel_pps_sma      = 0
+c_tds_clksel_pps_infini   = 1 * (not c_tds_clksel_pps_sma)
+
+################################################################################
+# Other constants (not from constants.tcl)
+c_eth_block               = 1400
+
+c_sens2v5                 =  2.5/192
+c_sens3v3                 =  3.3/192
+c_sens5v                  =  5.0/192
+c_sens12v                 = 12.0/192
+
+################################################################################
+# Functions
+
+def rspctl(tc, arg, applev=22):
+  cmd = 'rspctl %s' % arg
+  if tc != None:
+    tc.appendLog(applev,cmd)     # 22: show command line
+    res = cli.command(cmd)
+    tc.appendLog(applev+1,res)   # 23: show command return
+    return res
+  else:
+    return cli.command(cmd)
+
+
+def i2bb(s):
+  """ Convert list of integers into list of byte-bytes
+  Input:
+  - s   = list of integers
+  Return:
+  - ret = list of two bytes, LSByte first per pair
+  """
+  ret = []
+  for i in s:
+    ret.extend([i%256, (i/256)%256])
+  return ret
+
+  
+def i2bbbb(s):
+  """ Convert list of integers into list of byte-byte-byte-bytes
+  Input:
+  - s   = list of integers
+  Return:
+  - ret = list of four bytes, LSByte first per four
+  """
+  ret = []
+  for i in s:
+    ret.extend([i%256, (i/256)%256, (i/(256*256))%256, (i/(256*256*256))%256])
+  return ret
+  
+  
+def calculate_next_sequence_value(in_word, seq='PRSG', width=12):
+  """ Calculate next sequence value for PRSG or COUNTER
+  
+  Input:
+  - in_word  = seed
+  - seq      = PRSG   : use PRSG sequence as in RCU (width=12)
+               others : use COUNTER sequence
+  Return:
+  - out_word = next sequence value after in_word
+  """
+  if seq=='PRSG':
+    # Polynome
+    w    = 2**width-1
+    taps = [0, 3, 5, 11]
+    
+    # Feedback shift register
+    p = 0
+    for t in taps:
+      b = 2**t
+      b = 1 * (not (not (in_word & b)))
+      p = p ^ b
+    out_word = ((in_word << 1) & w) + 1 * (not p)
+  else:
+    w        = 2**width - 1
+    out_word = (in_word + 1) & w
+  return out_word
+
+  
+def reorder(data, index):
+  """Reorder the data list according to the indices in the index list
+  
+  Input:
+  - data  = Input data list
+  - index = List with reorder indices
+  Return:
+            Reordered data list
+  """
+  nof    = len(data)
+  redata = nof * [0]
+  for i in range(nof):
+    redata[index[i]] = data[i]
+  return redata
+  
+
+def write_mem(tc, msg, pid, regid, data, blpId=['blp0'], rspId=['rsp0'], width=2, offset=0, bc=1):
+  """Write data to memory register
+  
+  Input:
+  - tc     = Testcase
+  - msg    = MepMessage
+  - pid    = Process ID string
+  - regid  = Register ID string
+  - data   = List of words to write
+  - blpId  = List of ['blp#']
+  - rspId  = List of ['rsp#']
+  - width  = Nof bytes per data word
+  - offset = Offset in nof bytes
+  - bc     = When !=0 use MEP broadcast
+  Return: void
+  """
+  msg.packAddr(blpId, pid, regid)
+  msg.packPayload(data,width)
+  nof = width * len(data)       # nof octets
+  for ri in rspId:
+    i = 0
+    n = c_eth_block
+    while i < nof:
+      if nof - i < n:
+        n = nof - i
+      hexData = msg.getPayload(i, n)
+      if bc == 0:
+        # Individual accesses to BLPs on an RSP board
+        for bi in blpId:
+          msg.packAddr([bi], pid, regid)
+          rspctl(tc, '--writeblock=%s,%s,%d,%s' % (ri[3:], msg.hexAddr, offset+i, hexData))
+      else:
+        # Make use of MEP broadcast to BLPs on an RSP board
+        rspctl(tc, '--writeblock=%s,%s,%d,%s' % (ri[3:], msg.hexAddr, offset+i, hexData))
+      i = i + n
+
+
+def read_mem(tc, msg, pid, regid, nof, blpId=['blp0'], rspId=['rsp0'], sign='+', width=2, offset=0):
+  """Read data from memory register
+  
+  Input:
+  - tc     = Testcase
+  - msg    = MepMessage
+  - pid    = Process ID string
+  - regid  = Register ID string
+  - nof    = Nof bytes to read from the memory
+  - blpId  = List of one ['blp#']
+  - rspId  = List of one ['rsp#']
+  - width  = Nof bytes per data word
+  - sign   = 'h' for hex string, '+' for unsigned word list, '-' for signed word list
+  - offset = Offset in nof bytes
+  Return:
+  -          list of read words
+  """
+  msg.packAddr(blpId, pid, regid)
+  msg.clearPayload()
+  i = 0
+  n = c_eth_block
+  while i < nof:
+    if nof - i < n:
+      n = nof - i
+    msg.extractPayload(rspctl(tc, '--readblock=%s,%s,%d,%d' % (rspId[0][3:], msg.hexAddr, offset+i, n)), True)
+    i = i + n
+  if sign == 'h':
+    return None  # use access via msg.hexPayload
+  else:
+    return msg.unpackPayload(width, sign)
+
+
+def write_cr_syncoff(tc, msg, blpId=['blp0'], rspId=['rsp0']):
+  """CR disable external sync
+  
+  Input:
+  - tc     = Testcase
+  - msg    = MepMessage
+  - blpId  = List of 'rsp, blp#'
+  - rspId  = List of 'rsp#'
+  Return: void
+  """
+  for ri in rspId:
+    msg.packAddr(blpId, 'cr', 'syncoff')
+    msg.packPayload([1],1)
+    rspctl(tc, '--writeblock=%s,%s,0,%s' % (ri[3:], msg.hexAddr, msg.hexPayload))
+  
+
+def write_cr_syncon(tc, msg, blpId=['blp0'], rspId=['rsp0']):
+  """CR enable external sync
+  
+  Input:
+  - tc     = Testcase
+  - msg    = MepMessage
+  - blpId  = List of 'rsp, blp#'
+  - rspId  = List of 'rsp#'
+  Return: void
+  """
+  for ri in rspId:
+    msg.packAddr(blpId, 'cr', 'syncoff')
+    msg.packPayload([0],1)
+    rspctl(tc, '--writeblock=%s,%s,0,%s' % (ri[3:], msg.hexAddr, msg.hexPayload))
+
+
+def write_cr_sync_delay(tc, msg, syncdelay=0, syncedge=0, blpId=['blp0'], rspId=['rsp0']):
+  """CR write external sync input delay
+  
+  Input:
+  - tc        = Testcase
+  - msg       = MepMessage
+  - syncdelay = 0 is reset input delay to hardware default, > 0 increment input delay one time
+  - syncedge  = 0 is capture ext_sync on rising edge, != 0 is on falling edge
+  - blpId     = List of 'rsp, blp#'
+  - rspId     = List of 'rsp#'
+  Return: void
+  """
+  bit0 = syncdelay > 0
+  bit1 = syncedge  > 0
+  syncdata = (bit1 << 1) + bit0
+  for ri in rspId:
+    msg.packAddr(blpId, 'cr', 'syncdelay')
+    msg.packPayload([syncdata],1)
+    rspctl(tc, '--writeblock=%s,%s,0,%s' % (ri[3:], msg.hexAddr, msg.hexPayload))
+
+
+def read_cr_sync_delay(tc, msg, blpId=['blp0'], rspId=['rsp0'], applev=21):
+  """CR read sync delay bit
+  
+  Input:
+  - tc     = Testcase
+  - msg    = MepMessage
+  - blpId  = List of one 'rsp, blp#'
+  - rspId  = List of one 'rsp#'
+  - applev = Append logging level
+  Return:
+  - syncdata  = External sync data
+                . bit 0 : '0' is default input delay, '1' is incremented delay
+                . bit 1 : '0' capture external sync on rising edge, '1' on falling edge
+ 
+    tc appendlog messages are reported.
+  """
+  syncdata = -1
+  msg.packAddr(blpId, 'cr', 'syncdelay')
+  readData = rspctl(tc, '--readblock=%s,%s,0,1' % (rspId[0][3:], msg.hexAddr))
+  msg.extractPayload(readData)
+  syncdata = msg.unpackPayload(1, '+')
+  syncdata = syncdata[0]
+  bit0 =  syncdata & 1
+  bit1 = (syncdata & 2) >> 1
+  if   bit0==0 and bit1==0:
+    tc.appendLog(applev, '>>> RSP-%s, BLP-%-8s, read CR sync: default input delay,     default capture on rising edge' % (rspId, blpId))
+  elif bit0==0 and bit1!=0:
+    tc.appendLog(applev, '>>> RSP-%s, BLP-%-8s, read CR sync: default input delay,     capture on falling edge' % (rspId, blpId))
+  elif bit0!=0 and bit1==0:
+    tc.appendLog(applev, '>>> RSP-%s, BLP-%-8s, read CR sync: incremented input delay, default capture on rising edge' % (rspId, blpId))
+  else:
+    tc.appendLog(applev, '>>> RSP-%s, BLP-%-8s, read CR sync: incremented input delay, capture on falling edge' % (rspId, blpId))
+  return syncdata
+  
+
+def write_diag_bypass(tc, msg, bypass, blpId=['blp0'], rspId=['rsp0'], applev=21):
+  """Write DIAG bypass register
+  
+  Input:
+  - tc     = Testcase
+  - msg    = MepMessage
+  - bypass = Bypass enable word
+  - blpId  = List of ['blp#']
+  - rspId  = List of ['rsp#']
+  - applev = Append logging level
+  Return: void
+  """
+  tc.appendLog(applev, '>>> RSP-%s, BLP-%s, write DIAG bypass:' % (rspId, blpId))
+  tc.appendLog(applev, '      bit(0) : Bypass DC                     = %d' % ((bypass &  1    ) > 0))
+  tc.appendLog(applev, '      bit(1) : Bypass PFS                    = %d' % ((bypass & (1<<1)) > 0))
+  tc.appendLog(applev, '      bit(2) : Bypass PFT                    = %d' % ((bypass & (1<<2)) > 0))
+  tc.appendLog(applev, '      bit(3) : Bypass BF                     = %d' % ((bypass & (1<<3)) > 0))
+  tc.appendLog(applev, '      bit(4) : SI enable X                   = %d' % ((bypass & (1<<4)) > 0))
+  tc.appendLog(applev, '      bit(5) : SI enable Y                   = %d' % ((bypass & (1<<5)) > 0))
+  tc.appendLog(applev, '      bit(6) : DIAG result buffer use sync   = %d' % ((bypass & (1<<6)) > 0))
+  tc.appendLog(applev, '      bit(7) : DIAG result buffer use resync = %d' % ((bypass & (1<<7)) > 0))
+  tc.appendLog(applev, '      bit(8) : PFT switching disable         = %d' % ((bypass & (1<<8)) > 0))
+    
+  for ri in rspId:
+    msg.packAddr(blpId, 'diag', 'bypass')
+    msg.packPayload([bypass],2)
+    rspctl(tc, '--writeblock=%s,%s,0,%s' % (ri[3:], msg.hexAddr, msg.hexPayload))
+  
+
+def read_diag_bypass(tc, msg, blpId=['blp0'], rspId=['rsp0'], applev=21):
+  """Read DIAG bypass register
+  
+  Input:
+  - tc     = Testcase
+  - msg    = MepMessage
+  - blpId  = List of one 'blp#'
+  - rspId  = List of one 'rsp#'
+  - applev = Append logging level
+  Return:
+  - bypass = Bypass bits
+  """
+  msg.packAddr(blpId, 'diag', 'bypass')
+  readData = rspctl(tc, '--readblock=%s,%s,0,2' % (rspId[0][3:], msg.hexAddr))
+  msg.extractPayload(readData)
+  bypass = msg.unpackPayload(2, '+')
+  bypass = bypass[0]
+  
+  tc.appendLog(applev, '>>> RSP-%s, BLP-%s, read DIAG bypass:' % (rspId, blpId))
+  tc.appendLog(applev, '      bit(0) : Bypass DC                     = %d' % ((bypass &  1    ) > 0))
+  tc.appendLog(applev, '      bit(1) : Bypass PFS                    = %d' % ((bypass & (1<<1)) > 0))
+  tc.appendLog(applev, '      bit(2) : Bypass PFT                    = %d' % ((bypass & (1<<2)) > 0))
+  tc.appendLog(applev, '      bit(3) : Bypass BF                     = %d' % ((bypass & (1<<3)) > 0))
+  tc.appendLog(applev, '      bit(4) : SI enable X                   = %d' % ((bypass & (1<<4)) > 0))
+  tc.appendLog(applev, '      bit(5) : SI enable Y                   = %d' % ((bypass & (1<<5)) > 0))
+  tc.appendLog(applev, '      bit(6) : DIAG result buffer use sync   = %d' % ((bypass & (1<<6)) > 0))
+  tc.appendLog(applev, '      bit(7) : DIAG result buffer use resync = %d' % ((bypass & (1<<7)) > 0))
+  tc.appendLog(applev, '      bit(8) : PFT switching disable         = %d' % ((bypass & (1<<8)) > 0))
+  return bypass
+
+
+def write_diag_selftest(tc, msg, selftest, blpId=['rsp'], rspId=['rsp0'], applev=21):
+  """Write DIAG selftest register
+  
+  Input:
+  - tc       = Testcase
+  - msg      = MepMessage
+  - selftest = Selftest list: [interface, mode, duration, line]
+  - blpId    = List of ['rsp', 'blp#']
+  - rspId    = List of ['rsp#']
+  - applev   = Append logging level
+  Return: void
+  """
+  tc.appendLog(applev, '>>> RSP-%s write DIAG selftest:' % rspId)
+  tc.appendLog(applev, '      interface = %d' % selftest[0])
+  tc.appendLog(applev, '      mode      = %d' % selftest[1])
+  tc.appendLog(applev, '      duration  = %d' % selftest[2])
+  tc.appendLog(applev, '      line      = %d' % selftest[3])
+    
+  for ri in rspId:
+    msg.packAddr(blpId, 'diag', 'selftest')
+    msg.packPayload(selftest,1)
+    rspctl(tc, '--writeblock=%s,%s,0,%s' % (ri[3:], msg.hexAddr, msg.hexPayload))
+    
+
+def read_diag_result_buffer(tc, msg, nof, width, blpId=['blp0'], rspId=['rsp0']):
+  """Read DIAG result buffer
+  
+  Input:
+  - tc     = Testcase
+  - msg    = MepMessage
+  - nof    = Nof words to read from the result buffer
+  - width  = Word width of the result buffer samples, 1, 2, or 4
+  - blpId  = List of one 'blp#'
+  - rspId  = List of one 'rsp#'
+  Return:
+  - Read result buffer words
+  """
+  return read_mem(tc, msg, 'diag', 'result', width*nof, blpId, rspId, '-', width)
+
+
+def write_rsu_altsync(tc, msg, rspId=['rsp0']):
+  """RSU apply altsync
+  
+  Input:
+  - tc     = Testcase
+  - msg    = MepMessage
+  - rspId  = List of 'rsp#'
+  Return: void
+  """
+  for ri in rspId:
+    msg.packAddr(['rsp'], 'rsu', 'sysctrl')
+    msg.packPayload([1],1)
+    rspctl(tc, '--writeblock=%s,%s,0,%s' % (ri[3:], msg.hexAddr, msg.hexPayload))
+  
+
+def write_rd_smbh_protocol_list(tc, msg, smbh, protocol_list,  polId=['x', 'y'], blpId=['blp0'], rspId=['rsp0']):
+  """Write and readback protocol list to SMBus handler in RSP. The list will take effect at next sync.
+
+  Input:
+  - tc            = Testcase
+  - msg           = MepMessage
+  - smbh          = SMBus handler: 'tdsh' or 'rcuh'
+  - protocol_list = Protocol list
+  - polId         = Polarization ID: x, y or 'x y' for RCUH, ignored for TDSH
+  - blpId         = BLP ID: 'blp#' for RCUH, destination defaults to 'rsp' for TDSH
+  - rspId         = RSP ID: 'rsp#'
+  Report:
+    tc.appendlog messages are reported.
+    tc.setResult is set
+  Return: void
+  """
+  # - Write the protocol list to the SMBH
+  smbus.write_protocol_list(tc, msg, smbh, protocol_list, polId, blpId, rspId)
+
+  # - Read back the protocol list to verify that this is possible
+  for ri in rspId:
+    if smbh == 'tdsh':
+      rb_protocol_list = smbus.readback_protocol_list(tc, msg, smbh, len(protocol_list), None, None, [ri])
+      if protocol_list == rb_protocol_list:
+        tc.appendLog(21, '>>> RSP-%s, TDSH : The protocol list READBACK went OK' % ri)
+      else:
+        tc.appendLog(11, '>>> RSP-%s, TDSH : The protocol list READBACK went wrong:' % ri)
+        tc.appendLog(11, 'Expected protocol list: %s' % protocol_list)
+        tc.appendLog(11, 'Readback protocol list: %s' % rb_protocol_list)
+        tc.setResult('FAILED')
+    elif smbh == 'rcuh':
+      for bi in blpId:
+        for pi in polId:
+	  rb_protocol_list = smbus.readback_protocol_list(tc, msg, smbh, len(protocol_list), pi, [bi], [ri])
+          if protocol_list == rb_protocol_list:
+            tc.appendLog(21, '>>> RSP-%s, BLP-%s, RCUH-%s: The protocol list READBACK went OK' % (ri, bi, pi))
+          else:
+            tc.appendLog(11, '>>> RSP-%s, BLP-%s, RCUH-%s: The protocol list READBACK went wrong:' % (ri, bi, pi))
+            tc.appendLog(11, 'Expected protocol list: %s' % protocol_list)
+            tc.appendLog(11, 'Readback protocol list: %s' % rb_protocol_list)
+            tc.setResult('FAILED')
+
+
+def overwrite_rd_smbh_protocol_results(tc, msg, smbh, polId=['x', 'y'], blpId=['blp0'], rspId=['rsp0']):
+  """Overwrite and read protocol result of SMBus handler in RSP.
+
+  Input:
+  - tc            = Testcase
+  - msg           = MepMessage
+  - smbh          = SMBus handler: 'tdsh' or 'rcuh'
+  - polId         = Polarization ID: x, y or 'x y' for RCUH, ignored for TDSH
+  - blpId         = BLP ID: 'blp#' for RCUH, destination defaults to 'rsp' for TDSH
+  - rspId         = RSP ID: 'rsp#'
+  Report:
+    tc appendlog messages are reported.
+    tc setResult is set
+  Return: void
+  """
+  if smbh == 'rcuh':
+    nof_result_bytes = 2**c_rcuh_result_adr_w
+  if smbh == 'tdsh':
+    nof_result_bytes = 2**c_tdsh_result_adr_w
+  
+  # - Overwrite first entries of protocol result register to be sure that the results will be fresh
+  wr_result = []
+  for i in range(nof_result_bytes):
+    wr_result.append(17)      # Just some number not equal to 0, 1, 255 and < 256
+
+  # - Overwrite
+  smbus.overwrite_results(tc, msg, smbh, wr_result, polId, blpId, rspId)
+
+  # - Readback to verify overwrite
+  for ri in rspId:
+    if smbh == 'tdsh':
+      rd_result = smbus.read_results(tc, msg, smbh, nof_result_bytes, None, None, [ri])
+      if wr_result == rd_result:
+        tc.appendLog(21, '>>> RSP-%s, TDSH : The protocol results OVERWRITE and read went OK' % ri)
+      else:
+        tc.appendLog(11, '>>> RSP-%s, TDSH : The protocol results OVERWRITE and read went wrong:' % ri)
+        tc.appendLog(11, 'Expected protocol result: %s' % wr_result)
+        tc.appendLog(11, 'Readback protocol result: %s' % rd_result)
+        tc.setResult('FAILED')
+    elif smbh == 'rcuh':
+      for bi in blpId:
+        for pi in polId:
+          rd_result = smbus.read_results(tc, msg, smbh, nof_result_bytes, pi, [bi], [ri])
+          if wr_result == rd_result:
+            tc.appendLog(21, '>>> RSP-%s, BLP-%s, RCUH-%s: The protocol results OVERWRITE and read went OK' % (ri, bi, pi))
+          else:
+            tc.appendLog(11, '>>> RSP-%s, BLP-%s, RCUH-%s: The protocol results OVERWRITE and read went wrong:' % (ri, bi, pi))
+            tc.appendLog(11, 'Expected protocol result: %s' % wr_result)
+            tc.appendLog(11, 'Readback protocol result: %s' % rd_result)
+            tc.setResult('FAILED')
+
+
+def overwrite_rsr(tc, msg, procid='all', value=255, rspId=['rsp0']):
+  """Overwrite the selected process fields of the RSP status register
+  
+  Input:
+  - tc     = Testcase
+  - msg    = MepMessage
+  - procid = Process ID : 'rsp', 'eth', 'mep', 'diag', 'bs', 'rcuh', 'rsu', 'ado', 'rad' or 'all'
+  - value  = Byte value to use for overwrite
+  - rspId  = List of 'rsp#' 
+  Return: void
+  """
+  if   procid == 'rsp' : offset = c_ei_status_rsp_offset;  size =               c_ei_status_rsp_size
+  elif procid == 'eth' : offset = c_ei_status_eth_offset;  size =               c_ei_status_eth_size
+  elif procid == 'mep' : offset = c_ei_status_mep_offset;  size =               c_ei_status_mep_size
+  elif procid == 'diag': offset = c_ei_status_diag_offset; size =               c_ei_status_diag_size
+  elif procid == 'bs'  : offset = c_ei_status_bs_offset;   size = c_nof_blp    *c_ei_status_bs_size
+  elif procid == 'rcuh': offset = c_ei_status_rcuh_offset; size = c_nof_blp    *c_ei_status_rcuh_size
+  elif procid == 'rsu' : offset = c_ei_status_rsu_offset;  size =               c_ei_status_rsu_size
+  elif procid == 'ado' : offset = c_ei_status_ado_offset;  size = c_nof_blp    *c_ei_status_ado_size
+  elif procid == 'rad' : offset = c_ei_status_rad_offset;  size = c_rad_nof_rx *c_ei_status_rad_size
+  else:                  offset = c_ei_status_rsr_offset;  size =               c_ei_status_rsr_size
+  
+  status = []
+  for i in range(size):
+    status.append(value)
+    
+  for ri in rspId:
+    write_mem(tc, msg, 'rsr', 'status', status, ['rsp'], [ri], 1, offset)
+
+
+def read_rsr(tc, msg, procid='all', rspId=['rsp0'], applev=21):
+  """Read the selected process fields from the RSP status register
+  
+  Input:
+  - tc     = Testcase
+  - msg    = MepMessage
+  - procid   = Process ID : 'rsp', 'eth', 'mep', 'diag', 'bs', 'rcuh', 'rsu', 'ado', 'rad' or 'all'
+  - rspId    = List of 'rsp#' 
+  - applev   = Append log level
+  Return:
+  - ret      = List of read process status fields, list structure: [[first RSP], ..., [last RSP]],
+               where the data structure per RSP depends on the procid.
+  - retb     = Boolean telling wither the status is OK or ERROR
+  """
+  ret_rsp = []   # Declare return result
+
+  # Read all RSR fields
+  for ri in rspId:
+    ret = []
+    retb = []
+    
+    read_mem(tc, msg, 'rsr', 'status', c_ei_status_rsr_size, ['rsp'], [ri], 'h', 1, c_ei_status_rsr_offset)
+    
+    msg.setOffset(c_ei_status_rsr_offset)
+    # RSP status
+    rsp_volt_1v2         = msg.readUnsigned(1)
+    rsp_volt_2v5         = msg.readUnsigned(1)
+    rsp_volt_3v3         = msg.readUnsigned(1)
+    rsp_pcb_temp         = msg.readSigned(1)
+    rsp_bp_temp          = msg.readSigned(1)
+    rsp_ap0_temp         = msg.readSigned(1)
+    rsp_ap1_temp         = msg.readSigned(1)
+    rsp_ap2_temp         = msg.readSigned(1)
+    rsp_ap3_temp         = msg.readSigned(1)
+    rsp_clk              = msg.readUnsigned(1)
+    rsp_rsvd             = msg.readUnsigned(2)
+    # ETH status
+    eth_nof_frames       = msg.readUnsigned(4)
+    eth_nof_errors       = msg.readUnsigned(4)
+    eth_last_error       = msg.readUnsigned(1)
+    eth_rsvd             = msg.readUnsigned(3)
+    # MEP status
+    mep_seq_nr           = msg.readUnsigned(2)
+    mep_prev_error       = msg.readUnsigned(1)
+    mep_rsvd             = msg.readUnsigned(1)
+    # DIAG status
+    diag_interface       = msg.readUnsigned(1)
+    diag_mode            = msg.readUnsigned(1)
+    diag_ri_errors        = {}
+    diag_ri_errors['rsp'] = msg.readUnsigned(2)
+    diag_rcux_errors     = msg.readUnsigned(2)
+    diag_rcuy_errors     = msg.readUnsigned(2)
+    diag_eth_errors        = {}
+    diag_eth_errors['LCU'] = msg.readUnsigned(2)
+    diag_eth_errors['CEP'] = msg.readUnsigned(2)
+    diag_serdes_errors   = msg.readUnsigned(2)
+    diag_ri_errors['0']  = msg.readUnsigned(2)
+    diag_ri_errors['1']  = msg.readUnsigned(2)
+    diag_ri_errors['2']  = msg.readUnsigned(2)
+    diag_ri_errors['3']  = msg.readUnsigned(2)
+    diag_rsvd            = msg.readUnsigned(2)
+    # BS status
+    bs_ext_cnt    = {}
+    bs_sync_cnt   = {}
+    bs_sample_cnt = {}
+    bs_slice_cnt  = {}
+    for bi in range(c_nof_blp):
+      bs_ext_cnt[bi]     = msg.readUnsigned(4)
+      bs_sync_cnt[bi]    = msg.readUnsigned(4)
+      bs_sample_cnt[bi]  = msg.readUnsigned(4)
+      bs_slice_cnt[bi]   = msg.readUnsigned(4)
+    # RCU status
+    rcu_status    = {}
+    rcu_nof_ovr_x = {}
+    rcu_nof_ovr_y = {}
+    for bi in range(c_nof_blp):
+      rcu_status[bi]     = msg.readUnsigned(4)
+      rcu_nof_ovr_x[bi]  = msg.readUnsigned(4)
+      rcu_nof_ovr_y[bi]  = msg.readUnsigned(4)
+    # RSU status
+    rsu_cp_status  = msg.readUnsigned(4)
+    # ADO status
+    ado_x = {}
+    ado_y = {}
+    for bi in range(c_nof_blp):
+      ado_x[bi]          = msg.readSigned(4)
+      ado_y[bi]          = msg.readSigned(4)
+    # RAD BP status
+    rad_ri               = msg.readUnsigned(4)
+    rad_lane = {}
+    for la in range(c_nof_lanes):
+      rad_lane[la,'crosslets'] = msg.readUnsigned(4)
+      rad_lane[la,'beamlets']  = msg.readUnsigned(4)
+
+    # Report RSR fields indicated by procid
+    tc.appendLog(applev, '')
+    tc.appendLog(applev, '>>> RSR read outs for RSP-%s.' % ri)
+    tc.appendLog(applev, '')
+
+    if procid == 'rsp' or procid == 'all':
+      tc.appendLog(applev, 'RSP board status:')
+      tc.appendLog(applev, '')
+      tc.appendLog(applev, '  supply 1.2V = %6.3f V   (= %3d * %5.3f)' % (rsp_volt_1v2 * c_sens2v5, rsp_volt_1v2, c_sens2v5))
+      tc.appendLog(applev, '  supply 2.5V = %6.3f V   (= %3d * %5.3f)' % (rsp_volt_2v5 * c_sens3v3, rsp_volt_2v5, c_sens3v3))
+      tc.appendLog(applev, '  supply 3.3V = %6.3f V   (= %3d * %5.3f)' % (rsp_volt_3v3 * c_sens5v,  rsp_volt_3v3, c_sens5v))
+      tc.appendLog(applev, '')
+      tc.appendLog(applev, '  temp PCB = %4d degrees C' % rsp_pcb_temp)
+      tc.appendLog(applev, '')
+      tc.appendLog(applev, '  temp BP  = %4d degrees C' % rsp_bp_temp)
+      tc.appendLog(applev, '  temp AP0 = %4d degrees C' % rsp_ap0_temp)
+      tc.appendLog(applev, '  temp AP1 = %4d degrees C' % rsp_ap1_temp)
+      tc.appendLog(applev, '  temp AP2 = %4d degrees C' % rsp_ap2_temp)
+      tc.appendLog(applev, '  temp AP3 = %4d degrees C' % rsp_ap3_temp)
+      tc.appendLog(applev, '')
+      tc.appendLog(applev, '  clk rate = %4d MHz' % rsp_clk)
+      tc.appendLog(applev, '')
+      ret.append([rsp_volt_1v2, rsp_volt_2v5, rsp_volt_3v3, rsp_pcb_temp, rsp_bp_temp, rsp_ap0_temp, rsp_ap1_temp, rsp_ap2_temp, rsp_ap3_temp, rsp_clk])
+
+    if procid == 'eth' or procid == 'all':
+      tc.appendLog(applev, 'Ethernet status:')
+      tc.appendLog(applev, '')
+      tc.appendLog(applev, '  Number of frames = %d' % eth_nof_frames)
+      tc.appendLog(applev, '  Number of errors = %d' % eth_nof_errors)
+      if   eth_last_error == c_ei_eth_err_noerr          : tc.appendLog(applev, '  Last error       = OK')
+      elif eth_last_error == c_ei_eth_err_preamblevalue  : tc.appendLog(applev, '  Last error       = Preamble value error')
+      elif eth_last_error == c_ei_eth_err_framedelimiter : tc.appendLog(applev, '  Last error       = Frame delimiter error')
+      elif eth_last_error == c_ei_eth_err_preamblelength : tc.appendLog(applev, '  Last error       = Preamble length error')
+      elif eth_last_error == c_ei_eth_err_headerlength   : tc.appendLog(applev, '  Last error       = Frame header lenght error')
+      elif eth_last_error == c_ei_eth_err_crc            : tc.appendLog(applev, '  Last error       = CRC error')
+      elif eth_last_error == c_ei_eth_err_oddnibblelength: tc.appendLog(applev, '  Last error       = Odd nof nibbles error')
+      elif eth_last_error == c_ei_eth_err_framelength    : tc.appendLog(applev, '  Last error       = Frame size error')
+      else:                                                tc.appendLog(applev, '  Last error       = Illegal error code: %d' % eth_last_error)
+      tc.appendLog(applev, '')
+      ret.append([eth_nof_frames, eth_nof_errors, eth_last_error])
+    if procid == 'mep' or procid == 'all':
+      tc.appendLog(applev, 'MEP status:')
+      tc.appendLog(applev, '')
+      tc.appendLog(applev, '  Sequence number           = %d' % mep_seq_nr)
+      if   mep_prev_error == c_ei_mep_err_noerr   : tc.appendLog(applev, '  Error status previous msg = OK')
+      elif mep_prev_error == c_ei_mep_err_type    : tc.appendLog(applev, '  Error status previous msg = Unknown message type')
+      elif mep_prev_error == c_ei_mep_err_addr_blp: tc.appendLog(applev, '  Error status previous msg = Illegal BLP address')
+      elif mep_prev_error == c_ei_mep_err_pid     : tc.appendLog(applev, '  Error status previous msg = Invalid PID')
+      elif mep_prev_error == c_ei_mep_err_regid   : tc.appendLog(applev, '  Error status previous msg = Register does not exist')
+      elif mep_prev_error == c_ei_mep_err_offset  : tc.appendLog(applev, '  Error status previous msg = Offset too large')
+      elif mep_prev_error == c_ei_mep_err_size    : tc.appendLog(applev, '  Error status previous msg = Message too large')
+      elif mep_prev_error == c_ei_mep_err_ringcrc : tc.appendLog(applev, '  Error status previous msg = Ring CRC error')
+      elif mep_prev_error == c_ei_mep_err_timeout : tc.appendLog(applev, '  Error status previous msg = Timeout')
+      else:                                         tc.appendLog(applev, '  Error status previous msg = Illegal error code: %d' % mep_prev_error)
+      tc.appendLog(applev, '')
+      ret.append([mep_seq_nr, mep_prev_error])
+    if procid == 'diag' or procid == 'all':
+      tc.appendLog(applev, 'DIAG status:')
+      tc.appendLog(applev, '')
+      tc.appendLog(applev, '  Interface                 = %d' % diag_interface)
+      tc.appendLog(applev, '  Mode                      = %d' % diag_mode)
+      # - BP RI
+      if   diag_ri_errors['rsp'] == c_diag_res_ok:
+        tc.appendLog(applev, '  Test result RI-BP         = OK')
+      elif diag_ri_errors['rsp'] == c_diag_res_none:
+        tc.appendLog(applev, '  Test result RI-BP         = Nothing happened')
+      elif diag_ri_errors['rsp'] == c_diag_res_sync_timeout:
+        tc.appendLog(applev, '  Test result RI-BP         = Sync timeout')
+      elif diag_ri_errors['rsp'] == c_diag_res_data_timeout:
+        tc.appendLog(applev, '  Test result RI-BP         = Data timeout')
+      elif diag_ri_errors['rsp'] == c_diag_res_word_err:
+        tc.appendLog(applev, '  Test result RI-BP         = Data errors occured')
+      else:
+        tc.appendLog(applev, '  Test result RI-BP         = Unknown status %d' % diag_ri_errors['rsp'])
+        tc.appendLog(applev, '  Test result RCU-X         = %d' % diag_rcux_errors)
+        tc.appendLog(applev, '  Test result RCU-Y         = %d' % diag_rcuy_errors)
+      # - ETH
+      eth_interfaces = ['LCU', 'CEP']
+      for ei in eth_interfaces:
+        if   diag_eth_errors[ei] == c_diag_res_ok:
+          tc.appendLog(applev, '  Test result %s           = OK' % ei)
+        elif diag_eth_errors[ei] == c_diag_res_none:
+          tc.appendLog(applev, '  Test result %s           = Nothing happened' % ei)
+        elif diag_eth_errors[ei] == c_diag_res_data_timeout:
+          tc.appendLog(applev, '  Test result %s           = Data timeout (= frame lost)' % ei)
+        elif diag_eth_errors[ei] == c_diag_res_word_err:
+          tc.appendLog(applev, '  Test result %s           = Word errors occured' % ei)
+        else:
+          tc.appendLog(applev, '  Test result %s           = Unknown status %d' % (ei, diag_eth_errors[ei]))
+      # - SERDES lanes
+      lane_mask = 2**c_nof_lanes-1
+      lane_ref  = 2**c_nof_lanes
+      for i in range(c_nof_lanes):
+        lane_errors = (diag_serdes_errors >> (i*c_nof_lanes)) & lane_mask
+        if   lane_errors == c_diag_res_ok:
+          tc.appendLog(applev, '  Test result SERDES lane %d = OK' % i)
+        elif lane_errors == c_diag_res_none:
+          tc.appendLog(applev, '  Test result SERDES lane %d = nothing happened' % i)
+        elif lane_errors == c_diag_res_sync_timeout:
+          tc.appendLog(applev, '  Test result SERDES lane %d = sync timeout' % i)
+        elif lane_errors == c_diag_res_data_timeout:
+          tc.appendLog(applev, '  Test result SERDES lane %d = data timeout' % i)
+        elif lane_errors == c_diag_res_word_err:
+          tc.appendLog(applev, '  Test result SERDES lane %d = word errors occured' % i)
+        elif lane_errors == c_diag_res_illegal:
+          tc.appendLog(applev, '  Test result SERDES lane %d = illegal status %d' % (i, lane_errors))
+        else:
+          tc.appendLog(applev, '  Test result SERDES lane %d = unknown status %d' % (i, lane_errors))
+      # - APs RI
+      for ai in ['0','1','2','3']:
+        if   diag_ri_errors[ai] == c_diag_res_ok:
+          tc.appendLog(applev, '  Test result RI-AP%s        = OK' % ai)
+        elif diag_ri_errors[ai] == c_diag_res_none:
+          tc.appendLog(applev, '  Test result RI-AP%s        = Nothing happened.' % ai)
+        elif diag_ri_errors[ai] == c_diag_res_sync_timeout:
+          tc.appendLog(applev, '  Test result RI-AP%s        = Sync timeout.' % ai)
+        elif diag_ri_errors[ai] == c_diag_res_data_timeout:
+          tc.appendLog(applev, '  Test result RI-AP%s        = Data timeout.' % ai)
+        elif diag_ri_errors[ai] == c_diag_res_word_err:
+          tc.appendLog(applev, '  Test result RI-AP%s        = Data errors occured.' % ai)
+        else:
+          tc.appendLog(applev, '  Test result RI-AP%s        = Unknown status %d.' % (ai, diag_ri_errors[ai]))
+      tc.appendLog(applev, '')
+      ret.append([diag_interface, diag_mode, diag_ri_errors['rsp'], diag_rcux_errors, diag_rcuy_errors, diag_eth_errors['LCU'], diag_eth_errors['CEP'], diag_serdes_errors, diag_ri_errors['0'], diag_ri_errors['1'], diag_ri_errors['2'], diag_ri_errors['3']])
+    if procid == 'bs' or procid == 'all':
+      tc.appendLog(applev, 'BS status:')
+      tc.appendLog(applev, '')
+      for bi in range(c_nof_blp):
+        st  = 'BLP-%s: ' % bi
+        st += 'Ext_cnt = %u, '    % bs_ext_cnt[bi]
+        st += 'Sync_cnt = %u, '   % bs_sync_cnt[bi]
+        st += 'Sample_cnt = %u, ' % bs_sample_cnt[bi]
+        st += 'Slice_cnt = %u.'   % bs_slice_cnt[bi]
+        tc.appendLog(applev, '  %s' % st)
+        ret.append([bs_ext_cnt[bi], bs_sync_cnt[bi], bs_sample_cnt[bi], bs_slice_cnt[bi]])
+      tc.appendLog(applev, '')
+    if procid == 'rcuh' or procid == 'all':
+      tc.appendLog(applev, 'RCU status:')
+      tc.appendLog(applev, '')
+      for bi in range(c_nof_blp):
+        st  = 'BLP-%s: ' % bi
+        st += 'status = %u, '    % rcu_status[bi]
+        st += 'nof_ovr_x = %u, ' % rcu_nof_ovr_x[bi]
+        st += 'nof_ovr_y = %u.'  % rcu_nof_ovr_y[bi]
+        tc.appendLog(applev, '  %s' % st)
+        ret.append([rcu_status[bi], rcu_nof_ovr_x[bi], rcu_nof_ovr_y[bi]])
+      tc.appendLog(applev, '')
+    if procid == 'rsu' or procid == 'all':
+      tc.appendLog(applev, 'RSU status:')
+      tc.appendLog(applev, '')
+      tc.appendLog(applev, '  CP status = %d' % rsu_cp_status)
+      tc.appendLog(applev, '')
+      if ((rsu_cp_status >> c_cp_statusRdy) & 0x1) == 1:
+        tc.appendLog(applev, '    [%d] statusRdy       = 1 : CP is done' % c_cp_statusRdy)
+      else:
+        tc.appendLog(applev, '    [%d] statusRdy       = 0 : CP is in some intermediate state' % c_cp_statusRdy)
+      if ((rsu_cp_status >> c_cp_statusFpgaType) & 0x1) == c_cp_bp:
+        tc.appendLog(applev, '    [%d] statusFpgaType  = %d : Image was loaded via JTAG' % (c_cp_statusFpgaType, c_cp_bp))
+      else:
+        tc.appendLog(applev, '    [%d] statusFpgaType  = %d : Image was loaded from flash' % (c_cp_statusFpgaType, 1 * (not c_cp_bp)))
+      if ((rsu_cp_status >> c_cp_statusImageType) & 0x1) == 0:
+        tc.appendLog(applev, '    [%d] statusImageType = 0 : Factory image is running' % c_cp_statusImageType)
+      else:
+        tc.appendLog(applev, '    [%d] statusImageType = 1 : User image is running' % c_cp_statusImageType)
+      if   ((rsu_cp_status >> c_cp_statusTrigLo) & c_cp_trig_mask) == c_cp_trig_ButtonRst:
+        tc.appendLog(applev, '  [%d:%d] statusTrig      = %d : Reconfiguration due to button reset' % (c_cp_statusTrigHi, c_cp_statusTrigLo, c_cp_trig_ButtonRst))
+      elif ((rsu_cp_status >> c_cp_statusTrigLo) & c_cp_trig_mask) == c_cp_trig_TempRst:
+        tc.appendLog(applev, '  [%d:%d] statusTrig      = %d : Reconfiguration due to over temperature' % (c_cp_statusTrigHi, c_cp_statusTrigLo, c_cp_trig_TempRst))
+      elif ((rsu_cp_status >> c_cp_statusTrigLo) & c_cp_trig_mask) == c_cp_trig_UserRst:
+        tc.appendLog(applev, '  [%d:%d] statusTrig      = %d : Reconfiguration due to user reset' % (c_cp_statusTrigHi, c_cp_statusTrigLo, c_cp_trig_UserRst))
+      elif ((rsu_cp_status >> c_cp_statusTrigLo) & c_cp_trig_mask) == c_cp_trig_WdRst:
+        tc.appendLog(applev, '  [%d:%d] statusTrig      = %d : Reconfiguration due to watchdog reset' % (c_cp_statusTrigHi, c_cp_statusTrigLo, c_cp_trig_WdRst))
+      else:
+        tc.appendLog(applev, '  [%d:%d] statusTrig      = %d : Unknown reconfiguration trigger' % (c_cp_statusTrigHi, c_cp_statusTrigLo, (rsu_cp_status >> c_cp_statusTrigLo) & c_cp_trig_mask))
+      cp_version = (((rsu_cp_status >> c_cp_statusVersion1) & 0x1) << 1) + ((rsu_cp_status >> c_cp_statusVersion0) & 0x1)
+      tc.appendLog(applev, '  [%d,%d] statusVersion   = %d : CP version number' % (c_cp_statusVersion1, c_cp_statusVersion0, cp_version))
+      tc.appendLog(applev, '')
+      ret.append([rsu_cp_status])
+    elif procid == 'ado' or procid == 'all':
+      tc.appendLog(applev, 'ADC offset:')
+      tc.appendLog(applev, '')
+      for bi in range(c_nof_blp):
+        nof_samples_psync = bs_slice_cnt[bi] * c_slice_size
+        st = 'BLP-%s, RCU-X ADC offset = ' % bi
+        if nof_samples_psync != 0:
+          st += '%11.7f lsb    ' % (1.0 * ado_x[bi] * c_ado_scale / nof_samples_psync)
+        else:
+          st += '-----------'
+        st += '(%10d * %u / %11.0f)' % (ado_x[bi], c_ado_scale, nof_samples_psync)
+        tc.appendLog(applev, '  %s' % st)
+
+        st = 'BLP-%s, RCU-Y ADC offset = ' % bi
+        if nof_samples_psync != 0:
+          st += '%11.7f lsb    ' % (1.0 * ado_y[bi] * c_ado_scale / nof_samples_psync)
+        else:
+          st += '-----------'
+        st += '(%10d * %u / %11.0f)' % (ado_y[bi], c_ado_scale, nof_samples_psync)
+        tc.appendLog(applev, '  %s' % st)
+
+        ret.append([ado_x[bi], ado_y[bi]])
+      tc.appendLog(applev, '')
+    if procid == 'rad' or procid == 'all':
+      tc.appendLog(applev, 'RAD BP frame rx status:')
+      tc.appendLog(applev, '')
+      tc.appendLog(applev, '                     Align  Sync   CRC    Frame cnt')
+      retb = c_rsr_undefined              # default undefined
+      st = 'RI               : '
+      cnt = rad_ri & ((1<<18)-1)
+      if cnt==0:
+        st += '-      -      -      '
+      else:
+        # when rad is busy there is always input from RI, from lane only in case of multiple RSP
+        retb = c_rsr_ok
+        st += '-      '                              # not applicable for RI
+        if (rad_ri & (1<<19))!=0: st += 'OK     '
+        else: st += 'Error  '; retb = c_rsr_error    # sync error(s)
+        if (rad_ri & (1<<18))==0: st += 'OK     '
+        else: st += 'Error  '; retb = c_rsr_error    # CRC error(s)
+      st += '%u' % cnt
+      tc.appendLog(applev, '  %s' % st)
+      ret.append(rad_ri)
+      for la in range(c_nof_lanes):
+        for let in ['crosslets', 'beamlets']:
+          st = 'Lane-%d, %-9s: ' % (la, let)
+          cnt = rad_lane[la, let] & ((1<<18)-1)
+          if cnt==0:
+            st += '-      -      -      '
+          else:
+            # input from lane can keep retb as set by input from RI, or cause retb to indicate error
+            if (rad_lane[la, let] & (1<<20))==0: st += 'OK     '
+            else: st += 'Error  '; retb = c_rsr_error  # frame(s) discarded
+            if (rad_lane[la, let] & (1<<19))!=0: st += 'OK     '
+            else: st += 'Error  '; retb = c_rsr_error  # sync error(s)
+            if (rad_lane[la, let] & (1<<18))==0: st += 'OK     '
+            else: st += 'Error  '; retb = c_rsr_error  # CRC error(s)
+          st += '%u' % cnt
+          tc.appendLog(applev, '  %s' % st)
+          ret.append(rad_lane[la, let])
+      tc.appendLog(applev, '')
+      ret = [retb, ret]
+    ret_rsp.append(ret)
+  return ret_rsp
+
+
+def write_rad_settings(tc, msg, settings, rspId=['rsp0'], applev=21):
+  """RAD_BP write settings
+
+  Input:
+  - tc       = Testcase
+  - msg      = MepMessage
+  - settings = Lane settings for beamlets and crosslets
+  - rspId    = List of 'rsp#' 
+  - applev   = Append log level
+  Report:
+    tc appendlog messages are reported (see read_rad_settings for lane mode definition).
+  Return: void
+  """ 
+  tc.appendLog(applev, '>>> RSP-%s write RAD settings (= 0x%X):' % (rspId, settings))
+  # beamlet lane modes
+  for i in range(c_nof_lanes):
+    lane_mode = (settings >> (8*i)) & 0x3
+    if   lane_mode==0: tc.appendLog(applev, '      lane(%d): beamlet  mode local' % i)
+    elif lane_mode==1: tc.appendLog(applev, '      lane(%d): beamlet  mode disable' % i)
+    elif lane_mode==2: tc.appendLog(applev, '      lane(%d): beamlet  mode combine' % i)
+    else:              tc.appendLog(applev, '      lane(%d): beamlet  mode remote' % i)
+  # crosslet lane modes
+  for i in range(c_nof_lanes):
+    lane_mode = (settings >> (8*i + 2)) & 0x3
+    if   lane_mode==0: tc.appendLog(applev, '      lane(%d): crosslet mode local' % i)
+    elif lane_mode==1: tc.appendLog(applev, '      lane(%d): crosslet mode disable' % i)
+    elif lane_mode==2: tc.appendLog(applev, '      lane(%d): crosslet mode combine' % i)
+    else:              tc.appendLog(applev, '      lane(%d): crosslet mode remote' % i)
+  for ri in rspId:
+    msg.packAddr(['rsp'], 'rad', 'settings')
+    msg.packPayload([settings],4)
+    rspctl(tc, '--writeblock=%s,%s,0,%s' % (ri[3:], msg.hexAddr, msg.hexPayload))
+
+
+def read_rad_settings(tc, msg, rspId=['rsp0'], applev=21):
+  """RAD_BP read settings
+  Input:
+  - tc     = Testcase
+  - msg    = MepMessage
+  - rspId  = List of one 'rsp#'
+  - applev = Append log level
+  Report:
+    tc appendlog messages are reported.
+  Return:
+  - settings = Lane settings for beamlets and crosslets
+      lane mode: one byte for each lane
+        format: XXXXAABB
+        where XX = don't care
+              AA = xlet mode
+              BB = blet mode
+         mode 00 = ignore remote data (only local)  DEFAULT
+         mode 01 = disable
+         mode 10 = combine local and remote data
+         mode 11 = ignore local data (only remote)
+  """
+  msg.packAddr(['rsp'], 'rad', 'settings')
+  readData = rspctl(tc, '--readblock=%s,%s,0,4' % (rspId[0][3:], msg.hexAddr))
+  msg.extractPayload(readData)
+  settings = msg.unpackPayload(4, '+')
+  settings = settings[0]
+  tc.appendLog(applev, '>>> RSP-%s read RAD settings (= 0x%X):' % (rspId, settings))
+  # beamlet lane modes
+  for i in range(c_nof_lanes):
+    lane_mode = (settings >> (8*i)) & 0x3
+    if   lane_mode==0: tc.appendLog(applev, '      lane(%d): beamlet  mode local' % i)
+    elif lane_mode==1: tc.appendLog(applev, '      lane(%d): beamlet  mode disable' % i)
+    elif lane_mode==2: tc.appendLog(applev, '      lane(%d): beamlet  mode combine' % i)
+    else:              tc.appendLog(applev, '      lane(%d): beamlet  mode remote' % i)
+  # crosslet lane modes
+  for i in range(c_nof_lanes):
+    lane_mode = (settings >> (8*i + 2)) & 0x3
+    if   lane_mode==0: tc.appendLog(applev, '      lane(%d): crosslet mode local' % i)
+    elif lane_mode==1: tc.appendLog(applev, '      lane(%d): crosslet mode disable' % i)
+    elif lane_mode==2: tc.appendLog(applev, '      lane(%d): crosslet mode combine' % i)
+    else:              tc.appendLog(applev, '      lane(%d): crosslet mode remote' % i)
+  return settings
+
+
+def read_rad_latency(tc, msg, rspId=['rsp0'], applev=21):
+  """RAD_BP read latency
+
+  Input:
+  - tc     = Testcase
+  - msg    = MepMessage
+  - rspId  = List of 'rsp#'
+  - applev = Append log level
+  Report:  
+    tc appendlog messages are reported.
+  Return:
+  - latency = RI and lane latencies crosslets and beamlets
+  """
+  latency = []
+  nof_rd = 2*c_rad_nof_rx
+  
+  title_str = '>>>         '
+  title_str += 'Ri'
+  for i in range(c_nof_lanes-1,-1,-1):
+    title_str += '    X%d' % i
+  for i in range(c_nof_lanes-1,-1,-1):
+    title_str += '    B%d' % i
+  tc.appendLog(applev, title_str)
+
+  for ri in rspId:
+    lat = []
+    read_mem(tc, msg, 'rad', 'latency', nof_rd, ['rsp'], [ri], 'h', 1, 0)
+    
+    msg.setOffset(0)
+    lane = {}
+    for i in range(c_nof_lanes):
+      lane[i,'b'] = msg.readUnsigned(2)
+      lane[i,'x'] = msg.readUnsigned(2)
+    ring = msg.readUnsigned(2)
+
+    lat_str = 'RSP-%s' % ri
+    lat_str += '%6d' % ring
+    lat.append(ring)
+    for i in range(c_nof_lanes-1,-1,-1):
+      lat_str += '%6d' % lane[i,'x']
+      lat.append(lane[i,'x'])
+    for i in range(c_nof_lanes-1,-1,-1):
+      lat_str += '%6d' % lane[i,'b']
+      lat.append(lane[i,'b'])
+    tc.appendLog(applev, lat_str)
+    latency.append(lat)
+  return latency
+
+
+def write_ss(tc, msg, ss_map, blpId=['blp0'], rspId=['rsp0']):
+  """Write subband to beamlet mapping to SS register
+  
+  Input:
+  - tc     = Testcase
+  - msg    = MepMessage
+  - ss_map = List of words for subband to beamlet mapping
+  - blpId  = List of 'blp#'
+  - rspId  = List of 'rsp#'
+  Return: void
+  """
+  write_mem(tc, msg, 'ss', 'settings', ss_map, blpId, rspId, 2)
+
+
+def read_ss(tc, msg, nof, blpId=['blp0'], rspId=['rsp0']):
+  """Read subband to beamlet mapping from SS register
+  
+  Input:
+  - tc     = Testcase
+  - msg    = MepMessage
+  - nof    = Nof words to read from the SS register
+  - blpId  = List of one 'blp#'
+  - rspId  = List of one 'rsp#'
+  Return:
+  - Read SS register words
+  """
+  width = 2
+  return read_mem(tc, msg, 'ss', 'settings', width*nof, blpId, rspId, '+', width)
+  
+  
+################################################################################
+# Try some functions on the python command line
+if __name__ == "__main__":
+  import sys
+  sys.argv[1:]        # list of input arguments
diff --git a/StationTest/modules/smbus.py b/StationTest/modules/smbus.py
new file mode 100644
index 00000000000..d73e8825f3f
--- /dev/null
+++ b/StationTest/modules/smbus.py
@@ -0,0 +1,281 @@
+"""SMBus (I2C) access constants and functions (translated from RSP smbus.tcl)
+
+   Constants for I2C peripherals
+
+   - c_max6652 voltage temperature sensor
+   - c_pca9555 I/O expander
+
+   Procedures for accessing the SMBus (I2C) interface
+
+   - set_protocol
+   - write_protocol_list
+   - readback_protocol_list
+   - read_results
+   - overwrite_results
+"""
+
+################################################################################
+# System imports
+
+# User imports
+import rsp
+
+###############################################################################
+# - MAX6652 voltage temperature sensor constants
+
+c_max6652_addr_gnd             = 0x14   # I2C slave address
+c_max6652_addr_vcc             = 0x15
+c_max6652_addr_sda             = 0x16
+c_max6652_addr_scl             = 0x17
+
+c_max6652_cmd_read_2v5         = 0x20   # Commands
+c_max6652_cmd_read_12v         = 0x21
+c_max6652_cmd_read_3v3         = 0x22
+c_max6652_cmd_read_vcc         = 0x23
+c_max6652_cmd_read_temp        = 0x27
+c_max6652_cmd_config           = 0x40
+
+c_max6652_config_start         = 0x01   # Configuration bits
+c_max6652_config_int_en        = 0x02
+c_max6652_config_int_clr       = 0x08
+c_max6652_config_line_freq_sel = 0x10
+c_max6652_config_short_cycle   = 0x20
+c_max6652_config_reset         = 0x80
+
+c_max6652_unit_12v             = 12.0/192   # Unit in V
+c_max6652_unit_vcc             =  5.0/192
+c_max6652_unit_3v3             =  3.3/192
+c_max6652_unit_2v5             =  2.5/192
+c_max6652_unit_temp            =  1.0       # Unit in degree C
+
+
+###############################################################################
+# - PCA9555 I/O expander constants
+
+c_pca9555_base_addr            = 0x20
+c_pca9555_addr_000             = c_pca9555_base_addr + 0   # A2 A1 A0
+c_pca9555_addr_001             = c_pca9555_base_addr + 1
+c_pca9555_addr_010             = c_pca9555_base_addr + 2
+c_pca9555_addr_011             = c_pca9555_base_addr + 3
+c_pca9555_addr_100             = c_pca9555_base_addr + 4
+c_pca9555_addr_101             = c_pca9555_base_addr + 5
+c_pca9555_addr_110             = c_pca9555_base_addr + 6
+c_pca9555_addr_111             = c_pca9555_base_addr + 7
+
+c_pca9555_cmd_input_0          = 0
+c_pca9555_cmd_input_1          = 1
+c_pca9555_cmd_output_0         = 2
+c_pca9555_cmd_output_1         = 3
+c_pca9555_cmd_invert_0         = 4
+c_pca9555_cmd_invert_1         = 5
+c_pca9555_cmd_config_0         = 6
+c_pca9555_cmd_config_1         = 7
+
+
+###############################################################################
+# - SMBus functions
+
+def set_protocol(tc, protocol_id, cnt=1, addr=1, data='', cmd='', cmd2='', appLev=1):
+  """Returns filled in protocol message
+
+  See i2c_smbus(pkg).vhd for more detailed comments on the SMBus protocol definitions.
+
+  Input:
+  - tc             = Testcase
+  - protocol_id    = Protocol ID: STRING
+  - cnt            = Number of data bytes, or timeout value: INTEGER
+  - addr           = I2C slave address: BYTE
+  - data           = I2C write data: list of BYTE
+  - cmd            = I2C slave command (register)
+  - cmd2           = I2C slave command (register) 2
+
+  Return:
+  - msg            = Protocol request message
+  """
+
+  def error_len(data, le):
+    ret = 0
+    if len(data)!=le:
+      print 'Wrong SMBus protocol data length, must be %d bytes.' % le
+      ret = 1
+    return ret
+
+  # SMBUS protocol identifiers conform i2c_smbus(pkg).vhd
+  PROTOCOL_ARRAY = {'PROTOCOL_WRITE_QUICK'           :2,
+                    'PROTOCOL_READ_QUICK'            :3,
+                    'PROTOCOL_SEND_BYTE'             :4,
+                    'PROTOCOL_RECEIVE_BYTE'          :5,
+                    'PROTOCOL_WRITE_BYTE'            :6,
+                    'PROTOCOL_READ_BYTE'             :7,
+                    'PROTOCOL_WRITE_WORD'            :8,
+                    'PROTOCOL_READ_WORD'             :9,
+                    'PROTOCOL_WRITE_BLOCK'           :10,
+                    'PROTOCOL_READ_BLOCK'            :11,
+                    'PROTOCOL_PROCESS_CALL'          :12,
+                    'PROTOCOL_C_WRITE_BLOCK_NO_CNT'  :13,
+                    'PROTOCOL_C_READ_BLOCK_NO_CNT'   :14,
+                    'PROTOCOL_C_SEND_BLOCK'          :15,
+                    'PROTOCOL_C_RECEIVE_BLOCK'       :16,
+                    'PROTOCOL_C_NOP'                 :17,
+                    'PROTOCOL_C_WAIT'                :18,
+                    'PROTOCOL_C_END'                 :19,
+                    'PROTOCOL_C_UNKNOWN'             :20}    # To test unknown protocol
+
+  # First message field
+  msg = []
+  msg.append(PROTOCOL_ARRAY[protocol_id])
+
+  # Additional message fields:
+  if   protocol_id == 'PROTOCOL_WRITE_QUICK':          msg.append(addr)
+  elif protocol_id == 'PROTOCOL_READ_QUICK':           msg.append(addr)
+  elif protocol_id == 'PROTOCOL_SEND_BYTE':
+                                                       msg.append(addr)
+                                                       msg.extend(data)
+                                                       if error_len(data,1)!=0: msg = -1
+  elif protocol_id == 'PROTOCOL_RECEIVE_BYTE':           msg.append(addr)
+  elif protocol_id == 'PROTOCOL_WRITE_BYTE':
+                                                       msg.append(addr)
+                                                       msg.append(cmd)
+						       msg.extend(data)
+						       if error_len(data,1)!=0: msg = -1
+  elif protocol_id == 'PROTOCOL_READ_BYTE':              msg.append(addr); msg.append(cmd)
+  elif protocol_id == 'PROTOCOL_WRITE_WORD':
+                                                       msg.append(addr)
+                                                       msg.append(cmd)
+                                                       msg.extend(data)
+						       if error_len(data,2)!=0: msg = -1
+  elif protocol_id == 'PROTOCOL_READ_WORD':            msg.append(addr); msg.append(cmd)
+  elif protocol_id == 'PROTOCOL_WRITE_BLOCK':          msg.append(addr); msg.append(cmd); msg.append(cnt); msg.extend(data)
+  elif protocol_id == 'PROTOCOL_READ_BLOCK':           msg.append(addr); msg.append(cmd); msg.append(cnt)
+  elif protocol_id == 'PROTOCOL_PROCESS_CALL':
+                                                       msg.append(addr)
+						       msg.append(cmd)
+						       msg.extend(data)
+						       if error_len(data,2)!=0: msg = -1
+                                                       msg.append(addr); msg.append(cmd2)
+  elif protocol_id == 'PROTOCOL_C_WRITE_BLOCK_NO_CNT': msg.append(addr); msg.append(cmd); msg.append(cnt); msg.extend(data)
+  elif protocol_id == 'PROTOCOL_C_READ_BLOCK_NO_CNT':  msg.append(addr); msg.append(cmd); msg.append(cnt)
+  elif protocol_id == 'PROTOCOL_C_SEND_BLOCK':         msg.append(addr);                  msg.append(cnt); msg.extend(data)
+  elif protocol_id == 'PROTOCOL_C_RECEIVE_BLOCK':      msg.append(addr);                  msg.append(cnt)
+  elif protocol_id == 'PROTOCOL_C_NOP':                None
+  elif protocol_id == 'PROTOCOL_C_WAIT':               msg.extend(rsp.i2bbbb([cnt]))
+  elif protocol_id == 'PROTOCOL_C_END':                None
+  else:                                                tc.appendLog(appLev, 'Unknown SMBus protocol.')
+
+  return msg
+
+
+def test_protocols(tc):
+  """Procedure used to verify set_protocol in a Python shell
+  """
+  print set_protocol(tc, 'PROTOCOL_WRITE_QUICK',          None, 1, None,      None, None)
+  print set_protocol(tc, 'PROTOCOL_READ_QUICK',           None, 1, None,      None, None)
+  print set_protocol(tc, 'PROTOCOL_SEND_BYTE',            None, 1, [5],       None, None)
+  print set_protocol(tc, 'PROTOCOL_RECEIVE_BYTE',         None, 1, None,      None, None)
+  print set_protocol(tc, 'PROTOCOL_WRITE_BYTE',           None, 1, [5],       17,   None)
+  print set_protocol(tc, 'PROTOCOL_READ_BYTE',            None, 1, None,      17,   None)
+  print set_protocol(tc, 'PROTOCOL_WRITE_WORD',           None, 1, [5, 6],    17,   None)
+  print set_protocol(tc, 'PROTOCOL_READ_WORD',            None, 1, None,      17,   None)
+  print set_protocol(tc, 'PROTOCOL_WRITE_BLOCK',          3,    1, [9, 9, 9], 17,   None)
+  print set_protocol(tc, 'PROTOCOL_READ_BLOCK',           3,    1, None,      17,   None)
+  print set_protocol(tc, 'PROTOCOL_PROCESS_CALL',         None, 1, [5, 6],    17,   18)
+  print set_protocol(tc, 'PROTOCOL_C_WRITE_BLOCK_NO_CNT', 3,    1, [9, 9, 9], 17,   None)
+  print set_protocol(tc, 'PROTOCOL_C_READ_BLOCK_NO_CNT',  3,    1, None,      17,   None)
+  print set_protocol(tc, 'PROTOCOL_C_SEND_BLOCK',         3,    1, [9, 9, 9], None, None)
+  print set_protocol(tc, 'PROTOCOL_C_RECEIVE_BLOCK',      3,    1, None,      None, None)
+  print set_protocol(tc, 'PROTOCOL_C_NOP',                None, 1, None,      None, None)
+  print set_protocol(tc, 'PROTOCOL_C_WAIT',               1333, 1, None,      None, None)
+  print set_protocol(tc, 'PROTOCOL_C_END',                None, 1, None,      None, None)
+  set_protocol(      tc, 'PROTOCOL_C_UNKNOWN',            None, 1, None,      None, None)
+
+
+def write_protocol_list(tc, msg, smbh, protocol_list, polId=['x', 'y'], blpId=['blp0'], rspId=['rsp0']):
+  """Write SMBus protocol list to SMBus handler
+  
+  Input:
+  - tc             = Testcase
+  - msg            = MepMessage
+  - smbh           = I2C device handler: 'rcuh' or 'tdsh'
+  - protocol_list  = Protocol list: bytes
+  - polId          = Polarization: 'x' or 'y' for RCUH, ignored for TDSH
+  - blpId          = BLP ID: 'blp#' for RCUH, destination defaults to 'rsp' for TDSH
+  - rspId          = RSP ID: 'rsp#'
+ 
+  Return: void
+  """
+  width  = 1   # protocol_list is in bytes
+  offset = 0   # access from address 0
+  bc     = 1   # allow BLP broadcast
+  if smbh == 'tdsh':
+    rsp.write_mem(tc, msg, smbh, 'protocol', protocol_list, ['rsp'], rspId, width, offset, bc)
+  if smbh == 'rcuh':
+    for pi in polId:
+      rsp.write_mem(tc, msg, smbh, 'protocol'+pi, protocol_list, blpId, rspId, width, offset, bc)
+
+
+def readback_protocol_list(tc, msg, smbh, le, polId='x', blpId=['blp0'], rspId=['rsp0']):
+  """Read back SMBus protocol list from SMBus handler
+  
+  Input:
+  - tc             = Testcase
+  - msg            = MepMessage
+  - smbh           = I2C device handler: 'rcuh' or 'tdsh'
+  - le             = Number of bytes to read from the protocol list buffer, INTEGER
+  - polId          = Polarization ID: 'x' or 'y' for RCUH, ignored for TDSH          - only one
+  - blpId          = BLP ID: 'blp#' for RCUH, destination defaults to 'rsp' for TDSH - only one
+  - rspId          = RSP ID: 'rsp#'                                                  - only one
+
+  Return:            Read protocol list bytes
+  """
+  width  = 1   # protocol_list is in bytes
+  offset = 0   # access from address 0
+  if smbh == 'tdsh':
+    return rsp.read_mem(tc, msg, smbh, 'protocol',       width * le, ['rsp'], rspId, '+', width, offset)
+  if smbh == 'rcuh':
+    return rsp.read_mem(tc, msg, smbh, 'protocol'+polId, width * le, blpId,   rspId, '+', width, offset)
+  
+
+def read_results (tc, msg, smbh, le, polId='x', blpId=['blp0'], rspId=['rsp0']):
+  """Read the results of the SMBus protocol list from the SMBus handler
+ 
+  Input:
+  - tc             = Testcase
+  - msg            = MepMessage
+  - smbh           = I2C device handler: 'rcuh' or 'tdsh'
+  - le             = Number of bytes to read from the protocol result buffer, INTEGER
+  - polId          = Polarization ID: 'x' or 'y' for RCUH, ignored for TDSH          - only one
+  - blpId          = BLP ID: 'blp#' for RCUH, destination defaults to 'rsp' for TDSH - only one
+  - rspId          = RSP ID: 'rsp#'                                                  - only one
+  
+  Return:          = Read result data
+  """
+  width  = 1   # protocol_list is in bytes
+  offset = 0   # access from address 0
+  if smbh == 'tdsh':
+    return rsp.read_mem(tc, msg, smbh, 'result',       width * le, ['rsp'], rspId, '+', width, offset)
+  if smbh == 'rcuh':
+    return rsp.read_mem(tc, msg, smbh, 'result'+polId, width * le, blpId,   rspId, '+', width, offset)
+
+
+def overwrite_results (tc, msg, smbh, wr_result, polId=['x', 'y'], blpId=['blp0'], rspId=['rsp0']):
+  """Write SMBus results to SMBus handler
+  
+  Input:
+  - tc             = Testcase
+  - msg            = MepMessage
+  - smbh           = I2C device handler: 'rcuh' or 'tdsh'
+  - wr_result      = Overwrite results: bytes
+  - polId          = Polarization: 'x' or 'y' for RCUH, ignored for TDSH
+  - blpId          = BLP ID: 'blp#' for RCUH, destination defaults to 'rsp' for TDSH
+  - rspId          = RSP ID: 'rsp#'
+  
+  Return: void
+  """
+  width  = 1   # result is in bytes
+  offset = 0   # access from address 0
+  bc     = 1   # allow BLP broadcast
+  if smbh == 'tdsh':
+    rsp.write_mem(tc, msg, smbh, 'result', wr_result, ['rsp'], rspId, width, offset, bc)
+  if smbh == 'rcuh':
+    for pi in polId:
+      rsp.write_mem(tc, msg, smbh, 'result'+pi, wr_result, blpId, rspId, width, offset, bc)
diff --git a/StationTest/modules/testcase.py b/StationTest/modules/testcase.py
new file mode 100644
index 00000000000..1463e231162
--- /dev/null
+++ b/StationTest/modules/testcase.py
@@ -0,0 +1,72 @@
+"""Testcase utilities
+"""
+
+################################################################################
+# System imports
+import time
+
+################################################################################
+# Functions
+
+class Testcase:
+
+  def __init__(self, verbosity=11, testName='empty.py', repeat=1,
+                     rspId=['rsp0'], bpId='rsp', blpId='blp0',
+                     tbbId=None, tpId=None, mpId=None,
+                     polId=['x','y']):
+    self.startTime = time.time()
+    self.verbosity = verbosity
+    self.testName = testName
+    self.repeat = repeat
+    self.rspId = rspId
+    self.bpId = bpId
+    self.blpId = blpId
+    self.tbbId = tbbId
+    self.tpId = tpId
+    self.mpId = mpId
+    self.polId = polId
+    if testName != None:
+      self.logName = testName[0:-3] + '.log'
+      self.logFile = open(self.logName,'w')
+    self.result = 'RUNONLY'
+    
+  def setResult(self, res):                     # Use this method rather than direct access to result
+    if res in ['RUNONLY', 'PASSED', 'FAILED']:  # Ignore illegal res
+      if self.result != 'FAILED':               # Once FAILED the result can not be changed
+        self.result=res
+
+  def getResult(self):    # Method alterative to than direct access to result
+    return self.result
+    
+  def appendLog(self, level, string, nolevel=0, notime=0):
+    txt = 'Tc %s - ' % self.testName[0:-3]
+    if notime == 0:
+      t = time.localtime()
+      txt = txt + '[%d:%02d:%02d %02d:%02d:%02d]' % (t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec)
+    if nolevel == 0:
+      txt = txt + ' - (%02d) ' % level
+    txt = txt + string
+    
+    if level <= self.verbosity:
+      print txt
+      self.logFile.write(txt + '\n')
+
+  def appendFile(self, level, fileName):
+    try:
+      appFile = open(fileName,'r')
+      self.appendLog(level,appFile.read(),1,1,1)
+      appFile.close()
+    except IOError:
+      self.appendLog(level,'ERROR : Can not open file %s' % fileName)
+
+  def sleep(self, ms):
+    time.sleep(ms/1000.0)
+  
+  def setStartTime(self):
+    self.startTime = time.time()
+    
+  def getRunTime(self):
+    return int(time.time() - self.startTime)
+  
+  def closeLog(self):
+    self.logFile.close()
diff --git a/StationTest/modules/testlog.py b/StationTest/modules/testlog.py
new file mode 100644
index 00000000000..d31e7b62940
--- /dev/null
+++ b/StationTest/modules/testlog.py
@@ -0,0 +1,69 @@
+"""Test logging utilities
+"""
+
+################################################################################
+# System imports
+import time
+
+################################################################################
+# Functions
+
+class Testlog:
+
+  def __init__(self, verbosity=11, testId=None, logName='empty.dat'):
+    self.startTime = time.time()
+    self.verbosity = verbosity
+    self.testId = testId
+    self.logName = logName
+    if logName != None:
+      try:
+        self.logFile = open(self.logName,'w')
+      except IOError:
+        print 'ERROR : Can not open log file %s' % logName
+    self.result = 'RUNONLY'
+    
+  def setId(self, txt):  # Use this method rather than direct access to testId
+    self.testId=txt
+  
+  def setResult(self, res):                     # Use this method rather than direct access to result
+    if res in ['RUNONLY', 'PASSED', 'FAILED']:  # Ignore illegal res
+      if self.result != 'FAILED':               # Once FAILED the result can not be changed
+        self.result=res
+
+  def getResult(self):   # Method alternative for direct access to result
+    return self.result
+    
+  def appendLog(self, level, string, notime=0, nolevel=0, noId=0):
+    txt = ''
+    if notime == 0:
+      t = time.localtime()
+      txt = txt + '[%d:%02d:%02d %02d:%02d:%02d]' % (t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec)
+    if nolevel == 0:
+      txt = txt + ' - (%02d) ' % level
+    if noId == 0:
+      txt = txt + self.testId
+    txt = txt + string
+    
+    if level <= self.verbosity:
+      print txt
+      self.logFile.write(txt + '\n')
+
+  def appendFile(self, level, fileName):
+    try:
+      appFile = open(fileName,'r')
+      self.appendLog(level,appFile.read(),1,1,1)
+      appFile.close()
+    except IOError:
+      self.appendLog(level,'ERROR : Can not open file %s' % fileName)
+
+  def sleep(self, ms):
+    time.sleep(ms/1000.0)
+  
+  def setStartTime(self):
+    self.startTime = time.time()
+    
+  def getRunTime(self):
+    return int(time.time() - self.startTime)
+  
+  def closeLog(self):
+    self.logFile.close()
diff --git a/StationTest/prbs_dir_test.py b/StationTest/prbs_dir_test.py
new file mode 100644
index 00000000000..83709022e53
--- /dev/null
+++ b/StationTest/prbs_dir_test.py
@@ -0,0 +1,114 @@
+
+""" script for testing PRBS data in dir.
+Gijs, 16 dec 07
+"""
+# INIT
+
+import array
+import operator
+import os
+import time
+import commands
+
+# Open file for processing	
+def open_dir() :
+	files = os.listdir('./prbs/.')
+	files.sort()
+#	print files
+        return files
+
+def open_file(files, file_nr) :
+        file_name = './prbs/' + files[file_nr][:]
+ 	if files[file_nr][-3:] == 'dat':
+                fileinfo = os.stat(file_name)
+		size = int(fileinfo.st_size)
+		f=open(file_name,'rb')
+		max_frames = size/(88 + 1024*2 + 4)
+		frames_to_proces=max_frames
+	else :
+		frames_to_proces=0
+		f=open(file_name,'rb')
+	return f, frames_to_proces	
+
+
+# Read single frame from file	
+def read_frame(f, info_plot, frame_nr,f_log):
+	station_info = array.array('B')	  	
+	station_info.fromfile(f,4)       # Bytes 0..3
+	time_info = array.array('L')
+	time_info.fromfile(f,3)          # Bytes 4..15
+	if (info_plot) :
+		time_string = time.ctime(time_info[1])
+#		string_info =  'Frame nr %(FR)d Station %(ST)d  RSP %(RSP)d  RCU %(RCU)d  Sample rate %(S)d MHz  time of data  %(ti_D)s and %(SN)00.6f seconds'%\
+#				{"FR": frame_nr, "ST": station_info[0] ,"RSP": station_info[1], "RCU": station_info[2], "S": station_info[3], "ti_D": time_string,"SN": float(time_info[2])/float(200000000)}
+		string_info =  'Frame nr %(FR)d Station %(ST)d  RSP %(RSP)d  RCU %(RCU)d  Sample rate %(S)d MHz'%\
+				{"FR": frame_nr, "ST": station_info[0] ,"RSP": station_info[1], "RCU": station_info[2], "S": station_info[3]}
+#		print string_info
+		f_log.write(string_info + '\n')
+	div_info = array.array('H')
+	div_info.fromfile(f,36)          # Bytes 16..87
+	
+	# READ DATA SAMPLES
+	data_in = array.array('H')
+	samples = int(div_info[0])
+	data_in.fromfile(f,samples)
+	data_list = data_in.tolist()
+	
+	data_crc = array.array('l')
+	data_crc.fromfile(f,1)
+	return data_list, time_info[1], time_info[2]
+
+
+# Function for testing PRBS data
+def PRBS_CHECK(data_list, prev):
+	samples_chk=0
+	prbs_err=0
+ 	for i in range(0,len(data_list)) :
+		if prev == 0x0FFF :
+			prev = data_list[i] & 0x07FF
+		elif data_list[i] == 0xFFFF :
+			prbs_err = prbs_err + 1
+		else :
+			cur = data_list[i] & 0x0FFE
+			samples_chk = samples_chk + 1
+			if cur != 2*prev :
+				prbs_err = prbs_err + 1
+#				print(str(i) + ' ' + hex(2*prev) + ' ' + hex(cur))
+			prev = data_list[i] & 0x07FF
+	return samples_chk, prbs_err, prev
+
+
+# Main loop
+def main() :
+	files = open_dir()
+	f_log = file('prbs_dir_test.log', 'w')
+	f_log.write('\n \n PRSB test \n \n')
+	for file_cnt in range(len(files)) :
+		prev = 0x0FFF;
+		samples_chk=0
+		prbs_err=0
+		o_ta=0
+		o_tb=0
+		(f, frames_to_proces) = open_file(files, file_cnt)
+		if frames_to_proces >0 :
+			for frame_cnt in range(frames_to_proces):
+				data_list, ta, tb = read_frame(f, (frame_cnt==0), frame_cnt, f_log)
+                                if (((ta==o_ta) and tb==(o_tb+1024)) or (ta == (o_ta+1))) :
+#                                if (tb==(o_tb+1)) :
+                                	prev = prev
+                                else:
+                                	prev=0x0FFF
+				r_samples_chk, r_prbs_err, prev = PRBS_CHECK(data_list, prev)
+				samples_chk = samples_chk + r_samples_chk
+				prbs_err = prbs_err + r_prbs_err
+				o_ta = ta
+				o_tb = tb				
+			# plot results		
+#			print 'Samples checked : ' + str(samples_chk) + ' PRBS errors: ' + str(prbs_err)
+			f_log.write('Samples checked : ' + str(samples_chk) + ' PRBS errors: ' + str(prbs_err) + '\n')
+		
+		f.close
+	f_log.close
+
+if __name__ == "__main__":
+	main()
diff --git a/StationTest/prbs_test.py b/StationTest/prbs_test.py
new file mode 100644
index 00000000000..5dea30abe24
--- /dev/null
+++ b/StationTest/prbs_test.py
@@ -0,0 +1,103 @@
+
+""" script for testing PRBS data in dir.
+Gijs, 16 dec 07
+"""
+# INIT
+
+import array
+import operator
+import os
+import time
+
+# Open file for processing	
+def open_dir() :
+#	os.chdir('c:/test')
+	files = os.listdir('.')
+	return files
+
+def open_file(files, file_nr) :
+	if files[file_nr][-3:] == 'dat':
+		fileinfo = os.stat(files[file_nr])
+		size = int(fileinfo.st_size)
+		f=open(files[file_nr],'rb')
+		max_frames = size/(88 + 1024*2 + 4)
+		frames_to_proces=max_frames
+	else :
+		frames_to_proces=0
+		f=open(files[file_nr],'rb')
+	return f, frames_to_proces	
+	
+
+
+
+# Read single frame from file	
+def read_frame(f, info_plot, frame_nr,f_log):
+	station_info = array.array('B')	  	
+	station_info.fromfile(f,4)       # Bytes 0..3
+	time_info = array.array('L')
+	time_info.fromfile(f,3)           # Bytes 4..15
+	if (info_plot) :
+		time_string = time.ctime(time_info[1])
+		string_info =  'Frame nr %(FR)d Station %(ST)d  RSP %(RSP)d  RCU %(RCU)d  Sample rate %(S)d MHz  time of data  %(ti_D)s and %(SN)00.6f seconds'%\
+				{"FR": frame_nr, "ST": station_info[0] ,"RSP": station_info[1], "RCU": station_info[2], "S": station_info[3], "ti_D": time_string,"SN": float(time_info[2])/float(200000000)}
+		print string_info
+		f_log.write(string_info + '\n')
+	div_info = array.array('H')
+	div_info.fromfile(f,36)             # Bytes 16..87
+	
+	# READ DATA SAMPLES
+	data_in = array.array('H')
+	samples = int(div_info[0])
+	data_in.fromfile(f,samples)
+	data_list = data_in.tolist()
+	
+	data_crc = array.array('l')
+	data_crc.fromfile(f,1)
+	return data_list
+
+
+# Function for testing PRBS data
+def PRBS_CHECK(data_list, prev):
+	samples_chk=0
+	prbs_err=0
+ 	for i in range(0,len(data_list)) :
+		if prev == 0x0FFF :
+			prev = data_list[i] & 0x07FF
+		elif data_list[i] == 0xFFFF :
+					prbs_err = prbs_err + 1
+		else :
+			cur = data_list[i] & 0x0FFE
+			samples_chk = samples_chk + 1
+			if cur != 2*prev :
+				prbs_err = prbs_err + 1
+#				print(str(i) + ' ' + hex(2*prev) + ' ' + hex(cur))
+			prev = data_list[i] & 0x07FF
+	return samples_chk, prbs_err, prev
+
+
+# Main loop
+def main() :
+	files = open_dir()
+	f_log = file('prbs_test.log', 'a')
+	f_log.write('\n \n PRSB test \n \n')
+	for file_cnt in range(len(files)) :
+		prev = 0x0FFF;
+		samples_chk=0
+		prbs_err=0
+		f, frames_to_proces = open_file(files, file_cnt)
+		if frames_to_proces >1 :
+			for frame_cnt in range(frames_to_proces):
+				data_list = read_frame(f, (frame_cnt==0), frame_cnt, f_log)
+				# Test data
+				r_samples_chk, r_prbs_err, prev = PRBS_CHECK(data_list, prev)
+				samples_chk = samples_chk + r_samples_chk
+				prbs_err = prbs_err + r_prbs_err
+				
+			# plot results		
+			print 'Samples checked : ' + str(samples_chk) + ' PRBS errors: ' + str(prbs_err)
+			f_log.write('Samples checked : ' + str(samples_chk) + ' PRBS errors: ' + str(prbs_err) + '\n')
+		
+		f.close
+	f_log.close
+
+main()
diff --git a/StationTest/rmfiles.sh b/StationTest/rmfiles.sh
new file mode 100644
index 00000000000..c80deb914e2
--- /dev/null
+++ b/StationTest/rmfiles.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+rm -f tc/*.log
+rm -f *.log
+rm -f *.diff
+rm -f *.nfo
+rm -f *.dat
diff --git a/StationTest/rsp_version.sh b/StationTest/rsp_version.sh
new file mode 100644
index 00000000000..64d46a8b4cf
--- /dev/null
+++ b/StationTest/rsp_version.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+#
+# Get version info from the RSP boards and compare this with the expected golden result.
+#
+
+rm -f *.log
+rm -f *.diff
+rspctl --version > rsp_version.log
+diff rsp_version.log gold/rsp_version.gold > rsp_version.diff
+if [ -e rsp_version.log ] && [ -e gold/rsp_version.gold ] && [ -e rsp_version.diff ] && ! [ -s rsp_version.diff ]; then
+  # The files exists AND the diff has size 0
+  echo "RSP version test went OK"
+else
+  echo "RSP version test went wrong"
+fi
diff --git a/StationTest/rsp_xc_160.sh b/StationTest/rsp_xc_160.sh
new file mode 100644
index 00000000000..b6c6af8e664
--- /dev/null
+++ b/StationTest/rsp_xc_160.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+#
+# Test the SERDES ring between the RSP by verifing the crosslet statistics.
+#
+
+./xc_160_setup.sh
+
+sleep 2
+
+./xc_160_verify.sh
diff --git a/StationTest/rsp_xc_200.sh b/StationTest/rsp_xc_200.sh
new file mode 100644
index 00000000000..b5afc5a52a6
--- /dev/null
+++ b/StationTest/rsp_xc_200.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+#
+# Test the SERDES ring between the RSP by verifing the crosslet statistics.
+#
+
+./xc_200_setup.sh
+
+sleep 2
+
+./xc_200_verify.sh
diff --git a/StationTest/station_production.py b/StationTest/station_production.py
new file mode 100644
index 00000000000..69507897f3b
--- /dev/null
+++ b/StationTest/station_production.py
@@ -0,0 +1,191 @@
+#
+# Run the production tests for a LOFAR station
+#
+
+import sys
+from optparse import OptionParser
+
+import cli
+import testlog
+
+################################################################################
+# Parse command line for subrack ID
+#
+# -v  0 : only PASSED or FAILED
+# -v  1 : overall title
+# -v 11 : result per test
+# -v 21 : title per test
+  
+op = OptionParser(usage='usage: python %prog [options]', version='%prog 0.1')
+  
+op.add_option('-v', type='int', dest='verbosity',
+  help='Verbosity level',default=11)
+op.add_option('-r', type='int', dest='rsp_nr',
+  help='Provide number of rsp boards that will be used in this test',default=None)
+op.add_option('-t', type='int', dest='tbb_nr',
+  help='Provide number of tbb boards that will be used in this test',default=None)
+
+opts, args = op.parse_args()
+
+# - Option checks and/or reformatting
+if opts.rsp_nr==None:
+  op.error('Option -r must specify the number of rsp boards')
+if opts.tbb_nr==None:
+  op.error('Option -t must specify the number of tbb boards')
+
+
+################################################################################
+# Define subrack testlog class for pass/fail and logging
+vlev = opts.verbosity
+testId = ''
+appLev = False
+logName = '/home/lofartest/subracktest/data/SUBR-%05d-%05d.dat' % (opts.rsp_nr, opts.tbb_nr)
+cli.command('rm -f /home/lofartest/subracktest/data/SUBR-%05d-%05d.dat', appLev) 
+sr = testlog.Testlog(vlev, testId, logName)
+
+sr.setResult('PASSED')
+
+sr.setId('Station - ')
+sr.appendLog(11,'')
+sr.appendLog(1,'Station production test %s' % logName)
+sr.appendLog(11,'')
+
+
+################################################################################
+sr.setId('RSP version - ')
+sr.appendLog(21,'')
+sr.appendLog(21,'### Verify LCU - RSP ethernet link by getting the RSP version info')
+sr.appendLog(21,'')
+res = cli.command('./rsp_version.sh')
+if res.find('wrong')==-1:
+  sr.appendLog(11,'>>> RSP version test went OK')
+else:
+  sr.appendLog(11,'>>> RSP version test went wrong')
+  sr.appendLog(11,'CLI:')
+  sr.appendLog(11,res,1,1,1)
+  sr.appendLog(11,'Result:')
+  sr.appendFile(11,'rsp_version.log')
+  sr.appendLog(11,'Expected:')
+  sr.appendFile(11,'gold/rsp_version.gold')  
+  sr.setResult('FAILED')
+
+
+################################################################################
+sr.setId('TBB version - ')
+sr.appendLog(21,'')
+sr.appendLog(21,'### Verify LCU - TBB ethernet link by getting the TBB version info')
+sr.appendLog(21,'')
+res = cli.command('./tbb_version.sh')
+if res.find('wrong')==-1:
+  sr.appendLog(11,'>>> TBB version test went OK')
+else:
+  sr.appendLog(11,'>>> TBB version test went wrong')
+  sr.appendLog(11,'CLI:')
+  sr.appendLog(11,res,1,1,1)
+  sr.appendLog(11,'Result:')
+  sr.appendFile(11,'tbb_version.log')
+  sr.appendLog(11,'Expected:')
+  sr.appendFile(11,'gold/tbb_version.gold')
+  sr.setResult('FAILED')
+  
+
+################################################################################
+sr.setId('SPU status - ')
+sr.appendLog(21,'')
+sr.appendLog(21,'### Verify the RSP - SPU I2C interface by reading the SPU sensor data')
+sr.appendLog(21,'')
+
+res = cli.command('python i2c_spu.py')
+res = cli.command('python i2c_spu.py')
+if res.find('wrong')==-1:
+  sr.appendLog(11,'>>> RSP - SPU I2c interface test went OK')
+else:
+  sr.appendLog(11,'>>> RSP - SPU I2c interface test went wrong')
+  sr.appendLog(11,'CLI:')
+  sr.appendLog(11,res,1,1,1)
+  sr.appendLog(11,'Result:')
+  sr.appendFile(11,'spustat.log')
+  sr.setResult('FAILED')
+
+
+################################################################################
+sr.setId('TD status - ')
+sr.appendLog(21,'')
+sr.appendLog(21,'### Verify the RSP - TD I2C interface by reading the TD sensor data')
+sr.appendLog(21,'')
+
+res = cli.command('python i2c_td.py')
+if res.find('wrong')==-1:
+  sr.appendLog(11,'>>> RSP - TD I2c interface test went OK')
+else:
+  sr.appendLog(11,'>>> RSP - TD I2c interface test went wrong')
+  sr.appendLog(11,'CLI:')
+  sr.appendLog(11,res,1,1,1)
+  sr.appendLog(11,'Result:')
+  sr.appendFile(11,'tdstat.log')
+  sr.setResult('FAILED')
+
+
+################################################################################
+sr.setId('RCU-RSP - ')
+sr.appendLog(21,'')
+sr.appendLog(21,'### Verify the RCU -> RSP LVDS interfaces by capturing pseudo random data on RSP')
+sr.appendLog(21,'')
+
+
+res = cli.command('python verify.py --brd rsp0,rsp1,rsp2,rsp3 --fpga blp0,blp1,blp2,blp3 --pol x,y --rep 1 -v 11 --te tc/prsg.py')
+
+if res.find('FAILED')==-1:
+  sr.appendLog(11,'>>> RCU-RSP interface test went OK')
+  sr.appendFile(21,'tc/prsg.log')
+else:
+  sr.appendLog(11,'>>> RCU-RSP interface test went wrong')
+  sr.appendLog(11,'CLI:')
+  sr.appendLog(11,res,1,1,1)
+  sr.appendFile(11,'tc/prsg.log')
+  sr.setResult('FAILED')
+
+################################################################################
+sr.setId('Serdes ring -')
+sr.appendLog(21,'')
+sr.appendLog(21,'### Verify the Serdes ring connection between the RSP boards')
+sr.appendLog(21,'')
+
+res = cli.command('python verify.py --brd rsp0,rsp1,rsp2,rsp3,rsp4,rsp5,rsp6,rsp7,rsp8,rsp9,rsp10,rsp11 --rep 1 -v 21 --te tc/serdes.py')
+
+if res.find('FAILED')==-1:
+  sr.appendLog(11,'>>> Serdes ring test went OK')
+  sr.appendLog(21,'tc/serdes.log')
+else:
+  sr.appendLog(11,'>>> Serdes ring test went wrong')
+  sr.appendLog(11,'CLI:')
+  sr.appendLog(11,res,1,1,1)
+  sr.appendLog(11,'tc/serdes.log')
+  sr.appendLog('FAILED')
+
+  
+
+################################################################################
+sr.setId('RCU-RSP-TBB - ')
+sr.appendLog(21,'')
+sr.appendLog(21,'### Verify the RCU - RSP - TBB LVDS interfaces by capturing pseudo random data on TBB')
+sr.appendLog(21,'')
+
+res = cli.command('./tbb_prbs_tester.sh')
+if res.find('wrong')==-1:
+  sr.appendLog(11,'>>> RCU - RSP - TBB LVDS interfaces test went OK')
+else:
+  sr.appendLog(11,'>>> RCU - RSP - TBB LVDS interfaces went wrong')
+  sr.appendLog(11,'CLI:')
+  sr.appendLog(11,res,1,1,1)
+  sr.setResult('FAILED')
+
+
+################################################################################
+# End of the subrack test
+
+sr.setId('Subrack - ')
+dt = sr.getRunTime()
+sr.appendLog(2,'Duration: %02dm:%02ds' % (dt/60 % 60, dt % 60))
+sr.appendLog(0,sr.getResult())
+sr.closeLog()
diff --git a/StationTest/subrack_production.py b/StationTest/subrack_production.py
new file mode 100644
index 00000000000..a70b196447c
--- /dev/null
+++ b/StationTest/subrack_production.py
@@ -0,0 +1,170 @@
+#
+# Run the production tests for a LOFAR station subrack
+#
+
+import sys
+from optparse import OptionParser
+
+import cli
+import testlog
+
+################################################################################
+# Parse command line for subrack ID
+#
+# -v  0 : only PASSED or FAILED
+# -v  1 : overall title
+# -v 11 : result per test
+# -v 21 : title per test
+  
+op = OptionParser(usage='usage: python %prog [options]', version='%prog 0.1')
+  
+op.add_option('-v', type='int', dest='verbosity',
+  help='Verbosity level',default=11)
+op.add_option('-b', type='int', dest='batch_nr',
+  help='Provide subrack batch number that will be used for the log file name',default=None)
+op.add_option('-s', type='int', dest='serial_nr',
+  help='Provide subrack serial number that will be used for the log file name',default=None)
+
+opts, args = op.parse_args()
+
+# - Option checks and/or reformatting
+if opts.batch_nr==None:
+  op.error('Option -b must specify a subrack batch number')
+if opts.serial_nr==None:
+  op.error('Option -s must specify a subrack serial number')
+
+
+################################################################################
+# Define subrack testlog class for pass/fail and logging
+vlev = opts.verbosity
+testId = ''
+appLev = False
+logName = '/home/lofartest/subracktest/data/SUBR-%05d-%05d.dat' % (opts.batch_nr, opts.serial_nr)
+cli.command('rm -f /home/lofartest/subracktest/data/SUBR-%05d-%05d.dat', appLev) 
+sr = testlog.Testlog(vlev, testId, logName)
+
+sr.setResult('PASSED')
+
+sr.setId('Subrack - ')
+sr.appendLog(11,'')
+sr.appendLog(1,'Subrack production test %s' % logName)
+sr.appendLog(11,'')
+
+
+################################################################################
+sr.setId('RSP version - ')
+sr.appendLog(21,'')
+sr.appendLog(21,'### Verify LCU - RSP ethernet link by getting the RSP version info')
+sr.appendLog(21,'')
+res = cli.command('./rsp_version.sh')
+if res.find('wrong')==-1:
+  sr.appendLog(11,'>>> RSP version test went OK')
+else:
+  sr.appendLog(11,'>>> RSP version test went wrong')
+  sr.appendLog(11,'CLI:')
+  sr.appendLog(11,res,1,1,1)
+  sr.appendLog(11,'Result:')
+  sr.appendFile(11,'rsp_version.log')
+  sr.appendLog(11,'Expected:')
+  sr.appendFile(11,'gold/rsp_version.gold')  
+  sr.setResult('FAILED')
+
+
+################################################################################
+sr.setId('TBB version - ')
+sr.appendLog(21,'')
+sr.appendLog(21,'### Verify LCU - TBB ethernet link by getting the TBB version info')
+sr.appendLog(21,'')
+res = cli.command('./tbb_version.sh')
+if res.find('wrong')==-1:
+  sr.appendLog(11,'>>> TBB version test went OK')
+else:
+  sr.appendLog(11,'>>> TBB version test went wrong')
+  sr.appendLog(11,'CLI:')
+  sr.appendLog(11,res,1,1,1)
+  sr.appendLog(11,'Result:')
+  sr.appendFile(11,'tbb_version.log')
+  sr.appendLog(11,'Expected:')
+  sr.appendFile(11,'gold/tbb_version.gold')
+  sr.setResult('FAILED')
+ 
+
+################################################################################
+sr.setId('SPU status - ')
+sr.appendLog(21,'')
+sr.appendLog(21,'### Verify the RSP - SPU I2C interface by reading the SPU sensor data')
+sr.appendLog(21,'')
+
+res = cli.command('python i2c_spu.py')
+res = cli.command('python i2c_spu.py')
+if res.find('wrong')==-1:
+  sr.appendLog(11,'>>> RSP - SPU I2c interface test went OK')
+else:
+  sr.appendLog(11,'>>> RSP - SPU I2c interface test went wrong')
+  sr.appendLog(11,'CLI:')
+  sr.appendLog(11,res,1,1,1)
+  sr.appendLog(11,'Result:')
+  sr.appendFile(11,'spustat.log')
+  sr.setResult('FAILED')
+
+
+################################################################################
+sr.setId('TD status - ')
+sr.appendLog(21,'')
+sr.appendLog(21,'### Verify the RSP - TD I2C interface by reading the TD sensor data')
+sr.appendLog(21,'')
+
+res = cli.command('python i2c_td.py')
+if res.find('wrong')==-1:
+  sr.appendLog(11,'>>> RSP - TD I2c interface test went OK')
+else:
+  sr.appendLog(11,'>>> RSP - TD I2c interface test went wrong')
+  sr.appendLog(11,'CLI:')
+  sr.appendLog(11,res,1,1,1)
+  sr.appendLog(11,'Result:')
+  sr.appendFile(11,'tdstat.log')
+  sr.setResult('FAILED')
+
+
+################################################################################
+sr.setId('RCU-RSP - ')
+sr.appendLog(21,'')
+sr.appendLog(21,'### Verify the RCU -> RSP LVDS interfaces by capturing pseudo random data on RSP')
+sr.appendLog(21,'')
+
+res = cli.command('python verify.py --brd rsp0,rsp1,rsp2,rsp3 --fpga blp0,blp1,blp2,blp3 --pol x,y --rep 1 -v 11 --te tc/prsg.py')
+if res.find('FAILED')==-1:
+  sr.appendLog(11,'>>> RCU-RSP interface test went OK')
+  sr.appendFile(21,'tc/prsg.log')
+else:
+  sr.appendLog(11,'>>> RCU-RSP interface test went wrong')
+  sr.appendLog(11,'CLI:')
+  sr.appendLog(11,res,1,1,1)
+  sr.appendFile(11,'tc/prsg.log')
+  sr.setResult('FAILED')
+
+
+################################################################################
+sr.setId('RCU-RSP-TBB - ')
+sr.appendLog(21,'')
+sr.appendLog(21,'### Verify the RCU - RSP - TBB LVDS interfaces by capturing pseudo random data on TBB')
+sr.appendLog(21,'')
+
+res = cli.command('./tbb_prbs_tester.sh')
+if res.find('wrong')==-1:
+  sr.appendLog(11,'>>> RCU - RSP - TBB LVDS interfaces test went OK')
+else:
+  sr.appendLog(11,'>>> RCU - RSP - TBB LVDS interfaces went wrong')
+  sr.appendLog(11,'CLI:')
+  sr.appendLog(11,res,1,1,1)
+  sr.setResult('FAILED')
+
+
+################################################################################
+# End of the subrack test
+
+sr.setId('Subrack - ')
+dt = sr.getRunTime()
+sr.appendLog(2,'Duration: %02dm:%02ds' % (dt/60 % 60, dt % 60))
+sr.appendLog(0,sr.getResult())
+sr.closeLog()
diff --git a/StationTest/subracktest.sh b/StationTest/subracktest.sh
new file mode 100644
index 00000000000..4ac35bcf8ff
--- /dev/null
+++ b/StationTest/subracktest.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+#
+# Run the tests for a LOFAR station subrack
+#
+
+# Verify LCU - RSP, LCU - TBB ethernet links by getting the version info
+./rsp_version.sh
+./tbb_version.sh
+
+# Verify the RSP internal interfaces (Ethernet LCU, Ethernet CEP, 10 Gb Serdes, LVDS ring) by running the BIST
+python verify.py --brd rsp0,rsp1,rsp2,rsp3 --rep 1 -v 11 --te tc/bist.py
+
+# Verify the RSP - SPU, TD I2C interface by reading the sensor data
+python i2c_spu.py
+python i2c_td.py
+
+# Verify the RSP - RSP SERDES links using pseudo random data
+python verify.py --brd rsp0,rsp1,rsp2,rsp3 --rep 1 -v 11 --te tc/serdes.py --mode tx_rx
+
+# Verify the RSP - RSP SERDES links by capturing cross correlation statistics
+./rsp_xc_200.sh
+
+# Verify the RCU -> RSP LVDS interfaces by capturing pseudo random data on RSP
+python verify.py --brd rsp0,rsp1,rsp2,rsp3 --fpga blp0,blp1,blp2,blp3 --pol x,y --rep 1 -v 11 --te tc/prsg.py
+
+# Verify the RCU -> RSP -> TBB LVDS interfaces by capturing pseudo random data on TBB
+./tbb_prbs_tester.sh
+
diff --git a/StationTest/tbb_prbs_tester.sh b/StationTest/tbb_prbs_tester.sh
new file mode 100644
index 00000000000..4390bb7c21e
--- /dev/null
+++ b/StationTest/tbb_prbs_tester.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+#
+# Test the LVDS interfaces between RCU -> RSP -> TBB using the Pseudo Random generator in the RCUs.
+#
+
+nof_rcu=32
+
+rm -f *.log
+rm -f *.diff
+rm -f ./prbs/*.*
+rm -f ./prbs/.*
+
+
+# Set up RCU and RSP, make sure waveform generator is off
+rspctl --rcuprsg=1
+sleep 1
+rspctl --tbbmode=transient
+
+sleep 5
+# set up TBB
+nof_slices=10   # one slice contains 1024 transient (raw data) samples
+
+tbbctl --free
+tbbctl --alloc
+tbbctl --rec
+
+sleep 0.1
+
+# Freeze and get the captured data from TBB
+cd ./prbs
+tbbctl --stop
+for ((i = 0; i < $nof_rcu; i++)) do
+  tbbctl --readpage=$i,0,$nof_slices
+done
+cd ..
+# Verify the PRBS
+python prbs_dir_test.py
+
+
+echo ""
+diff prbs_dir_test.log ./gold/prbs_dir_test.gold > prbs_dir_test.diff
+if [ -e prbs_dir_test.log ] && [ -e ./gold/prbs_dir_test.gold ] && [ -e prbs_dir_test.diff ] && ! [ -s prbs_dir_test.diff ]; then
+  # The files exists AND has the diff size 0
+  echo "RCU -> RSP -> TBB interfaces test went OK"
+else
+  echo "RCU -> RSP -> TBB interfaces test went wrong"
+fi
diff --git a/StationTest/tbb_version.sh b/StationTest/tbb_version.sh
new file mode 100644
index 00000000000..c9b8155367c
--- /dev/null
+++ b/StationTest/tbb_version.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+#
+# Get version info from the TBB boards and compare this with the expected golden result.
+#
+
+rm -f *.log
+rm -f *.diff
+tbbctl --version --select=0,1 > tbb_version.log
+diff tbb_version.log gold/tbb_version.gold > tbb_version.diff
+if [ -e tbb_version.log ] && [ -e gold/tbb_version.gold ] && [ -e tbb_version.diff ] && ! [ -s tbb_version.diff ]; then
+  # The files exists AND has the diff size 0
+  echo "TBB version test went OK"
+else
+  echo "TBB version test went wrong"
+fi
diff --git a/StationTest/tc/Makefile.am b/StationTest/tc/Makefile.am
new file mode 100644
index 00000000000..8bee11394e1
--- /dev/null
+++ b/StationTest/tc/Makefile.am
@@ -0,0 +1,15 @@
+testdir		 =  $(prefix)/stationtest/tc
+test_SCRIPTS = 	bist.py \
+				empty.py \
+				hba_client.py \
+				hba_server.py \
+				prsg.py \
+				rad_lanemode.py \
+				rad_latency.py \
+				serdes.py \
+				spustat.py \
+				status.py \
+				sync_delay.py \
+				tdstat.py
+
+include $(top_srcdir)/Makefile.common
diff --git a/StationTest/tc/bist.py b/StationTest/tc/bist.py
new file mode 100644
index 00000000000..4f44e401d83
--- /dev/null
+++ b/StationTest/tc/bist.py
@@ -0,0 +1,146 @@
+"""Run the BIST messages manually, based on TCL testcase 11.5.
+"""
+
+# See bist/src/data/bist_msgrom.txt
+
+################################################################################
+# - Verify options
+rspId = tc.rspId
+bpId = ['rsp']
+fpgaId = ['rsp', 'blp0', 'blp1', 'blp2', 'blp3']
+
+tc.appendLog(11, '')
+tc.appendLog(11, '>>> Run the BIST messages manually on RSP-%s' % rspId)
+tc.appendLog(11, '')
+  
+################################################################################
+# - Test selections
+tst_duration = rsp.c_diag_duration_quick     # 1 = quick
+tst_duration = rsp.c_diag_duration_normal    # 2 = normal
+tst_lane = 0
+
+# Ensure CR ext sync is enabled 
+#rsp.write_cr_syncon(tc, msg, fpgaId, rspId)
+  
+# - Overwrite 20 (= 0x10+0x04) RSR selftest result fields with FE starting at offset 30 (= 0x1E).
+#
+#   ty st frlen blp rsp  pi rg  offset payld  seqnr  rsvd   Data ...
+#   02 00 20 00 00  01   01 00  1E 00  10 00  01 00  00 00  FE FE FE FE  FE FE FE FE  FE FE FE FE  FE FE FE FE
+#   02 00 14 00 00  01   01 00  2E 00  04 00  02 00  00 00  FE FE FE FE  00 00 00 00  00 00 00 00  00 00 00 00
+#
+value = 0xFE
+rsp.overwrite_rsr(tc, msg, 'mep', value, rspId)
+rsp.overwrite_rsr(tc, msg, 'diag', value, rspId)
+  
+# Check overwriten RSR DIAG
+for ri in rspId:
+  rsp.read_rsr(tc, msg, 'diag', [ri], 31)
+  
+# - Write DIAG selftest for LCU
+#
+#   ty st frlen blp rsp  pi rg  offset payld  seqnr  rsvd   Data ...
+#   02 00 14 00 00  01   03 06  00 00  04 00  03 00  00 00  03 01 02 00  00 00 00 00  00 00 00 00  00 00 00 00
+#
+tst_interface = rsp.c_diag_dev_lcu          # 3 = LCU
+tst_mode      = rsp.c_diag_mode_loop_local  # 1 = loop local
+selftest = [tst_interface, tst_mode, tst_duration, tst_lane]
+for ri in rspId:
+  rsp.write_diag_selftest(tc, msg, selftest, bpId, [ri], 99)
+tc.sleep(7000)
+  
+# - Write DIAG selftest for CEP
+#
+#   ty st frlen blp rsp  pi rg  offset payld  seqnr  rsvd   Data ...
+#   02 00 14 00 00  01   03 06  00 00  04 00  04 00  00 00  04 01 02 00  00 00 00 00  00 00 00 00  00 00 00 00
+#
+tst_interface = rsp.c_diag_dev_cep          # 4 = CEP
+tst_mode      = rsp.c_diag_mode_loop_local  # 1 = loop local
+selftest = [tst_interface, tst_mode, tst_duration, tst_lane]
+for ri in rspId:
+  rsp.write_diag_selftest(tc, msg, selftest, bpId, [ri], 99)
+tc.sleep(5000)
+  
+# - Write DIAG selftest for SERDES
+#
+#   ty st frlen blp rsp  pi rg  offset payld  seqnr  rsvd   Data ...
+#   02 00 14 00 00  01   03 06  00 00  04 00  05 00  00 00  05 01 02 00  00 00 00 00  00 00 00 00  00 00 00 00
+#
+tst_interface = rsp.c_diag_dev_serdes       # 5 = SERDES
+tst_mode      = rsp.c_diag_mode_loop_local  # 1 = loop local
+selftest = [tst_interface, tst_mode, tst_duration, tst_lane]
+for ri in rspId:
+  rsp.write_diag_selftest(tc, msg, selftest, bpId, [ri], 99)
+tc.sleep(1000)
+  
+# - Write DIAG selftest for RI
+#
+#   ty st frlen blp rsp  pi rg  offset payld  seqnr  rsvd   Data ...
+#   02 00 14 00 0F  01   03 06  00 00  04 00  06 00  00 00  00 06 02 00  00 00 00 00  00 00 00 00  00 00 00 00
+#
+tst_interface = rsp.c_diag_dev_ri           # 0 = RI
+tst_mode      = rsp.c_diag_mode_bus         # 6 = mode bus is mode tx,rx
+selftest = [tst_interface, tst_mode, tst_duration, tst_lane]
+for ri in rspId:
+  rsp.write_diag_selftest(tc, msg, selftest, fpgaId, [ri], 99)
+tc.sleep(1000)
+  
+# - Read RSR to get BIST result, starting with MEP status error field (offset 0x1A) and length 0x18 bytes
+#
+#   ty st frlen blp rsp  pi rg  offset payld  seqnr  rsvd   Data ...
+#   01 00 10 00 00  01   01 00  1A 00  18 00  07 00  00 00  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00
+#
+for ri in rspId:
+  rsp.read_mem(tc, msg, 'rsr', 'status', rsp.c_ei_status_rsr_size, bpId, [ri], 'h', 1, rsp.c_ei_status_rsr_offset)
+  
+  msg.setOffset(rsp.c_ei_status_mep_offset)
+  dummy          = msg.readUnsigned(2)
+  mep_prev_msg   = msg.readUnsigned(1)
+  dummy          = msg.readUnsigned(1)
+
+  msg.setOffset(rsp.c_ei_status_diag_offset)
+  # DIAG status
+  diag_interface = msg.readUnsigned(1)
+  diag_mode      = msg.readUnsigned(1)
+  diag_ri_bp     = msg.readUnsigned(2)
+  diag_rcux      = msg.readUnsigned(2)
+  diag_rcuy      = msg.readUnsigned(2)
+  diag_eth_LCU   = msg.readUnsigned(2)
+  diag_eth_CEP   = msg.readUnsigned(2)
+  diag_serdes    = msg.readUnsigned(2)
+  diag_ri_ap0    = msg.readUnsigned(2)
+  diag_ri_ap1    = msg.readUnsigned(2)
+  diag_ri_ap2    = msg.readUnsigned(2)
+  diag_ri_ap3    = msg.readUnsigned(2)
+
+  # Verify
+  if mep_prev_msg == 0                 and \
+     diag_ri_bp   == rsp.c_diag_res_ok and \
+     diag_rcux    != rsp.c_diag_res_ok and \
+     diag_rcuy    != rsp.c_diag_res_ok and \
+     diag_eth_LCU == rsp.c_diag_res_ok and \
+     diag_eth_CEP == rsp.c_diag_res_ok and \
+     diag_serdes  == rsp.c_diag_res_ok and \
+     diag_ri_ap0  == rsp.c_diag_res_ok and \
+     diag_ri_ap1  == rsp.c_diag_res_ok and \
+     diag_ri_ap2  == rsp.c_diag_res_ok and \
+     diag_ri_ap3  == rsp.c_diag_res_ok:
+    tc.appendLog(11, 'RSP-%s : BIST sequence went OK' % ri)
+    tc.setResult('PASSED')
+  else:
+    tc.appendLog(11, 'RSP-%s : BIST sequence went wrong:' % ri)
+    tc.appendLog(11, '  mep msg = %d' % mep_prev_msg)
+    tc.appendLog(11, '  ri-bp   = %d' % diag_ri_bp)
+    tc.appendLog(11, '  rcux    = %d' % diag_rcux)
+    tc.appendLog(11, '  rcuy    = %d' % diag_rcuy)
+    tc.appendLog(11, '  eth-LCU = %d' % diag_eth_LCU)
+    tc.appendLog(11, '  eth-CEP = %d' % diag_eth_CEP)
+    tc.appendLog(11, '  serdes  = %d' % diag_serdes)
+    tc.appendLog(11, '  ri-ap0  = %d' % diag_ri_ap0)
+    tc.appendLog(11, '  ri-ap1  = %d' % diag_ri_ap1)
+    tc.appendLog(11, '  ri-ap2  = %d' % diag_ri_ap2)
+    tc.appendLog(11, '  ri-ap3  = %d' % diag_ri_ap3)
+    tc.setResult('FAILED')
+  
+# Read RSR DIAG again to also display result in text instead of numbers
+for ri in rspId:
+  rsp.read_rsr(tc, msg, 'diag', [ri], 21)
diff --git a/StationTest/tc/empty.py b/StationTest/tc/empty.py
new file mode 100644
index 00000000000..0f6116eefa8
--- /dev/null
+++ b/StationTest/tc/empty.py
@@ -0,0 +1,2 @@
+"""Empty testcase"""
+
diff --git a/StationTest/tc/hba_client.py b/StationTest/tc/hba_client.py
new file mode 100644
index 00000000000..6d74e533d8f
--- /dev/null
+++ b/StationTest/tc/hba_client.py
@@ -0,0 +1,167 @@
+"""Write and readback HBA client registers, based on TCL testcase 5.42
+
+   - Specific arguments
+     . client_rcu    : RCU to use for the HBA client I2C access, x or y
+     . client_access : r = read only, w = write only, wr = first write then readback
+     . client_reg    : client register to access: request, response, led, vref, version, speed
+     . data          : data byte(s) to write or verify read
+"""
+
+################################################################################
+# - Verify options
+rspId = tc.rspId
+blpId = tc.blpId
+repeat = tc.repeat    # When > 1 then the register access will be repeated
+
+# - Rename testcase specific options
+arg_rcu    = arg_hba_client_rcu
+arg_access = arg_hba_client_access
+arg_reg    = arg_hba_client_reg
+
+# Get rcuId
+rcuId = [arg_rcu]
+
+# Adapt access format
+if arg_access == 'w':
+  str_access = 'Write'
+elif arg_access == 'r':
+  str_access = 'Read'
+else:
+  str_access = 'Write and read'
+  arg_access = 'wr'
+
+tc.setResult('PASSED')
+  
+tc.appendLog(11, '')
+tc.appendLog(11, '>>> %s access of RSP-%s, BLP-%s, HBA client register %s via I2C access of RCU-%s' % (str_access, rspId, blpId, arg_reg, arg_rcu))
+tc.appendLog(11, '')
+
+################################################################################
+# - Testcase initializations
+
+# - Disable external sync
+rsp.write_cr_syncoff(tc, msg, blpId, rspId)
+
+# - Prepare the protocol list for RCU control register
+addr          = rsp.c_rcuh_i2c_addr_hba       # HBA client I2C address (7 bit)
+  
+cmd_request   = rsp.c_hba_cmd_request
+cmd_response  = rsp.c_hba_cmd_response
+cmd_led       = rsp.c_hba_cmd_led
+cmd_vref      = rsp.c_hba_cmd_vref
+cmd_speed     = rsp.c_hba_cmd_speed
+cmd_version   = rsp.c_hba_cmd_version
+  
+f_set_byte    = rsp.c_hba_f_set_byte
+f_get_byte    = rsp.c_hba_f_get_byte
+f_set_word    = rsp.c_hba_f_set_word
+f_get_word    = rsp.c_hba_f_get_word
+  
+bc_server     = rsp.c_hba_bc_server
+first_server  = 1
+last_server   = 16
+  
+reg_xdelay    = rsp.c_hba_sreg_xdelay
+
+# Select register
+if arg_reg == 'request':
+  cmd      = cmd_request
+  data_len = 2*(last_server - first_server + 1)
+  data     = []                 # primary data values
+  data.append(bc_server)
+  data.append(5 + data_len)
+  data.append(f_set_word)
+  data.append(reg_xdelay)
+  data.append(first_server)
+  data.append(last_server)
+  data2    = data               # alternate data values
+  for i in range(data_len):
+    data.append(i)              # count up data
+    data2.append(data_len - i)  # count down data
+elif arg_reg == 'response':
+  cmd   = cmd_response
+  data  = [17, 37, 59, 214]
+  data2 = [97, 231, 1, 14]
+elif arg_reg == 'led':
+  cmd   = cmd_led
+  data  = arg_data     # HBA client LED on  > 0
+  data2 = 0            # HBA client LED off = 0
+elif arg_reg == 'vref':
+  cmd   = cmd_vref
+  data  = arg_data     # HBA client VREF setting, see pic16f87 manual
+  data2 = 236          # HBA client default VREF "11101100", [5]=1 for 24 steps, [3:0]=12 for mid level
+elif arg_reg == 'speed':
+  cmd   = cmd_speed
+  data  = arg_data     # HBA modem default speed setting is 40
+  data2 = 41
+elif arg_reg == 'version':
+  cmd   = cmd_version
+  data  = arg_data     # HBA client version write access should be ignored
+  data2 = 29
+else:
+  tc.appendLog(11, 'Register -%s- is unknown or not supported!' % arg_reg)
+  sys.exit()
+
+# - HBA modem timing
+msec     = rsp.c_msec
+bc_wait  = rsp.hba_bc_wait
+gap_wait = rsp.hba_gap_wait
+bc_i2c   = rsp.hba_bc_i2c
+reg_i2c  = rsp.hba_reg_i2c
+
+for rep in range(1,1+repeat):
+  reg_dat = data
+  if repeat > 1:
+    tc.appendLog(11, '>>> %s' % rep)
+    if (rep % 2)==0 and arg_access != 'r':
+      reg_dat = data2           # alternate between write data and write data2
+      
+  protocol_list = []
+  exp_result    = []
+  if arg_access == 'wr' or arg_access == 'w':
+    protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_WRITE_BLOCK_NO_CNT', len(reg_dat), addr, reg_dat, cmd))
+    exp_result.append(0)
+  if arg_access == 'wr' and arg_reg == 'request':
+    # Broadcast request takes modem time, 38 msec seems minimum for broadcast 16 servers and modem speed = 40,
+    # other I2C only register accesses do not need wait.
+    protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_WAIT', bc_wait * msec))
+    exp_result.append(0)
+  else:
+    # Default I2C client register access wait time
+    protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_WAIT', gap_wait * msec))
+    exp_result.append(0)
+  if arg_access == 'wr' or arg_access == 'r':
+    protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_READ_BLOCK_NO_CNT', len(reg_dat), addr, None, cmd))
+    exp_result.extend(reg_dat)
+    exp_result.append(0)
+  protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_END'))
+  exp_result.append(0)
+
+  # - Overwrite and read the protocol results from the RCUH
+  rsp.overwrite_rd_smbh_protocol_results(tc, msg, 'rcuh', rcuId, blpId, rspId)
+   
+  # - Write (and readback) the protocol list to the RCUH
+  rsp.write_rd_smbh_protocol_list(tc, msg, 'rcuh', protocol_list, rcuId, blpId, rspId)
+
+  # - Apply altsync to start the RCUH SMBus protocols
+  rsp.write_rsu_altsync(tc, msg, rspId)
+  tc.sleep(bc_i2c + bc_wait + reg_i2c)
+  
+  # Read the protocol results from the RCUH
+  for ri in rspId:
+    for bi in blpId:
+      for pi in rcuId:
+        rd_result = smbus.read_results(tc, msg, 'rcuh', len(exp_result), pi, [bi], [ri])
+        # Equal?
+        if rd_result == exp_result:
+          tc.appendLog(21, '>>> RSP-%s, BLP-%s, RCU-%s, HBA client I2C access result buffer contents is OK' % (ri, bi, pi))
+        else:
+          tc.appendLog(11, '>>> RSP-%s, BLP-%s, RCU-%s, HBA client I2C access result buffer contents is wrong:' % (ri, bi, pi))
+          tc.appendLog(11, 'Expected protocol result: %s' % exp_result)
+          tc.appendLog(11, 'Read     protocol result: %s' % rd_result)
+          tc.setResult('FAILED')
+    
+  #tc.sleep(1000)
+      
+# - Enable external sync
+rsp.write_cr_syncon(tc, msg, blpId, rspId)
diff --git a/StationTest/tc/hba_server.py b/StationTest/tc/hba_server.py
new file mode 100644
index 00000000000..7aa8be90387
--- /dev/null
+++ b/StationTest/tc/hba_server.py
@@ -0,0 +1,337 @@
+"""HBA server access via modem, based on TCL testcase 5.43
+
+  - Specific arguments:
+     . client_rcu    : RCU to use for the HBA client I2C access, x or y
+     . server        : first server number and last server number: first,last
+     . server_access : bc = broadcast to all servers, uc = unicast to first server
+     . server_func   : server function: gb, gw, sb, sw
+     . server_reg    : server register: delay_x, delay_y, version, address
+     . data          : data byte(s) to write or verify for each server
+     . count         : use counter data for each write request (instead of data)
+     . rand          : use random data for each write request (instead of data)
+"""
+
+################################################################################
+# - Verify options
+rspId = tc.rspId
+blpId = tc.blpId
+repeat = tc.repeat    # When > 1 then the register access will be repeated
+
+# - Rename testcase specific options
+arg_rcu    = arg_hba_client_rcu
+arg_server = arg_hba_server
+arg_access = arg_hba_server_access
+arg_func   = arg_hba_server_function
+arg_reg    = arg_hba_server_reg
+
+# Get rcuId
+rcuId = [arg_rcu]
+
+# Adapt access format
+if arg_access == 'bc':
+  str_access = 'broadcast'
+else:
+  str_access = 'unicast'
+  arg_access = 'uc'
+
+# Get server addresses
+bc_server = rsp.c_hba_bc_server
+if arg_access == 'bc':
+  first_server = arg_server[0]
+  last_server  = arg_server[1]
+else:
+  first_server = arg_server[0]
+  last_server  = first_server
+if first_server > last_server:
+  tc.appendLog(11, 'First server %d must be <= last server %d!' % (first_server, last_server))
+  sys.exit()
+elif last_server - first_server + 1 > 16:
+  tc.appendLog(11, 'Maximum first server %d to %d range is 16!' % (first_server, last_server))
+  sys.exit()
+elif first_server < 1 or first_server > 127:
+  tc.appendLog(11, 'First server %d must be in range 1 to 127!' % first_server)
+  sys.exit()
+elif last_server < 1 or last_server > 127:
+  tc.appendLog(11, 'Last server %d must be in range 1 to 127!' % last_server)
+  sys.exit()
+  
+# Get function
+f_set_byte = rsp.c_hba_f_set_byte
+f_get_byte = rsp.c_hba_f_get_byte
+f_set_word = rsp.c_hba_f_set_word
+f_get_word = rsp.c_hba_f_get_word
+if arg_func == 'sb':
+  funcId    = f_set_byte
+  funcSet   = 1
+  funcWidth = 1
+elif arg_func == 'gb':
+  funcId    = f_get_byte
+  funcSet   = 0
+  funcWidth = 1
+elif arg_func == 'sw':
+  funcId    = f_set_word
+  funcSet   = 1
+  funcWidth = 2
+elif arg_func == 'gw':
+  funcId    = f_get_word
+  funcSet   = 0
+  funcWidth = 2
+else:
+  tc.appendLog(11, 'Function -%s- is unknown or not supported!' % arg_func)
+  sys.exit()
+  
+# Get server register
+if arg_reg == 'delay_x':
+  sreg = rsp.c_hba_sreg_xdelay           # HBA server frontend X delay register
+elif arg_reg == 'delay_y':
+  sreg = rsp.c_hba_sreg_ydelay           # HBA server frontend Y delay register
+  if funcWidth != 1 and funcSet == 1:
+    tc.appendLog(11, 'Combination -%s- and -%s- is not supported!' % (arg_func, arg_reg))
+    sys.exit()
+elif arg_reg == 'version':
+  sreg = rsp.c_hba_sreg_version          # HBA server version register
+  if funcWidth != 1 and funcSet == 1:
+    tc.appendLog(11, 'Combination -%s- and -%s- is not supported!' % (arg_func, arg_reg))
+    sys.exit()
+elif arg_reg == 'address':
+  sreg = rsp.c_hba_sreg_address          # HBA server address register
+  if funcWidth != 1 and funcSet == 1:
+    tc.appendLog(11, 'Combination -%s- and -%s- is not supported!' % (arg_func, arg_reg))
+    sys.exit()
+else:
+  tc.appendLog(11, 'Server register -%s- is unknown or not supported!' % arg_reg)
+  sys.exit()
+  
+# Define the server data: count values for bc and arg_data for uc
+data    = range(2)
+data[0] = arg_data[0]
+data[1] = 0
+if len(arg_data) == 2:
+  data[1] = arg_data[1]
+
+server_data = range(256)
+for i in range(256):
+  server_data[i]    = range(2)
+  server_data[i][0] = 0
+  server_data[i][1] = 0
+  
+if arg_access == 'bc':
+  for si in range(first_server, last_server+1):
+    offset = 1
+    for di in range(funcWidth):
+      server_data[si][di] = funcWidth*(si-first_server)+offset
+      offset += 1
+else:
+  for di in range(funcWidth):
+    server_data[first_server][di] = data[di]
+  
+# Init random seed to allow reproduceble results for arg_rand
+random.seed(0)
+    
+tc.setResult('PASSED')
+  
+tc.appendLog(11, '')
+tc.appendLog(11, '>>> HBA server access of RSP-%s, BLP-%s via I2C access and control modem of RCU-%s' % (rspId, blpId, rcuId))
+tc.appendLog(11, '   Server access   : str_access')
+if arg_access == 'bc':
+  tc.appendLog(11, '   First server    : %d' % first_server)
+  tc.appendLog(11, '   Last server     : %d' % last_server)
+else:
+  tc.appendLog(11, '   Server address  : %d' % first_server)
+tc.appendLog(11, '   Function        : %s' % arg_func)
+tc.appendLog(11, '   Register        : %s' % arg_reg)
+if funcSet == 1:
+  if arg_count==1:
+    tc.appendLog(11, '   Server data     : Counter')
+  elif arg_rand==1:
+    tc.appendLog(11, '   Server data     : Random')
+  else:
+    tc.appendLog(11, '   Server data     :')
+    for si in range(first_server, last_server+1):
+      if funcWidth == 1:
+        tc.appendLog(11, '   %-3d: d(0) = %3d'             % (si, server_data[si][0]))
+      else:
+        tc.appendLog(11, '   %-3d: d(0) = %3d, d(1) = %3d' % (si, server_data[si][0], server_data[si][1]))
+tc.appendLog(11, '')
+
+
+################################################################################
+# - Determine data request message
+  
+reg_response_size = rsp.c_hba_reg_response_sz    # HBA client RESPONSE register size in bytes
+  
+data_request_hdr = []
+if arg_access == 'bc':
+  # Broadcast request
+  data_request_hdr.append(bc_server)
+  if funcSet == 1:
+    # Set byte or word
+    data_request_hdr.append(5 + funcWidth*(last_server - first_server + 1))
+    data_request_hdr.append(funcId)
+    data_request_hdr.append(sreg)
+    data_request_hdr.append(first_server)
+    data_request_hdr.append(last_server)
+  else:
+    # Get byte or word
+    tc.appendLog(11, '')
+    tc.appendLog(11, '>>> Broadcast get function is allowed but void, because the HBA servers will not respond!')
+    tc.appendLog(11, '')
+    data_request_hdr.append(5)
+    data_request_hdr.append(funcId)
+    data_request_hdr.append(sreg)
+    data_request_hdr.append(first_server)
+    data_request_hdr.append(last_server)
+else:
+  # Unicast request
+  data_request_hdr.append(first_server)
+  if funcSet == 1:
+    # Set byte or word
+    data_request_hdr.append(3 + funcWidth)
+    data_request_hdr.append(funcId)
+    data_request_hdr.append(sreg)
+  else:
+    # Get byte or word
+    data_request_hdr.append(3)
+    data_request_hdr.append(funcId)
+    data_request_hdr.append(sreg)
+  
+################################################################################
+# - Testcase initializations
+
+# - Disable external sync
+rsp.write_cr_syncoff(tc, msg, blpId, rspId)
+
+# - HBA modem timing
+msec     = rsp.c_msec
+bc_wait  = rsp.hba_bc_wait
+uc_wait  = rsp.hba_uc_wait
+gap_wait = rsp.hba_gap_wait
+bc_i2c   = rsp.hba_bc_i2c
+uc_i2c   = rsp.hba_uc_i2c
+reg_i2c  = rsp.hba_reg_i2c
+  
+  
+###############################################################################
+# - HBA client I2C access
+  
+i2c_addr     = rsp.c_rcuh_i2c_addr_hba         # HBA client I2C address (7 bit)
+  
+cmd_request  = rsp.c_hba_cmd_request           # HBA client REQUEST register
+cmd_response = rsp.c_hba_cmd_response          # HBA client RESPONSE register
+  
+for rep in range(1,1+repeat):
+
+  if arg_count==1:
+    # - Use counter write data for each new data request
+    count = rep-1
+    for si in range(first_server, last_server+1):
+      server_data[si][0] = (count >> 8) & 0xFF   # byte data repeats after 2^8 count
+      if funcWidth==2:
+        server_data[si][1] = count & 0xFF        # word data repeats after 2^16 count
+                                                 # use same count for all servers
+  elif arg_rand==1:
+    # - Use random write data for each new data request
+    for si in range(first_server, last_server+1):
+      for di in range(funcWidth):
+        server_data[si][di] = int(256*random.random())
+  # else: use default data
+    
+  # - Append the write data to the fixed data request header 
+  data_request = data_request_hdr
+  if arg_access == 'bc':
+    # Broadcast request
+    if funcSet == 1:
+      # Set byte or word
+      for si in range(first_server, last_server+1):
+        for di in range(funcWidth):
+          data_request.append(server_data[si][di])
+    # else: Get byte or word
+  else:
+    # Unicast request
+    if funcSet == 1:
+      # Set byte or word
+      for di in range(funcWidth):
+        data_request.append(server_data[first_server][di])
+    # else: Get byte or word
+    
+  # - Define random data for response overwrite
+  repsonse_overwrite = []
+  for i in range(reg_response_size):
+    repsonse_overwrite.append(int(256*random.random()))
+    
+  if arg_access == 'bc':
+    # Broadcast request
+    # Define arbitrary response register data that will written first and should not be affected by the broadcast request
+    data_response = repsonse_overwrite
+  else:
+    # Unicast request
+    # Determine expected response register data
+    data_response = [first_server + 128]
+    if funcSet == 1:
+      data_response.append(1)
+    else:
+      data_response.append(funcWidth + 1)
+      for di in range(funcWidth):
+        data_response.append(server_data[first_server][di])
+
+  # Log for debugging
+  #tc.appendLog(11, 'Expected REQUEST  register: %s' % data_request)
+  #tc.appendLog(11, 'Expected RESPONSE register: %s' % data_response)
+    
+  if repeat > 1:
+    tc.appendLog(11, '>>> rep')
+    
+  protocol_list = []
+  exp_result    = []
+  tc.appendLog(21, 'Overwrite RESPONSE register: %s' % repsonse_overwrite)
+  protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_WRITE_BLOCK_NO_CNT', len(repsonse_overwrite), i2c_addr, repsonse_overwrite, cmd_response))
+  exp_result.append(0)
+  protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_WAIT', gap_wait * msec))
+  exp_result.append(0)
+  protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_WRITE_BLOCK_NO_CNT', len(data_request),       i2c_addr, data_request,       cmd_request))
+  exp_result.append(0)
+  if arg_access == 'bc':
+    protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_WAIT', bc_wait * msec))
+  else:
+    protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_WAIT', uc_wait * msec))
+  exp_result.append(0)
+  protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_READ_BLOCK_NO_CNT', len(data_response),       i2c_addr, None,               cmd_response))
+  exp_result.extend(data_response)
+  exp_result.append(0)
+  protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_END'))
+  exp_result.append(0)
+  
+  # - Overwrite and read the protocol results from the RCUH
+  rsp.overwrite_rd_smbh_protocol_results(tc, msg, 'rcuh', rcuId, blpId, rspId)
+   
+  # - Write (and readback) the protocol list to the RCUH
+  rsp.write_rd_smbh_protocol_list(tc, msg, 'rcuh', protocol_list, rcuId, blpId, rspId)
+
+  # - Apply altsync to start the RCUH SMBus protocols
+  rsp.write_rsu_altsync(tc, msg, rspId)
+  if arg_access == 'bc':
+    tc.sleep(reg_i2c + gap_wait + bc_i2c + bc_wait)
+  else:
+    tc.sleep(reg_i2c + gap_wait + uc_i2c + uc_wait)
+  
+  # Read the protocol results from the RCUH
+  for ri in rspId:
+    for bi in blpId:
+      for pi in rcuId:
+        rd_result = smbus.read_results(tc, msg, 'rcuh', len(exp_result), pi, [bi], [ri])
+        # Equal?
+        if rd_result == exp_result:
+          tc.appendLog(21, '>>> RSP-%s, BLP-%s, RCU-%s, HBA client I2C access result buffer contents is OK' % (ri, bi, pi))
+          #tc.appendLog(11, 'Expected protocol result: %s' % exp_result)     # useful for debugging
+        else:
+          tc.appendLog(11, '>>> RSP-%s, BLP-%s, RCU-%s, HBA client I2C access result buffer contents is wrong:' % (ri, bi, pi))
+          tc.appendLog(11, 'Expected protocol result: %s' % exp_result)
+          tc.appendLog(11, 'Read     protocol result: %s' % rd_result)
+          tc.setResult('FAILED')
+    
+  if tc.getResult()=='FAILED':
+    None
+    #break
+      
+# - Enable external sync
+rsp.write_cr_syncon(tc, msg, blpId, rspId)
diff --git a/StationTest/tc/prsg.py b/StationTest/tc/prsg.py
new file mode 100644
index 00000000000..73188b0e01f
--- /dev/null
+++ b/StationTest/tc/prsg.py
@@ -0,0 +1,150 @@
+"""Testcase for RCU - RSP data interface using PRSG, based on TCL testcase 5.10
+
+  Note: No specific arguments
+"""
+
+################################################################################
+# Constants
+
+nof_reflets_ap  = rsp.c_nof_reflets_ap
+nof_beamlets    = rsp.c_nof_beamlets_ap   # maximum capable by RSP gateware
+nof_beamlets    = 216                     # sufficient nof beamlets for 32 MHz BW
+nof_beamlets_ap = rsp.c_nof_beamlets_ap           # including reflets
+nof_beamlets_ap = nof_reflets_ap + nof_beamlets   # including reflets
+
+# - SS output size
+c_ss_reflets_size = rsp.c_pol * nof_reflets_ap
+c_ss_size         = rsp.c_pol * nof_beamlets_ap
+
+c_ss_gap          = rsp.c_slice_size - rsp.c_cpx * rsp.c_pol * nof_beamlets_ap
+
+# - Datapath result buffer
+c_res_word_width        = 4
+c_res_nof_words         = rsp.c_cpx * rsp.c_pol * nof_beamlets_ap    # include read reflets
+c_res_nof_words_per_pol = rsp.c_cpx *             nof_beamlets       # skipped reflets
+
+################################################################################
+# - Verify options
+rspId = tc.rspId
+blpId = tc.blpId
+polId = tc.polId
+repeat = tc.repeat
+tc.setResult('PASSED')   # self checking test, so start assuming it will run PASSED
+
+tc.appendLog(11,'')
+tc.appendLog(11,'>>> Capture PRSG data for RSP-%s, BLP-%s, RCU-%s' % (rspId, blpId, polId))
+tc.appendLog(11,'')
+  
+################################################################################
+# - Testcase initializations
+bypass = 0x8F  # Bypass data path to have direct access to RCU data via SS, use resync
+               # version of pps to preserve X and Y order in captured data
+
+# - Write incrementing SS mapping, repeat (r > 1) write to 'ensure' both pages are written
+#ss_map = []
+#for i in range(0, rsp.c_pol * nof_beamlets_ap):
+#  ss_map.append(i)
+#r = 1
+#for i in range(0,r):
+#  rsp.write_ss(tc, msg, ss_map, blpId, rspId)
+#  tc.sleep(1000)
+#  rsp.write_ss(tc, msg, ss_map, blpId, rspId)
+#  tc.sleep(1000)
+
+# Apparently rspctl updates the SS every pps, so overwriting it does not work.
+# Disabling SS update in RSPDriver.conf may be an option. However instead adapt
+# this test case to the actual SS by reordering the captured data accordingly.
+# Therefore read the actual SS into ss_map.
+
+# - Read actual SS mapping, to use it to reorder the read DIAG result
+#   . assume all BLP use same mapping
+#   . strip the reflets
+#   . assume that the beamlets mapping uses all subbands
+bi = [blpId[0]]
+ri = [rspId[0]]
+ss_map = rsp.read_ss(tc, msg, c_ss_size, bi, ri)
+ss_map = ss_map[c_ss_reflets_size:]
+
+rsp.write_cr_syncoff(tc, msg, blpId, rspId)
+rsp.write_diag_bypass(tc, msg, bypass, blpId, rspId)
+
+################################################################################
+# Set RCU in PRSG mode
+rsp.rspctl(tc, '--rcuprsg')
+
+################################################################################
+# Run the test
+for k in range(0, repeat):
+  rsp.write_rsu_altsync(tc, msg, rspId)      # Apply altsync to capture a new result buffer
+  tc.sleep(100)
+
+  for ri in rspId:
+    for bi in blpId:
+      res_buffer = rsp.read_diag_result_buffer(tc, msg, c_res_nof_words, c_res_word_width, [bi], [ri])
+    
+      res ={'x':[], 'y':[]}
+      for x in range(0, len(res_buffer), 2):
+        res['x'].append(res_buffer[x] & rsp.c_rcu_dat_mask)
+      for y in range(1, len(res_buffer), 2):
+        res['y'].append(res_buffer[y] & rsp.c_rcu_dat_mask)
+      res['x'] = res['x'][c_ss_reflets_size:]    # strip the reflets
+      res['y'] = res['y'][c_ss_reflets_size:]
+      res['x'] = rsp.reorder(res['x'], ss_map)   # reorder according to SS map
+      res['y'] = rsp.reorder(res['y'], ss_map)
+      
+      for pi in polId:
+        first = 1     # First result sample is used as starting seed for the expected samples
+        ok    = 0     # 0 = OK
+        if len(res[pi]) == c_res_nof_words_per_pol:
+          for rs in res[pi]:
+            if first == 0:
+              if ok == 0:
+                if rs != rsp.calculate_next_sequence_value(rs_prev):
+                  # Mismatch, so bridge the potential SS gap in the sample stream to verify whether this is the cause
+                  rs_gap = rs_prev
+                  for i in range(0, c_ss_gap):
+                    rs_gap = rsp.calculate_next_sequence_value(rs_gap)
+                  if rs != rsp.calculate_next_sequence_value(rs_prev):
+                    # Mismatch again, so assume the potential SS gap was not the cause of the initial mismatch
+                    nxt_rs_prev = rsp.calculate_next_sequence_value(rs_prev)
+                    exp.append(nxt_rs_prev)
+                    ok = 1   # 1 = sample mismatch
+                  else:
+                    # OK, so bridge the SS gap in the expected results
+                    nxt_rs_prev = rsp.calculate_next_sequence_value(rs_gap)
+                    exp.append(nxt_rs_prev)
+                else:
+                  # OK, no SS gap to bridge    
+                  nxt_rs_prev = rsp.calculate_next_sequence_value(rs_prev)
+                  exp.append(nxt_rs_prev)
+              else:
+                # A mismatch has aleready occured, no need to check for more mismatches
+                nxt_rs_prev = rsp.calculate_next_sequence_value(rs_prev)
+                exp.append(nxt_rs_prev)
+            else:
+              first       = 0
+              nxt_rs_prev = res[pi][0]
+              exp         = [nxt_rs_prev]
+            rs_prev = nxt_rs_prev
+        else:
+          ok = 2    # 2 = length error
+
+        # Report results      
+        if ok == 0:
+          tc.appendLog(11,'>>> %d : RSP-%s, BLP-%s, RCU-%s PRSG data is OK.' % (k, ri, bi, pi))
+        elif ok == 1:
+          tc.appendLog(11,'>>> %d : RSP-%s, BLP-%s, RCU-%s PRSG data mismatch.' % (k, ri, bi, pi))
+          tc.appendLog(11,'- Expected data:')
+          tc.appendLog(11,'%s' % exp)
+          tc.appendLog(11,'- Captured data:')
+          tc.appendLog(11,'%s' % res[pi])
+          tc.setResult('FAILED')
+        else:
+          tc.appendLog(11,'>>> %d : RSP-%s, BLP-%s, RCU-%s PRSG data length mismatch.' % (k, ri, bi, pi))
+          tc.appendLog(11,'Captured length %d != expected length %d' % (len(res[pi]), c_res_nof_words_per_pol))
+          tc.setResult('FAILED')
+
+# Restore defaults
+bypass = 1
+rsp.write_diag_bypass(tc, msg, bypass, blpId, rspId, 99)
+rsp.write_cr_syncon(tc, msg, blpId, rspId)
diff --git a/StationTest/tc/rad_lanemode.py b/StationTest/tc/rad_lanemode.py
new file mode 100644
index 00000000000..102806726d7
--- /dev/null
+++ b/StationTest/tc/rad_lanemode.py
@@ -0,0 +1,35 @@
+"""Write or read the RAD lane mode, based on TCL testcase 5.24"""
+
+################################################################################
+# - Verify options
+rspId = tc.rspId
+repeat = tc.repeat
+
+# - Construct settings word from arg_rad_lane_mode
+#
+#   settings: one byte for each lane, byte [3:0] for lane [3:0]
+#     format: XXXXAABB
+#       where XX = don't care
+#             AA = xlet mode
+#             BB = blet mode
+#   
+#        mode 00 = ignore remote data (only local)  DEFAULT
+#        mode 01 = disable
+#        mode 10 = combine local and remote data
+#        mode 11 = ignore local data (only remote)
+#
+#   arg_rad_lane_mode = [X3,X2,X1,X0,B3,B2,B1,B0]
+
+settings = 0
+for i in range(rsp.c_nof_lanes):
+  settings += ((arg_rad_lane_mode[i] << 2) + arg_rad_lane_mode[i+rsp.c_nof_lanes]) << (8*i)  # X,B[3:0]
+
+
+#############################################################################
+# Read RAD latency for each RSP board
+
+if arg_read:
+  for ri in rspId:
+    rsp.read_rad_settings(tc, msg, [ri], 11)
+else:
+  rsp.write_rad_settings(tc, msg, settings, rspId, 11)
diff --git a/StationTest/tc/rad_latency.py b/StationTest/tc/rad_latency.py
new file mode 100644
index 00000000000..b4bf54d46cf
--- /dev/null
+++ b/StationTest/tc/rad_latency.py
@@ -0,0 +1,21 @@
+"""Read the RAD latency, based on TCL testcase 5.49"""
+
+################################################################################
+# - Verify options
+rspId = tc.rspId
+repeat = tc.repeat
+
+tc.appendLog(11, '')
+tc.appendLog(11, '>>> Read RAD_BP latency for RSP-%s.' % rspId)
+tc.appendLog(11, '')
+
+
+#############################################################################
+# Read RAD latency for each RSP board
+
+if repeat==1:
+  latency = rsp.read_rad_latency(tc, msg, rspId, 11)
+else:
+  for rep in range(1,1+repeat):
+    tc.appendLog(11, '>>> Rep %d' % rep)
+    latency = rsp.read_rad_latency(tc, msg, rspId, 11)
diff --git a/StationTest/tc/serdes.py b/StationTest/tc/serdes.py
new file mode 100644
index 00000000000..06f92b21fd0
--- /dev/null
+++ b/StationTest/tc/serdes.py
@@ -0,0 +1,187 @@
+"""Test the SERDES ring between RSP boards, based on TCL testcase 3.8
+
+   - Specific arguments:
+     . diag_mode:
+         off    = rsp.c_diag_mode_no_tst   --> enable sync to stop continuous tx test
+         tx     = rsp.c_diag_mode_loop_tx  --> keep ext sync disabled to continue tx
+         rx     = rsp.c_diag_mode_loop_rx
+         tx_rx  = rsp.c_diag_mode_loop_tx_rx
+         local  = rsp.c_diag_mode_loop_local --> use local loopback (idem as testcase 3.6)
+     . diag_sync: When 0 use external sync, else use altsync with sync interval time
+                  given by 'sync' sec.
+     . diag_data:
+         cntr   = use incremental data
+         lfsr   = use LFSR data
+
+   - Note:
+     . All four lanes are verified in parallel
+"""
+################################################################################
+
+# NOTE:
+#   When using arg_sync = 0 to select the external sync the --brd order of RSP
+#   boards should match the fysical SERDES tx order. Due to the slow script
+#   (few MEP messages/sec) the test migth otherwise fail when too many boards
+#   are in the test.
+
+################################################################################
+# - Verify options
+rspId = tc.rspId
+repeat = tc.repeat
+
+# - Rename testcase specific options
+arg_mode = arg_diag_mode
+arg_sync = arg_diag_sync
+arg_data = arg_diag_data
+
+################################################################################
+# - Test selections
+tst_interface = rsp.c_diag_dev_serdes
+tst_lane      = 0xFF            # not used
+  
+if   arg_mode == 'off':   tst_mode = rsp.c_diag_mode_no_tst
+elif arg_mode == 'tx':    tst_mode = rsp.c_diag_mode_tx
+elif arg_mode == 'rx':    tst_mode = rsp.c_diag_mode_rx
+elif arg_mode == 'tx_rx': tst_mode = rsp.c_diag_mode_tx_rx
+elif arg_mode == 'local': tst_mode = rsp.c_diag_mode_loop_local
+else:
+  tst_mode = rsp.c_diag_mode_loop_local
+  arg_mode = 'local'
+  tc.appendLog(11, 'ILLEGAL test mode, default to test mode %s.' % arg_mode)
+  
+if arg_mode == 'tx':
+  # Use mode 'tx' as continuous tx, so no repeat necessary. Mode 'off' will stop the tx.
+  repeat = 1
+
+# Incremental data is generated for test duration debug, else LFSR data
+if   arg_data == 'cntr': tst_duration = rsp.c_diag_duration_debug
+elif arg_data == 'lfsr': tst_duration = rsp.c_diag_duration_quick
+else:
+  tst_duration = rsp.c_diag_duration_quick
+  arg_data = 'lfsr'
+
+selftest = [tst_interface, tst_mode, tst_duration, tst_lane]
+
+#############################################################################
+# Constants
+  
+if arg_mode == 'off':
+  tc.appendLog(11, '')
+  tc.appendLog(11, '>>> RSP-%s, stop any previous SERDES tx selftest using mode %s.' % (rspId, arg_mode))
+  tc.appendLog(11, '')
+  # - Stop any previous tx selftest
+  rsp.write_rsu_altsync(tc, msg, rspId)         # start of tst sync interval
+  rsp.write_rsu_altsync(tc, msg, rspId)         # end of tst sync interval
+  rsp.write_rsu_altsync(tc, msg, rspId)         # end tx
+  rsp.write_cr_syncon(tc, msg, ['rsp'], rspId)  # restore CR ext sync enabled default
+else:
+  # - Run selftest
+    
+  tc.appendLog(11, '')
+  if arg_sync == 0:
+    tc.appendLog(11, '>>> RSP-%s, run SERDES test: mode %s, data %s, using external sync from TD clock board.' % (rspId, arg_mode, arg_data))
+  else:
+    tc.appendLog(11, '>>> RSP-%s, run SERDES test: mode %s, data %s, using RSP on board alternative sync.' % (rspId, arg_mode, arg_data))
+  tc.appendLog(11, '')
+  
+  for rep in range(1,1+repeat):
+    # Temporarily disable external sync
+    rsp.write_cr_syncoff(tc, msg, ['rsp'], rspId)
+  
+    value = 0xAB
+    tc.appendLog(31, '')
+    tc.appendLog(31, '>>> Overwrite RSR diag bytes with %#x to ensure fresh status.' % value)
+    tc.appendLog(31, '')
+    rsp.overwrite_rsr(tc, msg, 'diag', value, rspId)
+    for ri in rspId:
+      rsp.read_rsr(tc, msg, 'diag', [ri], 31)
+
+    # Configure DIAG tst
+    for ri in rspId:
+      rsp.write_diag_selftest(tc, msg, selftest, ['rsp'], [ri], 99)
+
+    tc.sleep(100)        # wait DIAG ack_period_done
+
+    # Sync control
+    if arg_mode != 'tx':
+      if arg_sync == 0:
+        # Enable external sync, first ext sync will start test, next ext sync will end test
+        rsp.write_cr_syncon(tc, msg, ['rsp'], rspId)
+
+        # Wait for serdes_diag_lane tx, rx test to finish (1 until start sync, 1 measurement sync interval, 1 sync interval
+        # for tx to finish, so worst case 3 sec)
+        tc.sleep(3000)
+      else:
+        # Run serdes_diag_lane tx, rx test for 1 sync interval (arbitrary long, typically 1 sec)
+        rsp.write_rsu_altsync(tc, msg, rspId)        # start of sync interval
+        tc.sleep(arg_sync*1000)
+        rsp.write_rsu_altsync(tc, msg, rspId)        # end of sync interval
+        rsp.write_rsu_altsync(tc, msg, rspId)        # end tx
+        tc.sleep(1000)                               # allow time for DIAG tst result event to reach RSR
+        rsp.write_cr_syncon(tc, msg, ['rsp'], rspId)  # restore CR ext sync enabled default
+    # else: For mode 'tx' keep ext sync off to run tx forever, i.e. until tc is rerun with mode 'off'.
+
+    for ri in rspId:
+      tc.appendLog(31, '')
+      tc.appendLog(31, '>>> %d: RSP-%s, read RSR diag status:' % (rep, ri))
+      tc.appendLog(31, '')
+
+      status = rsp.read_rsr(tc, msg, 'diag', [ri], 31)
+      status = status[0][0][:]
+      diag_interface     = status[0]
+      diag_mode          = status[1]
+      diag_ri_errors     = status[2]
+      diag_rcux_errors   = status[3]
+      diag_rcuy_errors   = status[4]
+      diag_lcu_errors    = status[5]
+      diag_cep_errors    = status[6]
+      diag_serdes_errors = status[7]
+      diag_ap0_ri_errors = status[8]
+      diag_ap1_ri_errors = status[9]
+      diag_ap2_ri_errors = status[10]
+      diag_ap3_ri_errors = status[11]
+
+      if arg_mode == 'tx':
+        if diag_interface == value:
+          tc.appendLog(11, '>>> RSP-%s, SERDES tx only is active, use mode off to stop it.' % ri)
+          tc.appendLog(11, '')
+        else:
+          tc.appendLog(11, '>>> RSP-%s, SERDES tx only went wrong.' % ri)
+          tc.appendLog(11, '    Unexpected test interface %d.' % diag_interface)
+          tc.setResult('FAILED')
+      elif diag_interface     == tst_interface and \
+           diag_mode          == tst_mode      and \
+           diag_serdes_errors == 0:
+        tc.appendLog(11, '>>> %d: RSP-%s, SERDES test went OK.' % (rep, ri))
+        tc.setResult('PASSED')
+      else:
+        tc.appendLog(11, '>>> %d: RSP-%s, SERDES test went wrong.' % (rep, ri))
+        if diag_interface != tst_interface:
+          tc.appendLog(11, '    Unexpected test interface %d.' % diag_interface)
+        elif diag_mode != tst_mode:
+          tc.appendLog(11, '    Unexpected test mode %d.' % diag_mode)
+        else:
+          lane_mask = 2**rsp.c_nof_lanes - 1
+          lane_ref  = 2**rsp.c_nof_lanes
+          for i in range(rsp.c_nof_lanes):
+            lane_errors = (diag_serdes_errors >> (i*rsp.c_nof_lanes)) & lane_mask
+            if lane_errors == rsp.c_diag_res_ok:
+              tc.appendLog(11, '    Lane %d went OK.' % i)
+            elif lane_errors == rsp.c_diag_res_none:
+              tc.appendLog(11, '    Lane %d went wrong, nothing happened.' % i)
+            elif lane_errors == rsp.c_diag_res_sync_timeout:
+              tc.appendLog(11, '    Lane %d went wrong, sync timeout.' % i)
+            elif lane_errors == rsp.c_diag_res_data_timeout:
+              tc.appendLog(11, '    Lane %d went wrong, data timeout.' % i)
+            elif lane_errors == rsp.c_diag_res_word_err:
+              tc.appendLog(11, '    Lane %d went wrong, word errors occured.' % i)
+            elif lane_errors == rsp.c_diag_res_illegal:
+              tc.appendLog(11, '    Lane %d illegal status %d.' % (i, lane_errors))
+            else:
+              tc.appendLog(11, '    Lane %d unknown status %d.' % (i, lane_errors))
+        tc.setResult('FAILED')
+    # Break repeat loop in case test FAILED
+    if tc.getResult() == 'FAILED':
+      break
+  # Restore external sync enabled
+  rsp.write_cr_syncon(tc, msg, ['rsp'], rspId)
diff --git a/StationTest/tc/spustat.py b/StationTest/tc/spustat.py
new file mode 100644
index 00000000000..3c571e43513
--- /dev/null
+++ b/StationTest/tc/spustat.py
@@ -0,0 +1,102 @@
+"""SPU monitor voltages and temperature via I2C, based on TCL testcase 9.6"""
+
+################################################################################
+# - Verify options
+rspId = tc.rspId    # allow multiple rsp, e.g. rsp0,rsp4 to access SPU in two subracks
+repeat = tc.repeat  # use >1 for continuous T,V monitoring or I2C stress test
+
+tc.setResult('PASSED')
+
+
+tc.appendLog(11,'')
+tc.appendLog(11,'>>> Monitor T and V of the SPU board using an I2C access via RSP-%s.' % rspId)
+tc.appendLog(11,'')
+
+# Handle older versions of the SPU (Subrack Power Unit).
+spu_version = 2
+#spu_version = 3
+if spu_version == 2:
+  v48 = 8
+if spu_version == 3:
+  v48 = 48
+
+################################################################################
+# - Testcase initializations
+
+# - Disable external sync to avoid asynchronous trigger of TDSH protocol list
+rsp.write_cr_syncoff(tc, msg, ['rsp'], rspId)
+
+
+################################################################################
+# Read SPU sensor status via I2C
+
+addr   = smbus.c_max6652_addr_vcc
+config = smbus.c_max6652_config_start + smbus.c_max6652_config_line_freq_sel
+protocol_list = []
+protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_WRITE_BYTE', None, addr, [config], smbus.c_max6652_cmd_config))
+protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_READ_BYTE',  None, addr, None,     smbus.c_max6652_cmd_read_2v5))
+protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_READ_BYTE',  None, addr, None,     smbus.c_max6652_cmd_read_3v3))
+protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_READ_BYTE',  None, addr, None,     smbus.c_max6652_cmd_read_12v))
+protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_READ_BYTE',  None, addr, None,     smbus.c_max6652_cmd_read_vcc))
+protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_READ_BYTE',  None, addr, None,     smbus.c_max6652_cmd_read_temp))
+protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_END'))
+exp_result = '0 ? 0 ? 0 ? 0 ? 0 ? 0 0'
+len_result = len(exp_result.split())
+
+
+for rep in range(1,1+repeat):
+  for ri in rspId:
+    # - Overwrite and read the protocol results from the TDSH
+    rsp.overwrite_rd_smbh_protocol_results(tc, msg, 'tdsh', None, None, [ri])
+    
+    # - Write (and readback) the protocol list to the TDSH
+    rsp.write_rd_smbh_protocol_list(tc, msg, 'tdsh', protocol_list, None, None, [ri])
+
+    # Apply altsync to start the TDSH SMBus protocols
+    rsp.write_rsu_altsync(tc, msg, [ri])
+    tc.sleep(100)
+
+    # Read the protocol results from the TDSH
+    rd_result = smbus.read_results(tc, msg, 'tdsh', len_result, None, None, [ri])
+
+    # Sensor values  
+    spu_volt_2v5 = rd_result[1]
+    spu_volt_3v3 = rd_result[3]
+    spu_volt_12v = rd_result[5]
+    spu_volt_vcc = rd_result[7]
+    spu_temp     = rd_result[9]
+    
+    # SPU voltages
+    v_rcu     = spu_volt_2v5 * smbus.c_max6652_unit_2v5 * (10+10)/10
+    v_lba_rcu = spu_volt_3v3 * smbus.c_max6652_unit_3v3 * (10+20)/10
+    v_hba     = spu_volt_12v * smbus.c_max6652_unit_12v * (10+30.1)/10
+    v_monitor = spu_volt_vcc * smbus.c_max6652_unit_vcc
+  
+    tc.appendLog(11, '')
+    tc.appendLog(11, 'SPU voltage and temperature measurements:')
+    tc.appendLog(11, '')
+    tc.appendLog(11, '  V_RCU     = %6.3f V   (= %4d * %7.1f mV)' % (v_rcu,     spu_volt_2v5, 1000 * smbus.c_max6652_unit_2v5 * (10+10)/10))
+    tc.appendLog(11, '  V_LBA_RCU = %6.3f V   (= %4d * %7.1f mV)' % (v_lba_rcu, spu_volt_3v3, 1000 * smbus.c_max6652_unit_3v3 * (10+20)/10))
+    tc.appendLog(11, '  V_HBA     = %6.3f V   (= %4d * %7.1f mV)' % (v_hba,     spu_volt_12v, 1000 * smbus.c_max6652_unit_12v * (10+30.1)/10))
+    tc.appendLog(11, '')
+    tc.appendLog(11, '  V_monitor = %6.3f V   (= %4d * %7.1f mV)    (This is the supply voltage of the sensor itself)' \
+                                                                  % (v_monitor, spu_volt_vcc, 1000 * smbus.c_max6652_unit_vcc))
+    tc.appendLog(11, '')
+    tc.appendLog(11, '  Temp      = %4d degrees C' % spu_temp)
+    tc.appendLog(11, '')
+  
+    if rd_result[ 0] == 0 and v_rcu     >  4.0  and v_rcu     < 5.5   and \
+       rd_result[ 2] == 0 and v_lba_rcu >  7    and v_lba_rcu < 9     and \
+       rd_result[ 4] == 0 and v_hba     > v48-5 and v_hba     < v48+5 and \
+       rd_result[ 6] == 0 and v_monitor >  3    and v_monitor < 4     and \
+       rd_result[ 8] == 0 and spu_temp  >  0    and spu_temp  < 70    and \
+       rd_result[10] == 0:
+      tc.appendLog(11, '>>> Rep-%d, RSP-%s, I2C access to the MAX6652 T,V sensor on the SPU board went OK' % (rep, ri))
+    else:
+      tc.appendLog(11, '>>> Rep-%d, RSP-%s, I2C access to the MAX6652 T,V sensor on the SPU board went wrong:' % (rep, ri))
+      tc.appendLog(11, 'Expected protocol result: %s' % exp_result)
+      tc.appendLog(11, 'Read     protocol result: %s   (slave address 0x%x)' % (rd_result, addr))
+      tc.setResult('FAILED')
+
+# - Enable external sync
+rsp.write_cr_syncon(tc, msg, ['rsp'], rspId)
diff --git a/StationTest/tc/status.py b/StationTest/tc/status.py
new file mode 100644
index 00000000000..c0dae7045ea
--- /dev/null
+++ b/StationTest/tc/status.py
@@ -0,0 +1,57 @@
+""" Read the RSP status for one or all pid, based on TCL testcase 11.1"""
+
+################################################################################
+# - Verify options
+rspId = tc.rspId
+repeat = tc.repeat
+
+# Testcase specific options
+
+if not (arg_procid in ['rsp',
+                       'eth',
+                       'mep',
+                       'diag',
+                       'bs',
+                       'rcuh',
+                       'rsu',
+                       'ado',
+                       'rad',
+                       'all']):
+  arg_procid = 'all'
+  tc.appendLog(11, 'Forced unknown procid to \'all\'.')
+
+tc.appendLog(11, '')
+tc.appendLog(11, '>>> Selected RSR read %s for RSP-%s.' % (arg_procid, rspId))
+tc.appendLog(11, '')
+
+
+#############################################################################
+# Read RSR for each RSP board
+
+if repeat==1:
+  status = rsp.read_rsr(tc, msg, arg_procid, rspId, 11)
+else:
+  for rep in range(1,1+repeat):
+    tc.appendLog(11, '>>> %d' % rep)
+    if arg_procid == 'rad':
+      for ri in rspId:
+        status = rsp.read_rsr(tc, msg, arg_procid, [ri], 99)
+        rad_status = status[0][0]  # based on bit 20 (= align, 0 is ok),
+                                   #          bit 19 (= sync, 1 is ok),
+                                   #          bit 18 (= brc, 0 is ok)
+        rad_raw =  status[0][1]    # rad_status info with count (bits 17:0)
+        rad_cnt =  status[0][1][0] & 0x3FFFF # use RI count bits 17:0
+        
+        rsr_str   = '%d' % rad_status
+        for rd in rad_raw:
+          rsr_str += '%8d' % rd
+        if rad_status == rsp.c_rsr_undefined:
+          tc.appendLog(11, '%s, %d: RAD status is OFF    (%s)' % (ri, rep, rsr_str))
+        elif rad_status == rsp.c_rsr_ok:
+          tc.appendLog(21, '%s, %d: RAD status is OK    (%s), RI count = %d' % (ri, rep, rsr_str, rad_cnt))
+        else:
+          tc.appendLog(11, '%s, %d: RAD status is wrong : %s' % (ri, rep, rsr_str))
+    else:
+      for ri in rspId:
+        status = rsp.read_rsr(tc, msg, arg_procid, [ri], 11)
+    tc.sleep(100)   # less than 1 sec so we do not miss an interval status
diff --git a/StationTest/tc/sync_delay.py b/StationTest/tc/sync_delay.py
new file mode 100644
index 00000000000..378e45e658c
--- /dev/null
+++ b/StationTest/tc/sync_delay.py
@@ -0,0 +1,37 @@
+""" Read the RSP status for one or all pid, based on TCL testcase 11.1"""
+
+################################################################################
+# - Verify options
+rspId = tc.rspId
+blpId = tc.bpId
+blpId.extend(tc.blpId)
+
+# Testcase specific options
+arg_edge  = arg_pps_edge
+arg_delay = arg_pps_delay
+
+tc.appendLog(11, '')
+if arg_read:
+  tc.appendLog(11, '>>> Read PPS input delay status for RSP-%s, BLP-%s.' % (rspId, blpId))
+  tc.appendLog(11, '')
+  for ri in rspId:
+    for bi in blpId:
+      rsp.read_cr_sync_delay(tc, msg, [bi], [ri])
+else:
+  if arg_delay==0:
+    if arg_edge=='r':
+      tc.appendLog(11, '>>> RSP-%s, BLP-%s: Reset PPS input delay to default and capture on rising edge.' % (rspId, blpId))
+      rsp.write_cr_sync_delay(tc, msg, 0, 0, blpId, rspId)
+    else:
+      tc.appendLog(11, '>>> RSP-%s, BLP-%s: Reset PPS input delay to default and capture on falling edge.' % (rspId, blpId))
+      rsp.write_cr_sync_delay(tc, msg, 0, 1, blpId, rspId)
+  else:
+    if arg_edge=='r':
+      tc.appendLog(11, '>>> RSP-%s, BLP-%s: Increment PPS input delay %d times and capture on rising edge.' % (rspId, blpId, arg_delay))
+      for ri in range(arg_delay):
+        rsp.write_cr_sync_delay(tc, msg, 1, 0, blpId, rspId)
+    else:
+      tc.appendLog(11, '>>> RSP-%s, BLP-%s: Increment PPS input delay %d times and capture on falling edge.' % (rspId, blpId, arg_delay))
+      for ri in range(arg_delay):
+        rsp.write_cr_sync_delay(tc, msg, 1, 1, blpId, rspId)
+tc.appendLog(11, '')
diff --git a/StationTest/tc/tdstat.py b/StationTest/tc/tdstat.py
new file mode 100644
index 00000000000..33839489073
--- /dev/null
+++ b/StationTest/tc/tdstat.py
@@ -0,0 +1,95 @@
+"""TDS monitor voltages and temperature via I2C, based on TCL testcase 9.1"""
+
+################################################################################
+# - Verify options
+rspId = tc.rspId    # allow multiple rsp, e.g. rsp0,rsp4 to access TDS in two subracks
+repeat = tc.repeat  # use >1 for continuous T,V monitoring or I2C stress test
+
+tc.setResult('PASSED')
+
+tc.appendLog(11,'')
+tc.appendLog(11,'>>> Monitor T and V of the TDS board using an I2C access via RSP-%s.' % rspId)
+tc.appendLog(11,'')
+
+# Handle older versions of the TDS (Timing Distribution Subrack) clock board.
+td_version = 2
+#td_version = 3
+if td_version == 2:
+  v5 = 0
+if td_version == 3:
+  v5 = 5
+
+################################################################################
+# - Testcase initializations
+
+# - Disable external sync to avoid asynchronous trigger of TDSH protocol list
+rsp.write_cr_syncoff(tc, msg, ['rsp'], rspId)
+
+
+################################################################################
+# Read TD sensor status via I2C
+
+addr   = smbus.c_max6652_addr_gnd
+config = smbus.c_max6652_config_start + smbus.c_max6652_config_line_freq_sel
+protocol_list = []
+protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_WRITE_BYTE', None, addr, [config], smbus.c_max6652_cmd_config))
+protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_READ_BYTE',  None, addr, None,     smbus.c_max6652_cmd_config))
+protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_READ_BYTE',  None, addr, None,     smbus.c_max6652_cmd_read_2v5))
+protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_READ_BYTE',  None, addr, None,     smbus.c_max6652_cmd_read_vcc))
+protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_READ_BYTE',  None, addr, None,     smbus.c_max6652_cmd_read_temp))
+protocol_list.extend(smbus.set_protocol(tc, 'PROTOCOL_C_END'))
+exp_result = '0 %d 0 ? 0 ? 0 ? 0 0' % config
+len_result = len(exp_result.split())
+
+
+for rep in range(1,1+repeat):
+  for ri in rspId:
+    # - Overwrite and read the protocol results from the TDSH
+    rsp.overwrite_rd_smbh_protocol_results(tc, msg, 'tdsh', None, None, [ri])
+    
+    # - Write (and readback) the protocol list to the TDSH
+    rsp.write_rd_smbh_protocol_list(tc, msg, 'tdsh', protocol_list, None, None, [ri])
+
+    # Apply altsync to start the TDSH SMBus protocols
+    rsp.write_rsu_altsync(tc, msg, [ri])
+    tc.sleep(100)
+
+    # Read the protocol results from the TDSH
+    rd_result = smbus.read_results(tc, msg, 'tdsh', len_result, None, None, [ri])
+
+    # Sensor values  
+    volt_2v5 = rd_result[3]
+    volt_vcc = rd_result[5]
+    temp     = rd_result[7]
+
+    # TDS voltages
+    tds_5v  = volt_2v5 * smbus.c_max6652_unit_2v5 * (10+10)/10
+    tds_3v3 = volt_vcc * smbus.c_max6652_unit_vcc               # note vcc unit is based on 5v, independent of true VCC
+
+    tc.appendLog(11, '')
+    tc.appendLog(11, '>>> TDS voltage and temperature measurements:')
+    tc.appendLog(11, '')
+    tc.appendLog(11, '    5V via 2v5 input = %6.3f V  (= %4d * %7.4f mV)' % (tds_5v,  volt_2v5, 1000*smbus.c_max6652_unit_2v5 * (10+10)/10))
+    tc.appendLog(11, '  3.3V via vcc input = %6.3f V  (= %4d * %7.4f mV)' % (tds_3v3, volt_vcc, 1000*smbus.c_max6652_unit_vcc))
+    tc.appendLog(11, '  Temp               = %4d degrees C' % temp)
+    tc.appendLog(11, '')
+
+    if rd_result[0] == 0        and \
+       rd_result[1] == config   and \
+       rd_result[2] == 0        and \
+       tds_5v        > v5-1.0 and tds_5v  < v5+0.5 and \
+       rd_result[4] == 0      and \
+       tds_3v3       > 3.0    and tds_3v3 < 4.0    and \
+       rd_result[6] == 0      and \
+       temp            >  0   and temp    < 70     and \
+       rd_result[8] == 0      and \
+       rd_result[9] == 0:
+      tc.appendLog(11, '>>> Rep-%d, RSP-%s, I2C access to the MAX6652 T,V sensor on the TDS board went OK' % (rep, ri))
+    else:
+      tc.appendLog(11, '>>> Rep-%d, RSP-%s, I2C access to the MAX6652 T,V sensor on the TDS board went wrong:' % (rep, ri))
+      tc.appendLog(11, 'Expected protocol result: %s' % exp_result)
+      tc.appendLog(11, 'Read     protocol result: %s   (slave address 0x%x)' % (rd_result, addr))
+      tc.setResult('FAILED')
+
+# - Enable external sync
+rsp.write_cr_syncon(tc, msg, ['rsp'], rspId)
diff --git a/StationTest/verify.py b/StationTest/verify.py
new file mode 100644
index 00000000000..b61f451fc71
--- /dev/null
+++ b/StationTest/verify.py
@@ -0,0 +1,188 @@
+"""Master script to execute a LOFAR station testcase script
+
+  Features:
+  - Imports several modules
+  - Provides argument parsing using optparse
+  - Instantiates a Testcase class for logging
+  - Instantiates a MepMessage class for using rspctl --writeblock, --readblock
+  - Executes one or more testcase scripts (all use the same arguments)
+  
+  Notes:
+  - The structure resembles the TCL/C testcase suite used for the station
+    gateware (VHDL) development.
+  - Most TCL testcase will work directly if they are translated to Python. The
+    python scripts ougth to use high level rspctl commands wherever possible.
+  - The TCL suite only works under Windows, because it uses WinPCap for ethernet
+    access. This Python suite only works under Linux, because it uses rspctl.
+"""
+
+################################################################################
+# Parse command line for testcase and options
+
+import sys
+from optparse import OptionParser
+
+# Define empty class to be used as record, to keep local verify variables less
+# easily known in the testcase scripts.
+class v:
+  pass           
+  
+verify = OptionParser(usage='usage: python %prog [options]', version='%prog 0.1')
+
+# - Common options
+verify.add_option('-v', type='int', dest='verbosity',
+  help='Verbosity level for the log file', default=11)
+verify.add_option('--te', type='string', dest='testname',
+  help='File names of one or more testcases')
+  # Multiple testcases can be run using comma seperator, each with the same options though
+verify.add_option('--rep', type='int', dest='repeat',
+  help='Repeat the test', default=1)
+verify.add_option('--brd', type='string', dest='brdId',
+  help='Board id: rsp0,rsp1 for RSP 0 and 1, tbb0 for TBB 0', default='rsp0')
+  # Note multiple values for an option are possible by providing them with comma seperator and no spaces
+verify.add_option('--fpga', type='string', dest='fpId',
+  help='FPGA id: rsp for BP, blp0 for AP0, tbb for TP, mp0 for MP0', default='rsp')
+  # On RSP and BLP is equivalent to an AP, but generaly an AP could implement multiple BLP
+verify.add_option('--pol', type='string', dest='polId',
+  help='Polarization id: x, y or x,y', default='x,y')
+  
+# - Testcase specific options
+#   Define the testcase specific options here, rather than passing an --args
+#   string to the testcase. The advantage is that they all show up with --help.
+#   The disadvantage is that for every new options also this verify.py needs to
+#   be updated.
+verify.add_option('--pid', type='string', dest='pid',
+  help='Process ID: rsp, eth, mep, diag, bs, rcuh, rsu, ado, rad, all', default='all')
+verify.add_option('--data', type='string', dest='data',
+  help='Data values(s) to write or verify read', default='40')
+verify.add_option('--count', action='store_true', dest='count',
+  help='Use counter data values')
+verify.add_option('--rand', action='store_true', dest='rand',
+  help='Use random data values')
+verify.add_option('--read', action='store_true', dest='read',
+  help='Run the testcase read only')
+verify.add_option('--pps_edge', type='string', dest='pps_edge',
+  help='Capture PPS on rising or falling clock edge: r, f', default='r')
+verify.add_option('--pps_delay', type='int', dest='pps_delay',
+  help='Increment PPS input delay in steps of about 75 ps, use 0 for reset', default=1)
+verify.add_option('--diag_mode', type='string', dest='diag_mode',
+  help='Diag mode: off, tx, rx, tx_rx, local', default='tx_rx')
+verify.add_option('--diag_sync', type='int', dest='diag_sync',
+  help='Diag sync: 0 for pps, > 0 for alt sync interval in s', default=1)
+verify.add_option('--diag_data', type='string', dest='diag_data',
+  help='Diag data: lfsr, cntr', default='lfsr')
+verify.add_option('--rad_lane_mode', type='string', dest='rad_lane_mode',
+  help='RAD lane mode: X lane 3:0, B lane 3:0, where 0=local, 1=disable, 2=combine, 3=remote', default='0,0,0,0,0,0,0,0')
+verify.add_option('--client_rcu', type='string', dest='client_rcu',
+  help='HBA control via this RCU, power via the other RCU: x or y', default='y')
+verify.add_option('--client_access', type='string', dest='client_access',
+  help='HBA client access: r = read only, w = write only, wr = first write then readback', default='r')
+verify.add_option('--client_reg', type='string', dest='client_reg',
+  help='HBA client register: request, response, led, vref, version, speed', default='led')
+verify.add_option('--server', type='string', dest='server',
+  help='HBA server range, first server and last server', default='1,16')
+verify.add_option('--server_access', type='string', dest='server_access',
+  help='HBA server access: bc = broadcast to all servers, uc = unicast to first server', default='uc')
+verify.add_option('--server_function', type='string', dest='server_function',
+  help='HBA server function: gb, gw, sb, sw', default='gb')
+verify.add_option('--server_reg', type='string', dest='server_reg',
+  help='HBA server register: delay_x, delay_y, version, address', default='delay_x')
+
+v.opts, v.args = verify.parse_args()
+
+# - Option checks and/or reformatting
+if v.opts.testname==None:
+  verify.error('Option --te must specify a testcase file name')
+else:
+  v.testname = v.opts.testname.split(',')
+
+v.strId = v.opts.brdId.split(',')
+v.rspId = []
+v.tbbId = []
+for brd in v.strId:
+  if brd[:3] == 'rsp':
+    v.rspId.append(brd)
+  elif brd[:3] == 'tbb':
+    v.tbbId.append(brd)
+  else:
+    verify.error('Option --brd has invalid board id %s' % brd)
+
+v.strId = v.opts.fpId.split(',')
+v.bpId = []  # RSP
+v.blpId = []
+v.tpId = []  # TBB
+v.mpId = []
+for fp in v.strId:
+  if fp == 'rsp':
+    v.bpId.append(fp)
+  elif fp[:3] == 'blp':
+    v.blpId.append(fp)
+  elif fp == 'tbb':
+    v.tpId.append(fp)
+  elif fp[:2] == 'mp':
+    v.mpId.append(fp)
+  else:
+    verify.error('Option --fp has invalid FPGA id %s' % fp)
+
+v.polId = v.opts.polId.split(',')
+
+# Pass the testcase specific options on directly, to avoid having to edit
+# testcase.py for every new option. Rename with prefix arg_ so it is easier
+# to search for the specific arguments, e.g. with grep or an editor.
+
+arg_procid              = v.opts.pid
+data_str                = v.opts.data.split(',')
+arg_data = []
+for di in data_str:
+  arg_data.append(int(di))
+arg_count               = v.opts.count
+arg_rand                = v.opts.rand
+arg_read                = v.opts.read
+arg_pps_edge            = v.opts.pps_edge
+arg_pps_delay           = v.opts.pps_delay
+arg_diag_mode           = v.opts.diag_mode
+arg_diag_sync           = v.opts.diag_sync
+arg_diag_data           = v.opts.diag_data
+rad_lane_mode_str       = v.opts.rad_lane_mode.split(',')
+arg_rad_lane_mode = []
+for lm in rad_lane_mode_str:
+  arg_rad_lane_mode.append(int(lm))
+arg_hba_client_rcu      = v.opts.client_rcu
+arg_hba_client_access   = v.opts.client_access
+arg_hba_client_reg      = v.opts.client_reg
+server_str              = v.opts.server.split(',')
+arg_hba_server = []
+for si in server_str:
+  arg_hba_server.append(int(si))
+arg_hba_server_access   = v.opts.server_access
+arg_hba_server_function = v.opts.server_function
+arg_hba_server_reg      = v.opts.server_reg
+
+
+################################################################################
+# Run the testcase
+
+# Import here so no need in Testcase
+import random
+import mep
+import testcase
+import rsp
+import smbus
+
+msg = mep.MepMessage()
+  
+for te in v.testname:
+  # Pass the common options on via the testcase class instance.
+  tc = testcase.Testcase(v.opts.verbosity,
+                         te,
+                         v.opts.repeat,
+                         v.rspId, v.bpId, v.blpId,
+                         v.tbbId, v.tpId, v.mpId,
+                         v.polId)
+  tc.appendLog(2,'--------------------------------------------------------------------------------')
+  tc.setResult('RUNONLY')
+  execfile(tc.testName)
+  dt = tc.getRunTime()
+  tc.appendLog(2,'Duration: %d %02d:%02d:%02d' % (dt/60/60/24, dt/60/60 % 24, dt/60 % 60, dt % 60))
+  tc.appendLog(0,tc.getResult())
+  tc.closeLog()
diff --git a/StationTest/xc_160_setup.sh b/StationTest/xc_160_setup.sh
new file mode 100644
index 00000000000..919a24161ea
--- /dev/null
+++ b/StationTest/xc_160_setup.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+#
+# Setup part - Test the SERDES ring between the RSP by verifing the crosslet statistics.
+#
+
+pi=$(echo "4*a(1)" | bc -l)
+
+nof_subbands=512
+
+# Start waveform generators for crosscorrelation measurement
+
+nof_rcu=32         # nof RCU in a subrack
+sample_freq=160000000
+rf_freq=40000000
+xc_subband=$(echo "$nof_subbands * $rf_freq / ($sample_freq/2)" | bc -l)
+
+for ((i = 0; i < $nof_rcu; i++)) do
+    phs=$(echo "($i * 2 * $pi) / $nof_rcu" | bc -l)
+    amp=$(echo "0.498 * $i / $nof_rcu" | bc -l)              # use 0.498 for deterministic result, see bug 767
+    rspctl --wg=$rf_freq --select=$i --ampli=$amp --phase=$phs
+done
+
+rspctl --xcsubband=$xc_subband
diff --git a/StationTest/xc_160_verify.sh b/StationTest/xc_160_verify.sh
new file mode 100644
index 00000000000..6c3dbfa0d00
--- /dev/null
+++ b/StationTest/xc_160_verify.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+#
+# Verify part - Test the SERDES ring between the RSP by verifing the crosslet statistics.
+#
+
+rm -f *.dat
+rm -f *.diff
+
+# Capture crosscorrelation data for 1 sec
+
+rspctl --xcstat --duration=1
+
+
+# Verify the captured data
+
+xc_dat=$(ls *.dat)
+diff $xc_dat gold/xst_160.gold > xst.diff
+if [ -e $xc_dat ] && [ -e gold/xst_160.gold ] && [ -e xst.diff ] && ! [ -s xst.diff ]; then
+  # The files exists AND the diff has size 0
+  echo "RSP serdes crosscorrelation test at 160 MHz went OK"
+else
+  echo "RSP serdes crosscorrelation test at 160 MHz went wrong"
+fi
+
diff --git a/StationTest/xc_200_setup.sh b/StationTest/xc_200_setup.sh
new file mode 100644
index 00000000000..42d7b17d6f4
--- /dev/null
+++ b/StationTest/xc_200_setup.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+#
+# Setup part - Test the SERDES ring between the RSP by verifing the crosslet statistics.
+#
+
+pi=$(echo "4*a(1)" | bc -l)
+
+nof_subbands=512
+
+# Start waveform generators for crosscorrelation measurement
+
+nof_rcu=32         # nof RCU in a subrack
+sample_freq=200000000
+rf_freq=50000000
+xc_subband=$(echo "$nof_subbands * $rf_freq / ($sample_freq/2)" | bc -l)
+
+for ((i = 0; i < $nof_rcu; i++)) do
+    phs=$(echo "($i * 2 * $pi) / $nof_rcu" | bc -l)
+    amp=$(echo "0.498 * $i / $nof_rcu" | bc -l)              # use 0.498 for deterministic result, see bug 767
+    rspctl --wg=$rf_freq --select=$i --ampli=$amp --phase=$phs
+done
+
+rspctl --xcsubband=$xc_subband
diff --git a/StationTest/xc_200_verify.sh b/StationTest/xc_200_verify.sh
new file mode 100644
index 00000000000..1fbfe22a32b
--- /dev/null
+++ b/StationTest/xc_200_verify.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+#
+# Verify part - Test the SERDES ring between the RSP by verifing the crosslet statistics.
+#
+
+rm -f *.dat
+rm -f *.diff
+
+# Capture crosscorrelation data for 1 sec
+
+rspctl --xcstat --duration=1
+
+
+# Verify the captured data, at 200 MHz it is necessary to distinghuis between even or odd sec
+
+xc_dat=$(ls *.dat)
+diff $xc_dat gold/xst_200_even.gold > xst.diff
+if [ -e $xc_dat ] && [ -e gold/xst_200_even.gold ] && [ -e xst.diff ] && ! [ -s xst.diff ]; then
+  # The files exists AND the diff has size 0
+  echo "RSP serdes crosscorrelation test even second went OK"
+else
+  diff $xc_dat gold/xst_200_odd.gold > xst.diff
+  if [ -e $xc_dat ] && [ -e gold/xst_200_odd.gold ] && [ -e xst.diff ] && ! [ -s xst.diff ]; then
+    # The files exists AND the diff has size 0
+    echo "RSP serdes crosscorrelation test odd second went OK"
+  else
+    echo "RSP serdes crosscorrelation test went wrong"
+  fi
+fi
+
-- 
GitLab