Skip to content

Commit 72527b5

Browse files
committed
PRJ: Merge branch 'development'
2 parents 9905248 + a830c8d commit 72527b5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1308
-930
lines changed

.travis.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,19 @@ install:
3737
- conda update --yes conda
3838
- conda update --yes --all
3939
- conda info -a
40-
- conda create --yes -n test-environment python=$TRAVIS_PYTHON_VERSION numpy bitarray nose pyyaml coverage six
40+
- conda create --yes -n test-environment python=$TRAVIS_PYTHON_VERSION numpy bitarray nose pyyaml coverage six flake8
4141
- source activate test-environment
42-
- pip install pyvisa pyvisa-sim coveralls cocotb==1.0.dev3
42+
- pip install pyvisa pyvisa-sim coveralls cocotb==1.2.0 flake8-diff
4343
# install basil
4444
- python setup.py develop
4545

4646
script:
4747
- nosetests --with-coverage --cover-package=basil tests/test_*.py examples/*/*/test_*.py
48+
- export BRANCH=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi)
49+
# Check code style flaws of changed lines
50+
- git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
51+
- git fetch
52+
- if [ "$BRANCH" == "development" ]; then flake8-diff origin/master; else flake8-diff origin/development; fi
4853

4954
after_success:
5055
- coveralls
@@ -57,4 +62,5 @@ deploy:
5762
on:
5863
tags: true
5964
repo: SiLab-Bonn/basil
65+
skip_existing: true
6066
distributions: sdist bdist_wheel

README.rst

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,17 @@ Basil is a modular data acquisition system and system testing framework in Pytho
2020

2121
It also provides generic FPGA firmware modules for different hardware platforms and drivers for wide range of lab appliances.
2222

23-
Documentation
24-
=============
25-
26-
Documentation can be found under: http://basil.rtfd.org
23+
Features
24+
========
25+
Firmware:
26+
- very simple single master bus definition
27+
- multiple basic modules (SPI, SEQ, GPIO, I2C, JTAG)
28+
- multiple interfaces (UART, USB2, USB3, Ethernet)
29+
Software:
30+
- layer structure following hardware
31+
- generation based on yaml file
32+
- register abstract layer (RAL)
33+
- simulator interface allows software test against simulated RTL (thanks to `cocotb <https://github.com/potentialventures/cocotb>`_)
2734

2835
Installation
2936
============
@@ -34,42 +41,37 @@ Clone the repository to get a copy of the source code (for developers):
3441
3542
git clone https://github.com/SiLab-Bonn/basil.git
3643
cd basil
37-
python setup.py develop
44+
pip install -e .
3845
3946
or install via PyPI into the Python's site-packages folder (for non-developers):
4047

4148
.. code-block:: bash
4249
4350
pip install basil_daq==version
4451
45-
where version is a version number (e.g., 3.0.0)
52+
where version is a version number (e.g., 3.0.1)
4653

4754
or install from git, when no PyPI package is available (for non-developers):
4855

4956
.. code-block:: bash
5057
5158
pip install git+https://github.com/SiLab-Bonn/basil.git@branch
5259
53-
where branch is a branch name or tag (e.g., master or v3.0.0).
60+
where branch is a branch name or tag (e.g., master or v3.0.1).
5461

5562
Check `.travis.yml <.travis.yml>`_ for installation/testing hints.
5663

5764
Support
5865
=======
5966

60-
Basil mailing list: `subscribe <https://e-groups.cern.ch/e-groups/EgroupsSubscription.do?egroupName=basil-devel>`_
67+
Please use GitHub's `issue tracker <https://github.com/SiLab-Bonn/basil/issues>`_ for bug reports/feature requests/questions.
6168

62-
Features
63-
============
64-
Firmware:
65-
- very simple single master bus definition
66-
- multiple basic modules (SPI, SEQ, GPIO, I2C, JTAG)
67-
- multiple interfaces (UART, USB2, USB3, Ethernet)
68-
Software:
69-
- layer structure following hardware
70-
- generation based on yaml file
71-
- register abstract layer (RAL)
72-
- simulator interface allows software test against simulated RTL (thanks to `cocotb <https://github.com/potentialventures/cocotb>`_)
69+
*For CERN users*: Feel free to subscribe to the `basil mailing list <https://e-groups.cern.ch/e-groups/EgroupsSubscription.do?egroupName=basil-devel>`_
70+
71+
Documentation
72+
=============
73+
74+
Documentation can be found under: https://basil.rtfd.org
7375

