diff --git a/prodtest/RCU2HQM.yaml b/prodtest/RCU2HQM.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..050507e0455355c9c084ac19480c6d72b9b99c9c
--- /dev/null
+++ b/prodtest/RCU2HQM.yaml
@@ -0,0 +1,88 @@
+PCB_number:
+- {ID: 0081cf88, number: '3'}
+- {ID: 00817e5b, number: '7'}
+- {ID: 00820526, number: '4'}
+- {ID: 0081b11b, number: '6'}
+- {ID: 0081612a, number: '5'}
+- {ID: 008212c8, number: '2'}
+- {ID: 0081ed2b, number: '1'}
+ant_power:
+- ID: 00817e5b
+  Ioff: 0.024
+  Ion: 0.03
+  Iout: [0.003643820544, 0.003630087552, 0.0035522672640000003]
+  Vin: [43.9113927232, 43.6596229632, 43.569901376]
+  Vout: [42.0107599168, 41.2234072128, 40.5184518848]
+  time: 2022-01-29 12:40
+- ID: 00820526
+  Ioff: 0.025
+  Ion: 0.033
+  Iout: [0.00361635456, 0.0035751555840000003, 0.0035980439040000003]
+  Vin: [43.7658240256, 43.6907508608, 43.4344034688]
+  Vout: [43.5955361152, 43.6349037504, 44.2574617024]
+  time: 2022-01-29 16:59
+- ID: 0081cf88
+  Ioff: 0.02
+  Ion: 0.023
+  Iout: [0.0044082904320000005, 0.002856462336, 0.003579733248]
+  Vin: [43.39595136, 43.4041910976, 43.718216652799995]
+  Vout: [0.0466918464, 0.0466918464, 43.525956108799996]
+  time: 2022-01-29 12:56
+- ID: 0081b11b
+  Ioff: 0.024
+  Ion: 0.033
+  Iout: [0.003680441856, 0.003648398208, 0.003698752512]
+  Vin: [43.5177163712, 43.789627712, 43.742020339199996]
+  Vout: [44.0752719488, 43.326371353599995, 44.0075229952]
+  time: 2022-01-30 16:17
+- ID: 008212c8
+  Ioff: 0.024
+  Ion: 0.033
+  Iout: [0.003634665216, 0.00359346624, 0.003579733248]
+  Vin: [43.2201702912, 43.326371353599995, 43.4673624192]
+  Vout: [43.583634272, 43.2705242432, 43.8061071872]
+  time: 2022-01-30 16:06
+- ID: 0081ed2b
+  Ioff: 0.025
+  Ion: 0.033
+  Iout: [0.00357057792, 0.003611776896, 0.003634665216]
+  Vin: [43.6861732288, 43.702652704, 43.4893350528]
+  Vout: [43.7877966592, 43.8244177152, 43.611100064]
+  time: 2022-01-30 16:07
+- ID: 0081612a
+  Ioff: 0.024
+  Ion: 0.033
+  Iout: [0.003630087552, 0.00363924288, 0.00363924288]
+  Vin: [43.6669471744, 43.9699864128, 43.0919965952]
+  Vout: [44.0212558912, 43.748429023999996, 43.8070227136]
+  time: 2022-02-02 23:56
+off_power:
+- {ID: 00817e5b, I_4V: 0.02, I_6V: 0.033, V_3v3: 3.026841664, temp: 283.38169600000003,
+  time: '2022-01-29 12:40'}
+- {ID: 00820526, I_4V: 0.03, I_6V: 0.023, V_3v3: 3.025905344, temp: 275.544, time: '2022-01-29
+    16:59'}
+- {ID: 0081cf88, I_4V: 0.03, I_6V: 0.034, V_3v3: 3.014669504, temp: 273.339648, time: '2022-01-29
+    12:56'}
+- {ID: 0081b11b, I_4V: 0.03, I_6V: 0.025, V_3v3: 3.019632, temp: 283.136768, time: '2022-01-30
+    16:17'}
+- {ID: 0081612a, I_4V: 0.03, I_6V: 0.023, V_3v3: 3.017852992, temp: 272.115008, time: '2022-02-02
+    23:56'}
+- {ID: 008212c8, I_4V: 0.03, I_6V: 0.023, V_3v3: 3.005774464, temp: 266.726592, time: '2022-01-30
+    15:55'}
+- {ID: 0081ed2b, I_4V: 0.02, I_6V: 0.023, V_3v3: 3.02244096, temp: 267.706304, time: '2022-01-30
+    16:07'}
+on_power:
+- {ID: 00817e5b, I_4V: 0.5, I_6V: 1.228, V_1v8: 1.64008545792, V_2v5: 2.33419665024,
+  time: '2022-01-29 12:40'}
+- {ID: 00820526, I_4V: 0.7, I_6V: 1.2, V_1v8: 1.63797973248, V_2v5: 2.31062168064,
+  time: '2022-01-29 16:59'}
+- {ID: 0081cf88, I_4V: 0.51, I_6V: 1.235, V_1v8: 1.62809197824, V_2v5: 2.30764619904,
+  time: '2022-01-29 12:56'}
+- {ID: 0081b11b, I_4V: 0.51, I_6V: 1.243, V_1v8: 1.64274050304, V_2v5: 2.30027616,
+  time: '2022-01-30 16:17'}
+- {ID: 008212c8, I_4V: 0.5, I_6V: 1.22, V_1v8: 1.63738463616, V_2v5: 2.32508709888,
+  time: '2022-01-30 15:55'}
+- {ID: 0081ed2b, I_4V: 0.51, I_6V: 1.219, V_1v8: 1.63921570176, V_2v5: 2.31963967872,
+  time: '2022-01-30 16:07'}
+- {ID: 0081612a, I_4V: 0.51, I_6V: 1.238, V_1v8: 1.64594486784, V_2v5: 2.32092142464,
+  time: '2022-02-02 23:56'}
diff --git a/prodtest/RCU2HQM.yaml.2 b/prodtest/RCU2HQM.yaml.2
new file mode 100644
index 0000000000000000000000000000000000000000..e5d8727ae177d7fac2e90cb60523f78aed2ad331
--- /dev/null
+++ b/prodtest/RCU2HQM.yaml.2
@@ -0,0 +1,40 @@
+PCB_number:
+- {ID: 0081cf88, number: '3'}
+- {ID: 00817e5b, number: '7'}
+- {ID: 00820526, number: '4'}
+ant_power:
+- ID: 00817e5b
+  Ioff: 0.024
+  Ion: 0.03
+  Iout: [0.003643820544, 0.003630087552, 0.0035522672640000003]
+  Vin: [43.9113927232, 43.6596229632, 43.569901376]
+  Vout: [42.0107599168, 41.2234072128, 40.5184518848]
+  time: 2022-01-29 12:40
+- ID: 00820526
+  Ioff: 0.025
+  Ion: 0.03
+  Iout: [0.003588888576, 0.003556844928, 0.003579733248]
+  Vin: [43.7511756032, 43.7108924416, 43.4252482048]
+  Vout: [41.953997279999996, 41.2591127424, 41.574053823999996]
+  time: 2022-01-29 12:52
+- ID: 0081cf88
+  Ioff: 0.02
+  Ion: 0.023
+  Iout: [0.0044082904320000005, 0.002856462336, 0.003579733248]
+  Vin: [43.39595136, 43.4041910976, 43.718216652799995]
+  Vout: [0.0466918464, 0.0466918464, 43.525956108799996]
+  time: 2022-01-29 12:56
+off_power:
+- {ID: 00817e5b, I_4V: 0.02, I_6V: 0.033, V_3v3: 3.026841664, temp: 283.38169600000003,
+  time: '2022-01-29 12:40'}
+- {ID: 00820526, I_4V: 0.03, I_6V: 0.023, V_3v3: 3.024594496, temp: 269.4208, time: '2022-01-29
+    12:52'}
+- {ID: 0081cf88, I_4V: 0.03, I_6V: 0.034, V_3v3: 3.014669504, temp: 273.339648, time: '2022-01-29
+    12:56'}
+on_power:
+- {ID: 00817e5b, I_4V: 0.5, I_6V: 1.228, V_1v8: 1.64008545792, V_2v5: 2.33419665024,
+  time: '2022-01-29 12:40'}
+- {ID: 00820526, I_4V: 0.7, I_6V: 1.2, V_1v8: 1.637659296, V_2v5: 2.31043857408, time: '2022-01-29
+    12:52'}
+- {ID: 0081cf88, I_4V: 0.51, I_6V: 1.235, V_1v8: 1.62809197824, V_2v5: 2.30764619904,
+  time: '2022-01-29 12:56'}
diff --git a/prodtest/RCU2HQM.yaml_v1 b/prodtest/RCU2HQM.yaml_v1
new file mode 100644
index 0000000000000000000000000000000000000000..9ae1f8ba659f2be926be7412469d2bcd600523ad
--- /dev/null
+++ b/prodtest/RCU2HQM.yaml_v1
@@ -0,0 +1,79 @@
+PCB_number:
+- {ID: 0081cf88, number: '3'}
+- {ID: 00817e5b, number: '7'}
+- {ID: 00820526, number: '4'}
+- {ID: 0081b11b, number: '6'}
+- {ID: 0081612a, number: '5'}
+- {ID: 008212c8, number: '2'}
+- {ID: 0081ed2b, number: '1'}
+ant_power:
+- ID: 00817e5b
+  Ioff: 0.024
+  Ion: 0.03
+  Iout: [0.003643820544, 0.003630087552, 0.0035522672640000003]
+  Vin: [43.9113927232, 43.6596229632, 43.569901376]
+  Vout: [42.0107599168, 41.2234072128, 40.5184518848]
+  time: 2022-01-29 12:40
+- ID: 00820526
+  Ioff: 0.025
+  Ion: 0.033
+  Iout: [0.00361635456, 0.0035751555840000003, 0.0035980439040000003]
+  Vin: [43.7658240256, 43.6907508608, 43.4344034688]
+  Vout: [43.5955361152, 43.6349037504, 44.2574617024]
+  time: 2022-01-29 16:59
+- ID: 0081cf88
+  Ioff: 0.02
+  Ion: 0.023
+  Iout: [0.0044082904320000005, 0.002856462336, 0.003579733248]
+  Vin: [43.39595136, 43.4041910976, 43.718216652799995]
+  Vout: [0.0466918464, 0.0466918464, 43.525956108799996]
+  time: 2022-01-29 12:56
+- ID: 0081b11b
+  Ioff: 0.024
+  Ion: 0.033
+  Iout: [0.003680441856, 0.003648398208, 0.003698752512]
+  Vin: [43.5177163712, 43.789627712, 43.742020339199996]
+  Vout: [44.0752719488, 43.326371353599995, 44.0075229952]
+  time: 2022-01-30 16:17
+- ID: 008212c8
+  Ioff: 0.024
+  Ion: 0.033
+  Iout: [0.003634665216, 0.00359346624, 0.003579733248]
+  Vin: [43.2201702912, 43.326371353599995, 43.4673624192]
+  Vout: [43.583634272, 43.2705242432, 43.8061071872]
+  time: 2022-01-30 16:06
+- ID: 0081ed2b
+  Ioff: 0.025
+  Ion: 0.033
+  Iout: [0.00357057792, 0.003611776896, 0.003634665216]
+  Vin: [43.6861732288, 43.702652704, 43.4893350528]
+  Vout: [43.7877966592, 43.8244177152, 43.611100064]
+  time: 2022-01-30 16:07
+off_power:
+- {ID: 00817e5b, I_4V: 0.02, I_6V: 0.033, V_3v3: 3.026841664, temp: 283.38169600000003,
+  time: '2022-01-29 12:40'}
+- {ID: 00820526, I_4V: 0.03, I_6V: 0.023, V_3v3: 3.025905344, temp: 275.544, time: '2022-01-29
+    16:59'}
+- {ID: 0081cf88, I_4V: 0.03, I_6V: 0.034, V_3v3: 3.014669504, temp: 273.339648, time: '2022-01-29
+    12:56'}
+- {ID: 0081b11b, I_4V: 0.03, I_6V: 0.025, V_3v3: 3.019632, temp: 283.136768, time: '2022-01-30
+    16:17'}
+- {ID: 0081612a, I_4V: 0.03, I_6V: 0.023, V_3v3: 3.0172912, temp: 267.951232, time: '2022-01-30
+    13:31'}
+- {ID: 008212c8, I_4V: 0.03, I_6V: 0.023, V_3v3: 3.005774464, temp: 266.726592, time: '2022-01-30
+    15:55'}
+- {ID: 0081ed2b, I_4V: 0.02, I_6V: 0.023, V_3v3: 3.02244096, temp: 267.706304, time: '2022-01-30
+    16:07'}
+on_power:
+- {ID: 00817e5b, I_4V: 0.5, I_6V: 1.228, V_1v8: 1.64008545792, V_2v5: 2.33419665024,
+  time: '2022-01-29 12:40'}
+- {ID: 00820526, I_4V: 0.7, I_6V: 1.2, V_1v8: 1.63797973248, V_2v5: 2.31062168064,
+  time: '2022-01-29 16:59'}
+- {ID: 0081cf88, I_4V: 0.51, I_6V: 1.235, V_1v8: 1.62809197824, V_2v5: 2.30764619904,
+  time: '2022-01-29 12:56'}
+- {ID: 0081b11b, I_4V: 0.51, I_6V: 1.243, V_1v8: 1.64274050304, V_2v5: 2.30027616,
+  time: '2022-01-30 16:17'}
+- {ID: 008212c8, I_4V: 0.5, I_6V: 1.22, V_1v8: 1.63738463616, V_2v5: 2.32508709888,
+  time: '2022-01-30 15:55'}
+- {ID: 0081ed2b, I_4V: 0.51, I_6V: 1.219, V_1v8: 1.63921570176, V_2v5: 2.31963967872,
+  time: '2022-01-30 16:07'}
diff --git a/prodtest/RCU2HQM2.yaml b/prodtest/RCU2HQM2.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..ff936f9ff0cc8b081b67f3086c9f990a52205107
--- /dev/null
+++ b/prodtest/RCU2HQM2.yaml
@@ -0,0 +1,10 @@
+Monitor_ADC:
+- {ID: I2C1, time: 333x33}
+PCB_number:
+- {ID: 12c1, number: 1}
+- {ID: 12c2, number: 1}
+Power_supply:
+- {ID: I2C1, Ioff_3V: 3, Ioff_6V: 50, Ion_3V: 3, Ion_6V: 5, time: '22-01-29 11:11'}
+Test_log:
+- {ID: 4343, message: null, time: 333}
+description: Test results on RCU2HQM
diff --git a/prodtest/test1.yaml b/prodtest/test1.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..ce38f63cf993981a293982bb1361deaa35c28ea3
--- /dev/null
+++ b/prodtest/test1.yaml
@@ -0,0 +1,11 @@
+Monitor_ADC:
+- {ID: I2C1, time: 333x33}
+PCB_number:
+- {ID: 12c1, number: 1}
+- {ID: 12c2, number: 1}
+- {ID: 0081cf88, number: '3'}
+Power_supply:
+- {ID: I2C1, Ioff_3V: 3, Ioff_6V: 3, Ion_3V: 3, Ion_6V: 5, time: 333x33}
+Test_log:
+- {ID: 4343, message: null, time: 333}
+description: Test results on RCU2HQM
diff --git a/prodtest/yamllog.py b/prodtest/yamllog.py
new file mode 100644
index 0000000000000000000000000000000000000000..884c5af4407d14ecd6b87a145e71bcf106321c59
--- /dev/null
+++ b/prodtest/yamllog.py
@@ -0,0 +1,31 @@
+import yaml
+
+class yamllog():
+  def __init__(self,yamlfile):
+    self.conf=yaml.load(open(yamlfile+'.yaml'))
+  def getdata(self,table,field,value):
+    for D in self.conf[table]:
+       if D[field]==value: return D
+    return None;
+  def insert(self,table,D):
+    self.conf[table].append(D);
+  def replace(self,table,field,value,Dnew):
+    for i,D in enumerate(self.conf[table]):
+       if D[field]==value: 
+           self.conf[table][i]=Dnew;
+           return;
+    self.insert(table,Dnew);
+  def save(self,yamlfile):
+    with open(yamlfile+".yaml","w") as file:
+      yaml.dump(self.conf,file)
+
+if False:
+ from datetime import datetime;
+ testtime=datetime.now().strftime("%y-%m-%d %H:%M")
+ T1=yamllog("RCU2HQM")
+ D=T1.getdata("Power_supply","ID","I2C1")
+ D['Ioff_6V']=50;
+ D['time']=testtime;
+ T1.replace("Power_supply","ID","I2C1",D)
+ print(D)
+ T1.save("RCU2HQM2")
diff --git a/testRCU1.py b/testRCU1.py
new file mode 100644
index 0000000000000000000000000000000000000000..e1c09bdb932f6d8b110368e28ff898d1806452a8
--- /dev/null
+++ b/testRCU1.py
@@ -0,0 +1,279 @@
+name='RECVTR_HB' #YAML config file with all register values etc
+logPath='log'
+
+import logging
+import argparse
+from opcuaserv import opcuaserv
+from opcuaserv import i2client
+from opcuaserv import yamlreader
+#from opcuaserv import pypcc2
+from i2cserv import i2cthread
+import threading
+import time
+import sys
+import signal
+from yamlconfig import Find;
+import yamlconfig as yc
+from datetime import datetime
+
+testtime=datetime.now().strftime("%y-%m-%d %H:%M")
+
+RCUNR=(0 if len(sys.argv)<2 else int(sys.argv[1]));
+print("RCU NR=",RCUNR," tested at ",testtime);
+logging.basicConfig(level="WARNING",format='%(asctime)s [%(levelname)-8s,%(filename)-20s:%(lineno)-3d] %(message)s')
+#logging.basicConfig(level="DEBUG",format='%(asctime)s [%(levelname)-8s,%(filename)-20s:%(lineno)-3d] %(message)s')
+
+RunTimer=True;
+conf=yc.yamlconfig(name)
+conf.linkdevices()
+conf.loaddrivers()
+conf.linkdrivers()
+
+Bands=[2,1,4]
+Band=Bands[0]; #0=110, 1=170, 2=210
+DAB=1; #1=DAB filter enables
+Att=10;
+
+def GetVal(name,N=1):
+ varid=conf.getvarid(name);
+ var1=conf.getvars()[varid]
+ drv=var1.get('drivercls');
+ mask=[False]*RCUNR*N+[True]*N+[False]*((32-RCUNR-1)*N);
+ data=drv.OPCUAReadVariable(varid,var1,mask)
+ data=data[0].data
+ N3=len(data)//32;
+ return data[N3*RCUNR:N3*(RCUNR+1)],var1
+
+
+data,var1=GetVal('RCU_PCB_ID');
+ID=("%.2x%.2x%.2x%.2x" % (data[0],data[1],data[2],data[3]))
+
+rootLogger = logging.getLogger()
+#fileHandler = logging.FileHandler("{0}/{1}.log".format(logPath, "RCU2L"+ID))
+#fileHandler.setFormatter(logFormatter)
+#rootLogger.addHandler(fileHandler)
+
+logging.warning("ID=%s" % ID)
+now=datetime.now();
+logging.warning("Time="+now.strftime("%Y-%m-%d %H:%M"));
+#exit();
+#print("Check 
+def Check(D,Dmin,Dmax):
+  for d in D:
+    if (d<Dmin): 
+        logging.error("Value to small");
+#        return False;
+    if (d>Dmax): 
+        logging.error("Value to large");
+#        return False;
+  return True
+
+if True:
+ data,var1=GetVal('RCU_TEMP');
+ D=((data[0]*256+data[1])*256+data[2])*var1.get('scale',1.)
+ logging.warning("RCU Temperature=%.3f K" % D)
+ if not Check([D],290,350): exit();
+
+ data,var1=GetVal('RCU_PWR_3V3');
+ D=((data[0]*256+data[1])*256+data[2])*var1.get('scale',1.)
+ logging.warning("3V3 =%.3f V" % D)
+# print("3V3=",D,"V")
+ if not Check([D],3.2,3.4): exit();
+# if (D<3.2) or (D>3.4): exit()
+#print("data=",[hex(d) for d in data[:3]]);
+#exit()
+
+def SetRegister(regname,value):
+  methodid=conf.getmethodid("RCU_on");
+  var1=conf.getmethod(methodid)
+  drv=var1.get('drivercls');
+  v1=conf.getdevreg(regname)
+  drv2=v1.get('drivercls')
+  mask=[False]*(RCUNR)+[True]+[False]*(31-RCUNR);
+  if drv:  drv.Setdevreg(v1,value,mask)
+  elif drv2: drv2.Setdevreg(v1,value,mask)
+  else: logging.warn("Driver not specified for instruction"+key)
+
+
+
+if True:
+# logging.warning("Switch RCU Power off");
+# SetRegister("IO1.GPIO1",[0])
+# SetRegister("IO1.GPIO2",[0x0]) #Analog power off
+# SetRegister("IO2.GPIO1",[0x0]) #Digital power off
+# SetRegister("IO2.GPIO2",[0x80])
+ SetRegister("IO1.CONF1",[0])
+ SetRegister("IO1.CONF2",[0])
+ SetRegister("IO2.CONF1",[0x80]) #Pgood on 0x80
+ SetRegister("IO2.CONF2",[0])
+ SetRegister("IO4.CONF1",[0xC0])#pin 0x40, 0x80 not used
+ SetRegister("IO4.CONF2",[0xF8])
+ time.sleep(1.0)
+ logging.warning("Switch RCU Power on");
+ SetRegister("IO1.GPIO1",[Att])#0x0a = 10dB att
+ SetRegister("IO1.GPIO2",[0x80+Att])#0x80 Analog on, 0x0a=10dB att
+ SetRegister("IO2.GPIO1",[0x40+Att])#0x40 Dig on, 0x0a =10dB att
+ SetRegister("IO2.GPIO2",[0x40+Band+(Band<<3)])#0x09 #Band0 (or 0x12 or 0x24)  #LED green=on=low 0x40
+ SetRegister("IO4.GPIO1",[0x51 if DAB else 0x2A])#DAB switch states: 0x2A or 0x51
+ SetRegister("IO4.GPIO2",[Band])#Band select
+ time.sleep(0.5)
+
+# logging.warning("  Check IO expander 1&2");
+# print("IO expander status:");
+# data,var=GetVal('RCU_IO1_GPIO1');
+# if not Check(data,0,0): 
+#   logging.warning("  IO1_GPIO1 =%x" % data[0])
+#   exit();
+# data,var=GetVal('RCU_IO1_GPIO2');
+# if not Check(data,0x80,0x80): 
+#   logging.warning("  IO1_GPIO2 =%x" % data[0])
+#   exit();
+# data,var=GetVal('RCU_IO2_GPIO1');
+# if not Check(data,0xC0,0xC0): 
+#   logging.warning("  IO2_GPIO1 =%x" % data[0])
+#   exit();
+# data,var=GetVal('RCU_IO2_GPIO2');
+# if not Check(data,0x40,0x40): 
+#   logging.warning("  IO2_GPIO2 =%x" % data[0])
+#   exit();
+# time.sleep(0.5)
+
+if True:
+ logging.warning("Check voltages")
+ data,var1=GetVal('RCU_PWR_1V8');
+ D=((data[0]*256+data[1])*256+data[2])*var1.get('scale',1.)
+ logging.warning("  1V8 =%.3f V" % D)
+ if not Check([D],1.7,1.9): exit();
+
+ data,var1=GetVal('RCU_PWR_2V5');
+ D=((data[0]*256+data[1])*256+data[2])*var1.get('scale',1.)
+ logging.warning("  2V5 =%.3f V" % D)
+ if not Check([D],2.4,2.6): exit();
+if False:
+ data,var1=GetVal('RCU_PWR_ANT_VIN');
+ D0=((data[0]*256+data[1])*256+data[2])*var1.get('scale',1.)
+ D1=((data[3]*256+data[4])*256+data[5])*var1.get('scale',1.)
+ D2=((data[6]*256+data[7])*256+data[8])*var1.get('scale',1.)
+ logging.warning("  Vant_in=%.2f %.2f %.2f" % (D0,D1,D2))
+ if not Check([D0,D1,D2],5,10): exit();
+
+ logging.warning("Switch Antenna power on")
+ SetRegister("IO1.GPIO1",[0xC0]) #Antenna power on
+ SetRegister("IO1.GPIO2",[0xC0]) #Analog power on
+
+ data,var1=GetVal('RCU_PWR_ANT_VOUT');
+ D0=((data[0]*256+data[1])*256+data[2])*var1.get('scale',1.)
+ D1=((data[3]*256+data[4])*256+data[5])*var1.get('scale',1.)
+ D2=((data[6]*256+data[7])*256+data[8])*var1.get('scale',1.)
+ logging.warning("  Vant_out=%.2f %.2f %.2f" % (D0,D1,D2))
+ if not Check([D0,D1,D2],5,10): exit();
+
+ data,var1=GetVal('RCU_PWR_ANT_IOUT');
+ D0=((data[0]*256+data[1])*256+data[2])*var1.get('scale',1.)
+ D1=((data[3]*256+data[4])*256+data[5])*var1.get('scale',1.)
+ D2=((data[6]*256+data[7])*256+data[8])*var1.get('scale',1.)
+ logging.warning("  Iant_out=%.2f %.2f %.2f" % (D0,D1,D2))
+# print("Iant=",D0,D1,D2)
+#exit()
+
+if False:
+ logging.warning("Test ADC read")
+ logging.warning("  Check IO expander 3");
+ SetRegister("IO3.GPIO1",[0x15]) #ADC_SDIO=high, clk=low,  DTH_EN=low
+ SetRegister("IO3.GPIO2",[0x47]) #ADC SC=high, DTH_SDA=high
+ SetRegister("IO3.CONF1",[0]) #All output
+ SetRegister("IO3.CONF2",[0])
+ data,var=GetVal('RCU_IO3_GPIO1');
+ if not Check(data,0x15,0x15): exit();
+ data,var=GetVal('RCU_IO3_GPIO2');
+ if not Check(data,0x47,0x47): exit();
+
+if False:
+ #Test reading register from ADCs
+ data,var=GetVal('RCU_ADC_JESD');
+ logging.warning("  ADC JESD (0x14)=%x %x %x" % (data[0],data[1],data[2]))
+ if not Check(data,0x14,0x14): exit();
+
+ logging.warning("Test ADC write & ADC lock")
+ #Test writing ADC register
+ SetRegister("ADC1.SYNC_control",[1])
+ SetRegister("ADC1.CML_level",[7]);
+ SetRegister("ADC1.Update",[1])
+ SetRegister("ADC2.SYNC_control",[1])
+ SetRegister("ADC2.CML_level",[7]);
+ SetRegister("ADC2.Update",[1])
+ SetRegister("ADC3.SYNC_control",[1])
+ SetRegister("ADC3.CML_level",[7]);
+ SetRegister("ADC3.Update",[1])
+ data,var=GetVal('RCU_ADC_sync');
+ logging.warning("  ADC sync (0x1)=%x %x %x" % (data[0],data[1],data[2]))
+ if not Check(data,0x1,0x1): exit();
+
+ data,var=GetVal('RCU_ADC_locked');
+ logging.warning("  ADC locked (0x1)=%x %x %x" % (data[0],data[1],data[2]))
+ if not Check(data,0x1,0x1): logging.error("*** FAILED ADC lock!")
+#      - RCU_ADC_locked: Update
+
+#exit()
+#Need to update I2c bitbang....
+if False:
+ logging.warning("Test DITHER communication")
+ SetRegister("IO3.GPIO1",[0x15]) #ADC_SDIO=high, clk=low,  DTH_SDN=low
+ SetRegister("IO3.GPIO2",[0x47]) #ADC SC=high, DTH_SDA=high
+ SetRegister("IO3.CONF1",[0]) #All output
+ SetRegister("IO3.CONF2",[0x0]) #All output (DTH_SDA=input)
+
+
+# data,var=GetVal('RCU_IO3_GPIO1');print("IO3_1",hex(data[0]))
+# data,var=GetVal('RCU_IO3_GPIO2');print("IO3_2",hex(data[0]))
+ f0=102.2e6;
+ f=int(f0)
+ logging.warning("  Set frequency %f"%f0);
+# print("Frequency set=",f)
+ d=[0]*4;
+ for i in range(4):
+   d[3-i]=f%256;f//=256
+# print([hex(h) for h in d])
+ SetRegister("DTH1.Freq",d) #DTH_SDA=input
+ SetRegister("DTH2.Freq",d) #DTH_SDA=input
+ SetRegister("DTH3.Freq",d) #DTH_SDA=input
+
+ f=int(f0)
+ data,var1=GetVal("RCU_DTH_freq")
+# data,var1=GetVal("RCU_DTH_Rev")
+ for j in range(3):
+   f2=0;
+   for i in range(4):
+     f2=f2*256+data[j*4+i];
+   #print("Frequency read back=",f)
+   logging.warning("  Readback frequency %f" % f2);
+   if not Check([f2],f-1,f+1): exit();
+# print([hex(h) for h in data[:30]])
+
+ logging.warning("Test DITHER on")
+ SetRegister("DTH1.CONF",[0])
+ SetRegister("DTH1.Tune",[0,0])
+ SetRegister("DTH1.Start",[0,1,0,0,1])
+ SetRegister("DTH2.CONF",[0])
+ SetRegister("DTH2.Tune",[0,0])
+ SetRegister("DTH2.Start",[0,1,0,0,1])
+ SetRegister("DTH3.CONF",[0])
+ SetRegister("DTH3.Tune",[0,0])
+ SetRegister("DTH3.Start",[0,1,0,0,1])
+ time.sleep(0.1)
+ data,var=GetVal('RCU_DTH_on');
+ logging.warning("  DTH on (0x1)=%x %x %x" % (data[0],data[1],data[2]))
+ if not Check(data,0x1,0x1): logging.error("*** FAILED: Dither on! ***")
+
+
+logging.warning("** PASSED Power and Control test **");
+
+
+#print(data)
+#scale=float(scale)
+#data2=[(d*scale) for d in data2]
+
+#print("ID=",[hex(d) for d in data[:4]]);
+
+
+
diff --git a/testRCUH.py b/testRCUH.py
new file mode 100644
index 0000000000000000000000000000000000000000..ad425780dbfddefc9e2a37cfc2246557165eee40
--- /dev/null
+++ b/testRCUH.py
@@ -0,0 +1,285 @@
+name='RECVTR_HB' #YAML config file with all register values etc
+logPath='log'
+
+import logging
+import argparse
+from opcuaserv import opcuaserv
+from opcuaserv import i2client
+from opcuaserv import yamlreader
+#from opcuaserv import pypcc2
+from i2cserv import i2cthread
+import threading
+import time
+import sys
+import signal
+from yamlconfig import Find;
+import yamlconfig as yc
+from datetime import datetime
+
+testtime=datetime.now().strftime("%y-%m-%d %H:%M")
+
+RCUNR=(0 if len(sys.argv)<2 else int(sys.argv[1]));
+print("RCU NR=",RCUNR," tested at ",testtime);
+logging.basicConfig(level="WARNING",format='%(asctime)s [%(levelname)-8s,%(filename)-20s:%(lineno)-3d] %(message)s')
+#logging.basicConfig(level="DEBUG",format='%(asctime)s [%(levelname)-8s,%(filename)-20s:%(lineno)-3d] %(message)s')
+
+RunTimer=True;
+conf=yc.yamlconfig(name)
+conf.linkdevices()
+conf.loaddrivers()
+conf.linkdrivers()
+
+Bands=[2,1,4]
+Band=Bands[2]; #0=110, 1=170, 2=210
+DAB=0; #1=DAB filter enables
+Att=10;
+
+def GetVal(name,N=1):
+ varid=conf.getvarid(name);
+ var1=conf.getvars()[varid]
+ drv=var1.get('drivercls');
+ mask=[False]*RCUNR*N+[True]*N+[False]*((32-RCUNR-1)*N);
+ data=drv.OPCUAReadVariable(varid,var1,mask)
+ data=data[0].data
+ N3=len(data)//32;
+ return data[N3*RCUNR:N3*(RCUNR+1)],var1
+
+
+data,var1=GetVal('RCU_PCB_ID');
+ID=("%.2x%.2x%.2x%.2x" % (data[0],data[1],data[2],data[3]))
+
+rootLogger = logging.getLogger()
+#fileHandler = logging.FileHandler("{0}/{1}.log".format(logPath, "RCU2L"+ID))
+#fileHandler.setFormatter(logFormatter)
+#rootLogger.addHandler(fileHandler)
+
+logging.warning("ID=%s" % ID)
+now=datetime.now();
+logging.warning("Time="+now.strftime("%Y-%m-%d %H:%M"));
+#exit();
+#print("Check 
+def Check(D,Dmin,Dmax):
+  for d in D:
+    if (d<Dmin): 
+        logging.error("Value to small");
+#        return False;
+    if (d>Dmax): 
+        logging.error("Value to large");
+#        return False;
+  return True
+
+if True:
+ data,var1=GetVal('RCU_TEMP');
+ D=((data[0]*256+data[1])*256+data[2])*var1.get('scale',1.)
+ logging.warning("RCU Temperature=%.3f K" % D)
+ if not Check([D],290,350): exit();
+
+ data,var1=GetVal('RCU_PWR_3V3');
+ D=((data[0]*256+data[1])*256+data[2])*var1.get('scale',1.)
+ logging.warning("3V3 =%.3f V" % D)
+# print("3V3=",D,"V")
+ if not Check([D],3.2,3.4): exit();
+# if (D<3.2) or (D>3.4): exit()
+#print("data=",[hex(d) for d in data[:3]]);
+#exit()
+
+def SetRegister(regname,value):
+  methodid=conf.getmethodid("RCU_on");
+  var1=conf.getmethod(methodid)
+  drv=var1.get('drivercls');
+  v1=conf.getdevreg(regname)
+  drv2=v1.get('drivercls')
+  mask=[False]*(RCUNR)+[True]+[False]*(31-RCUNR);
+  if drv:  drv.Setdevreg(v1,value,mask)
+  elif drv2: drv2.Setdevreg(v1,value,mask)
+  else: logging.warn("Driver not specified for instruction"+key)
+
+
+
+if True:
+# logging.warning("Switch RCU Power off");
+# SetRegister("IO1.GPIO1",[0])
+# SetRegister("IO1.GPIO2",[0x0]) #Analog power off
+# SetRegister("IO2.GPIO1",[0x0]) #Digital power off
+# SetRegister("IO2.GPIO2",[0x80])
+ SetRegister("IO1.CONF1",[0])
+ SetRegister("IO1.CONF2",[0])
+ SetRegister("IO2.CONF1",[0x80]) #Pgood on 0x80
+ SetRegister("IO2.CONF2",[0])
+ SetRegister("IO4.CONF1",[0xC0])#pin 0x40, 0x80 not used
+ SetRegister("IO4.CONF2",[0xF8])
+ time.sleep(1.0)
+ logging.warning("Switch RCU Power on");
+ SetRegister("IO1.GPIO1",[Att])#0x0a = 10dB att
+ SetRegister("IO1.GPIO2",[0x80+Att])#0x80 Analog on, 0x0a=10dB att
+ SetRegister("IO2.GPIO1",[0x40+Att])#0x40 Dig on, 0x0a =10dB att
+ SetRegister("IO2.GPIO2",[0x40+Band+(Band<<3)])#0x09 #Band0 (or 0x12 or 0x24)  #LED green=on=low 0x40
+ SetRegister("IO4.GPIO1",[0x51 if DAB else 0x2A])#DAB switch states: 0x2A or 0x51
+ SetRegister("IO4.GPIO2",[Band])#Band select
+ time.sleep(0.5)
+
+# logging.warning("  Check IO expander 1&2");
+# print("IO expander status:");
+# data,var=GetVal('RCU_IO1_GPIO1');
+# if not Check(data,0,0): 
+#   logging.warning("  IO1_GPIO1 =%x" % data[0])
+#   exit();
+# data,var=GetVal('RCU_IO1_GPIO2');
+# if not Check(data,0x80,0x80): 
+#   logging.warning("  IO1_GPIO2 =%x" % data[0])
+#   exit();
+# data,var=GetVal('RCU_IO2_GPIO1');
+# if not Check(data,0xC0,0xC0): 
+#   logging.warning("  IO2_GPIO1 =%x" % data[0])
+#   exit();
+# data,var=GetVal('RCU_IO2_GPIO2');
+# if not Check(data,0x40,0x40): 
+#   logging.warning("  IO2_GPIO2 =%x" % data[0])
+#   exit();
+# time.sleep(0.5)
+#exit()
+if True:
+ logging.warning("Check voltages")
+ data,var1=GetVal('RCU_PWR_1V8');
+ D=((data[0]*256+data[1])*256+data[2])*var1.get('scale',1.)
+ logging.warning("  1V8 =%.3f V" % D)
+ if not Check([D],1.7,1.9): exit();
+
+ data,var1=GetVal('RCU_PWR_2V5');
+ D=((data[0]*256+data[1])*256+data[2])*var1.get('scale',1.)
+ logging.warning("  2V5 =%.3f V" % D)
+ if not Check([D],2.4,2.6): exit();
+if False:
+ data,var1=GetVal('RCU_PWR_ANT_VIN');
+ D0=((data[0]*256+data[1])*256+data[2])*var1.get('scale',1.)
+ D1=((data[3]*256+data[4])*256+data[5])*var1.get('scale',1.)
+ D2=((data[6]*256+data[7])*256+data[8])*var1.get('scale',1.)
+ logging.warning("  Vant_in=%.2f %.2f %.2f" % (D0,D1,D2))
+ if not Check([D0,D1,D2],5,10): exit();
+
+ logging.warning("Switch Antenna power on")
+ SetRegister("IO1.GPIO1",[0xC0]) #Antenna power on
+ SetRegister("IO1.GPIO2",[0xC0]) #Analog power on
+
+ data,var1=GetVal('RCU_PWR_ANT_VOUT');
+ D0=((data[0]*256+data[1])*256+data[2])*var1.get('scale',1.)
+ D1=((data[3]*256+data[4])*256+data[5])*var1.get('scale',1.)
+ D2=((data[6]*256+data[7])*256+data[8])*var1.get('scale',1.)
+ logging.warning("  Vant_out=%.2f %.2f %.2f" % (D0,D1,D2))
+ if not Check([D0,D1,D2],5,10): exit();
+
+ data,var1=GetVal('RCU_PWR_ANT_IOUT');
+ D0=((data[0]*256+data[1])*256+data[2])*var1.get('scale',1.)
+ D1=((data[3]*256+data[4])*256+data[5])*var1.get('scale',1.)
+ D2=((data[6]*256+data[7])*256+data[8])*var1.get('scale',1.)
+ logging.warning("  Iant_out=%.2f %.2f %.2f" % (D0,D1,D2))
+# print("Iant=",D0,D1,D2)
+#exit()
+
+if True:
+ logging.warning("Test ADC read")
+ logging.warning("  Check IO expander 3");
+ SetRegister("IO3.GPIO1",[0x15]) #ADC_SDIO=high, clk=low,  DTH_EN=low
+ SetRegister("IO3.GPIO2",[0x47]) #ADC SC=high, DTH_SDA=high
+ SetRegister("IO3.CONF1",[0]) #All output
+ SetRegister("IO3.CONF2",[0])
+ data,var=GetVal('RCU_IO3_GPIO1');
+ if not Check(data,0x15,0x15): exit();
+ data,var=GetVal('RCU_IO3_GPIO2');
+ if not Check(data,0x47,0x47): exit();
+
+#if True:
+# SetRegister("IO3.GPIO1",[0xD5]) #ADC_SDIO=high, clk=low,  DTH_EN=low
+# SetRegister("IO3.GPIO2",[0xC7]) #ADC SC=high, DTH_SDA=high
+
+# SetRegister("RCU_DTH_shutdown
+
+if False:
+ #Test reading register from ADCs
+ data,var=GetVal('RCU_ADC_JESD');
+ logging.warning("  ADC JESD (0x14)=%x %x %x" % (data[0],data[1],data[2]))
+ if not Check(data,0x14,0x14): exit();
+
+ logging.warning("Test ADC write & ADC lock")
+ #Test writing ADC register
+ SetRegister("ADC1.SYNC_control",[1])
+ SetRegister("ADC1.CML_level",[7]);
+ SetRegister("ADC1.Update",[1])
+ SetRegister("ADC2.SYNC_control",[1])
+ SetRegister("ADC2.CML_level",[7]);
+ SetRegister("ADC2.Update",[1])
+ SetRegister("ADC3.SYNC_control",[1])
+ SetRegister("ADC3.CML_level",[7]);
+ SetRegister("ADC3.Update",[1])
+ data,var=GetVal('RCU_ADC_sync');
+ logging.warning("  ADC sync (0x1)=%x %x %x" % (data[0],data[1],data[2]))
+ if not Check(data,0x1,0x1): exit();
+
+ data,var=GetVal('RCU_ADC_locked');
+ logging.warning("  ADC locked (0x1)=%x %x %x" % (data[0],data[1],data[2]))
+ if not Check(data,0x1,0x1): logging.error("*** FAILED ADC lock!")
+#      - RCU_ADC_locked: Update
+
+#exit()
+#Need to update I2c bitbang....
+if False:
+ logging.warning("Test DITHER communication")
+ SetRegister("IO3.GPIO1",[0x15]) #ADC_SDIO=high, clk=low,  DTH_SDN=low
+ SetRegister("IO3.GPIO2",[0x47]) #ADC SC=high, DTH_SDA=high
+ SetRegister("IO3.CONF1",[0]) #All output
+ SetRegister("IO3.CONF2",[0x0]) #All output (DTH_SDA=input)
+
+
+# data,var=GetVal('RCU_IO3_GPIO1');print("IO3_1",hex(data[0]))
+# data,var=GetVal('RCU_IO3_GPIO2');print("IO3_2",hex(data[0]))
+ f0=102.2e6;
+ f=int(f0)
+ logging.warning("  Set frequency %f"%f0);
+# print("Frequency set=",f)
+ d=[0]*4;
+ for i in range(4):
+   d[3-i]=f%256;f//=256
+# print([hex(h) for h in d])
+ SetRegister("DTH1.Freq",d) #DTH_SDA=input
+ SetRegister("DTH2.Freq",d) #DTH_SDA=input
+ SetRegister("DTH3.Freq",d) #DTH_SDA=input
+
+ f=int(f0)
+ data,var1=GetVal("RCU_DTH_freq")
+# data,var1=GetVal("RCU_DTH_Rev")
+ for j in range(3):
+   f2=0;
+   for i in range(4):
+     f2=f2*256+data[j*4+i];
+   #print("Frequency read back=",f)
+   logging.warning("  Readback frequency %f" % f2);
+   if not Check([f2],f-1,f+1): exit();
+# print([hex(h) for h in data[:30]])
+
+ logging.warning("Test DITHER on")
+ SetRegister("DTH1.CONF",[0])
+ SetRegister("DTH1.Tune",[0,0])
+ SetRegister("DTH1.Start",[0,1,0,0,1])
+ SetRegister("DTH2.CONF",[0])
+ SetRegister("DTH2.Tune",[0,0])
+ SetRegister("DTH2.Start",[0,1,0,0,1])
+ SetRegister("DTH3.CONF",[0])
+ SetRegister("DTH3.Tune",[0,0])
+ SetRegister("DTH3.Start",[0,1,0,0,1])
+ time.sleep(0.1)
+ data,var=GetVal('RCU_DTH_on');
+ logging.warning("  DTH on (0x1)=%x %x %x" % (data[0],data[1],data[2]))
+ if not Check(data,0x1,0x1): logging.error("*** FAILED: Dither on! ***")
+
+
+logging.warning("** PASSED Power and Control test **");
+
+
+#print(data)
+#scale=float(scale)
+#data2=[(d*scale) for d in data2]
+
+#print("ID=",[hex(d) for d in data[:4]]);
+
+
+
diff --git a/testRCUH_pwr.py b/testRCUH_pwr.py
new file mode 100644
index 0000000000000000000000000000000000000000..7c625fe2e37cda48675790c859a1f990aef28081
--- /dev/null
+++ b/testRCUH_pwr.py
@@ -0,0 +1,280 @@
+name='RECVTR_HB' #YAML config file with all register values etc
+logPath='log'
+yamllogfile="prodtest/RCU2HQM"
+savedb=False;
+savedb=True;
+
+
+from test_common import *
+from datetime import datetime
+from prodtest.yamllog import yamllog
+
+loadconf(name);
+
+Bands=[2,1,4]
+Band=Bands[0]; #0=110, 1=170, 2=210
+DAB=1; #1=DAB filter enables
+Att=10;
+skip_know_user_input=True;
+#skip_know_user_input=False;
+db=yamllog(yamllogfile)
+
+
+data,var1=GetVal('RCU_PCB_ID');
+ID=("%.2x%.2x%.2x%.2x" % (data[0],data[1],data[2],data[3]))
+
+logging.warning("ID=%s" % ID)
+testtime=datetime.now().strftime("%Y-%m-%d %H:%M");
+logging.warning("Time="+testtime);
+
+#If we so not know number, ask it
+PCBnum=db.getdata("PCB_number","ID",ID)
+if (PCBnum is None) or not(skip_know_user_input):
+ print("Enter PCB number:");
+ PCBnum=input();
+ PCBnum={"ID":ID,"number":PCBnum}
+ db.replace("PCB_number","ID",ID,PCBnum)
+ if savedb: db.save(yamllogfile);
+else:
+  print("PCB nunber=",PCBnum['number']);
+
+if True:
+ offpwr=db.getdata("off_power","ID",ID)
+ if (offpwr is None) or not(skip_know_user_input):
+    print("Enter 4V current (A):");
+    Ioff3=float(input());
+    print("Enter 6V current (A):");
+    Ioff6=float(input());
+    offpwr={"ID":ID,"I_4V":Ioff3,"I_6V":Ioff6}
+ offpwr['time']=testtime;
+ data,var1=GetVal('RCU_TEMP');
+ D=((data[0]*256+data[1])*256+data[2])*var1.get('scale',1.)
+ offpwr['temp']=D;
+ logging.warning("RCU Temperature=%.3f K" % D)
+ if not Check([D],290,350): exit();
+
+ data,var1=GetVal('RCU_PWR_3V3');
+ D=((data[0]*256+data[1])*256+data[2])*var1.get('scale',1.)
+ offpwr['V_3v3']=D;
+ logging.warning("3V3 =%.3f V" % D)
+# print("3V3=",D,"V")
+ if not Check([D],3.2,3.4): exit();
+ db.replace("off_power","ID",ID,offpwr)
+ if savedb: db.save(yamllogfile);
+# if (D<3.2) or (D>3.4): exit()
+#print("data=",[hex(d) for d in data[:3]]);
+#exit()
+
+
+if True:
+# logging.warning("Switch RCU Power off");
+# SetRegister("IO1.GPIO1",[0])
+# SetRegister("IO1.GPIO2",[0x0]) #Analog power off
+# SetRegister("IO2.GPIO1",[0x0]) #Digital power off
+# SetRegister("IO2.GPIO2",[0x80])
+ SetRegister("IO1.CONF1",[0])
+ SetRegister("IO1.CONF2",[0])
+ SetRegister("IO2.CONF1",[0x80]) #Pgood on 0x80
+ SetRegister("IO2.CONF2",[0])
+ SetRegister("IO4.CONF1",[0xC0])#pin 0x40, 0x80 not used
+ SetRegister("IO4.CONF2",[0xF8])
+ time.sleep(1.0)
+ logging.warning("Switch RCU Power on");
+ SetRegister("IO1.GPIO1",[Att])#0x0a = 10dB att
+ SetRegister("IO1.GPIO2",[0x80+Att])#0x80 Analog on, 0x0a=10dB att
+ SetRegister("IO2.GPIO1",[0x40+Att])#0x40 Dig on, 0x0a =10dB att
+ SetRegister("IO2.GPIO2",[0x40+Band+(Band<<3)])#0x09 #Band0 (or 0x12 or 0x24)  #LED green=on=low 0x40
+ SetRegister("IO4.GPIO1",[0x51 if DAB else 0x2A])#DAB switch states: 0x2A or 0x51
+ SetRegister("IO4.GPIO2",[Band])#Band select
+ time.sleep(0.5)
+
+# logging.warning("  Check IO expander 1&2");
+# print("IO expander status:");
+# data,var=GetVal('RCU_IO1_GPIO1');
+# if not Check(data,0,0): 
+#   logging.warning("  IO1_GPIO1 =%x" % data[0])
+#   exit();
+# data,var=GetVal('RCU_IO1_GPIO2');
+# if not Check(data,0x80,0x80): 
+#   logging.warning("  IO1_GPIO2 =%x" % data[0])
+#   exit();
+# data,var=GetVal('RCU_IO2_GPIO1');
+# if not Check(data,0xC0,0xC0): 
+#   logging.warning("  IO2_GPIO1 =%x" % data[0])
+#   exit();
+# data,var=GetVal('RCU_IO2_GPIO2');
+# if not Check(data,0x40,0x40): 
+#   logging.warning("  IO2_GPIO2 =%x" % data[0])
+#   exit();
+# time.sleep(0.5)
+
+if True:
+ logging.warning("Check voltages")
+ onpwr=db.getdata("on_power","ID",ID)
+ if (onpwr is None) or not(skip_know_user_input):
+    print("Enter 4V current (A):");
+    Ioff3=float(input());
+    print("Enter 6V current (A):");
+    Ioff6=float(input());
+    onpwr={"ID":ID,"I_4V":Ioff3,"I_6V":Ioff6}
+ onpwr['time']=testtime;
+ data,var1=GetVal('RCU_PWR_1V8');
+ D=((data[0]*256+data[1])*256+data[2])*var1.get('scale',1.)
+ onpwr['V_1v8']=D;
+ logging.warning("  1V8 =%.3f V" % D)
+ if not Check([D],1.7,1.9): exit();
+
+ data,var1=GetVal('RCU_PWR_2V5');
+ D=((data[0]*256+data[1])*256+data[2])*var1.get('scale',1.)
+ onpwr['V_2v5']=D;
+ logging.warning("  2V5 =%.3f V" % D)
+ if not Check([D],2.4,2.6): exit();
+ db.replace("on_power","ID",ID,onpwr)
+ if savedb: db.save(yamllogfile);
+
+if True:
+ antpwr=db.getdata("ant_power","ID",ID)
+ if (antpwr is None) or not(skip_know_user_input):
+    print("Enter ant current (A):");
+    Ioff=float(input());  
+    antpwr={"ID":ID,"Ioff":Ioff}
+ antpwr['time']=testtime;
+ data,var1=GetVal('RCU_PWR_ANT_VIN');
+ D0=((data[0]*256+data[1])*256+data[2])*var1.get('scale',1.)
+ D1=((data[3]*256+data[4])*256+data[5])*var1.get('scale',1.)
+ D2=((data[6]*256+data[7])*256+data[8])*var1.get('scale',1.)
+ logging.warning("  Vant_in=%.2f %.2f %.2f" % (D0,D1,D2))
+ antpwr['Vin']=[D0,D1,D2]
+
+ if not Check([D0,D1,D2],5,10): exit();
+
+ logging.warning("Switch Antenna power on")
+ SetRegister("IO1.GPIO1",[0xC0]) #Antenna power on
+ SetRegister("IO1.GPIO2",[0xC0]) #Analog power on
+
+ data,var1=GetVal('RCU_PWR_ANT_VOUT');
+ D0=((data[0]*256+data[1])*256+data[2])*var1.get('scale',1.)
+ D1=((data[3]*256+data[4])*256+data[5])*var1.get('scale',1.)
+ D2=((data[6]*256+data[7])*256+data[8])*var1.get('scale',1.)
+ logging.warning("  Vant_out=%.2f %.2f %.2f" % (D0,D1,D2))
+ antpwr['Vout']=[D0,D1,D2]
+ if not Check([D0,D1,D2],5,10): exit();
+
+ data,var1=GetVal('RCU_PWR_ANT_IOUT');
+ D0=((data[0]*256+data[1])*256+data[2])*var1.get('scale',1.)
+ D1=((data[3]*256+data[4])*256+data[5])*var1.get('scale',1.)
+ D2=((data[6]*256+data[7])*256+data[8])*var1.get('scale',1.)
+ antpwr['Iout']=[D0,D1,D2]
+ logging.warning("  Iant_out=%.2f %.2f %.2f" % (D0,D1,D2))
+
+ if (antpwr.get("Ion") is None) or not(skip_know_user_input):
+    print("Enter ant current (A):");
+    Ion=float(input());  
+    antpwr["Ion"]=Ion
+
+ db.replace("ant_power","ID",ID,antpwr)
+ if savedb: db.save(yamllogfile);
+# print("Iant=",D0,D1,D2)
+#exit()
+
+if True:
+ logging.warning("Test ADC read")
+ logging.warning("  Check IO expander 3");
+ SetRegister("IO3.GPIO1",[0x15]) #ADC_SDIO=high, clk=low,  DTH_EN=low
+ SetRegister("IO3.GPIO2",[0x47]) #ADC SC=high, DTH_SDA=high
+ SetRegister("IO3.CONF1",[0]) #All output
+ SetRegister("IO3.CONF2",[0])
+ data,var=GetVal('RCU_IO3_GPIO1');
+ if not Check(data,0x15,0x15): exit();
+ data,var=GetVal('RCU_IO3_GPIO2');
+ if not Check(data,0x47,0x47): exit();
+
+if True:
+ #Test reading register from ADCs
+ data,var=GetVal('RCU_ADC_JESD');
+ logging.warning("  ADC JESD (0x14)=%x %x %x" % (data[0],data[1],data[2]))
+ if not Check(data,0x14,0x14): exit();
+
+ logging.warning("Test ADC write & ADC lock")
+ #Test writing ADC register
+ SetRegister("ADC1.SYNC_control",[1])
+ SetRegister("ADC1.CML_level",[7]);
+ SetRegister("ADC1.Update",[1])
+ SetRegister("ADC2.SYNC_control",[1])
+ SetRegister("ADC2.CML_level",[7]);
+ SetRegister("ADC2.Update",[1])
+ SetRegister("ADC3.SYNC_control",[1])
+ SetRegister("ADC3.CML_level",[7]);
+ SetRegister("ADC3.Update",[1])
+ data,var=GetVal('RCU_ADC_sync');
+ logging.warning("  ADC sync (0x1)=%x %x %x" % (data[0],data[1],data[2]))
+ if not Check(data,0x1,0x1): exit();
+
+ data,var=GetVal('RCU_ADC_locked');
+ logging.warning("  ADC locked (0x1)=%x %x %x" % (data[0],data[1],data[2]))
+ if not Check(data,0x1,0x1): logging.error("*** FAILED ADC lock!")
+#      - RCU_ADC_locked: Update
+
+#exit()
+#Need to update I2c bitbang....
+if False:
+ logging.warning("Test DITHER communication")
+ SetRegister("IO3.GPIO1",[0x15]) #ADC_SDIO=high, clk=low,  DTH_SDN=low
+ SetRegister("IO3.GPIO2",[0x47]) #ADC SC=high, DTH_SDA=high
+ SetRegister("IO3.CONF1",[0]) #All output
+ SetRegister("IO3.CONF2",[0x0]) #All output (DTH_SDA=input)
+
+
+# data,var=GetVal('RCU_IO3_GPIO1');print("IO3_1",hex(data[0]))
+# data,var=GetVal('RCU_IO3_GPIO2');print("IO3_2",hex(data[0]))
+ f0=102.2e6;
+ f=int(f0)
+ logging.warning("  Set frequency %f"%f0);
+# print("Frequency set=",f)
+ d=[0]*4;
+ for i in range(4):
+   d[3-i]=f%256;f//=256
+# print([hex(h) for h in d])
+ SetRegister("DTH1.Freq",d) #DTH_SDA=input
+ SetRegister("DTH2.Freq",d) #DTH_SDA=input
+ SetRegister("DTH3.Freq",d) #DTH_SDA=input
+
+ f=int(f0)
+ data,var1=GetVal("RCU_DTH_freq")
+# data,var1=GetVal("RCU_DTH_Rev")
+ for j in range(3):
+   f2=0;
+   for i in range(4):
+     f2=f2*256+data[j*4+i];
+   #print("Frequency read back=",f)
+   logging.warning("  Readback frequency %f" % f2);
+   if not Check([f2],f-1,f+1): exit();
+# print([hex(h) for h in data[:30]])
+
+ logging.warning("Test DITHER on")
+ SetRegister("DTH1.CONF",[0])
+ SetRegister("DTH1.Tune",[0,0])
+ SetRegister("DTH1.Start",[0,1,0,0,1])
+ SetRegister("DTH2.CONF",[0])
+ SetRegister("DTH2.Tune",[0,0])
+ SetRegister("DTH2.Start",[0,1,0,0,1])
+ SetRegister("DTH3.CONF",[0])
+ SetRegister("DTH3.Tune",[0,0])
+ SetRegister("DTH3.Start",[0,1,0,0,1])
+ time.sleep(0.1)
+ data,var=GetVal('RCU_DTH_on');
+ logging.warning("  DTH on (0x1)=%x %x %x" % (data[0],data[1],data[2]))
+ if not Check(data,0x1,0x1): logging.error("*** FAILED: Dither on! ***")
+
+
+logging.warning("** PASSED Power and Control test **");
+
+
+#print(data)
+#scale=float(scale)
+#data2=[(d*scale) for d in data2]
+
+#print("ID=",[hex(d) for d in data[:4]]);
+
+
+
diff --git a/test_common.py b/test_common.py
new file mode 100644
index 0000000000000000000000000000000000000000..967e86ad597ca5af93217e16ec6ab6e7e9868e79
--- /dev/null
+++ b/test_common.py
@@ -0,0 +1,70 @@
+logPath='log'
+
+import logging
+import argparse
+from opcuaserv import opcuaserv
+from opcuaserv import i2client
+from opcuaserv import yamlreader
+#from opcuaserv import pypcc2
+#from i2cserv import i2cthread
+#import threading
+import time
+import sys
+import signal
+from yamlconfig import Find;
+import yamlconfig as yc
+#from datetime import datetime
+#from prodtest.yamllog import yamllog
+
+RCUNR=(0 if len(sys.argv)<2 else int(sys.argv[1]));
+print("RCU NR=",RCUNR);
+logging.basicConfig(level="WARNING",format='%(asctime)s [%(levelname)-8s,%(filename)-20s:%(lineno)-3d] %(message)s')
+#logging.basicConfig(level="DEBUG",format='%(asctime)s [%(levelname)-8s,%(filename)-20s:%(lineno)-3d] %(message)s')
+
+global conf
+conf=None
+
+RunTimer=True;
+def loadconf(name):
+  global conf
+  conf=yc.yamlconfig(name)
+  conf.linkdevices()
+  conf.loaddrivers()
+  conf.linkdrivers()
+  
+
+#db=yamllog(yamllogfile)
+rootLogger = logging.getLogger()
+
+def GetVal(name,N=1):
+ varid=conf.getvarid(name);
+ var1=conf.getvars()[varid]
+ drv=var1.get('drivercls');
+ mask=[False]*RCUNR*N+[True]*N+[False]*((32-RCUNR-1)*N);
+ data=drv.OPCUAReadVariable(varid,var1,mask)
+ data=data[0].data
+ N3=len(data)//32;
+ return data[N3*RCUNR:N3*(RCUNR+1)],var1
+
+def Check(D,Dmin,Dmax):
+  for d in D:
+    if (d<Dmin): 
+        logging.error("Value to small");
+#        return False;
+    if (d>Dmax): 
+        logging.error("Value to large");
+#        return False;
+  return True
+
+def SetRegister(regname,value):
+  methodid=conf.getmethodid("RCU_on");
+  var1=conf.getmethod(methodid)
+  drv=var1.get('drivercls');
+  v1=conf.getdevreg(regname)
+  drv2=v1.get('drivercls')
+  mask=[False]*(RCUNR)+[True]+[False]*(31-RCUNR);
+  if drv:  drv.Setdevreg(v1,value,mask)
+  elif drv2: drv2.Setdevreg(v1,value,mask)
+  else: logging.warn("Driver not specified for instruction"+key)
+
+