From 6ce567f7ba5aa7c97701e54e34648c5c3f0477b8 Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Fri, 8 Feb 2019 15:34:32 +0100 Subject: [PATCH 01/41] PRJ: bump to version v3.0.1.dev0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 4a36342fc..763327302 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.0.0 +3.0.1.dev0 From 1d42f073b94936c1eb5904dac04a60f44ac4253f Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Fri, 8 Feb 2019 16:05:29 +0100 Subject: [PATCH 02/41] PRJ: remove deploy from travis, not working --- .travis.yml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 212712f47..3805d4e9e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,13 +48,3 @@ script: after_success: - coveralls - -deploy: - provider: pypi - user: davidlp - password: - secure: EWWzZuUU5hJAd9iVPr4kPYbs1wbm7D8eVU596GUH8ZI/Q4seXsYeL+Pi++FI6M268qNUGJuVsvWbU5S+/E74VmIeU3b0n6BNSfUas0tSqMmazN/Sj0iMtGJ3Tll5Z7JfPK2RbZfBvSHN5T9W5RXz7M2US0x88ATrNVt3iuRNqWQ= - on: - tags: true - repo: SiLab-Bonn/basil - distributions: sdist bdist_wheel From 0b00265113cc92560f9d91a7e7cce0fe9b7dd44b Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Fri, 8 Feb 2019 16:25:57 +0100 Subject: [PATCH 03/41] PRJ: adding deploy to travis, this time with skip_existing --- .travis.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.travis.yml b/.travis.yml index 3805d4e9e..67f2c280b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,3 +48,14 @@ script: after_success: - coveralls + +deploy: + provider: pypi + user: davidlp + password: + secure: EWWzZuUU5hJAd9iVPr4kPYbs1wbm7D8eVU596GUH8ZI/Q4seXsYeL+Pi++FI6M268qNUGJuVsvWbU5S+/E74VmIeU3b0n6BNSfUas0tSqMmazN/Sj0iMtGJ3Tll5Z7JfPK2RbZfBvSHN5T9W5RXz7M2US0x88ATrNVt3iuRNqWQ= + on: + tags: true + repo: SiLab-Bonn/basil + skip_existing: true + distributions: sdist bdist_wheel From 8747a95ef1207f96c864f2d131b4c44e82ee5593 Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Fri, 8 Feb 2019 16:33:52 +0100 Subject: [PATCH 04/41] PRJ: specify supported Python versions in setup.py --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 184a5fb6a..f6de8671e 100644 --- a/setup.py +++ b/setup.py @@ -32,6 +32,7 @@ def package_files(directory): setup( name='basil_daq', version=version, + python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*', description='Basil - a data acquisition and system testing framework', url='https://github.com/SiLab-Bonn/basil', license='BSD 3-Clause ("BSD New" or "BSD Simplified") License', From 7c5df007d84db20c85f45f48d1947a3a6e152f84 Mon Sep 17 00:00:00 2001 From: thirono Date: Mon, 25 Mar 2019 13:17:45 +0100 Subject: [PATCH 05/41] ENH: add a switch to aviod power reset (and harm CMOS active sensor) at initialization --- basil/HL/GPAC.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/basil/HL/GPAC.py b/basil/HL/GPAC.py index 6ef4c559a..e7100c120 100644 --- a/basil/HL/GPAC.py +++ b/basil/HL/GPAC.py @@ -96,6 +96,16 @@ def __init__(self, intf, conf): super(PowerGpio, self).__init__(intf, conf) self.PCA9554_ADD = self.POWER_GPIO_ADD self.GPIO_CFG = self.POWER_GPIO_CFG + self._init.setdefault('no_power_reset', False) + def init(self): + self._intf.write(self._base_addr + self.PCA9554_ADD, (self.PCA9554_CFG, self.GPIO_CFG)) + if self._init['no_power_reset']==False: + logging.info("########GPAC ##########") + logging.info("########POWER RESET!!!!!##########") + self._intf.write(self._base_addr + self.PCA9554_ADD, (self.PCA9554_OUT, 0x00)) + else: + logging.info("########GPAC #####") + logging.info("########SKIPPING POWER RESET #####") class AdcMuxGpio(GpioPca9554): From c4aff952be96f32c18a12ddc4bee448ec2a2001b Mon Sep 17 00:00:00 2001 From: Christian Bespin Date: Fri, 29 Mar 2019 16:05:31 +0100 Subject: [PATCH 06/41] ENH: Add module to control ISO-DEBYEFLEX3003 X-Ray machine --- basil/HL/debyeflex3003.py | 186 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 basil/HL/debyeflex3003.py diff --git a/basil/HL/debyeflex3003.py b/basil/HL/debyeflex3003.py new file mode 100644 index 000000000..895ef1c38 --- /dev/null +++ b/basil/HL/debyeflex3003.py @@ -0,0 +1,186 @@ +# +# ------------------------------------------------------------ +# Copyright (c) All rights reserved +# SiLab, Institute of Physics, University of Bonn +# ------------------------------------------------------------ +# + +from basil.HL.RegisterHardwareLayer import HardwareLayer +import logging + + +class debyeflex3003(HardwareLayer): + + """Driver for the ISO-DEBYEFLEX 3003 X-Ray tube. + A simple protocol via RS 232 serial port is used with 9600 baud rate. + """ + + def __init__(self, intf, conf): + super(debyeflex3003, self).__init__(intf, conf) + + def init(self): + super(debyeflex3003, self).init() + + def read(self): + ret = self._intf.read() + if ret[-1:] != "\r": + print("debyeflex3003.read() terminator error") + return ret[1:-1] + + def write(self, cmd): + self._intf.write(str(cmd)) + + def get_nominal_current(self): + """Read nominal current in mA. + """ + self.write("CN") + curr = self.read() + return int(curr) / 1000. + + def get_actual_current(self): + """Read actual current in mA. + """ + self.write("CA") + curr = self.read() + return int(curr) / 1000. + + def set_current(self, curr): + """Set current in mA + """ + if curr > 80 or curr < 0: + raise ValueError("Illegal value for tube current (0 - 80 mA)") + else: + self.write("SC:{:02d}".format(int(curr))) + logging.info("Set tube current to {:.1f} mA".format(self.get_nominal_current())) + + def get_nominal_voltage(self): + """Read nominal voltage in kV. + """ + self.write("VN") + vol = self.read() + return int(vol) / 1000. + + def get_actual_voltage(self): + """Read actual voltage in kV. + """ + self.write("VA") + vol = self.read() + return int(vol) / 1000. + + def set_voltage(self, vol): + """Set high voltage in kV + """ + if vol > 60 or vol < 0: + raise ValueError("Illegal value for tube voltage (0 - 60 kV)") + else: + self.write("SV:{:02d}".format(vol)) + logging.info("Set tube voltage to {:.1f} kV".format(self.get_nominal_voltage())) + + def set_highvoltage_on(self): + self.write("HV:1") + + def set_highvoltage_off(self): + self.write("HV:0") + + def open_shutter(self, shutter=1): + """Open the shutter with given number. Only shuttter=1 supported from hardware currently + """ + if not isinstance(shutter, int): + raise TypeError("Invalid type for shutter number") + elif shutter > 4 or shutter < 1: + raise ValueError("Invalid value for shutter number") + else: + self.write("OS:{:1d}".format(shutter)) + logging.info("Opened shutter number {:1d}".format(shutter)) + + def close_shutter(self, shutter=1): + """Close the shutter with given number. Only shuttter=1 supported from hardware currently + """ + if not isinstance(shutter, int): + raise TypeError("Invalid type for shutter number") + elif shutter > 4 or shutter < 1: + raise ValueError("Invalid value for shutter number") + else: + self.write("CS:{:1d}".format(shutter)) + logging.info("Closed shutter number {:1d}".format(shutter)) + + def start_timer(self, timer=1): + """Start the timer with the given number (corresponds to shutter number) + """ + if not isinstance(timer, int): + raise TypeError("Invalid type for timer number") + elif timer > 4 or timer < 1: + raise ValueError("Invalid value for timer number") + else: + self.write("TS:{:1d}".format(timer)) + logging.info("Started timer number {:1d}".format(timer)) + + def stop_timer(self, timer=1): + """Stop the timer with the given number (corresponds to shutter number) + """ + if not isinstance(timer, int): + raise TypeError("Invalid type for timer number") + elif timer > 4 or timer < 1: + raise ValueError("Invalid value for timer number") + else: + self.write("TE:{:1d}".format(timer)) + logging.info("Stopped timer number {:1d}".format(timer)) + + def set_timer(self, timer=1, dur=3600): + """Set the timer with the given number (corresponds to shutter number) to the given duration (in s) + """ + if not isinstance(timer, int): + raise TypeError("Invalid type for timer number") + elif not isinstance(dur, int): + raise TypeError("Illegal type for duration") + elif timer > 4 or timer < 1: + raise ValueError("Invalid value for timer number") + else: + h = dur // 3600 + m = (dur % 3600) // 60 + s = (dur % 3600) % 60 + self.write("TP:{:1d},{:02d},{:02d},{:02d}".format(timer, h, m, s)) + time = self.get_nominal_time(timer) + logging.info("Set timer number {:1d} to {:02d}:{:02d}:{:02d} (HH:MM:SS)".format( + timer, time // 3600, (time % 3600) // 60, (time % 3600) % 60) + ) + + def get_actual_time(self, timer=1): + """Get the actual time of the given timer in s + """ + if not isinstance(timer, int): + raise TypeError("Invalid type for timer number") + elif timer > 4 or timer < 1: + raise ValueError("Invalid value for timer number (1, 2, 3, 4)") + else: + self.write("TA:{:1d}".format(timer)) + time = self.read() + return int(time) + + def get_nominal_time(self, timer=1): + """Get the nominal time of the given timer in s + """ + if not isinstance(timer, int): + raise TypeError("Invalid type for timer number") + elif timer > 4 or timer < 1: + raise ValueError("Invalid value for timer number (1, 2, 3, 4)") + else: + self.write("TN:{:1d}".format(timer)) + time = self.read() + return int(time) + + def lock_keyboard(self): + """Locks the hardware keyboard on the device. Only STOP key still works. + """ + self.write("KB:0") + + def unlock_keyboard(self): + self.write("KB:1") + + def get_status(self, status_word): + """ Get a pre-selected range of status parameters + """ + self.write("SR:{:02d}".format(status_word)) + response = self.read() + status = bin(int(response[7:10]))[2:].zfill(8) # Convert response to 8 char long string of binary values + logging.info("Status word {:02d}: {:8s}".format(status_word, status)) From e480eac57038e17789ec16961bac76b315b1e8a7 Mon Sep 17 00:00:00 2001 From: thirono Date: Wed, 15 May 2019 19:57:52 +0200 Subject: [PATCH 07/41] EHN: add chiller (julaboF32HD) --- basil/HL/julaboF32HD.py | 73 +++++++++++++++++++++++++++ examples/lab_devices/julaboF32HD.py | 24 +++++++++ examples/lab_devices/julaboF32HD.yaml | 19 +++++++ 3 files changed, 116 insertions(+) create mode 100644 basil/HL/julaboF32HD.py create mode 100644 examples/lab_devices/julaboF32HD.py create mode 100644 examples/lab_devices/julaboF32HD.yaml diff --git a/basil/HL/julaboF32HD.py b/basil/HL/julaboF32HD.py new file mode 100644 index 000000000..38eedc355 --- /dev/null +++ b/basil/HL/julaboF32HD.py @@ -0,0 +1,73 @@ +# +# ------------------------------------------------------------ +# Copyright (c) All rights reserved +# SiLab, Institute of Physics, University of Bonn +# ------------------------------------------------------------ +# + +from basil.HL.RegisterHardwareLayer import HardwareLayer +import logging +import time +import string + +class julaboF32HD(HardwareLayer): + + """Driver for the Julabo F32-HD tillar. + A simple protocol via RS 232 serial port is used with 4800 baud rate. + """ + + def __init__(self, intf, conf): + super(julaboF32HD, self).__init__(intf, conf) + self.pre_time=time.time() + + def init(self): + super(julaboF32HD, self).init() + + def read(self): + ret = self._intf.read() + if len(ret)<2 or ret[-2:] != "\r\n": + print("julabo.read() terminator error") + return ret[:-2] + + def write(self, cmd): + if time.time()-self.pre_time<1.0: + time.sleep(1.0) + self._intf.write(str(cmd)) + self.pre_time=time.time() + + def get_identifier(self): + """Read identifier + """ + self.write("version") + ret = self.read() + return ret + + def start_thermostat(self,start=True): + """ start tiller + """ + if start==True: + self.write("out_mode_05 1") + else: + self.write("out_mode_05 0") + + def stop_thermostat(self): + """ stop tiller + """ + self.start_thermostat(False) + + def get_status(self): + """ Get status + """ + self.write("status") + ret = self.read() + logging.debug("status:{:s}".format(ret)) + try: + tmp=ret.split(" ", 1) + status=int(tmp[0]) + status_str=tmp[1:] + except: + print("julabo.get_status() wrong format ".format(repr(ret))) + status=-99 + status_str=ret + return status,status_str + diff --git a/examples/lab_devices/julaboF32HD.py b/examples/lab_devices/julaboF32HD.py new file mode 100644 index 000000000..f16c2162b --- /dev/null +++ b/examples/lab_devices/julaboF32HD.py @@ -0,0 +1,24 @@ +# +# ------------------------------------------------------------ +# Copyright (c) All rights reserved +# SiLab, Institute of Physics, University of Bonn +# ------------------------------------------------------------ +# + +''' Example how to use the tiller. +''' + +import time + +from basil.dut import Dut + +dut = Dut('julaboF32HD.yaml') +dev.init() +print "ID",dev["tiller"].get_identifier() +print "status",dev["tiller"].get_status() + +### start +### set menu->confiuration->setpoint->rs232 +dev["tiller"].start_thermostat() +dev["tiller"].get_status() + diff --git a/examples/lab_devices/julaboF32HD.yaml b/examples/lab_devices/julaboF32HD.yaml new file mode 100644 index 000000000..5b48673bb --- /dev/null +++ b/examples/lab_devices/julaboF32HD.yaml @@ -0,0 +1,19 @@ +transfer_layer: + - name : Serial + type : Serial + init : + port : /dev/ttyUSB5 + read_termination : "\r\n" + write_termination : "\r" + baudrate : 4800 + timeout : 2.0 + parity : "N" ### serial.PARITY_NONE + xonxoff : True ### software handshake on + rtscts : False + dsrdtr : False + + +hw_drivers: + - name : tiller + type : julaboF32HD + interface : Serial From dd8d65f24963e54535c28b1a62e3c1a525cb8de4 Mon Sep 17 00:00:00 2001 From: Michael Daas Date: Thu, 11 Jul 2019 13:55:12 +0200 Subject: [PATCH 08/41] FIX: Missing encoding for serial write_termination in special case --- basil/TL/Serial.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/basil/TL/Serial.py b/basil/TL/Serial.py index a0577bdd1..28c73efc9 100644 --- a/basil/TL/Serial.py +++ b/basil/TL/Serial.py @@ -53,7 +53,7 @@ def write(self, data): try: self._port.write(bytes(data, 'utf-8') + self.write_termination) except TypeError: - self._port.write(bytes(data + self.write_termination)) + self._port.write(bytes(data + self.write_termination, 'utf-8')) def read(self, size=None): if size is None: @@ -82,4 +82,4 @@ def _readline(self): # http://stackoverflow.com/questions/16470903/pyserial-2-6 data += character if not character: break - return data.decode('utf-8') + return data.decode('utf-8', errors='ignore') From 116d724bba492b971f33a385001364654468052e Mon Sep 17 00:00:00 2001 From: Tomasz Hemperek Date: Thu, 18 Jul 2019 12:50:45 +0200 Subject: [PATCH 09/41] ENH: change yaml.load to yaml.safe_load (#112) --- basil/HL/JtagGpio.py | 2 +- basil/utils/sim/Test.py | 2 +- examples/MIO/tb/test_SimExample.py | 2 +- examples/bdaq/test/test_bdaq53_eth.py | 2 +- examples/lx9/host/lx9.py | 2 +- examples/mio_pixel/tests/test_Sim.py | 2 +- examples/mio_sram_test/tests/test_Sim.py | 2 +- examples/mmc3_eth/test/test_mmc3_eth.py | 2 +- tests/test_SimJtagGpio.py | 2 +- tests/test_SimScpi.py | 2 +- tests/test_StdRegister.py | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/basil/HL/JtagGpio.py b/basil/HL/JtagGpio.py index 75f3affd3..6f93ecd18 100644 --- a/basil/HL/JtagGpio.py +++ b/basil/HL/JtagGpio.py @@ -40,7 +40,7 @@ class JtagGpio(HardwareLayer): def __init__(self, intf, conf): super(JtagGpio, self).__init__(intf, conf) - cfg = yaml.load(self.jtag_gpio_yaml) + cfg = yaml.safe_load(self.jtag_gpio_yaml) self.reg = StdRegister(driver=None, conf=cfg) # self.RESETB = 0 diff --git a/basil/utils/sim/Test.py b/basil/utils/sim/Test.py index 02eeb9f18..00cd34a85 100644 --- a/basil/utils/sim/Test.py +++ b/basil/utils/sim/Test.py @@ -47,7 +47,7 @@ def socket_test(dut, debug=False): sim_modules = [] sim_modules_data = os.getenv("SIMULATION_MODULES", "") if sim_modules_data: - sim_modules_yml = yaml.load(sim_modules_data) + sim_modules_yml = yaml.safe_load(sim_modules_data) for mod in sim_modules_yml: mod_import = import_driver(mod) kargs = dict(sim_modules_yml[mod]) diff --git a/examples/MIO/tb/test_SimExample.py b/examples/MIO/tb/test_SimExample.py index ede2028f2..9d97f54a7 100644 --- a/examples/MIO/tb/test_SimExample.py +++ b/examples/MIO/tb/test_SimExample.py @@ -26,7 +26,7 @@ def setUp(self): ) with open(os.path.join(os.path.dirname(__file__), 'example.yaml'), 'r') as f: - cnfg = yaml.load(f) + cnfg = yaml.safe_load(f) # change to simulation interface cnfg['transfer_layer'][0]['type'] = 'SiSim' diff --git a/examples/bdaq/test/test_bdaq53_eth.py b/examples/bdaq/test/test_bdaq53_eth.py index eb8265a69..9082ca7e6 100644 --- a/examples/bdaq/test/test_bdaq53_eth.py +++ b/examples/bdaq/test/test_bdaq53_eth.py @@ -29,7 +29,7 @@ def setUp(self): with open(proj_dir + '/bdaq53_eth.yaml') as conf_file: try: - conf = yaml.load(conf_file) + conf = yaml.safe_load(conf_file) except yaml.YAMLError as exception: print(exception) diff --git a/examples/lx9/host/lx9.py b/examples/lx9/host/lx9.py index 3b7e34707..dfa2a9cab 100644 --- a/examples/lx9/host/lx9.py +++ b/examples/lx9/host/lx9.py @@ -103,7 +103,7 @@ def _clear_strobes(self): print("Start") stream = open("lx9.yaml", 'r') -cnfg = yaml.load(stream) +cnfg = yaml.safe_load(stream) chip = Pixel(cnfg) chip.init() diff --git a/examples/mio_pixel/tests/test_Sim.py b/examples/mio_pixel/tests/test_Sim.py index 6d8526510..57c479001 100644 --- a/examples/mio_pixel/tests/test_Sim.py +++ b/examples/mio_pixel/tests/test_Sim.py @@ -56,7 +56,7 @@ def setUp(self): ) with open(os.path.join(os.path.dirname(__file__), '../pixel.yaml'), 'r') as f: - cnfg = yaml.load(f) + cnfg = yaml.safe_load(f) # change to simulation interface cnfg['transfer_layer'][0]['type'] = 'SiSim' diff --git a/examples/mio_sram_test/tests/test_Sim.py b/examples/mio_sram_test/tests/test_Sim.py index 2a8cf5e70..989719449 100644 --- a/examples/mio_sram_test/tests/test_Sim.py +++ b/examples/mio_sram_test/tests/test_Sim.py @@ -38,7 +38,7 @@ def setUp(self): ) with open(os.path.join(os.path.dirname(__file__), '../sram_test.yaml'), 'r') as f: - cnfg = yaml.load(f) + cnfg = yaml.safe_load(f) # change to simulation interface cnfg['transfer_layer'][0]['type'] = 'SiSim' diff --git a/examples/mmc3_eth/test/test_mmc3_eth.py b/examples/mmc3_eth/test/test_mmc3_eth.py index 4569fcbb8..f3cc7876c 100644 --- a/examples/mmc3_eth/test/test_mmc3_eth.py +++ b/examples/mmc3_eth/test/test_mmc3_eth.py @@ -64,7 +64,7 @@ def setUp(self): ''' with open("test_mmc3_eth.yaml") as conf_file: try: - conf = yaml.load(conf_file) + conf = yaml.safe_load(conf_file) except yaml.YAMLError as exception: print(exception) diff --git a/tests/test_SimJtagGpio.py b/tests/test_SimJtagGpio.py index f9bd82c72..e7a203b6e 100644 --- a/tests/test_SimJtagGpio.py +++ b/tests/test_SimJtagGpio.py @@ -175,7 +175,7 @@ def test_gpio(self): ret_ir = BitLogic('0101') # TEST REG INIT - dev1ret = StdRegister(driver=None, conf=yaml.load(gpio_yaml)) + dev1ret = StdRegister(driver=None, conf=yaml.safe_load(gpio_yaml)) dev1ret.init() dev1ret['F1'] = 0x1 dev1ret['F2'] = 0x2f diff --git a/tests/test_SimScpi.py b/tests/test_SimScpi.py index 1b8fa99ed..7dedf01e5 100644 --- a/tests/test_SimScpi.py +++ b/tests/test_SimScpi.py @@ -32,7 +32,7 @@ class TestSimScpi(unittest.TestCase): def setUp(self): - self.cfg = yaml.load(cnfg_yaml) + self.cfg = yaml.safe_load(cnfg_yaml) self.device = Dut(self.cfg) self.device.init() diff --git a/tests/test_StdRegister.py b/tests/test_StdRegister.py index 0e5229cb7..d443a0deb 100644 --- a/tests/test_StdRegister.py +++ b/tests/test_StdRegister.py @@ -66,7 +66,7 @@ class TestClass(unittest.TestCase): @classmethod def setUpClass(cls): - cls.cnfg = yaml.load(cnfg_yaml) + cls.cnfg = yaml.safe_load(cnfg_yaml) cls.dut = Dut(cls.cnfg) cls.dut['spi_module']._require_version = "==2" cls.dut.init() From 5599ce2068ef3c4faec76a87154a84c5400a6dd9 Mon Sep 17 00:00:00 2001 From: Christian Bespin Date: Mon, 12 Aug 2019 11:11:20 +0200 Subject: [PATCH 10/41] ENH: Return status, more descriptive names, add example for xray tube --- basil/HL/debyeflex3003.py | 33 ++++++++++---------- examples/lab_devices/xray_tube.py | 24 ++++++++++++++ examples/lab_devices/xray_tube_pyserial.yaml | 13 ++++++++ 3 files changed, 54 insertions(+), 16 deletions(-) create mode 100644 examples/lab_devices/xray_tube.py create mode 100644 examples/lab_devices/xray_tube_pyserial.yaml diff --git a/basil/HL/debyeflex3003.py b/basil/HL/debyeflex3003.py index 895ef1c38..70b5b5241 100644 --- a/basil/HL/debyeflex3003.py +++ b/basil/HL/debyeflex3003.py @@ -104,27 +104,27 @@ def close_shutter(self, shutter=1): self.write("CS:{:1d}".format(shutter)) logging.info("Closed shutter number {:1d}".format(shutter)) - def start_timer(self, timer=1): - """Start the timer with the given number (corresponds to shutter number) + def activate_timer(self, shutter=1): + """Activate the timer for a given shutter number """ - if not isinstance(timer, int): - raise TypeError("Invalid type for timer number") - elif timer > 4 or timer < 1: - raise ValueError("Invalid value for timer number") + if not isinstance(shutter, int): + raise TypeError("Invalid type for shutter number") + elif shutter > 4 or shutter < 1: + raise ValueError("Invalid value for shutter number") else: - self.write("TS:{:1d}".format(timer)) - logging.info("Started timer number {:1d}".format(timer)) + self.write("TS:{:1d}".format(shutter)) + logging.info("Started timer number {:1d}".format(shutter)) - def stop_timer(self, timer=1): - """Stop the timer with the given number (corresponds to shutter number) + def deactivate_timer(self, shutter=1): + """Deactivate the timer for a given shutter number """ - if not isinstance(timer, int): - raise TypeError("Invalid type for timer number") - elif timer > 4 or timer < 1: - raise ValueError("Invalid value for timer number") + if not isinstance(shutter, int): + raise TypeError("Invalid type for shutter number") + elif shutter > 4 or shutter < 1: + raise ValueError("Invalid value for shutter number") else: - self.write("TE:{:1d}".format(timer)) - logging.info("Stopped timer number {:1d}".format(timer)) + self.write("TE:{:1d}".format(shutter)) + logging.info("Stopped timer number {:1d}".format(shutter)) def set_timer(self, timer=1, dur=3600): """Set the timer with the given number (corresponds to shutter number) to the given duration (in s) @@ -184,3 +184,4 @@ def get_status(self, status_word): response = self.read() status = bin(int(response[7:10]))[2:].zfill(8) # Convert response to 8 char long string of binary values logging.info("Status word {:02d}: {:8s}".format(status_word, status)) + return status diff --git a/examples/lab_devices/xray_tube.py b/examples/lab_devices/xray_tube.py new file mode 100644 index 000000000..28d8d5042 --- /dev/null +++ b/examples/lab_devices/xray_tube.py @@ -0,0 +1,24 @@ +import time +from basil.dut import Dut + +# Initialize x-ray tube +devices = Dut('xray_tube_pyserial.yaml') +devices.init() + +# Set high voltage and current +devices["xray_tube"].set_voltage(10) # 40 kV +devices["xray_tube"].set_current(50) # 50 mA +print(devices["xray_tube"].get_actual_voltage()) # in kV +print(devices["xray_tube"].get_actual_current()) # in mA + +devices["xray_tube"].set_high_voltage_on() # Turn on HV +devices["xray_tube"].set_timer(dur=3600) # 3600 s +devices["xray_tube"].activate_timer() # Activate the timer (clock symbol on display) +devices["xray_tube"].open_shutter() # Starts actual irradiation (and timer, if set) + +time.sleep(10) +# Print remaining irradiation time in seconds +print(devices["xray_tube"].get_actual_time()) + +# Print status of HV (bit 6 of status word 0) +print(devices["xray_tube"].get_status(0)[1]) diff --git a/examples/lab_devices/xray_tube_pyserial.yaml b/examples/lab_devices/xray_tube_pyserial.yaml new file mode 100644 index 000000000..10823bd18 --- /dev/null +++ b/examples/lab_devices/xray_tube_pyserial.yaml @@ -0,0 +1,13 @@ +transfer_layer: + - name : Serial + type : Serial + init : + port : /dev/ttyUSB0 + read_termination : "\r" + baudrate : 9600 + timeout : 2.0 + +hw_drivers: + - name : xray_tube + type : debyeflex3003 + interface : Serial From d865bf6dbf3e21eebd5d853cd583c870a7554b17 Mon Sep 17 00:00:00 2001 From: hansk Date: Wed, 14 Aug 2019 18:48:13 +0200 Subject: [PATCH 11/41] Update keithley_2410.yaml Added commands --- basil/HL/keithley_2410.yaml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/basil/HL/keithley_2410.yaml b/basil/HL/keithley_2410.yaml index 46f1dc569..e5cbb04a2 100644 --- a/basil/HL/keithley_2410.yaml +++ b/basil/HL/keithley_2410.yaml @@ -15,8 +15,14 @@ get_voltage_limit : SENS:VOLT:PROT? source_volt : SOUR:FUNC VOLT source_current : SOUR:FUNC CURR get_source_mode : SOUR:FUNC? -set_autorange : SOUR:CURR:RANG:AUTO ON -get_autorange : SOUR:CURR:RANG:AUTO? +set_current_autorange : SOUR:CURR:RANG:AUTO ON +get_current_autorange : SOUR:CURR:RANG:AUTO? +set_voltage_range: SOUR:VOLT:RANGE four_wire_on: SYST:RSEN ON four_wire_off: SYST:RSEN OFF -get_remote_sense: SYST:RSEN ? +get_remote_sense: SYST:RSEN? +set_current_sense_range: SENS:CURR:RANGE +get_current_sense_range: SENS:CURR:RANGE? +get_reading: READ? +set_current_nlpc: SENS:CURR:NPLC + From 8f6e29b203cf10454c893526111ae94c05001b88 Mon Sep 17 00:00:00 2001 From: hansk Date: Wed, 14 Aug 2019 18:49:13 +0200 Subject: [PATCH 12/41] Update MIO_PLL.py float type fix --- basil/HL/MIO_PLL.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/basil/HL/MIO_PLL.py b/basil/HL/MIO_PLL.py index 641306be6..7e7924324 100644 --- a/basil/HL/MIO_PLL.py +++ b/basil/HL/MIO_PLL.py @@ -129,8 +129,8 @@ def _calculateParameters(self, fout): break for self.div in range(2, 128): q_d_f = self.q_total * self.div * fout - if isinstance(q_d_f, six.integer_types) and q_d_f > (15 * self.fref): # = f0 * p - if int(q_d_f) % int(self.fref) == 0: # p, q, and d found + if float(q_d_f).is_integer() and q_d_f > (15 * self.fref): # = f0 * p + if (int(q_d_f) % int(self.fref)) == 0: # p, q, and d found self.p_total = q_d_f / self.fref while self.p_total <= 16: # counter constraint self.p_total = self.p_total * 2 @@ -176,7 +176,7 @@ def _calculateParameters(self, fout): fvco = self.fref * self.p_total / self.q_total logger.info('PLL frequency set to ' + str(ftest) + ' MHz' + ' (VCO @ ' + str(fvco) + ' MHz)') return True - logger.error('MIO_PLL: Could not find PLL parameters') + logger.error('MIO_PLL: Could not find PLL parameters for '+ str(fout) + ' MHz)') return False def _updateRegisters(self): From 644ba8e614cc96d73eba831480db80d56d6f3d1a Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Thu, 15 Aug 2019 11:46:57 +0200 Subject: [PATCH 13/41] 2to3: reduce dependency on six --- basil/dut.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/basil/dut.py b/basil/dut.py index ceada9316..5259f9848 100644 --- a/basil/dut.py +++ b/basil/dut.py @@ -11,7 +11,7 @@ import sys import warnings from collections import OrderedDict -from six import string_types, iteritems, itervalues +from six import string_types # FIXME: Bad practice # Logger settings should not be defined in a module, but once by the @@ -118,13 +118,13 @@ def catch_exception_on_init(mod): except NotImplementedError: pass - for item in itervalues(self._transfer_layer): + for item in self._transfer_layer.values(): update_init(item) catch_exception_on_init(item) - for item in itervalues(self._hardware_layer): + for item in self._hardware_layer.values(): update_init(item) catch_exception_on_init(item) - for item in itervalues(self._registers): + for item in self._registers.values(): update_init(item) catch_exception_on_init(item) @@ -137,17 +137,17 @@ def catch_exception_on_close(mod): # restore status after close() failed mod._is_initialized = True - for item in itervalues(self._registers): + for item in self._registers.values(): catch_exception_on_close(item) - for item in itervalues(self._hardware_layer): + for item in self._hardware_layer.values(): catch_exception_on_close(item) - for item in itervalues(self._transfer_layer): + for item in self._transfer_layer.values(): catch_exception_on_close(item) def set_configuration(self, conf): conf = self._open_conf(conf) if conf: - for item, item_conf in iteritems(conf): + for item, item_conf in conf.items(): if item != 'conf_path': try: self[item].set_configuration(item_conf) @@ -156,17 +156,17 @@ def set_configuration(self, conf): def get_configuration(self): conf = {} - for key, value in iteritems(self._registers): + for key, value in self._registers.items(): try: conf[key] = value.get_configuration() except NotImplementedError: conf[key] = {} - for key, value in iteritems(self._hardware_layer): + for key, value in self._hardware_layer.items(): try: conf[key] = value.get_configuration() except NotImplementedError: conf[key] = {} - for key, value in iteritems(self._transfer_layer): + for key, value in self._transfer_layer.items(): try: conf[key] = value.get_configuration() except NotImplementedError: @@ -304,11 +304,11 @@ def get_modules(self, type_name): return modules def __iter__(self): - for item in itervalues(self._registers): + for item in self._registers.values(): yield item - for item in itervalues(self._hardware_layer): + for item in self._hardware_layer.values(): yield item - for item in itervalues(self._transfer_layer): + for item in self._transfer_layer.values(): yield item # TODO: From 3396223abede51cd270f351a8c275d7631522979 Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Thu, 15 Aug 2019 12:07:53 +0200 Subject: [PATCH 14/41] 2to3: remove abc metaclass, raise NotImplementedError --- basil/HL/FEI4AdapterCard.py | 14 ++++---------- basil/HL/HardwareLayer.py | 2 +- basil/HL/agilent33250a.py | 4 ++-- basil/RL/StdRegister.py | 3 +-- basil/TL/TransferLayer.py | 9 ++------- 5 files changed, 10 insertions(+), 22 deletions(-) diff --git a/basil/HL/FEI4AdapterCard.py b/basil/HL/FEI4AdapterCard.py index efc3096ce..f62581bd2 100644 --- a/basil/HL/FEI4AdapterCard.py +++ b/basil/HL/FEI4AdapterCard.py @@ -11,7 +11,6 @@ from collections import OrderedDict from math import log import string -import abc from basil.HL.HardwareLayer import HardwareLayer @@ -115,15 +114,13 @@ def _read_eeprom(self, address, size): return data def _write_eeprom(self, address, data): - raise NotImplementedError() + raise NotImplementedError("_write_eeprom() not implemented") class Fei4Dcs(object): '''FEI4AdapterCard interface ''' - __metaclass__ = abc.ABCMeta - # EEPROM HEADER_ADDR = 0 HEADER_FORMAT = '>H' # Version of EEPROM data @@ -210,17 +207,14 @@ def get_id(self): ret = self._read_eeprom(self.ID_ADDR, size=calcsize(self.ID_FORMAT)) return unpack_from(self.ID_FORMAT, ret)[0] - @abc.abstractmethod def _get_adc_value(self, channel): - pass + raise NotImplementedError("_get_adc_value() not implemented") - @abc.abstractmethod def _set_dac_value(self, channel, value): - pass + raise NotImplementedError("_set_dac_value() not implemented") - @abc.abstractmethod def _read_eeprom(self, address, size): - pass + raise NotImplementedError("_read_eeprom() not implemented") class FEI4AdapterCard(AdcMax1239, DacMax520, Eeprom24Lc128, Fei4Dcs): diff --git a/basil/HL/HardwareLayer.py b/basil/HL/HardwareLayer.py index 84e28cf5a..1cbc048a6 100644 --- a/basil/HL/HardwareLayer.py +++ b/basil/HL/HardwareLayer.py @@ -21,7 +21,7 @@ def __init__(self, intf, conf): @property def is_ready(self): - raise NotImplementedError + raise NotImplementedError("is_ready() not implemented") def wait_for_ready(self, timeout=None, times=None, delay=None, delay_between=None, abort=None): '''Determine the ready state of the device and wait until device is ready. diff --git a/basil/HL/agilent33250a.py b/basil/HL/agilent33250a.py index 823b98412..72ea4ef66 100644 --- a/basil/HL/agilent33250a.py +++ b/basil/HL/agilent33250a.py @@ -18,10 +18,10 @@ def __init__(self, intf, conf): super(agilent33250a, self).__init__(intf, conf) def set_repeat(self, repeat): - raise NotImplementedError("Not implemented") + raise NotImplementedError("set_repeat() not implemented") def get_repeat(self, repeat): - raise NotImplementedError("Not implemented") + raise NotImplementedError("get_repeat() not implemented") def set_voltage(self, low, high=0.75, unit='mV'): if unit == 'raw': diff --git a/basil/RL/StdRegister.py b/basil/RL/StdRegister.py index 6e380b069..2205002cc 100644 --- a/basil/RL/StdRegister.py +++ b/basil/RL/StdRegister.py @@ -120,8 +120,7 @@ def write(self, size=None): self._drv.start() def read(self): - raise NotImplementedError("Not implemented") -# return self._drv.get_data() + raise NotImplementedError("read() not implemented") def _construct_reg(self): diff --git a/basil/TL/TransferLayer.py b/basil/TL/TransferLayer.py index 3d18d69c8..5baaf9946 100644 --- a/basil/TL/TransferLayer.py +++ b/basil/TL/TransferLayer.py @@ -5,8 +5,6 @@ # ------------------------------------------------------------ # -import abc - from basil.dut import Base @@ -14,7 +12,6 @@ class TransferLayer(Base): '''Transfer Layer implements minimum API needed access to hardware. On error ``raise IOError``. ''' - __metaclass__ = abc.ABCMeta def __init__(self, conf): super(TransferLayer, self).__init__(conf) @@ -24,15 +21,13 @@ def init(self): ''' super(TransferLayer, self).init() - @abc.abstractmethod def read(self): '''Read access. :rtype: None ''' - pass + raise NotImplementedError("read() not implemented") - @abc.abstractmethod def write(self, data): '''Write access. @@ -41,4 +36,4 @@ def write(self, data): :rtype: None ''' - pass + raise NotImplementedError("write() not implemented") From 227d83f7aaf08b535c36d44576afe3070bc377d7 Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Thu, 15 Aug 2019 12:57:38 +0200 Subject: [PATCH 15/41] MAINT: change to UNIX LF --- basil/HL/RegisterHardwareLayer.py | 570 +++++++++++++++--------------- basil/TL/SiUart.py | 220 ++++++------ tests/test_SimScpi.py | 117 +++--- tests/test_SimSpi.py | 306 ++++++++-------- 4 files changed, 607 insertions(+), 606 deletions(-) diff --git a/basil/HL/RegisterHardwareLayer.py b/basil/HL/RegisterHardwareLayer.py index 40c0c3521..1f95d97c7 100644 --- a/basil/HL/RegisterHardwareLayer.py +++ b/basil/HL/RegisterHardwareLayer.py @@ -1,285 +1,285 @@ -# -# ------------------------------------------------------------ -# Copyright (c) All rights reserved -# SiLab, Institute of Physics, University of Bonn -# ------------------------------------------------------------ -# - -import logging -from copy import deepcopy -import collections -import array -from collections import namedtuple -from six import integer_types - -from basil.utils.utils import tobytes -from basil.utils.BitLogic import BitLogic -from basil.HL.HardwareLayer import HardwareLayer - -logger = logging.getLogger(__name__) - - -# description attributes -read_only = ['read_only', 'read-only', 'readonly', 'ro'] -write_only = ['write_only', 'write-only', 'writeonly', 'wo'] -is_byte_array = ['byte_array', 'byte-array', 'bytearray'] - - -class RegisterHardwareLayer(HardwareLayer): - '''Register Hardware Layer. - - Implementation of advanced register operations. - - Example: - _registers = {'RESET': {'descr': {'addr': 0, 'size': 8, 'properties': ['writeonly']}}, <-- 8-bit reset register, writeonly - 'LOST_DATA_COUNTER': {'descr': {'addr': 0, 'size': 8, 'properties': ['ro']}}, <-- 8-bit data register, 'ro' equivalent to 'readonly' - 'ENABLE': {'descr': {'addr': 1, 'size': 1, 'offset': 0}}, <-- 1-bit register - 'ENABLE_EXTERN': {'descr': {'addr': 1, 'size': 1, 'offset': 1}}, <-- 1-bit register - 'EN_ARMING': {'descr': {'addr': 1, 'size': 1, 'offset': 2}}, <-- 1-bit register - 'EN_WRITE_TIMESTAMP': {'descr': {'addr': 1, 'size': 1, 'offset': 3}}, <-- 1-bit register - 'EVENT_COUNTER': {'descr': {'addr': 2, 'size': 32, 'properties': ['ro']}} <-- 32-bit register, 'ro' equivalent to 'readonly' - _require_version = '==3' <-- or use '<=', '>=', ... accordingly - ''' - _registers = {} - _require_version = None - - def __init__(self, intf, conf): - super(RegisterHardwareLayer, self).__init__(intf, conf) - # require interface and base address - self._intf = intf - self._base_addr = conf['base_addr'] - rv = namedtuple('_register_values', field_names=iter(self._registers.keys())) - self._register_values = rv(*([None] * len(self._registers))) - for reg in self._registers.keys(): - if not reg.isupper(): - raise ValueError("Register %s must be uppercase." % reg) - self.add_property(reg) - - def init(self): - super(RegisterHardwareLayer, self).init() - # reset during initialization to get default state and to remove any prior settings - if "RESET" in self._registers: - self.RESET # assign no value, to read back value and write same value or default value - if 'VERSION' in self._registers: - version = str(self.VERSION) - else: - version = None - logger.info("Initializing %s (firmware version: %s), module %s, base_addr %s" % (self.name, version if 'VERSION' in self._registers else 'n/a', self.__class__.__module__, hex(self._base_addr))) - if self._require_version and not eval(version + self._require_version): - raise Exception("FPGA module %s does not satisfy version requirements (read: %s, require: %s)" % (self.__class__.__module__, version, self._require_version.strip())) - for reg, value in self._registers.items(): - if reg in self._init: - self[reg] = self._init[reg] - elif 'default' in value and not ('properties' in value['descr'] and [i for i in read_only if i in value['descr']['properties']]): - self[reg] = value['default'] - else: # do nothing here, keep existing value - pass - unknown_regs = set(self._init.keys()).difference(set(self._registers.keys())) - if unknown_regs: - raise KeyError("Attempt to write to unknown register(s) in %s, module %s during initialization: %s" % (self.name, self.__class__.__module__, ", ".join(unknown_regs))) - - def set_value(self, value, addr, size, offset, **kwargs): - '''Writing a value of any arbitrary size (max. unsigned int 64) and offset to a register - - Parameters - ---------- - value : int, str - The register value (int, long, bit string) to be written. - addr : int - The register address. - size : int - Bit size/length of the value to be written to the register. - offset : int - Offset of the value to be written to the register (in number of bits). - - Returns - ------- - nothing - ''' - div_offset, mod_offset = divmod(offset, 8) - div_size, mod_size = divmod(size + mod_offset, 8) - if mod_size: - div_size += 1 - if mod_offset == 0 and mod_size == 0: - reg = BitLogic.from_value(0, size=div_size * 8) - else: - ret = self._intf.read(self._base_addr + addr + div_offset, size=div_size) - reg = BitLogic() - reg.frombytes(tobytes(ret)) - reg[size + mod_offset - 1:mod_offset] = value - self._intf.write(self._base_addr + addr + div_offset, data=array.array('B', reg.tobytes())) - - def get_value(self, addr, size, offset, **kwargs): - '''Reading a value of any arbitrary size (max. unsigned int 64) and offset from a register - - Parameters - ---------- - addr : int - The register address. - size : int - Bit size/length of the value. - offset : int - Offset of the value to be written to the register (in number of bits). - - Returns - ------- - reg : int - Register value. - ''' - div_offset, mod_offset = divmod(offset, 8) - div_size, mod_size = divmod(size + mod_offset, 8) - if mod_size: - div_size += 1 - ret = self._intf.read(self._base_addr + addr + div_offset, size=div_size) - reg = BitLogic() - reg.frombytes(tobytes(ret)) - return reg[size + mod_offset - 1:mod_offset].tovalue() - - def set_bytes(self, data, addr, **kwargs): - '''Writing bytes of any arbitrary size - - Parameters - ---------- - data : iterable - The data (byte array) to be written. - addr : int - The register address. - - Returns - ------- - nothing - ''' - self._intf.write(self._conf['base_addr'] + addr, data) - - def get_bytes(self, addr, size, **kwargs): - '''Reading bytes of any arbitrary size - - Parameters - ----------. - addr : int - The register address. - size : int - Byte length of the value. - - Returns - ------- - data : iterable - Byte array. - ''' - return self._intf.read(self._conf['base_addr'] + addr, size) - - def set_configuration(self, conf): - if conf: - for reg, value in conf.items(): - self[reg] = value - - def get_configuration(self): - conf = {} - for reg in self._registers.keys(): - descr = self._registers[reg]['descr'] - if not ('properties' in descr and [i for i in write_only if i in descr['properties']]) and not ('properties' in descr and [i for i in read_only if i in descr['properties']]): - conf[reg] = self[reg] - return conf - - def add_property(self, attribute): - # create local setter and getter with a particular attribute name -# getter = lambda self: self._get(attribute) -# setter = lambda self, value: self._set(attribute, value) - # Workaround: obviously dynamic properties catch exceptions - # Print error message and return None - - def getter(self): - try: - return self._get(attribute) - except Exception as e: - logger.error(e) - return None - - def setter(self, value): - try: - return self._set(attribute, value) - except Exception as e: - logger.error(e) - return None - # construct property attribute and add it to the class - setattr(self.__class__, attribute, property(fget=getter, fset=setter, doc=attribute + ' register')) - - def set_default(self): - for reg, value in self._registers.items(): - if 'default' in value and not ('properties' in value['descr'] and [i for i in read_only if i in self._registers[reg]['descr']['properties']]): - self._set(reg, value['default']) - - def _get(self, reg): - descr = deepcopy(self._registers[reg]['descr']) - if 'properties' in descr and [i for i in write_only if i in descr['properties']]: - # allows a lazy-style of programming - if 'default' in self._registers[reg]: - return self._set(reg, self._registers[reg]['default']) - else: - descr.setdefault('offset', 0) - return self._set(reg, self.get_value(**descr)) - # raise error when doing read on write-only register -# raise IOError('Register is write-only') - # return None to prevent misuse -# return None - else: - if 'properties' in descr and [i for i in is_byte_array if i in descr['properties']]: - ret_val = self.get_bytes(**descr) - ret_val = array.array('B', ret_val).tolist() - else: - descr.setdefault('offset', 0) - curr_val = self._register_values._asdict()[reg] - if not self.is_initialized: # this test allows attributes to be set in the __init__ method - ret_val = curr_val - else: - ret_val = self.get_value(**descr) - if curr_val is not None and 'properties' in descr and not [i for i in read_only if i in descr['properties']] and curr_val != ret_val: - raise ValueError('Read value was not expected: read: %s, expected: %s' % (str(ret_val), str(curr_val))) - return ret_val - - def _set(self, reg, value): - descr = deepcopy(self._registers[reg]['descr']) - if 'properties' in descr and [i for i in read_only if i in descr['properties']]: - raise IOError('Register is read-only') - if 'properties' in descr and [i for i in is_byte_array if i in descr['properties']]: - if not isinstance(value, collections.Iterable): - raise ValueError('For array byte_register iterable object is needed') - value = array.array('B', value).tolist() - self.set_bytes(value, **descr) - self._register_values = self._register_values._replace(**{reg: value}) - else: - descr.setdefault('offset', 0) - value = value if isinstance(value, integer_types) else int(value, base=2) - try: - self.set_value(value, **descr) - except ValueError: - raise - else: - self._register_values = self._register_values._replace(**{reg: value}) - - def __getitem__(self, name): - return self._get(name) - - def __setitem__(self, name, value): - return self._set(name, value) - - def __getattr__(self, name): - '''called only on last resort if there are no attributes in the instance that match the name - ''' - if name.isupper(): - _ = self._register_values._asdict()[name] - - def method(*args, **kwargs): - nsplit = name.split('_', 1) - if len(nsplit) == 2 and nsplit[0] == 'set' and nsplit[1].isupper() and len(args) == 1 and not kwargs: - self[nsplit[1]] = args[0] # returns None - elif len(nsplit) == 2 and nsplit[0] == 'get' and nsplit[1].isupper() and not args and not kwargs: - return self[nsplit[1]] - else: - raise AttributeError("%r object has no attribute %r" % (self.__class__, name)) - return method - - def __setattr__(self, name, value): - if name.isupper(): - _ = self._register_values._asdict()[name] - super(RegisterHardwareLayer, self).__setattr__(name, value) +# +# ------------------------------------------------------------ +# Copyright (c) All rights reserved +# SiLab, Institute of Physics, University of Bonn +# ------------------------------------------------------------ +# + +import logging +from copy import deepcopy +import collections +import array +from collections import namedtuple +from six import integer_types + +from basil.utils.utils import tobytes +from basil.utils.BitLogic import BitLogic +from basil.HL.HardwareLayer import HardwareLayer + +logger = logging.getLogger(__name__) + + +# description attributes +read_only = ['read_only', 'read-only', 'readonly', 'ro'] +write_only = ['write_only', 'write-only', 'writeonly', 'wo'] +is_byte_array = ['byte_array', 'byte-array', 'bytearray'] + + +class RegisterHardwareLayer(HardwareLayer): + '''Register Hardware Layer. + + Implementation of advanced register operations. + + Example: + _registers = {'RESET': {'descr': {'addr': 0, 'size': 8, 'properties': ['writeonly']}}, <-- 8-bit reset register, writeonly + 'LOST_DATA_COUNTER': {'descr': {'addr': 0, 'size': 8, 'properties': ['ro']}}, <-- 8-bit data register, 'ro' equivalent to 'readonly' + 'ENABLE': {'descr': {'addr': 1, 'size': 1, 'offset': 0}}, <-- 1-bit register + 'ENABLE_EXTERN': {'descr': {'addr': 1, 'size': 1, 'offset': 1}}, <-- 1-bit register + 'EN_ARMING': {'descr': {'addr': 1, 'size': 1, 'offset': 2}}, <-- 1-bit register + 'EN_WRITE_TIMESTAMP': {'descr': {'addr': 1, 'size': 1, 'offset': 3}}, <-- 1-bit register + 'EVENT_COUNTER': {'descr': {'addr': 2, 'size': 32, 'properties': ['ro']}} <-- 32-bit register, 'ro' equivalent to 'readonly' + _require_version = '==3' <-- or use '<=', '>=', ... accordingly + ''' + _registers = {} + _require_version = None + + def __init__(self, intf, conf): + super(RegisterHardwareLayer, self).__init__(intf, conf) + # require interface and base address + self._intf = intf + self._base_addr = conf['base_addr'] + rv = namedtuple('_register_values', field_names=iter(self._registers.keys())) + self._register_values = rv(*([None] * len(self._registers))) + for reg in self._registers.keys(): + if not reg.isupper(): + raise ValueError("Register %s must be uppercase." % reg) + self.add_property(reg) + + def init(self): + super(RegisterHardwareLayer, self).init() + # reset during initialization to get default state and to remove any prior settings + if "RESET" in self._registers: + self.RESET # assign no value, to read back value and write same value or default value + if 'VERSION' in self._registers: + version = str(self.VERSION) + else: + version = None + logger.info("Initializing %s (firmware version: %s), module %s, base_addr %s" % (self.name, version if 'VERSION' in self._registers else 'n/a', self.__class__.__module__, hex(self._base_addr))) + if self._require_version and not eval(version + self._require_version): + raise Exception("FPGA module %s does not satisfy version requirements (read: %s, require: %s)" % (self.__class__.__module__, version, self._require_version.strip())) + for reg, value in self._registers.items(): + if reg in self._init: + self[reg] = self._init[reg] + elif 'default' in value and not ('properties' in value['descr'] and [i for i in read_only if i in value['descr']['properties']]): + self[reg] = value['default'] + else: # do nothing here, keep existing value + pass + unknown_regs = set(self._init.keys()).difference(set(self._registers.keys())) + if unknown_regs: + raise KeyError("Attempt to write to unknown register(s) in %s, module %s during initialization: %s" % (self.name, self.__class__.__module__, ", ".join(unknown_regs))) + + def set_value(self, value, addr, size, offset, **kwargs): + '''Writing a value of any arbitrary size (max. unsigned int 64) and offset to a register + + Parameters + ---------- + value : int, str + The register value (int, long, bit string) to be written. + addr : int + The register address. + size : int + Bit size/length of the value to be written to the register. + offset : int + Offset of the value to be written to the register (in number of bits). + + Returns + ------- + nothing + ''' + div_offset, mod_offset = divmod(offset, 8) + div_size, mod_size = divmod(size + mod_offset, 8) + if mod_size: + div_size += 1 + if mod_offset == 0 and mod_size == 0: + reg = BitLogic.from_value(0, size=div_size * 8) + else: + ret = self._intf.read(self._base_addr + addr + div_offset, size=div_size) + reg = BitLogic() + reg.frombytes(tobytes(ret)) + reg[size + mod_offset - 1:mod_offset] = value + self._intf.write(self._base_addr + addr + div_offset, data=array.array('B', reg.tobytes())) + + def get_value(self, addr, size, offset, **kwargs): + '''Reading a value of any arbitrary size (max. unsigned int 64) and offset from a register + + Parameters + ---------- + addr : int + The register address. + size : int + Bit size/length of the value. + offset : int + Offset of the value to be written to the register (in number of bits). + + Returns + ------- + reg : int + Register value. + ''' + div_offset, mod_offset = divmod(offset, 8) + div_size, mod_size = divmod(size + mod_offset, 8) + if mod_size: + div_size += 1 + ret = self._intf.read(self._base_addr + addr + div_offset, size=div_size) + reg = BitLogic() + reg.frombytes(tobytes(ret)) + return reg[size + mod_offset - 1:mod_offset].tovalue() + + def set_bytes(self, data, addr, **kwargs): + '''Writing bytes of any arbitrary size + + Parameters + ---------- + data : iterable + The data (byte array) to be written. + addr : int + The register address. + + Returns + ------- + nothing + ''' + self._intf.write(self._conf['base_addr'] + addr, data) + + def get_bytes(self, addr, size, **kwargs): + '''Reading bytes of any arbitrary size + + Parameters + ----------. + addr : int + The register address. + size : int + Byte length of the value. + + Returns + ------- + data : iterable + Byte array. + ''' + return self._intf.read(self._conf['base_addr'] + addr, size) + + def set_configuration(self, conf): + if conf: + for reg, value in conf.items(): + self[reg] = value + + def get_configuration(self): + conf = {} + for reg in self._registers.keys(): + descr = self._registers[reg]['descr'] + if not ('properties' in descr and [i for i in write_only if i in descr['properties']]) and not ('properties' in descr and [i for i in read_only if i in descr['properties']]): + conf[reg] = self[reg] + return conf + + def add_property(self, attribute): + # create local setter and getter with a particular attribute name +# getter = lambda self: self._get(attribute) +# setter = lambda self, value: self._set(attribute, value) + # Workaround: obviously dynamic properties catch exceptions + # Print error message and return None + + def getter(self): + try: + return self._get(attribute) + except Exception as e: + logger.error(e) + return None + + def setter(self, value): + try: + return self._set(attribute, value) + except Exception as e: + logger.error(e) + return None + # construct property attribute and add it to the class + setattr(self.__class__, attribute, property(fget=getter, fset=setter, doc=attribute + ' register')) + + def set_default(self): + for reg, value in self._registers.items(): + if 'default' in value and not ('properties' in value['descr'] and [i for i in read_only if i in self._registers[reg]['descr']['properties']]): + self._set(reg, value['default']) + + def _get(self, reg): + descr = deepcopy(self._registers[reg]['descr']) + if 'properties' in descr and [i for i in write_only if i in descr['properties']]: + # allows a lazy-style of programming + if 'default' in self._registers[reg]: + return self._set(reg, self._registers[reg]['default']) + else: + descr.setdefault('offset', 0) + return self._set(reg, self.get_value(**descr)) + # raise error when doing read on write-only register +# raise IOError('Register is write-only') + # return None to prevent misuse +# return None + else: + if 'properties' in descr and [i for i in is_byte_array if i in descr['properties']]: + ret_val = self.get_bytes(**descr) + ret_val = array.array('B', ret_val).tolist() + else: + descr.setdefault('offset', 0) + curr_val = self._register_values._asdict()[reg] + if not self.is_initialized: # this test allows attributes to be set in the __init__ method + ret_val = curr_val + else: + ret_val = self.get_value(**descr) + if curr_val is not None and 'properties' in descr and not [i for i in read_only if i in descr['properties']] and curr_val != ret_val: + raise ValueError('Read value was not expected: read: %s, expected: %s' % (str(ret_val), str(curr_val))) + return ret_val + + def _set(self, reg, value): + descr = deepcopy(self._registers[reg]['descr']) + if 'properties' in descr and [i for i in read_only if i in descr['properties']]: + raise IOError('Register is read-only') + if 'properties' in descr and [i for i in is_byte_array if i in descr['properties']]: + if not isinstance(value, collections.Iterable): + raise ValueError('For array byte_register iterable object is needed') + value = array.array('B', value).tolist() + self.set_bytes(value, **descr) + self._register_values = self._register_values._replace(**{reg: value}) + else: + descr.setdefault('offset', 0) + value = value if isinstance(value, integer_types) else int(value, base=2) + try: + self.set_value(value, **descr) + except ValueError: + raise + else: + self._register_values = self._register_values._replace(**{reg: value}) + + def __getitem__(self, name): + return self._get(name) + + def __setitem__(self, name, value): + return self._set(name, value) + + def __getattr__(self, name): + '''called only on last resort if there are no attributes in the instance that match the name + ''' + if name.isupper(): + _ = self._register_values._asdict()[name] + + def method(*args, **kwargs): + nsplit = name.split('_', 1) + if len(nsplit) == 2 and nsplit[0] == 'set' and nsplit[1].isupper() and len(args) == 1 and not kwargs: + self[nsplit[1]] = args[0] # returns None + elif len(nsplit) == 2 and nsplit[0] == 'get' and nsplit[1].isupper() and not args and not kwargs: + return self[nsplit[1]] + else: + raise AttributeError("%r object has no attribute %r" % (self.__class__, name)) + return method + + def __setattr__(self, name, value): + if name.isupper(): + _ = self._register_values._asdict()[name] + super(RegisterHardwareLayer, self).__setattr__(name, value) diff --git a/basil/TL/SiUart.py b/basil/TL/SiUart.py index 3582591ae..c691e2ed3 100644 --- a/basil/TL/SiUart.py +++ b/basil/TL/SiUart.py @@ -1,110 +1,110 @@ -# -# ------------------------------------------------------------ -# Copyright (c) All rights reserved -# SiLab, Institute of Physics, University of Bonn -# ------------------------------------------------------------ -# - -import logging -import array -from struct import pack -from time import sleep - -import serial - -from basil.TL.TransferLayer import TransferLayer - -logger = logging.getLogger(__name__) - - -class SiUart(TransferLayer): - _ser = None - - def __init__(self, conf): - super(SiUart, self).__init__(conf) - - def init(self): - super(SiUart, self).init() - self._init.setdefault('board_id', None) - self._init.setdefault('avoid_download', False) - if self._init['board_id'] and int(self._init['board_id']) >= 0: - self._ser = serial.Serial() - if 'port' in self._init.keys(): - self._ser.setPort(self._init['port']) - if 'baudrate' in self._init.keys(): - self._ser.setBaudrate(self._init['baudrate']) - if 'parity' in self._init.keys() and self._init["parity"] == 0: - self._ser.setParity(serial.PARITY_NONE) - if 'stopbits' in self._init.keys(): - self._ser.setStopbits(self._init['stopbits']) - if 'bytesize' in self._init.keys(): - self._ser.setByteSize(self._init['bytesize']) - if 'timeout' in self._init.keys(): - self._ser.setTimeout(self._init['timeout']) - - self._ser.open() - if not self._ser.isOpen(): - raise IOError("Port at %s not open" % self._ser.port) - else: - logger.info('Found board') - - def __del__(self): - self._ser.close() - - def write(self, addr, data): - logger.debug("------------ writing ------------") - logger.debug('Addr: %s \tdata: %s', addr, data) - done = False - - a = array.array('B', 'a') + array.array('B', pack(" 0: - logger.debug("writing ...") - sleep(0.3) - if "OK" in self._ser.readall(): - done = True - logger.debug("Writing finished") - return done - - raise Exception("Write serial port failed.") - - def read(self, addr, size): - logger.debug("------------ reading ------------") - logger.debug('Addr: %s \tSize: %s', addr, size) - - a = array.array('B', 'a') + array.array('B', pack(" 0: - logger.info("reading ...") - sleep(0.3) - if "OK" in self._ser.read(): - a = array.array('B', dataOut) - logger.debug("Reading finished") - return a - raise Exception("Read serial port failed") - - def close(self): - super(SiUart, self).close() - self._ser.close() - logger.debug("_serial _port closed successfully") +# +# ------------------------------------------------------------ +# Copyright (c) All rights reserved +# SiLab, Institute of Physics, University of Bonn +# ------------------------------------------------------------ +# + +import logging +import array +from struct import pack +from time import sleep + +import serial + +from basil.TL.TransferLayer import TransferLayer + +logger = logging.getLogger(__name__) + + +class SiUart(TransferLayer): + _ser = None + + def __init__(self, conf): + super(SiUart, self).__init__(conf) + + def init(self): + super(SiUart, self).init() + self._init.setdefault('board_id', None) + self._init.setdefault('avoid_download', False) + if self._init['board_id'] and int(self._init['board_id']) >= 0: + self._ser = serial.Serial() + if 'port' in self._init.keys(): + self._ser.setPort(self._init['port']) + if 'baudrate' in self._init.keys(): + self._ser.setBaudrate(self._init['baudrate']) + if 'parity' in self._init.keys() and self._init["parity"] == 0: + self._ser.setParity(serial.PARITY_NONE) + if 'stopbits' in self._init.keys(): + self._ser.setStopbits(self._init['stopbits']) + if 'bytesize' in self._init.keys(): + self._ser.setByteSize(self._init['bytesize']) + if 'timeout' in self._init.keys(): + self._ser.setTimeout(self._init['timeout']) + + self._ser.open() + if not self._ser.isOpen(): + raise IOError("Port at %s not open" % self._ser.port) + else: + logger.info('Found board') + + def __del__(self): + self._ser.close() + + def write(self, addr, data): + logger.debug("------------ writing ------------") + logger.debug('Addr: %s \tdata: %s', addr, data) + done = False + + a = array.array('B', 'a') + array.array('B', pack(" 0: + logger.debug("writing ...") + sleep(0.3) + if "OK" in self._ser.readall(): + done = True + logger.debug("Writing finished") + return done + + raise Exception("Write serial port failed.") + + def read(self, addr, size): + logger.debug("------------ reading ------------") + logger.debug('Addr: %s \tSize: %s', addr, size) + + a = array.array('B', 'a') + array.array('B', pack(" 0: + logger.info("reading ...") + sleep(0.3) + if "OK" in self._ser.read(): + a = array.array('B', dataOut) + logger.debug("Reading finished") + return a + raise Exception("Read serial port failed") + + def close(self): + super(SiUart, self).close() + self._ser.close() + logger.debug("_serial _port closed successfully") diff --git a/tests/test_SimScpi.py b/tests/test_SimScpi.py index 7dedf01e5..32dc398c9 100644 --- a/tests/test_SimScpi.py +++ b/tests/test_SimScpi.py @@ -1,58 +1,59 @@ -# -# ------------------------------------------------------------ -# Copyright (c) All rights reserved -# SiLab, Institute of Physics, University of Bonn -# ------------------------------------------------------------ -# - -import unittest -import yaml - -from basil.dut import Dut - -cnfg_yaml = r""" -transfer_layer: - - name : Visa - type : Visa - init : - resource_name : ASRL1::INSTR - read_termination : "\n" - write_termination : "\r\n" - backend : "@sim" - -hw_drivers: - - name : Pulser - type : scpi - interface : Visa - init : - device : scpi sim device -""" - - -class TestSimScpi(unittest.TestCase): - - def setUp(self): - self.cfg = yaml.safe_load(cnfg_yaml) - self.device = Dut(self.cfg) - self.device.init() - - def tearDown(self): - self.device.close() - - def test_read(self): - self.assertEqual(self.device['Pulser'].get_frequency(), u'100.00') - - def test_write(self): - self.device['Pulser'].set_on(1) - self.assertEqual(self.device['Pulser'].get_on(), u'OK') - - def test_invalid_parameter(self): - with self.assertRaises(ValueError): - self.device['Pulser'].set_on(1, 2) - - def test_exception(self): - with self.assertRaises(ValueError): - self.device['Pulser'].unknown_function() - -if __name__ == '__main__': - unittest.main() +# +# ------------------------------------------------------------ +# Copyright (c) All rights reserved +# SiLab, Institute of Physics, University of Bonn +# ------------------------------------------------------------ +# + +import unittest +import yaml + +from basil.dut import Dut + +cnfg_yaml = r""" +transfer_layer: + - name : Visa + type : Visa + init : + resource_name : ASRL1::INSTR + read_termination : "\n" + write_termination : "\r\n" + backend : "@sim" + +hw_drivers: + - name : Pulser + type : scpi + interface : Visa + init : + device : scpi sim device +""" + + +class TestSimScpi(unittest.TestCase): + + def setUp(self): + self.cfg = yaml.safe_load(cnfg_yaml) + self.device = Dut(self.cfg) + self.device.init() + + def tearDown(self): + self.device.close() + + def test_read(self): + self.assertEqual(self.device['Pulser'].get_frequency(), u'100.00') + + def test_write(self): + self.device['Pulser'].set_on(1) + self.assertEqual(self.device['Pulser'].get_on(), u'OK') + + def test_invalid_parameter(self): + with self.assertRaises(ValueError): + self.device['Pulser'].set_on(1, 2) + + def test_exception(self): + with self.assertRaises(ValueError): + self.device['Pulser'].unknown_function() + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_SimSpi.py b/tests/test_SimSpi.py index 66de025d0..9cdac8b21 100644 --- a/tests/test_SimSpi.py +++ b/tests/test_SimSpi.py @@ -1,153 +1,153 @@ -# -# ------------------------------------------------------------ -# Copyright (c) All rights reserved -# SiLab, Institute of Physics, University of Bonn -# ------------------------------------------------------------ -# - -import unittest -import os -import yaml - -import numpy as np - -from basil.dut import Dut -from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean - - -cnfg_yaml = """ -transfer_layer: - - name : INTF - type : SiSim - init: - host : localhost - port : 12345 - -hw_drivers: - - name : GPIO - type : gpio - interface : INTF - base_addr : 0x0000 - size : 8 - - - name : SPI - type : spi - interface : INTF - base_addr : 0x1000 - - - name : SPI_RX - type : fast_spi_rx - interface : INTF - base_addr : 0x2000 - - - name : PULSE_GEN - type : pulse_gen - interface : INTF - base_addr : 0x3000 - - - name : FIFO - type : bram_fifo - interface : INTF - base_addr : 0x8000 - base_data_addr: 0x80000000 - -registers: - - name : CONTROL - type : StdRegister - hw_driver : GPIO - size : 8 - fields: - - name : OUT - size : 8 - offset : 7 -""" - - -class TestSimSpi(unittest.TestCase): - def setUp(self): - cocotb_compile_and_run([os.path.join(os.path.dirname(__file__), 'test_SimSpi.v')]) - - self.chip = Dut(cnfg_yaml) - self.chip.init() - - def test_io(self): - size = self.chip['SPI'].get_SIZE() - self.chip['GPIO'].reset() - self.assertEqual(size, 16 * 8) - - self.chip['SPI'].set_data(range(16)) - ret = self.chip['SPI'].get_data(size=16, addr=0) # to read back what was written - self.assertEqual(ret.tolist(), list(range(16))) - - self.chip['SPI'].set_data(range(16)) - ret = self.chip['SPI'].get_data(addr=0) # to read back what was written - self.assertEqual(ret.tolist(), list(range(16))) - - self.chip['SPI'].start() - while(not self.chip['SPI'].is_ready): - pass - - ret = self.chip['SPI'].get_data() # read back what was received (looped) - self.assertEqual(ret.tolist(), list(range(16))) - - # ext_start - self.chip['SPI'].set_en(1) - self.assertEqual(self.chip['SPI'].get_en(), 1) - - self.chip['PULSE_GEN'].set_DELAY(1) - self.chip['PULSE_GEN'].set_WIDTH(1 + size) - self.chip['PULSE_GEN'].set_REPEAT(1) - self.assertEqual(self.chip['PULSE_GEN'].get_DELAY(), 1) - self.assertEqual(self.chip['PULSE_GEN'].get_WIDTH(), 1 + size) - self.assertEqual(self.chip['PULSE_GEN'].get_REPEAT(), 1) - - self.chip['PULSE_GEN'].start() - while(not self.chip['PULSE_GEN'].is_ready): - pass - - ret = self.chip['SPI'].get_data() # read back what was received (looped) - self.assertEqual(ret.tolist(), list(range(16))) - - # SPI_RX - ret = self.chip['SPI_RX'].get_en() - self.assertEqual(ret, False) - - self.chip['SPI_RX'].set_en(True) - ret = self.chip['SPI_RX'].get_en() - self.assertEqual(ret, True) - - self.chip['SPI'].start() - while(not self.chip['SPI'].is_ready): - pass - - ret = self.chip['FIFO'].get_FIFO_SIZE() - self.assertEqual(ret, 32) - - ret = self.chip['FIFO'].get_data() - - data0 = ret.astype(np.uint8) - data1 = np.right_shift(ret, 8).astype(np.uint8) - data = np.reshape(np.vstack((data1, data0)), -1, order='F') - self.assertEqual(data.tolist(), list(range(16))) - - def test_dut_iter(self): - conf = yaml.safe_load(cnfg_yaml) - - def iter_conf(): - for item in conf['registers']: - yield item - for item in conf['hw_drivers']: - yield item - for item in conf['transfer_layer']: - yield item - - for mod, mcnf in zip(self.chip, iter_conf()): - self.assertEqual(mod.name, mcnf['name']) - self.assertEqual(mod.__class__.__name__, mcnf['type']) - - def tearDown(self): - self.chip.close() # let it close connection and stop simulator - cocotb_compile_clean() - -if __name__ == '__main__': - unittest.main() +# +# ------------------------------------------------------------ +# Copyright (c) All rights reserved +# SiLab, Institute of Physics, University of Bonn +# ------------------------------------------------------------ +# + +import unittest +import os +import yaml + +import numpy as np + +from basil.dut import Dut +from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean + + +cnfg_yaml = """ +transfer_layer: + - name : INTF + type : SiSim + init: + host : localhost + port : 12345 + +hw_drivers: + - name : GPIO + type : gpio + interface : INTF + base_addr : 0x0000 + size : 8 + + - name : SPI + type : spi + interface : INTF + base_addr : 0x1000 + + - name : SPI_RX + type : fast_spi_rx + interface : INTF + base_addr : 0x2000 + + - name : PULSE_GEN + type : pulse_gen + interface : INTF + base_addr : 0x3000 + + - name : FIFO + type : bram_fifo + interface : INTF + base_addr : 0x8000 + base_data_addr: 0x80000000 + +registers: + - name : CONTROL + type : StdRegister + hw_driver : GPIO + size : 8 + fields: + - name : OUT + size : 8 + offset : 7 +""" + + +class TestSimSpi(unittest.TestCase): + def setUp(self): + cocotb_compile_and_run([os.path.join(os.path.dirname(__file__), 'test_SimSpi.v')]) + + self.chip = Dut(cnfg_yaml) + self.chip.init() + + def test_io(self): + size = self.chip['SPI'].get_SIZE() + self.chip['GPIO'].reset() + self.assertEqual(size, 16 * 8) + + self.chip['SPI'].set_data(range(16)) + ret = self.chip['SPI'].get_data(size=16, addr=0) # to read back what was written + self.assertEqual(ret.tolist(), list(range(16))) + + self.chip['SPI'].set_data(range(16)) + ret = self.chip['SPI'].get_data(addr=0) # to read back what was written + self.assertEqual(ret.tolist(), list(range(16))) + + self.chip['SPI'].start() + while(not self.chip['SPI'].is_ready): + pass + + ret = self.chip['SPI'].get_data() # read back what was received (looped) + self.assertEqual(ret.tolist(), list(range(16))) + + # ext_start + self.chip['SPI'].set_en(1) + self.assertEqual(self.chip['SPI'].get_en(), 1) + + self.chip['PULSE_GEN'].set_DELAY(1) + self.chip['PULSE_GEN'].set_WIDTH(1 + size) + self.chip['PULSE_GEN'].set_REPEAT(1) + self.assertEqual(self.chip['PULSE_GEN'].get_DELAY(), 1) + self.assertEqual(self.chip['PULSE_GEN'].get_WIDTH(), 1 + size) + self.assertEqual(self.chip['PULSE_GEN'].get_REPEAT(), 1) + + self.chip['PULSE_GEN'].start() + while(not self.chip['PULSE_GEN'].is_ready): + pass + + ret = self.chip['SPI'].get_data() # read back what was received (looped) + self.assertEqual(ret.tolist(), list(range(16))) + + # SPI_RX + ret = self.chip['SPI_RX'].get_en() + self.assertEqual(ret, False) + + self.chip['SPI_RX'].set_en(True) + ret = self.chip['SPI_RX'].get_en() + self.assertEqual(ret, True) + + self.chip['SPI'].start() + while(not self.chip['SPI'].is_ready): + pass + + ret = self.chip['FIFO'].get_FIFO_SIZE() + self.assertEqual(ret, 32) + + ret = self.chip['FIFO'].get_data() + + data0 = ret.astype(np.uint8) + data1 = np.right_shift(ret, 8).astype(np.uint8) + data = np.reshape(np.vstack((data1, data0)), -1, order='F') + self.assertEqual(data.tolist(), list(range(16))) + + def test_dut_iter(self): + conf = yaml.safe_load(cnfg_yaml) + + def iter_conf(): + for item in conf['registers']: + yield item + for item in conf['hw_drivers']: + yield item + for item in conf['transfer_layer']: + yield item + + for mod, mcnf in zip(self.chip, iter_conf()): + self.assertEqual(mod.name, mcnf['name']) + self.assertEqual(mod.__class__.__name__, mcnf['type']) + + def tearDown(self): + self.chip.close() # let it close connection and stop simulator + cocotb_compile_clean() + +if __name__ == '__main__': + unittest.main() From 9475b13e08ebd8318783a6da6756499d3bfb8072 Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Thu, 15 Aug 2019 13:03:54 +0200 Subject: [PATCH 16/41] MAINT: code cleanup --- basil/HL/julaboF32HD.py | 59 +++++++++++++-------------- examples/lab_devices/julaboF32HD.py | 19 ++++----- examples/lab_devices/julaboF32HD.yaml | 4 +- 3 files changed, 39 insertions(+), 43 deletions(-) diff --git a/basil/HL/julaboF32HD.py b/basil/HL/julaboF32HD.py index 38eedc355..cd644fb19 100644 --- a/basil/HL/julaboF32HD.py +++ b/basil/HL/julaboF32HD.py @@ -5,69 +5,68 @@ # ------------------------------------------------------------ # -from basil.HL.RegisterHardwareLayer import HardwareLayer import logging import time -import string -class julaboF32HD(HardwareLayer): +from basil.HL.RegisterHardwareLayer import HardwareLayer + - """Driver for the Julabo F32-HD tillar. +class julaboF32HD(HardwareLayer): + ''' Driver for the Julabo F32-HD chiller. A simple protocol via RS 232 serial port is used with 4800 baud rate. - """ + ''' def __init__(self, intf, conf): super(julaboF32HD, self).__init__(intf, conf) - self.pre_time=time.time() + self.pre_time = time.time() def init(self): super(julaboF32HD, self).init() def read(self): ret = self._intf.read() - if len(ret)<2 or ret[-2:] != "\r\n": + if len(ret) < 2 or ret[-2:] != "\r\n": print("julabo.read() terminator error") return ret[:-2] def write(self, cmd): - if time.time()-self.pre_time<1.0: + if time.time() - self.pre_time < 1.0: time.sleep(1.0) self._intf.write(str(cmd)) - self.pre_time=time.time() + self.pre_time = time.time() def get_identifier(self): - """Read identifier - """ + ''' Read identifier + ''' self.write("version") ret = self.read() return ret - - def start_thermostat(self,start=True): - """ start tiller - """ - if start==True: + + def start_thermostat(self, start=True): + ''' Start chiller + ''' + if start is True: self.write("out_mode_05 1") else: self.write("out_mode_05 0") def stop_thermostat(self): - """ stop tiller - """ + ''' Stop chiller + ''' self.start_thermostat(False) - + def get_status(self): - """ Get status - """ + ''' Get status + ''' self.write("status") ret = self.read() logging.debug("status:{:s}".format(ret)) try: - tmp=ret.split(" ", 1) - status=int(tmp[0]) - status_str=tmp[1:] - except: - print("julabo.get_status() wrong format ".format(repr(ret))) - status=-99 - status_str=ret - return status,status_str - + tmp = ret.split(" ", 1) + status = int(tmp[0]) + status_str = tmp[1:] + except IndexError: + logging.warning("get_status() wrong format: {}".format(repr(ret))) + status = -99 + status_str = ret + return status, status_str diff --git a/examples/lab_devices/julaboF32HD.py b/examples/lab_devices/julaboF32HD.py index f16c2162b..8e82d282f 100644 --- a/examples/lab_devices/julaboF32HD.py +++ b/examples/lab_devices/julaboF32HD.py @@ -5,20 +5,17 @@ # ------------------------------------------------------------ # -''' Example how to use the tiller. +''' Example how to use the chiller. ''' -import time - from basil.dut import Dut dut = Dut('julaboF32HD.yaml') -dev.init() -print "ID",dev["tiller"].get_identifier() -print "status",dev["tiller"].get_status() - -### start -### set menu->confiuration->setpoint->rs232 -dev["tiller"].start_thermostat() -dev["tiller"].get_status() +dut.init() +print("ID", dut["chiller"].get_identifier()) +print("status", dut["chiller"].get_status()) +# start +# set menu->confiuration->setpoint->rs232 +dut["chiller"].start_thermostat() +dut["chiller"].get_status() diff --git a/examples/lab_devices/julaboF32HD.yaml b/examples/lab_devices/julaboF32HD.yaml index 5b48673bb..bbfcc8fee 100644 --- a/examples/lab_devices/julaboF32HD.yaml +++ b/examples/lab_devices/julaboF32HD.yaml @@ -11,9 +11,9 @@ transfer_layer: xonxoff : True ### software handshake on rtscts : False dsrdtr : False - + hw_drivers: - - name : tiller + - name : chiller type : julaboF32HD interface : Serial From a8a901e8f2dc0c1fcf9a99e11a8a2555a5239126 Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Thu, 15 Aug 2019 13:38:16 +0200 Subject: [PATCH 17/41] BUG: fix string format errors, cleanup --- basil/HL/Arduino.py | 2 +- basil/HL/binder_mk53.py | 22 +++++++++++----------- basil/HL/julaboF32HD.py | 2 +- basil/HL/weiss_sb22.py | 12 ++++++------ 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/basil/HL/Arduino.py b/basil/HL/Arduino.py index ce90566a1..2f3b95290 100644 --- a/basil/HL/Arduino.py +++ b/basil/HL/Arduino.py @@ -29,7 +29,7 @@ def set_output(self, channel, value): channel = 99 # All channels are internally channel 99 if channel < 2 or (channel > 13 and channel != 99): - raise ValueError('Arduino supports only 14 IOs and pins 0 and 1 are blocked by Serial communication. %d is out of range' % channel) + raise ValueError('Arduino supports only 14 IOs and pins 0 and 1 are blocked by Serial communication. %d is out of range.' % channel) self._intf.write('GPIO%d %d\r\n' % (channel, value)) diff --git a/basil/HL/binder_mk53.py b/basil/HL/binder_mk53.py index 6b8385087..13e8ee61e 100644 --- a/basil/HL/binder_mk53.py +++ b/basil/HL/binder_mk53.py @@ -73,9 +73,9 @@ def get_mode(self): def set_temperature(self, temperature): if temperature < self.min_temp: - raise RuntimeWarning('Set temperature %f is lower than minimum allowed temperature %f', temperature, self.min_temp) + raise RuntimeWarning('Set temperature %f is lower than minimum allowed temperature %f' % (temperature, self.min_temp)) if temperature > self.max_temp: - raise RuntimeWarning('Set temperature %f is higher than maximum allowed temperature %f', temperature, self.max_temp) + raise RuntimeWarning('Set temperature %f is higher than maximum allowed temperature %f' % (temperature, self.max_temp)) self.write(ADDR_MANSETPT, self._encode_float(temperature)) self.write(ADDR_BASICSETPT, self._encode_float(temperature)) @@ -86,7 +86,7 @@ def read(self, addr, n_words): # read n words resp = self._intf.read(exp_length) is_err, err_code = self._parse_error_response(resp) if is_err: - RuntimeWarning('Error code %d: %s', err_code[err_code]) + raise RuntimeWarning('Error code %d: %s' % (err_code, ERROR_CODES[err_code])) data = self._parse_read_response(resp) return data @@ -98,22 +98,22 @@ def write(self, addr, value): # write n words with acknowledge is_err, err_code = self._parse_error_response(resp) if is_err: - RuntimeWarning('Error code %d: %s', err_code[err_code]) + raise RuntimeWarning('Error code %d: %s' % (err_code, ERROR_CODES[err_code])) resp_addr, resp_words = self._parse_write_response(resp) if not (resp_addr == addr) and (resp_words == len(value)): raise RuntimeWarning('Write check failed') def _parse_read_response(self, msgbytes): if len(msgbytes) < 3: - raise RuntimeWarning('Read data is too short', len(msgbytes)) + raise RuntimeWarning('Read data is too short: %d' % len(msgbytes)) _, func, n_bytes = struct.unpack('>BBB', msgbytes[:3]) if func not in [FUNCTION_READN, FUNCTION_READN_ALT]: raise RuntimeWarning('Wrong function returned') if n_bytes & 1: raise RuntimeWarning("Odd number of bytes read") if len(msgbytes) < 5 + n_bytes: - raise RuntimeWarning('Read data is too short', len(msgbytes)) - crc, = struct.unpack('BBHH', msgbytes[:6]) if func != FUNCTION_WRITEN: raise RuntimeWarning('Wrong write function returned') @@ -138,13 +138,13 @@ def _parse_write_response(self, msgbytes): def _parse_error_response(self, msgbytes): # string -> (bool, int) if len(msgbytes) < 5: return False, None - crc, = struct.unpack('BBB', msgbytes[:3]) if not func & 0x80: return False, None checkcrc = self._calc_crc16(msgbytes[:3]) if crc != checkcrc: - raise RuntimeWarning(crc, checkcrc, msgbytes) + raise RuntimeWarning('CRC Error: %s - %s (bytes: %s)' % (str(crc), str(checkcrc), str(msgbytes))) return True, ecode def _make_write_request(self, addr, words): diff --git a/basil/HL/julaboF32HD.py b/basil/HL/julaboF32HD.py index cd644fb19..bc394b20d 100644 --- a/basil/HL/julaboF32HD.py +++ b/basil/HL/julaboF32HD.py @@ -26,7 +26,7 @@ def init(self): def read(self): ret = self._intf.read() if len(ret) < 2 or ret[-2:] != "\r\n": - print("julabo.read() terminator error") + logging.warning("read() termination error") return ret[:-2] def write(self, cmd): diff --git a/basil/HL/weiss_sb22.py b/basil/HL/weiss_sb22.py index 11e1e72ae..868b820b2 100644 --- a/basil/HL/weiss_sb22.py +++ b/basil/HL/weiss_sb22.py @@ -90,9 +90,9 @@ def set_digital_ch(self, channel, value=1): # Set channel to 0 or 1, functional def set_temperature(self, temperature): if temperature < self.min_temp: - raise RuntimeWarning('Set temperature %f is lower than minimum allowed temperature %f', temperature, self.min_temp) + raise RuntimeWarning('Set temperature %f is lower than minimum allowed temperature %f' % (temperature, self.min_temp)) if temperature > self.max_temp: - raise RuntimeWarning('Set temperature %f is higher than maximum allowed temperature %f', temperature, self.max_temp) + raise RuntimeWarning('Set temperature %f is higher than maximum allowed temperature %f' % (temperature, self.max_temp)) self._temperature = temperature msg = '%dT%05.1fF%02dR%s' % (self.slave_address, self._temperature, self._humidity, self._digital_ch) self.write(msg) @@ -100,9 +100,9 @@ def set_temperature(self, temperature): def set_humidity(self, humidity): if humidity < self.min_humidity: - raise RuntimeWarning('Set humidity %f is lower than minimum allowed humidity %f', humidity, self.min_humidity) + raise RuntimeWarning('Set humidity %f is lower than minimum allowed humidity %f' % (humidity, self.min_humidity)) if humidity > self.max_humidity: - raise RuntimeWarning('Set humidity %f is higher than maximum allowed humidity %f', humidity, self.max_humidity) + raise RuntimeWarning('Set humidity %f is higher than maximum allowed humidity %f' % (humidity, self.max_humidity)) self._humidity = humidity msg = '%dT%05.1fF%02dR%s' % (self.slave_address, self._temperature, self._humidity, self._digital_ch) self.write(msg) @@ -122,12 +122,12 @@ def check_for_errors(self, answer): if len(answer) > 6: # error codes are not in the ackowledge strings error_code = int(answer[20:22]) if answer[20:22] != '--' else 0 if error_code > 0: - raise RuntimeError('Climate chamber error %d: %s', error_code, self._ERROR_CODES[error_code]) + raise RuntimeError('Climate chamber error %d: %s' % (error_code, self._ERROR_CODES[error_code])) else: # ack answer if answer[2] != '\x06': raise RuntimeError('Data transmission not ackowledged') if int(answer[1]) != self.slave_address: - raise RuntimeError('Climate chamber address %s instead of %d', answer[1], self.slave_address) + raise RuntimeError('Climate chamber address %s instead of %d' % (answer[1], self.slave_address)) def _calc_crc(self, msg): ASCII = "0123456789ABCDEF" From a93472c28c9fc455d90b666fb58e9ad4b8fb5115 Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Thu, 15 Aug 2019 13:43:28 +0200 Subject: [PATCH 18/41] 2to3: remove iterkeys and iteritems --- basil/HL/FEI4AdapterCard.py | 4 ++-- basil/HL/FEI4QuadModuleAdapterCard.py | 4 ++-- basil/HL/GPAC.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/basil/HL/FEI4AdapterCard.py b/basil/HL/FEI4AdapterCard.py index f62581bd2..8926b4c14 100644 --- a/basil/HL/FEI4AdapterCard.py +++ b/basil/HL/FEI4AdapterCard.py @@ -333,7 +333,7 @@ def read_eeprom_calibration(self, temperature=False): # use default values for header = self.get_format() if header == self.HEADER_V1: data = self._read_eeprom(self.CAL_DATA_ADDR, size=calcsize(self.CAL_DATA_V1_FORMAT)) - for idx, channel in enumerate(self._ch_cal.iterkeys()): + for idx, channel in enumerate(self._ch_cal.keys()): ch_data = data[idx * calcsize(self.CAL_DATA_CH_V1_FORMAT):(idx + 1) * calcsize(self.CAL_DATA_CH_V1_FORMAT)] values = unpack_from(self.CAL_DATA_CH_V1_FORMAT, ch_data) self._ch_cal[channel]['name'] = "".join([c for c in values[0] if (c in string.printable)]) # values[0].strip() @@ -383,7 +383,7 @@ def get_temperature(self, channel, sensor='VNTC'): kwargs = self._ch_map[channel][sensor] temp_raw = self._get_adc_value(**kwargs) - v_adc = ((temp_raw - self._ch_cal.items()[0][1]['ADCV']['offset']) / self._ch_cal.items()[0][1]['ADCV']['gain']) # voltage, VDDA1 + v_adc = ((temp_raw - list(self._ch_cal.items())[0][1]['ADCV']['offset']) / list(self._ch_cal.items())[0][1]['ADCV']['gain']) # voltage, VDDA1 k = self._ch_cal[channel][sensor]['R4'] / (self._ch_cal[channel][sensor]['R2'] + self._ch_cal[channel][sensor]['R4']) # reference voltage divider r_ntc = self._ch_cal[channel][sensor]['R1'] * (k - v_adc / self._ch_cal[channel][sensor]['VREF']) / (1 - k + v_adc / self._ch_cal[channel][sensor]['VREF']) # NTC resistance diff --git a/basil/HL/FEI4QuadModuleAdapterCard.py b/basil/HL/FEI4QuadModuleAdapterCard.py index f5a43c6ee..327e9f2f3 100644 --- a/basil/HL/FEI4QuadModuleAdapterCard.py +++ b/basil/HL/FEI4QuadModuleAdapterCard.py @@ -157,7 +157,7 @@ def init(self): logger.info('FEI4QuadModuleAdapterCard: Using default calibration.') # setting up default current limit - for ch_name in self._ch_cal.iterkeys(): + for ch_name in self._ch_cal.keys(): self.set_current_limit(ch_name, 1.0) logger.info('Found adapter card: {}'.format('%s with ID %s' % ('Quad Module Adapter Card', self.get_id()))) @@ -167,7 +167,7 @@ def read_eeprom_calibration(self, temperature=False): # use default values for header = self.get_format() if header == self.HEADER_V2: data = self._read_eeprom(self.CAL_DATA_ADDR, size=calcsize(self.CAL_DATA_V2_FORMAT)) - for idx, channel in enumerate(self._ch_cal.iterkeys()): + for idx, channel in enumerate(self._ch_cal.keys()): ch_data = data[idx * calcsize(self.CAL_DATA_CH_V2_FORMAT):(idx + 1) * calcsize(self.CAL_DATA_CH_V2_FORMAT)] values = unpack_from(self.CAL_DATA_CH_V2_FORMAT, ch_data) self._ch_cal[channel]['name'] = "".join([c for c in values[0] if (c in string.printable)]) # values[0].strip() diff --git a/basil/HL/GPAC.py b/basil/HL/GPAC.py index e7100c120..6c0597902 100644 --- a/basil/HL/GPAC.py +++ b/basil/HL/GPAC.py @@ -729,7 +729,7 @@ def read_eeprom_calibration(self): # use default values for temperature, EEPROM header = self.get_format() if header == self.HEADER_GPAC: data = self._read_eeprom(self.CAL_DATA_ADDR, size=calcsize(self.CAL_DATA_GPAC_FORMAT)) - for idx, channel in enumerate(self._ch_cal.iterkeys()): + for idx, channel in enumerate(self._ch_cal.keys()): ch_data = data[idx * calcsize(self.CAL_DATA_CH_GPAC_FORMAT):(idx + 1) * calcsize(self.CAL_DATA_CH_GPAC_FORMAT)] values = unpack_from(self.CAL_DATA_CH_GPAC_FORMAT, ch_data) self._ch_cal[channel]['name'] = "".join([c for c in values[0] if (c in string.printable)]) # values[0].strip() From 784a36569077f06b893ac0cdcd281f37ef9901c5 Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Thu, 15 Aug 2019 13:45:52 +0200 Subject: [PATCH 19/41] MAINT: code cleanup --- basil/HL/JtagGpio.py | 12 +++++---- basil/RL/StdRegister.py | 1 + docs/conf.py | 16 +++++------ examples/bdaq/test/test_bdaq53_eth.py | 36 +++++++++++++------------ examples/mmc3_eth/test/test_mmc3_eth.py | 36 +++++++++++++------------ tests/test_SimScpi.py | 8 +++--- 6 files changed, 58 insertions(+), 51 deletions(-) diff --git a/basil/HL/JtagGpio.py b/basil/HL/JtagGpio.py index 6f93ecd18..ee5ba3dc1 100644 --- a/basil/HL/JtagGpio.py +++ b/basil/HL/JtagGpio.py @@ -11,10 +11,7 @@ from basil.utils.BitLogic import BitLogic -class JtagGpio(HardwareLayer): - '''GPIO based JTAG interface - ''' - jtag_gpio_yaml = """ +jtag_gpio_yaml = """ name : GPIO type : StdRegister driver : None @@ -37,10 +34,15 @@ class JtagGpio(HardwareLayer): offset : 4 """ + +class JtagGpio(HardwareLayer): + '''GPIO based JTAG interface + ''' + def __init__(self, intf, conf): super(JtagGpio, self).__init__(intf, conf) - cfg = yaml.safe_load(self.jtag_gpio_yaml) + cfg = yaml.safe_load(jtag_gpio_yaml) self.reg = StdRegister(driver=None, conf=cfg) # self.RESETB = 0 diff --git a/basil/RL/StdRegister.py b/basil/RL/StdRegister.py index 2205002cc..e053d13e0 100644 --- a/basil/RL/StdRegister.py +++ b/basil/RL/StdRegister.py @@ -12,6 +12,7 @@ from basil.utils import utils from six import integer_types + class StdRegister(RegisterLayer): def __init__(self, driver, conf): super(StdRegister, self).__init__(driver, conf) diff --git a/docs/conf.py b/docs/conf.py index 7ef06985e..57f5d96ce 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -54,8 +54,8 @@ master_doc = 'index' # General information about the project. -project = u'basil' -copyright = u'2015, SiLab, Institute of Physics, University of Bonn' +project = 'basil' +copyright = '2015, SiLab, Institute of Physics, University of Bonn' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -219,8 +219,8 @@ def setup(app): # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - ('index', 'basil.tex', u'basil Documentation', - u'T', 'manual'), + ('index', 'basil.tex', 'basil Documentation', + 'T', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -249,8 +249,8 @@ def setup(app): # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'basil', u'basil Documentation', - [u'T'], 1) + ('index', 'basil', 'basil Documentation', + ['T'], 1) ] # If true, show URL addresses after external links. @@ -263,8 +263,8 @@ def setup(app): # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'basil', u'basil Documentation', - u'T', 'basil', 'One line description of project.', + ('index', 'basil', 'basil Documentation', + 'T', 'basil', 'One line description of project.', 'Miscellaneous'), ] diff --git a/examples/bdaq/test/test_bdaq53_eth.py b/examples/bdaq/test/test_bdaq53_eth.py index 9082ca7e6..626233e76 100644 --- a/examples/bdaq/test/test_bdaq53_eth.py +++ b/examples/bdaq/test/test_bdaq53_eth.py @@ -6,15 +6,19 @@ # SiLab, Physics Institute, University of Bonn # ------------------------------------------------------------ # -import unittest -import yaml -import os, sys +import os +import sys import time +import yaml +import unittest + from basil.dut import Dut from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean -doprint=True -IntsToReceive=1000 + +doprint = True +IntsToReceive = 1000 + class TestSimBDAQ53Eth(unittest.TestCase): def setUp(self): @@ -22,9 +26,9 @@ def setUp(self): proj_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) cocotb_compile_and_run( - sim_files = [proj_dir + '/test/bdaq53_eth_tb.v'], - top_level = 'tb', - include_dirs = (proj_dir, proj_dir + '/firmware/src') + sim_files=[proj_dir + '/test/bdaq53_eth_tb.v'], + top_level='tb', + include_dirs=(proj_dir, proj_dir + '/firmware/src') ) with open(proj_dir + '/bdaq53_eth.yaml') as conf_file: @@ -48,7 +52,6 @@ def setUp(self): self.chip = Dut(conf) self.chip.init() - def test(self): testduration = 10 total_len = 0 @@ -56,7 +59,7 @@ def test(self): tick_old = 0 start_time = time.time() - self.chip['CONTROL']['EN'] = 0x01 #start data source + self.chip['CONTROL']['EN'] = 0x01 # start data source self.chip['CONTROL'].write() while time.time() - start_time < testduration: @@ -68,23 +71,22 @@ def test(self): print(tick) tick_old = tick - if doprint==True: + if doprint: print(data) for i in data: - if i<(len(data)-1): assert data[i] == data[i+1]-1 #Check, if received integers are increasing numbers - + if i < (len(data) - 1): + assert data[i] == data[i + 1] - 1 # Check, if received integers are increasing numbers if total_len >= IntsToReceive: break - total_len_bits = total_len*32 #32-bit ints to bits - print('Bits received:', total_len_bits, ' data rate:', round((total_len_bits/1e6/testduration),2), ' Mbit/s') + total_len_bits = total_len * 32 # 32-bit ints to bits + print(('Bits received:', total_len_bits, 'Data rate:', round((total_len_bits / 1e6 / testduration), 2), 'Mbit/s')) - self.chip['CONTROL']['EN'] = 0x00 #stop data source + self.chip['CONTROL']['EN'] = 0x00 # stop data source self.chip['CONTROL'].write() - def tearDown(self): self.chip.close() # let it close connection and stop simulator cocotb_compile_clean() diff --git a/examples/mmc3_eth/test/test_mmc3_eth.py b/examples/mmc3_eth/test/test_mmc3_eth.py index f3cc7876c..713dddb2e 100644 --- a/examples/mmc3_eth/test/test_mmc3_eth.py +++ b/examples/mmc3_eth/test/test_mmc3_eth.py @@ -7,13 +7,20 @@ # ------------------------------------------------------------ # from __future__ import print_function -import unittest -import os, sys + +import os +import sys import time +import unittest + from basil.dut import Dut from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean +doprint = True +IntsToReceive = 1000 + + cnfg_yaml = """ transfer_layer: - name : INTF @@ -47,18 +54,15 @@ """ -doprint=True -IntsToReceive=1000 - class TestSimMMC3Eth(unittest.TestCase): def setUp(self): sys.path = [os.path.dirname(os.getcwd())] + sys.path proj_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) cocotb_compile_and_run( - sim_files = [proj_dir + '/test/mmc3_eth_tb.v'], - top_level = 'tb', - include_dirs = (proj_dir, proj_dir + '/src') + sim_files=[proj_dir + '/test/mmc3_eth_tb.v'], + top_level='tb', + include_dirs=(proj_dir, proj_dir + '/src') ) ''' @@ -77,7 +81,6 @@ def setUp(self): self.chip = Dut(cnfg_yaml) self.chip.init() - def test(self): testduration = 10 total_len = 0 @@ -85,7 +88,7 @@ def test(self): tick_old = 0 start_time = time.time() - self.chip['GPIO_LED']['LED'] = 0x01 #start data source + self.chip['GPIO_LED']['LED'] = 0x01 # start data source self.chip['GPIO_LED'].write() while time.time() - start_time < testduration: @@ -97,23 +100,22 @@ def test(self): print (tick) tick_old = tick - if doprint==True: + if doprint: print (data) for i in data: - if i<(len(data)-1): assert data[i] == data[i+1]-1 #Check, if received integers are increasing numbers - + if i < (len(data) - 1): + assert data[i] == data[i + 1] - 1 # Check, if received integers are increasing numbers if total_len >= IntsToReceive: break - total_len_bits = total_len*32 #32-bit ints to bits - print(('Bits received:', total_len_bits, ' data rate:', round((total_len_bits/1e6/testduration),2), ' Mbit/s')) + total_len_bits = total_len * 32 # 32-bit ints to bits + print(('Bits received:', total_len_bits, 'Data rate:', round((total_len_bits / 1e6 / testduration), 2), 'Mbit/s')) - self.chip['GPIO_LED']['LED'] = 0x00 #stop data source + self.chip['GPIO_LED']['LED'] = 0x00 # stop data source self.chip['GPIO_LED'].write() - def tearDown(self): self.chip.close() # let it close connection and stop simulator cocotb_compile_clean() diff --git a/tests/test_SimScpi.py b/tests/test_SimScpi.py index 32dc398c9..147635727 100644 --- a/tests/test_SimScpi.py +++ b/tests/test_SimScpi.py @@ -10,7 +10,7 @@ from basil.dut import Dut -cnfg_yaml = r""" +cnfg_yaml = ''' transfer_layer: - name : Visa type : Visa @@ -26,7 +26,7 @@ interface : Visa init : device : scpi sim device -""" +''' class TestSimScpi(unittest.TestCase): @@ -40,11 +40,11 @@ def tearDown(self): self.device.close() def test_read(self): - self.assertEqual(self.device['Pulser'].get_frequency(), u'100.00') + self.assertEqual(self.device['Pulser'].get_frequency(), '100.00') def test_write(self): self.device['Pulser'].set_on(1) - self.assertEqual(self.device['Pulser'].get_on(), u'OK') + self.assertEqual(self.device['Pulser'].get_on(), 'OK') def test_invalid_parameter(self): with self.assertRaises(ValueError): From 87ca30f8e84af519242122aebdda09e1a5d23bd0 Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Thu, 15 Aug 2019 14:09:00 +0200 Subject: [PATCH 20/41] MAINT: code cleanup --- examples/lx9/host/lx9.py | 131 +++++++++++++++++++-------------------- 1 file changed, 64 insertions(+), 67 deletions(-) diff --git a/examples/lx9/host/lx9.py b/examples/lx9/host/lx9.py index dfa2a9cab..66f120fde 100644 --- a/examples/lx9/host/lx9.py +++ b/examples/lx9/host/lx9.py @@ -5,13 +5,14 @@ # ------------------------------------------------------------ # -from __future__ import print_function + import yaml import time + import numpy as np from bitarray import bitarray -from basil.dut import Dut +from basil.dut import Dut class Pixel(Dut): @@ -19,7 +20,7 @@ class Pixel(Dut): A class for communicating with a pixel chip. """ - + def program_global_reg(self): """ Send the global register to the chip. @@ -29,20 +30,19 @@ def program_global_reg(self): and DAC shadow registers. """ - + self._clear_strobes() - - gr_size = len(self['GLOBAL_REG'][:]) #get the size - self['SEQ']['SHIFT_IN'][0:gr_size] = self['GLOBAL_REG'][:] # this will be shifted out - self['SEQ']['GLOBAL_SHIFT_EN'][0:gr_size] = bitarray( gr_size * '1') #this is to enable clock - self['SEQ']['GLOBAL_CTR_LD'][gr_size+1:gr_size+2] = bitarray("1") # load signals - self['SEQ']['GLOBAL_DAC_LD'][gr_size+1:gr_size+2] = bitarray("1") - - + + gr_size = len(self['GLOBAL_REG'][:]) # get the size + self['SEQ']['SHIFT_IN'][0:gr_size] = self['GLOBAL_REG'][:] # this will be shifted out + self['SEQ']['GLOBAL_SHIFT_EN'][0:gr_size] = bitarray(gr_size * '1') # this is to enable clock + self['SEQ']['GLOBAL_CTR_LD'][gr_size + 1:gr_size + 2] = bitarray("1") # load signals + self['SEQ']['GLOBAL_DAC_LD'][gr_size + 1:gr_size + 2] = bitarray("1") + # Execute the program (write bits to output pins) # + 1 extra 0 bit so that everything ends on LOW instead of HIGH - self._run_seq(gr_size+3) - + self._run_seq(gr_size + 3) + def program_pixel_reg(self, enable_receiver=True): """ Send the pixel register to the chip and store the output. @@ -55,37 +55,36 @@ def program_pixel_reg(self, enable_receiver=True): self['DATA'], retrievable via `chip['DATA'].get_data()`. """ - + self._clear_strobes() - #enable receiver it work only if pixel register is enabled/clocked - self['PIXEL_RX'].set_en(enable_receiver) + # enable receiver it work only if pixel register is enabled/clocked + self['PIXEL_RX'].set_en(enable_receiver) + + px_size = len(self['PIXEL_REG'][:]) # get the size + self['SEQ']['SHIFT_IN'][0:px_size] = self['PIXEL_REG'][:] # this will be shifted out + self['SEQ']['PIXEL_SHIFT_EN'][0:px_size] = bitarray(px_size * '1') # this is to enable clock - px_size = len(self['PIXEL_REG'][:]) #get the size - self['SEQ']['SHIFT_IN'][0:px_size] = self['PIXEL_REG'][:] # this will be shifted out - self['SEQ']['PIXEL_SHIFT_EN'][0:px_size] = bitarray( px_size * '1') #this is to enable clock - print('px_size', px_size) - - - self._run_seq(px_size+1) #add 1 bit more so there is 0 at the end other way will stay high - + + self._run_seq(px_size + 1) # add 1 bit more so there is 0 at the end other way will stay high + def _run_seq(self, size): """ Send the contents of self['SEQ'] to the chip and wait until it finishes. """ - + # Write the sequence to the sequence generator (hw driver) - self['SEQ'].write(size) #write pattern to memory - + self['SEQ'].write(size) # write pattern to memory + self['SEQ'].set_size(size) # set size - self['SEQ'].set_repeat(1) # set repeat + self['SEQ'].set_repeat(1) # set repeat for _ in range(1): - self['SEQ'].start() # start - + self['SEQ'].start() # start + while not self['SEQ'].get_done(): - #time.sleep(0.1) + # time.sleep(0.1) print("Wait for done...") def _clear_strobes(self): @@ -93,13 +92,14 @@ def _clear_strobes(self): Resets the "enable" and "load" output streams to all 0. """ - #reset some stuff + # reset some stuff self['SEQ']['GLOBAL_SHIFT_EN'].setall(False) self['SEQ']['GLOBAL_CTR_LD'].setall(False) self['SEQ']['GLOBAL_DAC_LD'].setall(False) self['SEQ']['PIXEL_SHIFT_EN'].setall(False) self['SEQ']['INJECTION'].setall(False) + print("Start") stream = open("lx9.yaml", 'r') @@ -113,41 +113,41 @@ def _clear_strobes(self): chip['GPIO']['LED3'] = 0 chip['GPIO']['LED4'] = 0 chip['GPIO'].write() - -#settings for global register (to input into global SR) + +# settings for global register (to input into global SR) # can be an integer representing the binary number desired, # or a bitarray (of the form bitarray("10101100")). -chip['GLOBAL_REG']['global_readout_enable'] = 0# size = 1 bit -chip['GLOBAL_REG']['SRDO_load'] = 0# size = 1 bit -chip['GLOBAL_REG']['NCout2'] = 0# size = 1 bit -chip['GLOBAL_REG']['count_hits_not'] = 0# size = 1 -chip['GLOBAL_REG']['count_enable'] = 0# size = 1 -chip['GLOBAL_REG']['count_clear_not'] = 0# size = 1 -chip['GLOBAL_REG']['S0'] = 0# size = 1 -chip['GLOBAL_REG']['S1'] = 0# size = 1 -chip['GLOBAL_REG']['config_mode'] = 3# size = 2 -chip['GLOBAL_REG']['LD_IN0_7'] = 0# size = 8 -chip['GLOBAL_REG']['LDENABLE_SEL'] = 0# size = 1 -chip['GLOBAL_REG']['SRCLR_SEL'] = 0# size = 1 -chip['GLOBAL_REG']['HITLD_IN'] = 0# size = 1 -chip['GLOBAL_REG']['NCout21_25'] = 0# size = 5 -chip['GLOBAL_REG']['column_address'] = 0# size = 6 -chip['GLOBAL_REG']['DisVbn'] = 0# size = 8 -chip['GLOBAL_REG']['VbpThStep'] = 0# size = 8 -chip['GLOBAL_REG']['PrmpVbp'] = 0# size = 8 -chip['GLOBAL_REG']['PrmpVbnFol'] = 0# size = 8 -chip['GLOBAL_REG']['vth'] = 0# size = 8 -chip['GLOBAL_REG']['PrmpVbf'] = 0# size = 8 +chip['GLOBAL_REG']['global_readout_enable'] = 0 # size = 1 bit +chip['GLOBAL_REG']['SRDO_load'] = 0 # size = 1 bit +chip['GLOBAL_REG']['NCout2'] = 0 # size = 1 bit +chip['GLOBAL_REG']['count_hits_not'] = 0 # size = 1 +chip['GLOBAL_REG']['count_enable'] = 0 # size = 1 +chip['GLOBAL_REG']['count_clear_not'] = 0 # size = 1 +chip['GLOBAL_REG']['S0'] = 0 # size = 1 +chip['GLOBAL_REG']['S1'] = 0 # size = 1 +chip['GLOBAL_REG']['config_mode'] = 3 # size = 2 +chip['GLOBAL_REG']['LD_IN0_7'] = 0 # size = 8 +chip['GLOBAL_REG']['LDENABLE_SEL'] = 0 # size = 1 +chip['GLOBAL_REG']['SRCLR_SEL'] = 0 # size = 1 +chip['GLOBAL_REG']['HITLD_IN'] = 0 # size = 1 +chip['GLOBAL_REG']['NCout21_25'] = 0 # size = 5 +chip['GLOBAL_REG']['column_address'] = 0 # size = 6 +chip['GLOBAL_REG']['DisVbn'] = 0 # size = 8 +chip['GLOBAL_REG']['VbpThStep'] = 0 # size = 8 +chip['GLOBAL_REG']['PrmpVbp'] = 0 # size = 8 +chip['GLOBAL_REG']['PrmpVbnFol'] = 0 # size = 8 +chip['GLOBAL_REG']['vth'] = 0 # size = 8 +chip['GLOBAL_REG']['PrmpVbf'] = 0 # size = 8 print("program global register...") chip.program_global_reg() - -#settings for pixel register (to input into pixel SR) + +# settings for pixel register (to input into pixel SR) # can be an integer representing the binary number desired, # or a bitarray (of the form bitarray("10101100")). -chip['PIXEL_REG'][:] = bitarray('1111111010001100'*8) +chip['PIXEL_REG'][:] = bitarray('1111111010001100' * 8) print(chip['PIXEL_REG']) #chip['PIXEL_REG'][0] = 0 @@ -158,16 +158,13 @@ def _clear_strobes(self): # Get output size in bytes print("chip['DATA'].get_FIFO_SIZE() = ", chip['DATA'].get_FIFO_SIZE()) -rxd = chip['DATA'].get_data() #get data from sram fifo +rxd = chip['DATA'].get_data() # get data from sram fifo print(rxd) -data0 = rxd.astype(np.uint8) # Change type to unsigned int 8 bits and take from rxd only the last 8 bits -data1 = np.right_shift(rxd, 8).astype(np.uint8) # Rightshift rxd 8 bits and take again last 8 bits -data = np.reshape(np.vstack((data1, data0)), -1, order='F') # data is now a 1 dimensional array of all bytes read from the FIFO +data0 = rxd.astype(np.uint8) # Change type to unsigned int 8 bits and take from rxd only the last 8 bits +data1 = np.right_shift(rxd, 8).astype(np.uint8) # Rightshift rxd 8 bits and take again last 8 bits +data = np.reshape(np.vstack((data1, data0)), -1, order='F') # data is now a 1 dimensional array of all bytes read from the FIFO bdata = np.unpackbits(data) print("data = ", data) -print("bdata = ", bdata) - - - +print("bdata = ", bdata) From 5908509d1b417093b09d15c9a7697d2e6dd1f4ae Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Thu, 15 Aug 2019 14:21:03 +0200 Subject: [PATCH 21/41] MAINT: fix prints --- basil/HL/debyeflex3003.py | 2 +- basil/HL/tti_ql355tp.py | 12 ++++++------ basil/utils/sim/SiLibUsb.py | 6 +++--- basil/utils/sim/Test.py | 4 ++-- basil/utils/utils.py | 4 ++-- examples/bdaq/test/test_bdaq53_eth.py | 2 +- examples/lab_devices/MotorStage.py | 2 +- examples/lab_devices/ProbeStation.py | 2 +- examples/lab_devices/julaboF32HD.py | 4 ++-- examples/lab_devices/scpi_devices.py | 4 ++-- examples/lab_devices/temperature_control.py | 2 +- examples/lx9/host/lx9.py | 8 ++++---- examples/mio_pixel/pixel.py | 10 +++++----- examples/mio_sram_test/sram_test.py | 8 ++++---- examples/mmc3_eth/test/test_mmc3_eth.py | 3 +-- examples/register_example/simple_register_example.py | 12 ++++++------ 16 files changed, 42 insertions(+), 43 deletions(-) diff --git a/basil/HL/debyeflex3003.py b/basil/HL/debyeflex3003.py index 70b5b5241..2778842be 100644 --- a/basil/HL/debyeflex3003.py +++ b/basil/HL/debyeflex3003.py @@ -24,7 +24,7 @@ def init(self): def read(self): ret = self._intf.read() if ret[-1:] != "\r": - print("debyeflex3003.read() terminator error") + print("debyeflex3003.read() termination error") return ret[1:-1] def write(self, cmd): diff --git a/basil/HL/tti_ql355tp.py b/basil/HL/tti_ql355tp.py index 8414814ec..9f935b09e 100644 --- a/basil/HL/tti_ql355tp.py +++ b/basil/HL/tti_ql355tp.py @@ -5,7 +5,7 @@ # ------------------------------------------------------------ # -from __future__ import print_function + import time from basil.HL.RegisterHardwareLayer import HardwareLayer @@ -35,7 +35,7 @@ def ask(self, command): def read(self): ret = self._intf.read() if ret[-2:] != "\r\n": - print("ttiTp355tp.read() terminator error") + print("ttiTp355tp.read() termination error") return ret[:-2] def set_enable(self, on, channel=1): @@ -53,7 +53,7 @@ def get_current(self, channel): """ channel: 1=OP1, 2=OP2, AUX is not supported""" ret = self.ask("I%dO?" % channel) if ret[-1] != "A": - print("ttiQl355tp.get_current() format error", ret) + print("ttiQl355tp.get_current() format error: %s" % ret) return None return float(ret[:-1]) @@ -61,7 +61,7 @@ def get_voltage(self, channel): """ channel: 1=OP1, 2=OP2, AUX is not supported""" ret = self.ask("V%dO?" % channel) if ret[-1] != "V": - print("ttiQl355tp.get_voltage() format error", ret) + print("ttiQl355tp.get_voltage() format error: %s" % ret) return None return float(ret[:-1]) @@ -69,7 +69,7 @@ def get_set_voltage(self, channel): """ channel: 1=OP1, 2=OP2, AUX is not supported""" ret = self.ask("V%d?" % channel) if ret[:3] != "V%d " % channel: - print("ttiQl355tp.get_voltage() format error", ret) + print("ttiQl355tp.get_voltage() format error: %s" % ret) return None return float(ret[3:]) @@ -77,7 +77,7 @@ def get_current_limit(self, channel): """ channel: 1=OP1, 2=OP2, AUX is not supported""" ret = self.ask("I%d?" % channel) if ret[:3] != "I%d " % channel: - print("ttiQl355tp.get_current_limit() format error", ret) + print("ttiQl355tp.get_current_limit() format error: %s" % ret) return None return float(ret[3:]) diff --git a/basil/utils/sim/SiLibUsb.py b/basil/utils/sim/SiLibUsb.py index a61c397c6..e21ce3932 100644 --- a/basil/utils/sim/SiLibUsb.py +++ b/basil/utils/sim/SiLibUsb.py @@ -17,7 +17,7 @@ """ -from __future__ import print_function + import socket import array @@ -85,8 +85,8 @@ def FastBlockWrite(self, data): self._iface.send(req) def WriteI2C(self, address, data): - print('SiUSBDevice:WriteI2C', address, data) # raise NotImplementedError("To be implemented.") + print('SiUSBDevice:WriteI2C: {} {}'.format(address, data)) def ReadI2C(self, address, size): - print('SiUSBDevice:ReadI2C') # raise NotImplementedError("To be implemented.") + print('SiUSBDevice:ReadI2C') return array.array('B', range(size)) diff --git a/basil/utils/sim/Test.py b/basil/utils/sim/Test.py index 00cd34a85..ed061644e 100644 --- a/basil/utils/sim/Test.py +++ b/basil/utils/sim/Test.py @@ -7,7 +7,7 @@ # Initial version by Chris Higgs # -from __future__ import print_function + import os import socket import logging @@ -126,7 +126,7 @@ def bringup_test(dut): ret = yield bus.read(0, 4) - print(('bus.read', ret)) + print('bus.read {}'.format(ret)) for _ in range(10): yield RisingEdge(bus.clock) diff --git a/basil/utils/utils.py b/basil/utils/utils.py index 28c291430..cbb2044c1 100644 --- a/basil/utils/utils.py +++ b/basil/utils/utils.py @@ -5,7 +5,7 @@ # ------------------------------------------------------------ # -from __future__ import print_function + from array import array import numpy as np @@ -14,7 +14,7 @@ def logging(fn): def wrapped(*args, **kargs): - print(('loging:', locals())) + print('loging: {}'.format(locals())) # if args: # print("loging: arguments: " + str(args)) # if kargs: diff --git a/examples/bdaq/test/test_bdaq53_eth.py b/examples/bdaq/test/test_bdaq53_eth.py index 626233e76..23a564849 100644 --- a/examples/bdaq/test/test_bdaq53_eth.py +++ b/examples/bdaq/test/test_bdaq53_eth.py @@ -82,7 +82,7 @@ def test(self): break total_len_bits = total_len * 32 # 32-bit ints to bits - print(('Bits received:', total_len_bits, 'Data rate:', round((total_len_bits / 1e6 / testduration), 2), 'Mbit/s')) + print('Bits received: {}; Data rate: {}Mbit/s'.format(total_len_bits, round((total_len_bits / 1e6 / testduration), 2))) self.chip['CONTROL']['EN'] = 0x00 # stop data source self.chip['CONTROL'].write() diff --git a/examples/lab_devices/MotorStage.py b/examples/lab_devices/MotorStage.py index 154a14010..81e530b35 100644 --- a/examples/lab_devices/MotorStage.py +++ b/examples/lab_devices/MotorStage.py @@ -8,7 +8,7 @@ ''' This script shows how to use a Motor Stage ''' -from __future__ import print_function + from basil.dut import Dut dut = Dut('mercury_pyserial.yaml') diff --git a/examples/lab_devices/ProbeStation.py b/examples/lab_devices/ProbeStation.py index d8acde556..a0fb50c47 100644 --- a/examples/lab_devices/ProbeStation.py +++ b/examples/lab_devices/ProbeStation.py @@ -18,7 +18,7 @@ This virtual one is then used to steer the probe station within BASIL. ''' -from __future__ import print_function + from basil.dut import Dut dut = Dut('suss_pa_200.yaml') diff --git a/examples/lab_devices/julaboF32HD.py b/examples/lab_devices/julaboF32HD.py index 8e82d282f..ba5e51f72 100644 --- a/examples/lab_devices/julaboF32HD.py +++ b/examples/lab_devices/julaboF32HD.py @@ -12,8 +12,8 @@ dut = Dut('julaboF32HD.yaml') dut.init() -print("ID", dut["chiller"].get_identifier()) -print("status", dut["chiller"].get_status()) +print("ID: {}".format(dut["chiller"].get_identifier())) +print("Status: {}".format(dut["chiller"].get_status())) # start # set menu->confiuration->setpoint->rs232 diff --git a/examples/lab_devices/scpi_devices.py b/examples/lab_devices/scpi_devices.py index cedb8e1bf..46d6c37ba 100644 --- a/examples/lab_devices/scpi_devices.py +++ b/examples/lab_devices/scpi_devices.py @@ -12,7 +12,7 @@ all laboratory devices (> 90%) over TCP, RS232, USB, GPIB (Windows only so far). ''' -from __future__ import print_function + from basil.dut import Dut # Talk to a Keithley device via serial port using pySerial @@ -36,7 +36,7 @@ print(dut['Pulser'].get_info()) # Some additional implemented methods for this device dut['Pulser'].set_voltage(0., 1., unit='V') -print(dut['Pulser'].get_voltage(0, unit='mV'), 'mV') +print("{}{}".format(dut['Pulser'].get_voltage(0, unit='mV'), 'mV')) # Example for device with multiple channels dut = Dut('ttiql355tp.yaml') diff --git a/examples/lab_devices/temperature_control.py b/examples/lab_devices/temperature_control.py index a5ccc4524..b318f7dfb 100644 --- a/examples/lab_devices/temperature_control.py +++ b/examples/lab_devices/temperature_control.py @@ -11,7 +11,7 @@ For the communication with the Binder MK 53 also a serial TL has to be used (http://www.binder-world.com). ''' -from __future__ import print_function + from basil.dut import Dut # Sensirion sensor readout diff --git a/examples/lx9/host/lx9.py b/examples/lx9/host/lx9.py index 66f120fde..87d32dab0 100644 --- a/examples/lx9/host/lx9.py +++ b/examples/lx9/host/lx9.py @@ -65,7 +65,7 @@ def program_pixel_reg(self, enable_receiver=True): self['SEQ']['SHIFT_IN'][0:px_size] = self['PIXEL_REG'][:] # this will be shifted out self['SEQ']['PIXEL_SHIFT_EN'][0:px_size] = bitarray(px_size * '1') # this is to enable clock - print('px_size', px_size) + print('px_size = {}'.format(px_size)) self._run_seq(px_size + 1) # add 1 bit more so there is 0 at the end other way will stay high @@ -156,7 +156,7 @@ def _clear_strobes(self): time.sleep(0.5) # Get output size in bytes -print("chip['DATA'].get_FIFO_SIZE() = ", chip['DATA'].get_FIFO_SIZE()) +print("chip['DATA'].get_FIFO_SIZE() = {}".format(chip['DATA'].get_FIFO_SIZE())) rxd = chip['DATA'].get_data() # get data from sram fifo print(rxd) @@ -166,5 +166,5 @@ def _clear_strobes(self): data = np.reshape(np.vstack((data1, data0)), -1, order='F') # data is now a 1 dimensional array of all bytes read from the FIFO bdata = np.unpackbits(data) -print("data = ", data) -print("bdata = ", bdata) +print("data = {}".format(data)) +print("bdata = {}".format(bdata)) diff --git a/examples/mio_pixel/pixel.py b/examples/mio_pixel/pixel.py index fa755ccbf..8edcd917d 100644 --- a/examples/mio_pixel/pixel.py +++ b/examples/mio_pixel/pixel.py @@ -6,7 +6,7 @@ # -from __future__ import print_function + import time import numpy as np @@ -111,7 +111,7 @@ def _clear_strobes(self): # Set the output voltage on the pins chip['PWRAC'].set_voltage("VDDD1", 1.2) - print(("VDDD1", chip['PWRAC'].get_voltage("VDDD1"), chip['PWRAC'].get_current("VDDD1"))) + print("VDDD1 = {}V/{}A".format(chip['PWRAC'].get_voltage("VDDD1"), chip['PWRAC'].get_current("VDDD1"))) # settings for global register (to input into global SR) # can be an integer representing the binary number desired, @@ -152,7 +152,7 @@ def _clear_strobes(self): chip.program_pixel_reg() # Get output size in bytes - print(("chip['DATA'].get_FIFO_SIZE() = ", chip['DATA'].get_FIFO_SIZE())) + print("chip['DATA'].get_FIFO_SIZE() = {}".format(chip['DATA'].get_FIFO_SIZE())) # Get output in bytes print("chip['DATA'].get_data()") @@ -163,5 +163,5 @@ def _clear_strobes(self): data = np.reshape(np.vstack((data1, data0)), -1, order='F') # data is now a 1 dimensional array of all bytes read from the FIFO bdata = np.unpackbits(data) - print(("data = ", data)) - print(("bdata = ", bdata)) + print("data = {}".format(data)) + print("bdata = {}".format(bdata)) diff --git a/examples/mio_sram_test/sram_test.py b/examples/mio_sram_test/sram_test.py index 609977a17..ec7cd6b46 100644 --- a/examples/mio_sram_test/sram_test.py +++ b/examples/mio_sram_test/sram_test.py @@ -4,7 +4,7 @@ # ------------------------------------------------------------ # -from __future__ import print_function + import numpy as np from basil.dut import Dut @@ -90,6 +90,6 @@ def test_register(count=10000): if __name__ == "__main__": - print('test_register ...', 'errors:', test_register()) - print('test_direct ...', 'errors:', test_direct()) - print('test_sram ...', 'errors:', test_sram()) + print('test_register ... errors: {}'.format(test_register())) + print('test_direct ... errors: {}'.format(test_direct())) + print('test_sram ... errors: {}'.format(test_sram())) diff --git a/examples/mmc3_eth/test/test_mmc3_eth.py b/examples/mmc3_eth/test/test_mmc3_eth.py index 713dddb2e..cad4b8b8d 100644 --- a/examples/mmc3_eth/test/test_mmc3_eth.py +++ b/examples/mmc3_eth/test/test_mmc3_eth.py @@ -6,7 +6,6 @@ # SiLab, Institute of Physics, University of Bonn # ------------------------------------------------------------ # -from __future__ import print_function import os import sys @@ -111,7 +110,7 @@ def test(self): break total_len_bits = total_len * 32 # 32-bit ints to bits - print(('Bits received:', total_len_bits, 'Data rate:', round((total_len_bits / 1e6 / testduration), 2), 'Mbit/s')) + print('Bits received: {}; Data rate: {}Mbit/s'.format(total_len_bits, round((total_len_bits / 1e6 / testduration), 2))) self.chip['GPIO_LED']['LED'] = 0x00 # stop data source self.chip['GPIO_LED'].write() diff --git a/examples/register_example/simple_register_example.py b/examples/register_example/simple_register_example.py index c5e5ce1e5..b8080f957 100644 --- a/examples/register_example/simple_register_example.py +++ b/examples/register_example/simple_register_example.py @@ -4,13 +4,13 @@ # ------------------------------------------------------------ # -from __future__ import print_function + from basil.dut import Dut chip = Dut("simple_register_example.yaml") -print((chip['TEST'])) -print((chip['REG'])) +print(chip['TEST']) +print(chip['REG']) # chip['REG'][0] = 1 chip['REG']['VPULSE'][5] = 1 @@ -23,9 +23,9 @@ chip['REG']['COLUMN'][0]['DACR'] = 3 chip['REG']['VINJECT'] = 3 -print((chip['REG'])) +print(chip['REG']) chip['REG']['VINJECT'][0] = 1 -print((chip['REG'])) +print(chip['REG']) -print(('VINJECT', str(chip['REG']['VINJECT']))) +print('VINJECT {}'.format(str(chip['REG']['VINJECT']))) From e2cc2368187df7560198011d51ebef05c9f9eb50 Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Thu, 15 Aug 2019 14:23:59 +0200 Subject: [PATCH 22/41] MAINT: remove lambda in favor of function --- basil/utils/utils.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/basil/utils/utils.py b/basil/utils/utils.py index cbb2044c1..a200d0a58 100644 --- a/basil/utils/utils.py +++ b/basil/utils/utils.py @@ -23,12 +23,15 @@ def wrapped(*args, **kargs): return wrapped +def lsbits(b): + return (b * 0x0202020202 & 0x010884422010) % 1023 + + def bitvector_to_byte_array(bitvector): bsize = len(bitvector) size_bytes = int(((bsize - 1) / 8) + 1) bs = tobytes(array('B', bitvector.vector))[0:size_bytes] bitstream_swap = '' - lsbits = lambda b: (b * 0x0202020202 & 0x010884422010) % 1023 for b in bs: bitstream_swap += chr(lsbits(b)) return array('B', bitstream_swap) From 75bc57711714375c207d0b8bbf1e9c643666c0a7 Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Thu, 15 Aug 2019 14:38:56 +0200 Subject: [PATCH 23/41] 2to3: remove long() --- examples/test_eth/test_eth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/test_eth/test_eth.py b/examples/test_eth/test_eth.py index 64ee00460..eb7fe3a0e 100644 --- a/examples/test_eth/test_eth.py +++ b/examples/test_eth/test_eth.py @@ -257,7 +257,7 @@ def udp_read_write(self): time_read = time.time() while not self.stop_thread.wait(max(0.0, self.udp_readout_delay - time_read + time.time())): time_read = time.time() - write_value = long(np.random.randint(2**64, size=None, dtype=np.uint64)) # random.randint(0, 2**64 - 1) + write_value = int(np.random.randint(2**64, size=None, dtype=np.uint64)) # random.randint(0, 2**64 - 1) try: self.dut['REGISTERS'].TEST_DATA = write_value except Exception as e: From 43681d13b452529f39cbb70aaf12d30247bd0cf3 Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Thu, 15 Aug 2019 14:58:51 +0200 Subject: [PATCH 24/41] REG: fix string parsing --- tests/test_SimScpi.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_SimScpi.py b/tests/test_SimScpi.py index 147635727..14675ed64 100644 --- a/tests/test_SimScpi.py +++ b/tests/test_SimScpi.py @@ -16,8 +16,8 @@ type : Visa init : resource_name : ASRL1::INSTR - read_termination : "\n" - write_termination : "\r\n" + read_termination : "\\n" + write_termination : "\\r\\n" backend : "@sim" hw_drivers: From 8c624d5a03cfb37ac7280b7f99c025739dadfb7e Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Thu, 15 Aug 2019 15:27:51 +0200 Subject: [PATCH 25/41] REG: fix Python 2.7 compatibility --- basil/TL/Serial.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/basil/TL/Serial.py b/basil/TL/Serial.py index 28c73efc9..4231f5b61 100644 --- a/basil/TL/Serial.py +++ b/basil/TL/Serial.py @@ -47,13 +47,13 @@ def write(self, data): if self.write_termination is None: try: self._port.write(bytes(data, 'utf-8')) - except TypeError: + except TypeError: # Python 2.7 self._port.write(bytes(data)) else: try: self._port.write(bytes(data, 'utf-8') + self.write_termination) - except TypeError: - self._port.write(bytes(data + self.write_termination, 'utf-8')) + except TypeError: # Python 2.7 + self._port.write(bytes(data + self.write_termination)) def read(self, size=None): if size is None: From ab143e7345beab8f1f1ae9221d6d3d7abbd4641e Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Thu, 15 Aug 2019 15:58:47 +0200 Subject: [PATCH 26/41] MAINT: code cleanup --- basil/HL/GPAC.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/basil/HL/GPAC.py b/basil/HL/GPAC.py index 6c0597902..14e0494b9 100644 --- a/basil/HL/GPAC.py +++ b/basil/HL/GPAC.py @@ -97,9 +97,10 @@ def __init__(self, intf, conf): self.PCA9554_ADD = self.POWER_GPIO_ADD self.GPIO_CFG = self.POWER_GPIO_CFG self._init.setdefault('no_power_reset', False) + def init(self): self._intf.write(self._base_addr + self.PCA9554_ADD, (self.PCA9554_CFG, self.GPIO_CFG)) - if self._init['no_power_reset']==False: + if self._init['no_power_reset'] is False: logging.info("########GPAC ##########") logging.info("########POWER RESET!!!!!##########") self._intf.write(self._base_addr + self.PCA9554_ADD, (self.PCA9554_OUT, 0x00)) From 3d37e52f6548bd349ba23df81569198ab29b8a62 Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Thu, 15 Aug 2019 15:59:12 +0200 Subject: [PATCH 27/41] 2to3: fix decode issue --- basil/HL/GPAC.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basil/HL/GPAC.py b/basil/HL/GPAC.py index 14e0494b9..9ac0a087b 100644 --- a/basil/HL/GPAC.py +++ b/basil/HL/GPAC.py @@ -733,7 +733,7 @@ def read_eeprom_calibration(self): # use default values for temperature, EEPROM for idx, channel in enumerate(self._ch_cal.keys()): ch_data = data[idx * calcsize(self.CAL_DATA_CH_GPAC_FORMAT):(idx + 1) * calcsize(self.CAL_DATA_CH_GPAC_FORMAT)] values = unpack_from(self.CAL_DATA_CH_GPAC_FORMAT, ch_data) - self._ch_cal[channel]['name'] = "".join([c for c in values[0] if (c in string.printable)]) # values[0].strip() + self._ch_cal[channel]['name'] = "".join([c for c in values[0].decode('utf-8', errors='ignore') if (c in string.printable)]) # values[0].strip() self._ch_cal[channel]['default'] = values[1] self._ch_cal[channel]['min'] = values[2] self._ch_cal[channel]['max'] = values[3] From 3cefa04f355489af9c3c9e8fb90bfb1a4fe4a7b0 Mon Sep 17 00:00:00 2001 From: DavidLP Date: Fri, 16 Aug 2019 08:45:30 +0200 Subject: [PATCH 28/41] PRJ: add code style checks for changed code lines --- .travis.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 67f2c280b..c5b6ee2b9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,14 +37,16 @@ install: - conda update --yes conda - conda update --yes --all - conda info -a - - conda create --yes -n test-environment python=$TRAVIS_PYTHON_VERSION numpy bitarray nose pyyaml coverage six + - conda create --yes -n test-environment python=$TRAVIS_PYTHON_VERSION numpy bitarray nose pyyaml coverage six flake8 - source activate test-environment - - pip install pyvisa pyvisa-sim coveralls cocotb==1.0.dev3 + - pip install pyvisa pyvisa-sim coveralls cocotb==1.0.dev3 flake8-diff # install basil - python setup.py develop script: - nosetests --with-coverage --cover-package=basil tests/test_*.py examples/*/*/test_*.py + - export BRANCH=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi) + - if [ "$BRANCH" == "development" ]; then flake8-diff origin/master; else flake8-diff origin/development; fi # check code style flaws of changed lines against upstream after_success: - coveralls From 003eb344c8e3d5144307c2f7ef20d39f99a841e5 Mon Sep 17 00:00:00 2001 From: DavidLP Date: Fri, 16 Aug 2019 15:20:47 +0200 Subject: [PATCH 29/41] PRJ: reasonable flake8 config --- setup.cfg | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/setup.cfg b/setup.cfg index 0c27e1105..696aa819b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,2 +1,7 @@ [metadata] description-file = README.rst + +[flake8] +ignore = E501,E902,W503,W605,W504 +# max-line-length = 160 + From c5f548497d571e6a7ef6bd495fbc8ae7e6c32e01 Mon Sep 17 00:00:00 2001 From: DavidLP Date: Fri, 16 Aug 2019 15:20:58 +0200 Subject: [PATCH 30/41] TST: try fix flake8 check --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c5b6ee2b9..9276bd6c8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,7 +46,10 @@ install: script: - nosetests --with-coverage --cover-package=basil tests/test_*.py examples/*/*/test_*.py - export BRANCH=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi) - - if [ "$BRANCH" == "development" ]; then flake8-diff origin/master; else flake8-diff origin/development; fi # check code style flaws of changed lines against upstream + # Check code style flaws of changed lines + - git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" + - git fetch + - if [ "$BRANCH" == "development" ]; then flake8-diff origin/master; else flake8-diff origin/development; fi after_success: - coveralls From b9b9f79df0af901db0236f3ab8c5c41bd82da186 Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Fri, 16 Aug 2019 16:23:22 +0200 Subject: [PATCH 31/41] MAINT: PEP8 --- basil/HL/RegisterHardwareLayer.py | 4 +- docs/conf.py | 120 +++++++++++++++--------------- tests/test_SimSpi.py | 5 +- 3 files changed, 66 insertions(+), 63 deletions(-) diff --git a/basil/HL/RegisterHardwareLayer.py b/basil/HL/RegisterHardwareLayer.py index 1f95d97c7..80528b232 100644 --- a/basil/HL/RegisterHardwareLayer.py +++ b/basil/HL/RegisterHardwareLayer.py @@ -183,8 +183,8 @@ def get_configuration(self): def add_property(self, attribute): # create local setter and getter with a particular attribute name -# getter = lambda self: self._get(attribute) -# setter = lambda self, value: self._set(attribute, value) + # getter = lambda self: self._get(attribute) + # setter = lambda self, value: self._set(attribute, value) # Workaround: obviously dynamic properties catch exceptions # Print error message and return None diff --git a/docs/conf.py b/docs/conf.py index 57f5d96ce..85dea4fde 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -17,7 +17,6 @@ import sphinx_rtd_theme - # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. @@ -27,7 +26,7 @@ # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' +# needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom @@ -48,7 +47,7 @@ source_suffix = '.rst' # The encoding of source files. -#source_encoding = 'utf-8-sig' +# source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' @@ -72,13 +71,13 @@ # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. -#language = None +# language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: -#today = '' +# today = '' # Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +# today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. @@ -86,117 +85,120 @@ # The reST default role (used for this markup: `text`) to use for all # documents. -#default_role = None +# default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True +# add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). -#add_module_names = True +# add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. -#show_authors = False +# show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] +# modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False +# keep_warnings = False # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -#html_theme = 'default' +# html_theme = 'default' html_theme = "sphinx_rtd_theme" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -#html_theme_options = {} +# html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] +# html_theme_path = [] html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -#html_title = None +# html_title = None # A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None +# html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. -#html_logo = None +# html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -#html_favicon = None +# html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] + def setup(app): - app.add_stylesheet("theme_overrides.css") - app.add_javascript("http://wavedrom.com/skins/default.js") - app.add_javascript("http://wavedrom.com/WaveDrom.js") - app.add_javascript("WaveDrom_load.js") - + app.add_stylesheet("theme_overrides.css") + app.add_javascript("http://wavedrom.com/skins/default.js") + app.add_javascript("http://wavedrom.com/WaveDrom.js") + app.add_javascript("WaveDrom_load.js") + + # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. -#html_extra_path = [] +# html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' +# html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. -#html_use_smartypants = True +# html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -#html_sidebars = {} +# html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. -#html_additional_pages = {} +# html_additional_pages = {} # If false, no module index is generated. -#html_domain_indices = True +# html_domain_indices = True # If false, no index is generated. -#html_use_index = True +# html_use_index = True # If true, the index is split into individual pages for each letter. -#html_split_index = False +# html_split_index = False # If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True +# html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True +# html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True +# html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. -#html_use_opensearch = '' +# html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None +# html_file_suffix = None + # Output file base name for HTML help builder. htmlhelp_basename = 'basildoc' @@ -205,43 +207,43 @@ def setup(app): # -- Options for LaTeX output --------------------------------------------- latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', + # The paper size ('letterpaper' or 'a4paper'). + # 'papersize': 'letterpaper', -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', + # The font size ('10pt', '11pt' or '12pt'). + # 'pointsize': '10pt', -# Additional stuff for the LaTeX preamble. -#'preamble': '', + # Additional stuff for the LaTeX preamble. + # 'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - ('index', 'basil.tex', 'basil Documentation', - 'T', 'manual'), + ('index', 'basil.tex', 'basil Documentation', + 'T', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. -#latex_logo = None +# latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -#latex_use_parts = False +# latex_use_parts = False # If true, show page references after internal links. -#latex_show_pagerefs = False +# latex_show_pagerefs = False # If true, show URL addresses after external links. -#latex_show_urls = False +# latex_show_urls = False # Documents to append as an appendix to all manuals. -#latex_appendices = [] +# latex_appendices = [] # If false, no module index is generated. -#latex_domain_indices = True +# latex_domain_indices = True # -- Options for manual page output --------------------------------------- @@ -254,7 +256,7 @@ def setup(app): ] # If true, show URL addresses after external links. -#man_show_urls = False +# man_show_urls = False # -- Options for Texinfo output ------------------------------------------- @@ -263,22 +265,22 @@ def setup(app): # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'basil', 'basil Documentation', - 'T', 'basil', 'One line description of project.', - 'Miscellaneous'), + ('index', 'basil', 'basil Documentation', + 'T', 'basil', 'One line description of project.', + 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. -#texinfo_appendices = [] +# texinfo_appendices = [] # If false, no module index is generated. -#texinfo_domain_indices = True +# texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' +# texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. -#texinfo_no_detailmenu = False +# texinfo_no_detailmenu = False sys.path.append('./') sys.path.append('../') diff --git a/tests/test_SimSpi.py b/tests/test_SimSpi.py index 9cdac8b21..4fb634687 100644 --- a/tests/test_SimSpi.py +++ b/tests/test_SimSpi.py @@ -88,7 +88,7 @@ def test_io(self): pass ret = self.chip['SPI'].get_data() # read back what was received (looped) - self.assertEqual(ret.tolist(), list(range(16))) + self.assertEqual(ret.tolist(), list(range(16))) # ext_start self.chip['SPI'].set_en(1) @@ -128,7 +128,7 @@ def test_io(self): data0 = ret.astype(np.uint8) data1 = np.right_shift(ret, 8).astype(np.uint8) data = np.reshape(np.vstack((data1, data0)), -1, order='F') - self.assertEqual(data.tolist(), list(range(16))) + self.assertEqual(data.tolist(), list(range(16))) def test_dut_iter(self): conf = yaml.safe_load(cnfg_yaml) @@ -149,5 +149,6 @@ def tearDown(self): self.chip.close() # let it close connection and stop simulator cocotb_compile_clean() + if __name__ == '__main__': unittest.main() From 4ce367ced2d62b6193a657a4a1f7df49cf1d99fc Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Fri, 16 Aug 2019 16:44:10 +0200 Subject: [PATCH 32/41] ENH: add proper exceptions --- basil/HL/julaboF32HD.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basil/HL/julaboF32HD.py b/basil/HL/julaboF32HD.py index bc394b20d..059e07e16 100644 --- a/basil/HL/julaboF32HD.py +++ b/basil/HL/julaboF32HD.py @@ -65,7 +65,7 @@ def get_status(self): tmp = ret.split(" ", 1) status = int(tmp[0]) status_str = tmp[1:] - except IndexError: + except (ValueError, AttributeError): logging.warning("get_status() wrong format: {}".format(repr(ret))) status = -99 status_str = ret From 66913fd3e67b420a7c1891fc8eddabf0ca71387e Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Fri, 16 Aug 2019 17:01:13 +0200 Subject: [PATCH 33/41] ENH: use logger --- basil/HL/GPAC.py | 9 +++++---- basil/HL/debyeflex3003.py | 24 ++++++++++++++---------- basil/HL/julaboF32HD.py | 9 ++++++--- basil/HL/tti_ql355tp.py | 15 +++++++++------ 4 files changed, 34 insertions(+), 23 deletions(-) diff --git a/basil/HL/GPAC.py b/basil/HL/GPAC.py index 9ac0a087b..bb05eab95 100644 --- a/basil/HL/GPAC.py +++ b/basil/HL/GPAC.py @@ -15,6 +15,7 @@ from basil.HL.HardwareLayer import HardwareLayer from basil.HL.FEI4AdapterCard import Eeprom24Lc128 + logger = logging.getLogger(__name__) @@ -101,12 +102,12 @@ def __init__(self, intf, conf): def init(self): self._intf.write(self._base_addr + self.PCA9554_ADD, (self.PCA9554_CFG, self.GPIO_CFG)) if self._init['no_power_reset'] is False: - logging.info("########GPAC ##########") - logging.info("########POWER RESET!!!!!##########") + logger.info("########GPAC ##########") + logger.info("########POWER RESET!!!!!##########") self._intf.write(self._base_addr + self.PCA9554_ADD, (self.PCA9554_OUT, 0x00)) else: - logging.info("########GPAC #####") - logging.info("########SKIPPING POWER RESET #####") + logger.info("########GPAC #####") + logger.info("########SKIPPING POWER RESET #####") class AdcMuxGpio(GpioPca9554): diff --git a/basil/HL/debyeflex3003.py b/basil/HL/debyeflex3003.py index 2778842be..1ef6e23b1 100644 --- a/basil/HL/debyeflex3003.py +++ b/basil/HL/debyeflex3003.py @@ -5,9 +5,13 @@ # ------------------------------------------------------------ # -from basil.HL.RegisterHardwareLayer import HardwareLayer import logging +from basil.HL.RegisterHardwareLayer import HardwareLayer + + +logger = logging.getLogger(__name__) + class debyeflex3003(HardwareLayer): @@ -24,7 +28,7 @@ def init(self): def read(self): ret = self._intf.read() if ret[-1:] != "\r": - print("debyeflex3003.read() termination error") + logger.warning("debyeflex3003.read() termination error") return ret[1:-1] def write(self, cmd): @@ -51,7 +55,7 @@ def set_current(self, curr): raise ValueError("Illegal value for tube current (0 - 80 mA)") else: self.write("SC:{:02d}".format(int(curr))) - logging.info("Set tube current to {:.1f} mA".format(self.get_nominal_current())) + logger.info("Set tube current to {:.1f} mA".format(self.get_nominal_current())) def get_nominal_voltage(self): """Read nominal voltage in kV. @@ -74,7 +78,7 @@ def set_voltage(self, vol): raise ValueError("Illegal value for tube voltage (0 - 60 kV)") else: self.write("SV:{:02d}".format(vol)) - logging.info("Set tube voltage to {:.1f} kV".format(self.get_nominal_voltage())) + logger.info("Set tube voltage to {:.1f} kV".format(self.get_nominal_voltage())) def set_highvoltage_on(self): self.write("HV:1") @@ -91,7 +95,7 @@ def open_shutter(self, shutter=1): raise ValueError("Invalid value for shutter number") else: self.write("OS:{:1d}".format(shutter)) - logging.info("Opened shutter number {:1d}".format(shutter)) + logger.info("Opened shutter number {:1d}".format(shutter)) def close_shutter(self, shutter=1): """Close the shutter with given number. Only shuttter=1 supported from hardware currently @@ -102,7 +106,7 @@ def close_shutter(self, shutter=1): raise ValueError("Invalid value for shutter number") else: self.write("CS:{:1d}".format(shutter)) - logging.info("Closed shutter number {:1d}".format(shutter)) + logger.info("Closed shutter number {:1d}".format(shutter)) def activate_timer(self, shutter=1): """Activate the timer for a given shutter number @@ -113,7 +117,7 @@ def activate_timer(self, shutter=1): raise ValueError("Invalid value for shutter number") else: self.write("TS:{:1d}".format(shutter)) - logging.info("Started timer number {:1d}".format(shutter)) + logger.info("Started timer number {:1d}".format(shutter)) def deactivate_timer(self, shutter=1): """Deactivate the timer for a given shutter number @@ -124,7 +128,7 @@ def deactivate_timer(self, shutter=1): raise ValueError("Invalid value for shutter number") else: self.write("TE:{:1d}".format(shutter)) - logging.info("Stopped timer number {:1d}".format(shutter)) + logger.info("Stopped timer number {:1d}".format(shutter)) def set_timer(self, timer=1, dur=3600): """Set the timer with the given number (corresponds to shutter number) to the given duration (in s) @@ -141,7 +145,7 @@ def set_timer(self, timer=1, dur=3600): s = (dur % 3600) % 60 self.write("TP:{:1d},{:02d},{:02d},{:02d}".format(timer, h, m, s)) time = self.get_nominal_time(timer) - logging.info("Set timer number {:1d} to {:02d}:{:02d}:{:02d} (HH:MM:SS)".format( + logger.info("Set timer number {:1d} to {:02d}:{:02d}:{:02d} (HH:MM:SS)".format( timer, time // 3600, (time % 3600) // 60, (time % 3600) % 60) ) @@ -183,5 +187,5 @@ def get_status(self, status_word): self.write("SR:{:02d}".format(status_word)) response = self.read() status = bin(int(response[7:10]))[2:].zfill(8) # Convert response to 8 char long string of binary values - logging.info("Status word {:02d}: {:8s}".format(status_word, status)) + logger.info("Status word {:02d}: {:8s}".format(status_word, status)) return status diff --git a/basil/HL/julaboF32HD.py b/basil/HL/julaboF32HD.py index 059e07e16..944111fa0 100644 --- a/basil/HL/julaboF32HD.py +++ b/basil/HL/julaboF32HD.py @@ -11,6 +11,9 @@ from basil.HL.RegisterHardwareLayer import HardwareLayer +logger = logging.getLogger(__name__) + + class julaboF32HD(HardwareLayer): ''' Driver for the Julabo F32-HD chiller. A simple protocol via RS 232 serial port is used with 4800 baud rate. @@ -26,7 +29,7 @@ def init(self): def read(self): ret = self._intf.read() if len(ret) < 2 or ret[-2:] != "\r\n": - logging.warning("read() termination error") + logger.warning("read() termination error") return ret[:-2] def write(self, cmd): @@ -60,13 +63,13 @@ def get_status(self): ''' self.write("status") ret = self.read() - logging.debug("status:{:s}".format(ret)) + logger.debug("status:{:s}".format(ret)) try: tmp = ret.split(" ", 1) status = int(tmp[0]) status_str = tmp[1:] except (ValueError, AttributeError): - logging.warning("get_status() wrong format: {}".format(repr(ret))) + logger.warning("get_status() wrong format: {}".format(repr(ret))) status = -99 status_str = ret return status, status_str diff --git a/basil/HL/tti_ql355tp.py b/basil/HL/tti_ql355tp.py index 9f935b09e..bf85dbb40 100644 --- a/basil/HL/tti_ql355tp.py +++ b/basil/HL/tti_ql355tp.py @@ -5,12 +5,15 @@ # ------------------------------------------------------------ # - +import logging import time from basil.HL.RegisterHardwareLayer import HardwareLayer +logger = logging.getLogger(__name__) + + class ttiQl355tp(HardwareLayer): ''' HL for the TTi QL355TP. ''' @@ -35,7 +38,7 @@ def ask(self, command): def read(self): ret = self._intf.read() if ret[-2:] != "\r\n": - print("ttiTp355tp.read() termination error") + logger.warning("ttiTp355tp.read() termination error") return ret[:-2] def set_enable(self, on, channel=1): @@ -53,7 +56,7 @@ def get_current(self, channel): """ channel: 1=OP1, 2=OP2, AUX is not supported""" ret = self.ask("I%dO?" % channel) if ret[-1] != "A": - print("ttiQl355tp.get_current() format error: %s" % ret) + logger.warning("ttiQl355tp.get_current() format error: %s" % ret) return None return float(ret[:-1]) @@ -61,7 +64,7 @@ def get_voltage(self, channel): """ channel: 1=OP1, 2=OP2, AUX is not supported""" ret = self.ask("V%dO?" % channel) if ret[-1] != "V": - print("ttiQl355tp.get_voltage() format error: %s" % ret) + logger.warning("ttiQl355tp.get_voltage() format error: %s" % ret) return None return float(ret[:-1]) @@ -69,7 +72,7 @@ def get_set_voltage(self, channel): """ channel: 1=OP1, 2=OP2, AUX is not supported""" ret = self.ask("V%d?" % channel) if ret[:3] != "V%d " % channel: - print("ttiQl355tp.get_voltage() format error: %s" % ret) + logger.warning("ttiQl355tp.get_voltage() format error: %s" % ret) return None return float(ret[3:]) @@ -77,7 +80,7 @@ def get_current_limit(self, channel): """ channel: 1=OP1, 2=OP2, AUX is not supported""" ret = self.ask("I%d?" % channel) if ret[:3] != "I%d " % channel: - print("ttiQl355tp.get_current_limit() format error: %s" % ret) + logger.warning("ttiQl355tp.get_current_limit() format error: %s" % ret) return None return float(ret[3:]) From c78b7577b03fdb556b72fdb96eb2488dcb6858fb Mon Sep 17 00:00:00 2001 From: Tomasz Hemperek Date: Mon, 19 Aug 2019 14:08:49 +0200 Subject: [PATCH 34/41] update to latest cocotb --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9276bd6c8..f01889b66 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,7 +39,7 @@ install: - conda info -a - conda create --yes -n test-environment python=$TRAVIS_PYTHON_VERSION numpy bitarray nose pyyaml coverage six flake8 - source activate test-environment - - pip install pyvisa pyvisa-sim coveralls cocotb==1.0.dev3 flake8-diff + - pip install pyvisa pyvisa-sim coveralls cocotb==1.2.0 flake8-diff # install basil - python setup.py develop From 8166d34f278b569127bd9772857cfcbbd52b6c7c Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Mon, 19 Aug 2019 15:16:41 +0200 Subject: [PATCH 35/41] MAINT: code cleanup --- basil/HL/MIO_PLL.py | 2 +- basil/HL/keithley_2410.yaml | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/basil/HL/MIO_PLL.py b/basil/HL/MIO_PLL.py index 7e7924324..519e111cc 100644 --- a/basil/HL/MIO_PLL.py +++ b/basil/HL/MIO_PLL.py @@ -176,7 +176,7 @@ def _calculateParameters(self, fout): fvco = self.fref * self.p_total / self.q_total logger.info('PLL frequency set to ' + str(ftest) + ' MHz' + ' (VCO @ ' + str(fvco) + ' MHz)') return True - logger.error('MIO_PLL: Could not find PLL parameters for '+ str(fout) + ' MHz)') + logger.error('MIO_PLL: Could not find PLL parameters for {}MHz'.format(fout)) return False def _updateRegisters(self): diff --git a/basil/HL/keithley_2410.yaml b/basil/HL/keithley_2410.yaml index e5cbb04a2..5c65b0cef 100644 --- a/basil/HL/keithley_2410.yaml +++ b/basil/HL/keithley_2410.yaml @@ -10,19 +10,18 @@ set_voltage : SOUR:VOLT get_voltage : MEAS:VOLT? set_current_limit : SENS:CURR:PROT get_current_limit : SENS:CURR:PROT? -set_voltage_limit : SENS:VOLT:PROT +set_voltage_limit : SENS:VOLT:PROT get_voltage_limit : SENS:VOLT:PROT? source_volt : SOUR:FUNC VOLT source_current : SOUR:FUNC CURR get_source_mode : SOUR:FUNC? set_current_autorange : SOUR:CURR:RANG:AUTO ON get_current_autorange : SOUR:CURR:RANG:AUTO? -set_voltage_range: SOUR:VOLT:RANGE +set_voltage_range: SOUR:VOLT:RANGE four_wire_on: SYST:RSEN ON four_wire_off: SYST:RSEN OFF get_remote_sense: SYST:RSEN? set_current_sense_range: SENS:CURR:RANGE get_current_sense_range: SENS:CURR:RANGE? get_reading: READ? -set_current_nlpc: SENS:CURR:NPLC - +set_current_nlpc: SENS:CURR:NPLC From 63cd90d113a7576533ab84914a3542682bc49b86 Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Wed, 21 Aug 2019 10:32:25 +0200 Subject: [PATCH 36/41] BUG: fix non-keyword after keyword argument --- examples/lab_devices/arduino.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/lab_devices/arduino.py b/examples/lab_devices/arduino.py index 1fcfe253f..80290cc7a 100644 --- a/examples/lab_devices/arduino.py +++ b/examples/lab_devices/arduino.py @@ -17,5 +17,5 @@ time.sleep(1) # Wait for Arduino to reset -dut['Arduino'].set_output(channel=13, 1) -dut['Arduino'].set_output(channel='ALL', 'OFF') +dut['Arduino'].set_output(channel=13, value=1) +dut['Arduino'].set_output(channel='ALL', value='OFF') From 37a32536a8c035cc40cebb2cff31477c65a14a79 Mon Sep 17 00:00:00 2001 From: DavidLP Date: Tue, 27 Aug 2019 11:24:19 +0200 Subject: [PATCH 37/41] MAINT: remove callable import warning --- basil/RL/RegisterLayer.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/basil/RL/RegisterLayer.py b/basil/RL/RegisterLayer.py index ec0340dbf..dbc10fbea 100644 --- a/basil/RL/RegisterLayer.py +++ b/basil/RL/RegisterLayer.py @@ -5,7 +5,10 @@ # ------------------------------------------------------------ # -from collections import Callable +try: + from collections.abc import Callable # noqa +except ImportError: + from collections import Callable # noqa from basil.dut import Base From b59b40eeed7c3efd42dc2aa10e591bba784190cf Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Tue, 10 Sep 2019 12:22:18 +0200 Subject: [PATCH 38/41] 2to3: logging cosmetics --- basil/TL/SiUsb.py | 2 +- basil/TL/SiUsb3.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/basil/TL/SiUsb.py b/basil/TL/SiUsb.py index 18c26a307..31cbdf0e5 100644 --- a/basil/TL/SiUsb.py +++ b/basil/TL/SiUsb.py @@ -44,7 +44,7 @@ def init(self): if not devices: raise IOError('Can\'t find USB board. Connect or reset USB board!') else: - logger.info('Found USB board(s): {}'.format(', '.join(('%s with ID %s (FW %s)' % (device.board_name, list(filter(type(device.board_id).isdigit, device.board_id)), list(filter(type(device.fw_version).isdigit, device.fw_version)))) for device in devices))) + logger.info('Found USB board(s): {}'.format(', '.join(('%s with ID %s (FW %s)' % (device.board_name, "".join(filter(str.isdigit, device.board_id)), "".join(filter(str.isdigit, device.fw_version)))) for device in devices))) if len(devices) > 1: raise ValueError('Please specify ID of USB board') self._sidev = devices[0] diff --git a/basil/TL/SiUsb3.py b/basil/TL/SiUsb3.py index 5befb08f1..47db86217 100644 --- a/basil/TL/SiUsb3.py +++ b/basil/TL/SiUsb3.py @@ -44,7 +44,7 @@ def init(self): if not devices: raise IOError('Can\'t find USB board. Connect or reset USB board!') else: - logger.info('Found USB board(s): {}'.format(', '.join(('%s with ID %s (FW %s)' % (device.board_name, list(filter(type(device.board_id).isdigit, device.board_id)), list(filter(type(device.fw_version).isdigit, device.fw_version)))) for device in devices))) + logger.info('Found USB board(s): {}'.format(', '.join(('%s with ID %s (FW %s)' % (device.board_name, "".join(filter(type(device.board_id).isdigit, device.board_id)), "".join(filter(type(device.fw_version).isdigit, device.fw_version)))) for device in devices))) if len(devices) > 1: raise ValueError('Please specify ID of USB board') self._sidev = devices[0] From fb126c22c49222e7329cb6dd2d5cb11953c65c62 Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Wed, 11 Sep 2019 09:09:45 +0200 Subject: [PATCH 39/41] 2to3: fix more decode issues --- basil/HL/FEI4AdapterCard.py | 2 +- basil/HL/FEI4QuadModuleAdapterCard.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/basil/HL/FEI4AdapterCard.py b/basil/HL/FEI4AdapterCard.py index 8926b4c14..7d21ae97b 100644 --- a/basil/HL/FEI4AdapterCard.py +++ b/basil/HL/FEI4AdapterCard.py @@ -336,7 +336,7 @@ def read_eeprom_calibration(self, temperature=False): # use default values for for idx, channel in enumerate(self._ch_cal.keys()): ch_data = data[idx * calcsize(self.CAL_DATA_CH_V1_FORMAT):(idx + 1) * calcsize(self.CAL_DATA_CH_V1_FORMAT)] values = unpack_from(self.CAL_DATA_CH_V1_FORMAT, ch_data) - self._ch_cal[channel]['name'] = "".join([c for c in values[0] if (c in string.printable)]) # values[0].strip() + self._ch_cal[channel]['name'] = "".join([c for c in values[0].decode('utf-8', errors='ignore') if (c in string.printable)]) # values[0].strip() self._ch_cal[channel]['default'] = values[1] self._ch_cal[channel]['ADCI']['gain'] = values[2] self._ch_cal[channel]['ADCI']['offset'] = values[3] diff --git a/basil/HL/FEI4QuadModuleAdapterCard.py b/basil/HL/FEI4QuadModuleAdapterCard.py index 327e9f2f3..2625b847a 100644 --- a/basil/HL/FEI4QuadModuleAdapterCard.py +++ b/basil/HL/FEI4QuadModuleAdapterCard.py @@ -170,7 +170,7 @@ def read_eeprom_calibration(self, temperature=False): # use default values for for idx, channel in enumerate(self._ch_cal.keys()): ch_data = data[idx * calcsize(self.CAL_DATA_CH_V2_FORMAT):(idx + 1) * calcsize(self.CAL_DATA_CH_V2_FORMAT)] values = unpack_from(self.CAL_DATA_CH_V2_FORMAT, ch_data) - self._ch_cal[channel]['name'] = "".join([c for c in values[0] if (c in string.printable)]) # values[0].strip() + self._ch_cal[channel]['name'] = "".join([c for c in values[0].decode('utf-8', errors='ignore') if (c in string.printable)]) # values[0].strip() self._ch_cal[channel]['default'] = values[1] self._ch_cal[channel]['ADCI']['gain'] = values[2] self._ch_cal[channel]['ADCI']['offset'] = values[3] From 124bd8ce507b2c85e87a93ac386c48602ada1296 Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Fri, 13 Sep 2019 10:29:18 +0200 Subject: [PATCH 40/41] MAINT: logging --- basil/HL/FEI4AdapterCard.py | 4 ++-- basil/HL/FEI4QuadModuleAdapterCard.py | 4 ++-- basil/HL/GPAC.py | 10 ++++------ 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/basil/HL/FEI4AdapterCard.py b/basil/HL/FEI4AdapterCard.py index 7d21ae97b..0966b6205 100644 --- a/basil/HL/FEI4AdapterCard.py +++ b/basil/HL/FEI4AdapterCard.py @@ -323,9 +323,9 @@ def init(self): # read calibration if not self._init['no_calibration']: self.read_eeprom_calibration() - logger.info('Found adapter card: {}'.format('%s with ID %s' % ('Single Chip Adapter Card', self.get_id()))) + logger.info('Found adapter card: {}'.format('%s with ID %s' % ('FEI4 Single Chip Adapter Card', self.get_id()))) else: - logger.info('FEI4AdapterCard: Using default calibration.') + logger.info('FEI4 Single Chip Adapter Card: skip reading calibration parameters from EEPROM') def read_eeprom_calibration(self, temperature=False): # use default values for temperature, EEPROM values are usually not calibrated and random '''Reading EEPROM calibration for power regulators and temperature diff --git a/basil/HL/FEI4QuadModuleAdapterCard.py b/basil/HL/FEI4QuadModuleAdapterCard.py index 2625b847a..a1ca1232a 100644 --- a/basil/HL/FEI4QuadModuleAdapterCard.py +++ b/basil/HL/FEI4QuadModuleAdapterCard.py @@ -152,9 +152,9 @@ def init(self): # read calibration if not self._init['no_calibration']: self.read_eeprom_calibration() - logger.info('Found adapter card: {}'.format('%s with ID %s' % ('Single Chip Adapter Card', self.get_id()))) + logger.info('Found adapter card: {} with ID {}'.format('FEI4 Quad Module Adapter Card', self.get_id())) else: - logger.info('FEI4QuadModuleAdapterCard: Using default calibration.') + logger.info('FEI4 Quad Module Adapter Card: skip reading calibration parameters from EEPROM') # setting up default current limit for ch_name in self._ch_cal.keys(): diff --git a/basil/HL/GPAC.py b/basil/HL/GPAC.py index bb05eab95..151a90c2a 100644 --- a/basil/HL/GPAC.py +++ b/basil/HL/GPAC.py @@ -102,12 +102,10 @@ def __init__(self, intf, conf): def init(self): self._intf.write(self._base_addr + self.PCA9554_ADD, (self.PCA9554_CFG, self.GPIO_CFG)) if self._init['no_power_reset'] is False: - logger.info("########GPAC ##########") - logger.info("########POWER RESET!!!!!##########") + logger.info("GPAC: power reset") self._intf.write(self._base_addr + self.PCA9554_ADD, (self.PCA9554_OUT, 0x00)) else: - logger.info("########GPAC #####") - logger.info("########SKIPPING POWER RESET #####") + logger.info("GPAC: skipping power reset") class AdcMuxGpio(GpioPca9554): @@ -716,9 +714,9 @@ def init(self): # read calibration if not self._init['no_calibration']: self.read_eeprom_calibration() - logger.info('Found adapter card: {}'.format('%s with ID %s' % ('General Purpose Analog Card', self.get_id()))) + logger.info('Found adapter card: {} with ID {}'.format('General Purpose Analog Card (GPAC)', self.get_id())) else: - logger.info('GPAC: Skeeping calibration.') + logger.info('General Purpose Analog Card (GPAC): skip reading calibration parameters from EEPROM') # setup current limit and current source self.set_current_limit('PWR0', 0.1) From a830c8da10f64b33c0b9de2e250576f2a114399d Mon Sep 17 00:00:00 2001 From: Jens Janssen Date: Tue, 17 Sep 2019 22:47:21 +0200 Subject: [PATCH 41/41] PRJ: prepare for release 3.0.1 --- README.rst | 42 ++++++++++++++++++++++-------------------- VERSION | 2 +- setup.py | 2 ++ 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/README.rst b/README.rst index ca9ad5263..3430993a4 100644 --- a/README.rst +++ b/README.rst @@ -20,10 +20,17 @@ Basil is a modular data acquisition system and system testing framework in Pytho It also provides generic FPGA firmware modules for different hardware platforms and drivers for wide range of lab appliances. -Documentation -============= - -Documentation can be found under: http://basil.rtfd.org +Features +======== +Firmware: + - very simple single master bus definition + - multiple basic modules (SPI, SEQ, GPIO, I2C, JTAG) + - multiple interfaces (UART, USB2, USB3, Ethernet) +Software: + - layer structure following hardware + - generation based on yaml file + - register abstract layer (RAL) + - simulator interface allows software test against simulated RTL (thanks to `cocotb `_) Installation ============ @@ -34,7 +41,7 @@ Clone the repository to get a copy of the source code (for developers): git clone https://github.com/SiLab-Bonn/basil.git cd basil - python setup.py develop + pip install -e . or install via PyPI into the Python's site-packages folder (for non-developers): @@ -42,7 +49,7 @@ or install via PyPI into the Python's site-packages folder (for non-developers): pip install basil_daq==version -where version is a version number (e.g., 3.0.0) +where version is a version number (e.g., 3.0.1) or install from git, when no PyPI package is available (for non-developers): @@ -50,26 +57,21 @@ or install from git, when no PyPI package is available (for non-developers): pip install git+https://github.com/SiLab-Bonn/basil.git@branch -where branch is a branch name or tag (e.g., master or v3.0.0). +where branch is a branch name or tag (e.g., master or v3.0.1). Check `.travis.yml <.travis.yml>`_ for installation/testing hints. Support ======= -Basil mailing list: `subscribe `_ +Please use GitHub's `issue tracker `_ for bug reports/feature requests/questions. -Features -============ -Firmware: - - very simple single master bus definition - - multiple basic modules (SPI, SEQ, GPIO, I2C, JTAG) - - multiple interfaces (UART, USB2, USB3, Ethernet) -Software: - - layer structure following hardware - - generation based on yaml file - - register abstract layer (RAL) - - simulator interface allows software test against simulated RTL (thanks to `cocotb `_) +*For CERN users*: Feel free to subscribe to the `basil mailing list `_ + +Documentation +============= + +Documentation can be found under: https://basil.rtfd.org Example Projects: ================= @@ -78,7 +80,7 @@ Example Projects: - `fe65_p2 `_ - DAQ for FE65P2 prototype License -============ +======= If not stated otherwise. diff --git a/VERSION b/VERSION index 763327302..cb2b00e4f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.0.1.dev0 +3.0.1 diff --git a/setup.py b/setup.py index f6de8671e..c7be83c1f 100644 --- a/setup.py +++ b/setup.py @@ -22,6 +22,7 @@ with open('requirements.txt') as f: install_requires = f.read().splitlines() + def package_files(directory): paths = [] for (fpath, directories, filenames) in walk(directory): @@ -29,6 +30,7 @@ def package_files(directory): paths.append(path.join('..', fpath, filename)) return paths + setup( name='basil_daq', version=version,