7476
Example Projects:
7577
=================
@@ -78,7 +80,7 @@ Example Projects:
7880
- `fe65_p2 <https://github.com/SiLab-Bonn/fe65_p2>`_ - DAQ for FE65P2 prototype
7981

8082
License
81-
============
83+
=======
8284

8385
If not stated otherwise.
8486

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.0.0
1+
3.0.1

basil/HL/Arduino.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def set_output(self, channel, value):
2929
channel = 99 # All channels are internally channel 99
3030

3131
if channel < 2 or (channel > 13 and channel != 99):
32-
raise ValueError('Arduino supports only 14 IOs and pins 0 and 1 are blocked by Serial communication. %d is out of range' % channel)
32+
raise ValueError('Arduino supports only 14 IOs and pins 0 and 1 are blocked by Serial communication. %d is out of range.' % channel)
3333

3434
self._intf.write('GPIO%d %d\r\n' % (channel, value))
3535

basil/HL/FEI4AdapterCard.py

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
from collections import OrderedDict
1212
from math import log
1313
import string
14-
import abc
1514

1615
from basil.HL.HardwareLayer import HardwareLayer
1716

@@ -115,15 +114,13 @@ def _read_eeprom(self, address, size):
115114
return data
116115

117116
def _write_eeprom(self, address, data):
118-
raise NotImplementedError()
117+
raise NotImplementedError("_write_eeprom() not implemented")
119118

120119

121120
class Fei4Dcs(object):
122121
'''FEI4AdapterCard interface
123122
'''
124123

125-
__metaclass__ = abc.ABCMeta
126-
127124
# EEPROM
128125
HEADER_ADDR = 0
129126
HEADER_FORMAT = '>H' # Version of EEPROM data
@@ -210,17 +207,14 @@ def get_id(self):
210207
ret = self._read_eeprom(self.ID_ADDR, size=calcsize(self.ID_FORMAT))
211208
return unpack_from(self.ID_FORMAT, ret)[0]
212209

213-
@abc.abstractmethod
214210
def _get_adc_value(self, channel):
215-
pass
211+
raise NotImplementedError("_get_adc_value() not implemented")
216212

217-
@abc.abstractmethod
218213
def _set_dac_value(self, channel, value):
219-
pass
214+
raise NotImplementedError("_set_dac_value() not implemented")
220215

221-
@abc.abstractmethod
222216
def _read_eeprom(self, address, size):
223-
pass
217+
raise NotImplementedError("_read_eeprom() not implemented")
224218

225219

226220
class FEI4AdapterCard(AdcMax1239, DacMax520, Eeprom24Lc128, Fei4Dcs):
@@ -329,20 +323,20 @@ def init(self):
329323
# read calibration
330324
if not self._init['no_calibration']:
331325
self.read_eeprom_calibration()
332-
logger.info('Found adapter card: {}'.format('%s with ID %s' % ('Single Chip Adapter Card', self.get_id())))
326+
logger.info('Found adapter card: {}'.format('%s with ID %s' % ('FEI4 Single Chip Adapter Card', self.get_id())))
333327
else:
334-
logger.info('FEI4AdapterCard: Using default calibration.')
328+
logger.info('FEI4 Single Chip Adapter Card: skip reading calibration parameters from EEPROM')
335329

336330
def read_eeprom_calibration(self, temperature=False): # use default values for temperature, EEPROM values are usually not calibrated and random
337331
'''Reading EEPROM calibration for power regulators and temperature
338332
'''
339333
header = self.get_format()
340334
if header == self.HEADER_V1:
341335
data = self._read_eeprom(self.CAL_DATA_ADDR, size=calcsize(self.CAL_DATA_V1_FORMAT))
342-
for idx, channel in enumerate(self._ch_cal.iterkeys()):
336+
for idx, channel in enumerate(self._ch_cal.keys()):
343337
ch_data = data[idx * calcsize(self.CAL_DATA_CH_V1_FORMAT):(idx + 1) * calcsize(self.CAL_DATA_CH_V1_FORMAT)]
344338
values = unpack_from(self.CAL_DATA_CH_V1_FORMAT, ch_data)
345-
self._ch_cal[channel]['name'] = "".join([c for c in values[0] if (c in string.printable)]) # values[0].strip()
339+
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()
346340
self._ch_cal[channel]['default'] = values[1]
347341
self._ch_cal[channel]['ADCI']['gain'] = values[2]
348342
self._ch_cal[channel]['ADCI']['offset'] = values[3]
@@ -389,7 +383,7 @@ def get_temperature(self, channel, sensor='VNTC'):
389383
kwargs = self._ch_map[channel][sensor]
390384
temp_raw = self._get_adc_value(**kwargs)
391385

