diff --git a/.gitattributes b/.gitattributes
index f4f68e0047ea89dd925fbaeadd0389380bc47a99..90e8ece855f8ad1609d70a80813869d7c3e7010f 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 0000000000000000000000000000000000000000..4c094293917318ca8992b2fca5f67f12454eba5c
--- /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 0000000000000000000000000000000000000000..fd5eb2f8951b9d52a10f7fb6160dc1358e1bf45a
--- /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 0000000000000000000000000000000000000000..06f18cde1dbfd6912ef7d927c4d35d25c7137a62
--- /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 0000000000000000000000000000000000000000..4fcf2bda2634d76ed941ff55daa69eeb44ebdda2
--- /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 0000000000000000000000000000000000000000..46aa24695c7dcfad3a14ecee01a2319f53a15a37
--- /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 0000000000000000000000000000000000000000..99aaecba65323dda3992932384284bc2510e3b79
--- /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 0000000000000000000000000000000000000000..71915568991f8e6bf586340cfbe731800e1aad3a
--- /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 0000000000000000000000000000000000000000..6d3133946f03546a8b40db86c5e92e9767edb7a1
--- /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 0000000000000000000000000000000000000000..c6eee9a60977e6c7f437c99d72c9b8137f093d44
--- /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
Binary files /dev/null and b/StationTest/gold/xst_160.gold differ
diff --git a/StationTest/gold/xst_200_even.gold b/StationTest/gold/xst_200_even.gold
new file mode 100644
index 0000000000000000000000000000000000000000..0b0b7fe23fded1d1acea55d98510d328fd959f7e
Binary files /dev/null and b/StationTest/gold/xst_200_even.gold differ
diff --git a/StationTest/gold/xst_200_odd.gold b/StationTest/gold/xst_200_odd.gold
new file mode 100644
index 0000000000000000000000000000000000000000..5c689fb51c1a8c0819e177233ae009a03c0304ab
Binary files /dev/null and b/StationTest/gold/xst_200_odd.gold differ
diff --git a/StationTest/i2c_spu.py b/StationTest/i2c_spu.py
new file mode 100644
index 0000000000000000000000000000000000000000..78293b5328cfb4499fb78de53364249732668cc8
--- /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 0000000000000000000000000000000000000000..01b5d631bafb402fff37be65a1c31e0b6ad23345
--- /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 0000000000000000000000000000000000000000..0d289bbe166c99550d2ac031f1a2b7be228670b9
--- /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 0000000000000000000000000000000000000000..9cb9861031be8bcafa1567a2b8e6058a900acf42
--- /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 0000000000000000000000000000000000000000..92a3fb5ca8af152560e328ade0443f2e07a7edef
--- /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 0000000000000000000000000000000000000000..a17f8cd8201d10b75328d81b98f46b08acccc28c
--- /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 0000000000000000000000000000000000000000..d73e8825f3fd1679290b1257651c545e44cdb6d7
--- /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 0000000000000000000000000000000000000000..1463e2311627323696f203ef0cd2d2a11a82826a
--- /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 0000000000000000000000000000000000000000..d31e7b62940b28312a4f5885a0dffa21a35711f2
--- /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 0000000000000000000000000000000000000000..83709022e5305cb535c1705ade217e77ef51e644
--- /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 0000000000000000000000000000000000000000..5dea30abe241b8d9be5461025090a60ad43df857
--- /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 0000000000000000000000000000000000000000..c80deb914e2bab4c837b2f55744aa181ed9895fb
--- /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 0000000000000000000000000000000000000000..64d46a8b4cf6c212fca347551155992fb231b59f
--- /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 0000000000000000000000000000000000000000..b6c6af8e664ae76301886a3073afae05889743a3
--- /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 0000000000000000000000000000000000000000..b5afc5a52a6bbabcbb57e14f35e605723cb1b52e
--- /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 0000000000000000000000000000000000000000..69507897f3b97909906da3fc3c12cb11a9f94671
--- /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 0000000000000000000000000000000000000000..a70b196447cfe64a9549a386f44ba3b44a348df6
--- /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 0000000000000000000000000000000000000000..4ac35bcf8ffdead3e779f256a1954d1af0c03d1e
--- /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 0000000000000000000000000000000000000000..4390bb7c21e0bd961d73b5a1796b8339272c0a31
--- /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 0000000000000000000000000000000000000000..c9b8155367c13f54f2d3f3671fa4c554a0d04019
--- /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 0000000000000000000000000000000000000000..8bee11394e1dd9254b3d0236bd68d3ac3d8c5e29
--- /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 0000000000000000000000000000000000000000..4f44e401d83fca3d5edf5a496fb6a312b371351b
--- /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 0000000000000000000000000000000000000000..0f6116eefa8e11048bd70e1560e6ee42e911047b
--- /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 0000000000000000000000000000000000000000..6d74e533d8ff35184bdc11ab429dc3bd0fd2d2ad
--- /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 0000000000000000000000000000000000000000..7aa8be90387546446a21eac1ad9d898885ae8e1c
--- /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 0000000000000000000000000000000000000000..73188b0e01ff30d9e6d914e7a32569d1db1dd9c1
--- /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 0000000000000000000000000000000000000000..102806726d7d8bc078778e1e55e0c888ccc70820
--- /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 0000000000000000000000000000000000000000..b4bf54d46cf5351d293fafd84fa48883b7c2f258
--- /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 0000000000000000000000000000000000000000..06f92b21fd068603de40c8da651219c326c32cb0
--- /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 0000000000000000000000000000000000000000..3c571e43513f06966591649654356b96087cb9da
--- /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 0000000000000000000000000000000000000000..c0dae7045eaef06138422d833d04095b24d6f5e6
--- /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 0000000000000000000000000000000000000000..378e45e658cfcf434394849897b1a9ba18856ef8
--- /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 0000000000000000000000000000000000000000..338394890733783481a695fe83201c7aa5ff6c74
--- /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 0000000000000000000000000000000000000000..b61f451fc71fe0de3c7ec6c881629841d71b507c
--- /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 0000000000000000000000000000000000000000..919a24161ea1a89c04775b1910ba8b97529ed813
--- /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 0000000000000000000000000000000000000000..6c3dbfa0d003c547475c7dbc72ebd15d13941970
--- /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 0000000000000000000000000000000000000000..42d7b17d6f406dec3189507270ae4d158e4cad8c
--- /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 0000000000000000000000000000000000000000..1fbfe22a32b537f47cfef717288d09cc47449944
--- /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
+