Skip to content

Commit

Permalink
PRJ: Merge branch 'development'
Browse files Browse the repository at this point in the history
  • Loading branch information
laborleben committed Sep 17, 2019
2 parents 9905248 + a830c8d commit 72527b5
Show file tree
Hide file tree
Showing 55 changed files with 1,308 additions and 930 deletions.
10 changes: 8 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,19 @@ 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.2.0 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)
# 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
Expand All @@ -57,4 +62,5 @@ deploy:
on:
tags: true
repo: SiLab-Bonn/basil
skip_existing: true
distributions: sdist bdist_wheel
42 changes: 22 additions & 20 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <https://github.com/potentialventures/cocotb>`_)

Installation
============
Expand All @@ -34,42 +41,37 @@ 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):

.. code-block:: bash
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):

.. code-block:: bash
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 <https://e-groups.cern.ch/e-groups/EgroupsSubscription.do?egroupName=basil-devel>`_
Please use GitHub's `issue tracker <https://github.com/SiLab-Bonn/basil/issues>`_ 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 <https://github.com/potentialventures/cocotb>`_)
*For CERN users*: Feel free to subscribe to the `basil mailing list <https://e-groups.cern.ch/e-groups/EgroupsSubscription.do?egroupName=basil-devel>`_

Documentation
=============

Documentation can be found under: https://basil.rtfd.org

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

License
============
=======

If not stated otherwise.

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.0.0
3.0.1
2 changes: 1 addition & 1 deletion basil/HL/Arduino.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))

Expand Down
24 changes: 9 additions & 15 deletions basil/HL/FEI4AdapterCard.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
from collections import OrderedDict
from math import log
import string
import abc

from basil.HL.HardwareLayer import HardwareLayer

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -329,20 +323,20 @@ 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
'''
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()
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]
Expand Down Expand Up @@ -389,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

Expand Down
10 changes: 5 additions & 5 deletions basil/HL/FEI4QuadModuleAdapterCard.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,12 +152,12 @@ 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.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())))

Expand All @@ -167,10 +167,10 @@ 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()
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]
Expand Down
18 changes: 14 additions & 4 deletions basil/HL/GPAC.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from basil.HL.HardwareLayer import HardwareLayer
from basil.HL.FEI4AdapterCard import Eeprom24Lc128


logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -96,6 +97,15 @@ 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'] is False:
logger.info("GPAC: power reset")
self._intf.write(self._base_addr + self.PCA9554_ADD, (self.PCA9554_OUT, 0x00))
else:
logger.info("GPAC: skipping power reset")


class AdcMuxGpio(GpioPca9554):
Expand Down Expand Up @@ -704,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)
Expand All @@ -719,10 +729,10 @@ 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()
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]
Expand Down
2 changes: 1 addition & 1 deletion basil/HL/HardwareLayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
12 changes: 7 additions & 5 deletions basil/HL/JtagGpio.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.load(self.jtag_gpio_yaml)
cfg = yaml.safe_load(jtag_gpio_yaml)
self.reg = StdRegister(driver=None, conf=cfg)

# self.RESETB = 0
Expand Down
6 changes: 3 additions & 3 deletions basil/HL/MIO_PLL.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {}MHz'.format(fout))
return False

def _updateRegisters(self):
Expand Down

0 comments on commit 72527b5

Please sign in to comment.