392-
v_adc = ((temp_raw - self._ch_cal.items()[0][1]['ADCV']['offset']) / self._ch_cal.items()[0][1]['ADCV']['gain']) # voltage, VDDA1
386+
v_adc = ((temp_raw - list(self._ch_cal.items())[0][1]['ADCV']['offset']) / list(self._ch_cal.items())[0][1]['ADCV']['gain']) # voltage, VDDA1
393387
k = self._ch_cal[channel][sensor]['R4'] / (self._ch_cal[channel][sensor]['R2'] + self._ch_cal[channel][sensor]['R4']) # reference voltage divider
394388
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
395389

basil/HL/FEI4QuadModuleAdapterCard.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -152,12 +152,12 @@ def init(self):
152152
# read calibration
153153
if not self._init['no_calibration']:
154154
self.read_eeprom_calibration()
155-
logger.info('Found adapter card: {}'.format('%s with ID %s' % ('Single Chip Adapter Card', self.get_id())))
155+
logger.info('Found adapter card: {} with ID {}'.format('FEI4 Quad Module Adapter Card', self.get_id()))
156156
else:
157-
logger.info('FEI4QuadModuleAdapterCard: Using default calibration.')
157+
logger.info('FEI4 Quad Module Adapter Card: skip reading calibration parameters from EEPROM')
158158

159159
# setting up default current limit
160-
for ch_name in self._ch_cal.iterkeys():
160+
for ch_name in self._ch_cal.keys():
161161
self.set_current_limit(ch_name, 1.0)
162162
logger.info('Found adapter card: {}'.format('%s with ID %s' % ('Quad Module Adapter Card', self.get_id())))
163163

@@ -167,10 +167,10 @@ def read_eeprom_calibration(self, temperature=False): # use default values for
167167
header = self.get_format()
168168
if header == self.HEADER_V2:
169169
data = self._read_eeprom(self.CAL_DATA_ADDR, size=calcsize(self.CAL_DATA_V2_FORMAT))
170-
for idx, channel in enumerate(self._ch_cal.iterkeys()):
170+
for idx, channel in enumerate(self._ch_cal.keys()):
171171
ch_data = data[idx * calcsize(self.CAL_DATA_CH_V2_FORMAT):(idx + 1) * calcsize(self.CAL_DATA_CH_V2_FORMAT)]
172172
values = unpack_from(self.CAL_DATA_CH_V2_FORMAT, ch_data)
173-
self._ch_cal[channel]['name'] = "".join([c for c in values[0] if (c in string.printable)]) # values[0].strip()
173+
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()
174174
self._ch_cal[channel]['default'] = values[1]
175175
self._ch_cal[channel]['ADCI']['gain'] = values[2]
176176
self._ch_cal[channel]['ADCI']['offset'] = values[3]

basil/HL/GPAC.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from basil.HL.HardwareLayer import HardwareLayer
1616
from basil.HL.FEI4AdapterCard import Eeprom24Lc128
1717

18+
1819
logger = logging.getLogger(__name__)
1920

2021

@@ -96,6 +97,15 @@ def __init__(self, intf, conf):
9697
super(PowerGpio, self).__init__(intf, conf)
9798
self.PCA9554_ADD = self.POWER_GPIO_ADD
9899
self.GPIO_CFG = self.POWER_GPIO_CFG
100+
self._init.setdefault('no_power_reset', False)
101+
102+
def init(self):
103+
self._intf.write(self._base_addr + self.PCA9554_ADD, (self.PCA9554_CFG, self.GPIO_CFG))
104+
if self._init['no_power_reset'] is False:
105+
logger.info("GPAC: power reset")
106+
self._intf.write(self._base_addr + self.PCA9554_ADD, (self.PCA9554_OUT, 0x00))
107+
else:
108+
logger.info("GPAC: skipping power reset")
99109

100110

101111
class AdcMuxGpio(GpioPca9554):
@@ -704,9 +714,9 @@ def init(self):
704714
# read calibration
705715
if not self._init['no_calibration']:
706716
self.read_eeprom_calibration()
707-
logger.info('Found adapter card: {}'.format('%s with ID %s' % ('General Purpose Analog Card', self.get_id())))
717+
logger.info('Found adapter card: {} with ID {}'.format('General Purpose Analog Card (GPAC)', self.get_id()))
708718
else:
709-
logger.info('GPAC: Skeeping calibration.')
719+
logger.info('General Purpose Analog Card (GPAC): skip reading calibration parameters from EEPROM')
710720

711721
# setup current limit and current source
712722
self.set_current_limit('PWR0', 0.1)
@@ -719,10 +729,10 @@ def read_eeprom_calibration(self): # use default values for temperature, EEPROM
719729
header = self.get_format()
720730
if header == self.HEADER_GPAC:
721731
data = self._read_eeprom(self.CAL_DATA_ADDR, size=calcsize(self.CAL_DATA_GPAC_FORMAT))
722-
for idx, channel in enumerate(self._ch_cal.iterkeys()):
732+
for idx, channel in enumerate(self._ch_cal.keys()):
723733
ch_data = data[idx * calcsize(self.CAL_DATA_CH_GPAC_FORMAT):(idx + 1) * calcsize(self.CAL_DATA_CH_GPAC_FORMAT)]
724734
values = unpack_from(self.CAL_DATA_CH_GPAC_FORMAT, ch_data)
725-
self._ch_cal[channel]['name'] = "".join([c for c in values[0] if (c in string.printable)]) # values[0].strip()
735+
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()
726736
self._ch_cal[channel]['default'] = values[1]
727737
self._ch_cal[channel]['min'] = values[2]
728738
self._ch_cal[channel]['max'] = values[3]

basil/HL/HardwareLayer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def __init__(self, intf, conf):
2121

2222
@property
2323
def is_ready(self):
24-
raise NotImplementedError
24+
raise NotImplementedError("is_ready() not implemented")
2525

2626
def wait_for_ready(self, timeout=None, times=None, delay=None, delay_between=None, abort=None):
2727
'''Determine the ready state of the device and wait until device is ready.

basil/HL/JtagGpio.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,7 @@
1111
from basil.utils.BitLogic import BitLogic
1212

1313

14-
class JtagGpio(HardwareLayer):
15-
'''GPIO based JTAG interface
16-
'''
17-
jtag_gpio_yaml = """
14+
jtag_gpio_yaml = """
1815
name : GPIO
1916
type : StdRegister
2017
driver : None
@@ -37,10 +34,15 @@ class JtagGpio(HardwareLayer):
3734
offset : 4
3835
"""
3936

37+
38+
class JtagGpio(HardwareLayer):
39+
'''GPIO based JTAG interface
40+
'''
41+
4042
def __init__(self, intf, conf):
4143
super(JtagGpio, self).__init__(intf, conf)
4244

43-
cfg = yaml.load(self.jtag_gpio_yaml)
45+
cfg = yaml.safe_load(jtag_gpio_yaml)
4446
self.reg = StdRegister(driver=None, conf=cfg)
4547

4648
# self.RESETB = 0

basil/HL/MIO_PLL.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,8 @@ def _calculateParameters(self, fout):
129129
break
130130
for self.div in range(2, 128):
131131
q_d_f = self.q_total * self.div * fout
132-
if isinstance(q_d_f, six.integer_types) and q_d_f > (15 * self.fref): # = f0 * p
133-
if int(q_d_f) % int(self.fref) == 0: # p, q, and d found
132+
if float(q_d_f).is_integer() and q_d_f > (15 * self.fref): # = f0 * p
133+
if (int(q_d_f) % int(self.fref)) == 0: # p, q, and d found
134134
self.p_total = q_d_f / self.fref
135135
while self.p_total <= 16: # counter constraint
136136
self.p_total = self.p_total * 2
@@ -176,7 +176,7 @@ def _calculateParameters(self, fout):
176176
fvco = self.fref * self.p_total / self.q_total
177177
logger.info('PLL frequency set to ' + str(ftest) + ' MHz' + ' (VCO @ ' + str(fvco) + ' MHz)')
178178
return True
179-
logger.error('MIO_PLL: Could not find PLL parameters')
179+
logger.error('MIO_PLL: Could not find PLL parameters for {}MHz'.format(fout))
180180
return False
181181

182182
def _updateRegisters(self):

0 commit comments

Comments
 (0)