Dev/ctb clocks fix (#1434)
Build on RHEL9 docker image / build (push) Failing after 5m6s
Build on RHEL8 docker image / build (push) Failing after 5m12s
Run Simulator Tests on local RHEL9 / build (push) Successful in 17m57s
Run Simulator Tests on local RHEL8 / build (push) Successful in 20m26s

* introduced new type Hz, typetraits, String conversions, command generation (not yet generated)

* incorrect unit typo

* cmd generation and compiles

* default to MHz, removed space between units for consistency with timers, min and max checks for clks

* in python, but need to change the default to Hz again for clean code and intuition

* allow ints, doubles, implicit conversions

* dont allow raw ints, doubles and implicit conversions

* fixed tests

* added operators for Hz in python

* fix test for min clk for xilinx ctb

* fix test

* fix python tests

* fixed xilinx period and default clks

* test fix

* removed the 3 clock cycle check for ctb and implemented properly the max adc clk frq for altera ctb

* removing 3 clock cycle code from xilinx as well

* formatting

* loadpattern before 3 clk cycles code

* actualtime and measurement time to be implemented in 100ns already in fw

* fix tests

* pyzmq dependency forthe tests

* fixed pyctbgui for freq
This commit is contained in:
2026-04-23 17:27:13 +02:00
committed by GitHub
parent d1106fec41
commit 8ff128b062
42 changed files with 1573 additions and 625 deletions
@@ -34,6 +34,7 @@ jobs:
python3.12 -m pip install pytest
python3.12 -m pip install colorama
python3.12 -m pip install numpy
python3.12 -m pip install pyzmq
- name: Python unit tests
working-directory: ${{gitea.workspace}}
@@ -32,6 +32,7 @@ jobs:
python3.12 -m pip install pytest
python3.12 -m pip install colorama
python3.12 -m pip install numpy
python3.12 -m pip install pyzmq
- name: Python unit tests
working-directory: ${{gitea.workspace}}
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
with:
python-version: 3.12
cache: 'pip'
- run: pip install pytest numpy colorama
- run: pip install pytest numpy colorama pyzmq
- uses: awalsh128/cache-apt-pkgs-action@latest
with:
+48 -34
View File
@@ -7,7 +7,7 @@ import zmq
from PyQt5 import QtWidgets, uic
import logging
from slsdet import readoutMode, runStatus, detectorType
from slsdet import readoutMode, runStatus, detectorType, Hz, MHz, kHz
from pyctbgui.utils.defines import Defines
from pyctbgui.utils.numpyWriter.npy_writer import NumpyFileManager
from pyctbgui.utils.numpyWriter.npz_writer import NpzFileWriter
@@ -68,8 +68,11 @@ class AcquisitionTab(QtWidgets.QWidget):
if self.det.type in [detectorType.CHIPTESTBOARD, detectorType.XILINX_CHIPTESTBOARD]:
self.view.spinBoxRunF.editingFinished.connect(self.setRunFrequency)
self.view.comboBoxRunF.currentIndexChanged.connect(self.setRunFrequency)
self.view.spinBoxADCF.editingFinished.connect(self.setADCFrequency)
self.view.comboBoxADCF.currentIndexChanged.connect(self.setADCFrequency)
self.view.spinBoxDBITF.editingFinished.connect(self.setDBITFrequency)
self.view.comboBoxDBITF.currentIndexChanged.connect(self.setDBITFrequency)
if self.det.type == detectorType.CHIPTESTBOARD:
self.view.spinBoxADCPhase.editingFinished.connect(self.setADCPhase)
self.view.spinBoxADCPipeline.editingFinished.connect(self.setADCPipeline)
@@ -189,20 +192,49 @@ class AcquisitionTab(QtWidgets.QWidget):
self.view.comboBoxROMode.currentIndexChanged.connect(self.setReadOut)
self.getReadout()
def _getFrequency(self, det_attr, spinbox, combobox, setter):
spinbox.editingFinished.disconnect()
combobox.currentIndexChanged.disconnect()
f = getattr(self.det, det_attr).value
if f < 1e3:
combobox.setCurrentIndex(2) #Hz
spinbox.setValue(f)
elif f < 1e6:
combobox.setCurrentIndex(1) #kHz
spinbox.setValue(f / 1e3)
else:
combobox.setCurrentIndex(0) #MHz
spinbox.setValue(f / 1e6)
spinbox.editingFinished.connect(setter)
combobox.currentIndexChanged.connect(setter)
def _setFrequency(self, det_attr, spinbox, combobox, title, getter):
value = spinbox.value()
idx = combobox.currentIndex()
if idx == 0:
val = MHz(value)
elif idx == 1:
val = kHz(value)
else:
val = Hz((int)(value))
try:
setattr(self.det, det_attr, val)
except Exception as e:
QtWidgets.QMessageBox.warning(self.mainWindow, title + " Fail", str(e), QtWidgets.QMessageBox.Ok)
getter()
def getRunFrequency(self):
self.view.spinBoxRunF.editingFinished.disconnect()
self.view.spinBoxRunF.setValue(self.det.runclk)
self.view.spinBoxRunF.editingFinished.connect(self.setRunFrequency)
self._getFrequency('runclk', self.view.spinBoxRunF, self.view.comboBoxRunF, self.setRunFrequency)
def setRunFrequency(self):
self.view.spinBoxRunF.editingFinished.disconnect()
try:
self.det.runclk = self.view.spinBoxRunF.value()
except Exception as e:
QtWidgets.QMessageBox.warning(self.mainWindow, "Run Frequency Fail", str(e), QtWidgets.QMessageBox.Ok)
# TODO: handling double event exceptions
self.view.spinBoxRunF.editingFinished.connect(self.setRunFrequency)
self.getRunFrequency()
self._setFrequency('runclk', self.view.spinBoxRunF, self.view.comboBoxRunF, "Run Frequency Fail", self.getRunFrequency)
def getTransceiver(self):
self.view.spinBoxTransceiver.editingFinished.disconnect()
@@ -254,19 +286,10 @@ class AcquisitionTab(QtWidgets.QWidget):
self.getDigital()
def getADCFrequency(self):
self.view.spinBoxADCF.editingFinished.disconnect()
self.view.spinBoxADCF.setValue(self.det.adcclk)
self.view.spinBoxADCF.editingFinished.connect(self.setADCFrequency)
self._getFrequency('adcclk', self.view.spinBoxADCF, self.view.comboBoxADCF, self.setADCFrequency)
def setADCFrequency(self):
self.view.spinBoxADCF.editingFinished.disconnect()
try:
self.det.adcclk = self.view.spinBoxADCF.value()
except Exception as e:
QtWidgets.QMessageBox.warning(self.mainWindow, "ADC Frequency Fail", str(e), QtWidgets.QMessageBox.Ok)
# TODO: handling double event exceptions
self.view.spinBoxADCF.editingFinished.connect(self.setADCFrequency)
self.getADCFrequency()
self._setFrequency('adcclk', self.view.spinBoxADCF, self.view.comboBoxADCF, "ADC Frequency Fail", self.getADCFrequency)
def getADCPhase(self):
self.view.spinBoxADCPhase.editingFinished.disconnect()
@@ -299,19 +322,10 @@ class AcquisitionTab(QtWidgets.QWidget):
self.getADCPipeline()
def getDBITFrequency(self):
self.view.spinBoxDBITF.editingFinished.disconnect()
self.view.spinBoxDBITF.setValue(self.det.dbitclk)
self.view.spinBoxDBITF.editingFinished.connect(self.setDBITFrequency)
self._getFrequency('dbitclk', self.view.spinBoxDBITF, self.view.comboBoxDBITF, self.setDBITFrequency)
def setDBITFrequency(self):
self.view.spinBoxDBITF.editingFinished.disconnect()
try:
self.det.dbitclk = self.view.spinBoxDBITF.value()
except Exception as e:
QtWidgets.QMessageBox.warning(self.mainWindow, "DBit Frequency Fail", str(e), QtWidgets.QMessageBox.Ok)
# TODO: handling double event exceptions
self.view.spinBoxDBITF.editingFinished.connect(self.setDBITFrequency)
self.getDBITFrequency()
self._setFrequency('dbitclk', self.view.spinBoxDBITF, self.view.comboBoxDBITF, "DBit Frequency Fail", self.getDBITFrequency)
def getDBITPhase(self):
self.view.spinBoxDBITPhase.editingFinished.disconnect()
+368 -253
View File
@@ -45,13 +45,13 @@
</property>
<property name="minimumSize">
<size>
<width>125</width>
<width>90</width>
<height>31</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>125</width>
<width>90</width>
<height>31</height>
</size>
</property>
@@ -61,24 +61,17 @@
<property name="buttonSymbols">
<enum>QAbstractSpinBox::UpDownArrows</enum>
</property>
<property name="decimals">
<number>6</number>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="maximum">
<double>1000.000000000000000</double>
<double>10000.000000000000000</double>
</property>
<property name="singleStep">
<double>1.000000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_398">
<property name="text">
<string>Read Out Mode: </string>
<double>0.000000000000000</double>
</property>
</widget>
</item>
@@ -123,13 +116,67 @@
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_398">
<property name="text">
<string>Read Out Mode: </string>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QLabel" name="labelRunF">
<property name="text">
<string>Run Clock Frequency (MHz):</string>
<string>Run Clock Frequency:</string>
</property>
</widget>
</item>
<item row="1" column="6">
<widget class="QComboBox" name="comboBoxRunF">
<property name="minimumSize">
<size>
<width>60</width>
<height>31</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>60</width>
<height>16777215</height>
</size>
</property>
<item>
<property name="text">
<string>MHz</string>
</property>
</item>
<item>
<property name="text">
<string>kHz</string>
</property>
</item>
<item>
<property name="text">
<string>Hz</string>
</property>
</item>
</widget>
</item>
<item row="1" column="3">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QFrame" name="frame_13">
@@ -223,16 +270,128 @@
<enum>QFrame::Sunken</enum>
</property>
<layout class="QGridLayout" name="gridLayout_6">
<item row="2" column="3">
<widget class="QLabel" name="labelDBITF">
<property name="minimumSize">
<item row="4" column="0">
<widget class="QLabel" name="labelADCPipeline">
<property name="text">
<string>ADC Pipeline:</string>
</property>
</widget>
</item>
<item row="2" column="4">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>200</width>
<height>0</height>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="5">
<widget class="QLabel" name="labelDBITPhase">
<property name="text">
<string>DBIT Clock Frequency (MHz):</string>
<string>DBIT Clock Phase (a.u.):</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="spinBoxADCF">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>90</width>
<height>31</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>90</width>
<height>31</height>
</size>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="maximum">
<double>10000.000000000000000</double>
</property>
<property name="singleStep">
<double>1.000000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelADCPhase">
<property name="text">
<string>ADC Clock Phase (a.u.):</string>
</property>
</widget>
</item>
<item row="4" column="5">
<widget class="QLabel" name="labelDBITPipeline">
<property name="text">
<string>DBIT Pipeline:</string>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QLabel" name="labelDigital">
<property name="text">
<string>Digital Samples:</string>
</property>
</widget>
</item>
<item row="2" column="6">
<widget class="QDoubleSpinBox" name="spinBoxDBITF">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>90</width>
<height>31</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>90</width>
<height>31</height>
</size>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="maximum">
<double>10000.000000000000000</double>
</property>
<property name="singleStep">
<double>1.000000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
</widget>
</item>
@@ -251,225 +410,7 @@
</size>
</property>
<property name="text">
<string>ADC Clock Frequency (MHz):</string>
</property>
</widget>
</item>
<item row="3" column="4">
<widget class="QSpinBox" name="spinBoxDBITPhase">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>125</width>
<height>31</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>125</width>
<height>31</height>
</size>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="maximum">
<number>9999</number>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QLabel" name="labelDBITPipeline">
<property name="text">
<string>DBIT Pipeline:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="spinBoxADCF">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>125</width>
<height>31</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>125</width>
<height>31</height>
</size>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="decimals">
<number>6</number>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="maximum">
<double>1000.000000000000000</double>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="spinBoxADCPipeline">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>125</width>
<height>31</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>125</width>
<height>31</height>
</size>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="labelADCPipeline">
<property name="text">
<string>ADC Pipeline:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelADCPhase">
<property name="text">
<string>ADC Clock Phase (a.u.):</string>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QLabel" name="labelDBITPhase">
<property name="text">
<string>DBIT Clock Phase (a.u.):</string>
</property>
</widget>
</item>
<item row="2" column="2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="4">
<widget class="QDoubleSpinBox" name="spinBoxDBITF">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>125</width>
<height>31</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>125</width>
<height>31</height>
</size>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="decimals">
<number>6</number>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="maximum">
<double>1000.000000000000000</double>
</property>
</widget>
</item>
<item row="4" column="4">
<widget class="QSpinBox" name="spinBoxDBITPipeline">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>125</width>
<height>31</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>125</width>
<height>31</height>
</size>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="spinBoxADCPhase">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>125</width>
<height>31</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>125</width>
<height>31</height>
</size>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="maximum">
<number>9999</number>
<string>ADC Clock Frequency:</string>
</property>
</widget>
</item>
@@ -480,7 +421,51 @@
</property>
</widget>
</item>
<item row="0" column="1">
<item row="2" column="5">
<widget class="QLabel" name="labelDBITF">
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>DBIT Clock Frequency:</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QComboBox" name="comboBoxADCF">
<property name="minimumSize">
<size>
<width>60</width>
<height>31</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>60</width>
<height>16777215</height>
</size>
</property>
<item>
<property name="text">
<string>MHz</string>
</property>
</item>
<item>
<property name="text">
<string>kHz</string>
</property>
</item>
<item>
<property name="text">
<string>Hz</string>
</property>
</item>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QSpinBox" name="spinBoxAnalog">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@@ -490,13 +475,13 @@
</property>
<property name="minimumSize">
<size>
<width>125</width>
<width>155</width>
<height>32</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>125</width>
<width>155</width>
<height>32</height>
</size>
</property>
@@ -511,14 +496,60 @@
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="labelDigital">
<property name="text">
<string>Digital Samples:</string>
<item row="3" column="1" colspan="2">
<widget class="QSpinBox" name="spinBoxADCPhase">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>155</width>
<height>31</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>155</width>
<height>31</height>
</size>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="maximum">
<number>9999</number>
</property>
</widget>
</item>
<item row="0" column="4">
<item row="4" column="1" colspan="2">
<widget class="QSpinBox" name="spinBoxADCPipeline">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>155</width>
<height>31</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>155</width>
<height>31</height>
</size>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="6" colspan="2">
<widget class="QSpinBox" name="spinBoxDigital">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@@ -528,13 +559,13 @@
</property>
<property name="minimumSize">
<size>
<width>125</width>
<width>155</width>
<height>32</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>125</width>
<width>155</width>
<height>32</height>
</size>
</property>
@@ -552,6 +583,90 @@
</property>
</widget>
</item>
<item row="3" column="6" colspan="2">
<widget class="QSpinBox" name="spinBoxDBITPhase">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>155</width>
<height>31</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>155</width>
<height>31</height>
</size>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="maximum">
<number>9999</number>
</property>
</widget>
</item>
<item row="4" column="6" colspan="2">
<widget class="QSpinBox" name="spinBoxDBITPipeline">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>155</width>
<height>31</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>155</width>
<height>31</height>
</size>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="7">
<widget class="QComboBox" name="comboBoxDBITF">
<property name="minimumSize">
<size>
<width>60</width>
<height>31</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>60</width>
<height>16777215</height>
</size>
</property>
<item>
<property name="text">
<string>MHz</string>
</property>
</item>
<item>
<property name="text">
<string>kHz</string>
</property>
</item>
<item>
<property name="text">
<string>Hz</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
<widget class="QFrame" name="frame_11">
+1
View File
@@ -13,6 +13,7 @@ pybind11_add_module(_slsdet
src/DurationWrapper.cpp
src/pedestal.cpp
src/bit.cpp
src/frequency.cpp
)
target_link_libraries(_slsdet PUBLIC
+3
View File
@@ -34,6 +34,9 @@ scanParameters = _slsdet.scanParameters
currentSrcParameters = _slsdet.currentSrcParameters
DurationWrapper = _slsdet.DurationWrapper
pedestalParameters = _slsdet.pedestalParameters
Hz = _slsdet.Hz
kHz = _slsdet.kHz
MHz = _slsdet.MHz
import os
def read_version():
+37 -38
View File
@@ -14,11 +14,12 @@ powerIndex = slsDetectorDefs.powerIndex
detectorType = slsDetectorDefs.detectorType
streamingInterface = slsDetectorDefs.streamingInterface
defs = slsDetectorDefs
from .utils import element_if_equal, all_equal, get_set_bits, list_to_bitmask
from .utils import Geometry, to_geo, element, reduce_time, is_iterable, hostname_list
from ._slsdet import xy, freeSharedMemory, getUserDetails
from ._slsdet import xy, Hz, freeSharedMemory, getUserDetails
from .gaincaps import Mythen3GainCapsWrapper
from . import utils as ut
from .proxy import JsonProxy, ClkDivProxy, MaxPhaseProxy, ClkFreqProxy, PatLoopProxy, PatNLoopProxy, PatWaitProxy, PatWaitTimeProxy
@@ -3441,22 +3442,21 @@ class Detector(CppDetectorApi):
@element
def runclk(self):
"""
[Ctb][Xilinx Ctb] Sets Run clock frequency in MHz. \n
Accepts decimal inputs
"""
[Ctb][Xilinx Ctb] Sets Run clock frequency.
freq_hz = element_if_equal(self.getRUNClock())
if isinstance(freq_hz, list):
return [value / 1e6 for value in freq_hz]
return freq_hz / 1e6
Example
--------
>>> d.runclk
>>> 10MHz
>>> d.runclk = MHz(5)
>>> d.runclk = Hz(5 * 1000 * 1000)
>>> d.runclk = kHz(2000)
"""
return self.getRUNClock()
@runclk.setter
def runclk(self, freq):
if isinstance(freq, dict):
freq_hz = {key: int(round(value * 1e6)) for key, value in freq.items()}
else:
freq_hz = int(round(freq * 1e6))
ut.set_using_dict(self.setRUNClock, freq_hz)
ut.set_using_dict(self.setRUNClock, freq)
@property
@element
@@ -3533,21 +3533,21 @@ class Detector(CppDetectorApi):
@element
def dbitclk(self):
"""
[Ctb][Xilinx Ctb] Sets clock for latching the digital bits in MHz. \n
Accepts decimal inputs
[Ctb][Xilinx Ctb] Sets clock for latching the digital bits.
Example
--------
>>> d.dbitclk
>>> 10MHz
>>> d.dbitclk = MHz(5)
>>> d.dbitclk = Hz(5 * 1000 * 1000)
>>> d.dbitclk = kHz(2000)
"""
freq_hz = element_if_equal(self.getDBITClock())
if isinstance(freq_hz, list):
return [value / 1e6 for value in freq_hz]
return freq_hz / 1e6
return self.getDBITClock()
@dbitclk.setter
def dbitclk(self, value):
if isinstance(value, dict):
value_hz = {key: int(round(item * 1e6)) for key, item in value.items()}
else:
value_hz = int(round(value * 1e6))
ut.set_using_dict(self.setDBITClock, value_hz)
ut.set_using_dict(self.setDBITClock, value)
@property
@element
@@ -3670,28 +3670,27 @@ class Detector(CppDetectorApi):
@element
def adcclk(self):
"""
[Ctb][Xilinx Ctb] Sets ADC clock frequency in MHz. \n
Accepts decimal inputs
"""
[Ctb][Xilinx Ctb] Sets ADC clock frequency.
freq_hz = element_if_equal(self.getADCClock())
if isinstance(freq_hz, list):
return [value / 1e6 for value in freq_hz]
return freq_hz / 1e6
Example
--------
>>> d.adcclk
>>> 10MHz
>>> d.adcclk = MHz(5)
>>> d.adcclk = Hz(5 * 1000 * 1000)
>>> d.adcclk = kHz(2000)
"""
return self.getADCClock()
@adcclk.setter
def adcclk(self, value):
if isinstance(value, dict):
value_hz = {key: int(round(item * 1e6)) for key, item in value.items()}
else:
value_hz = int(round(value * 1e6))
ut.set_using_dict(self.setADCClock, value_hz)
ut.set_using_dict(self.setADCClock, value)
@property
@element
def syncclk(self):
"""
[Ctb] Sync clock in MHz.
[Ctb] Sync clock.
:setter: Not implemented
"""
@@ -3724,7 +3723,7 @@ class Detector(CppDetectorApi):
[Ctb][Mythen3][Xilinx Ctb] Gets the pattern file name including path of the last pattern uploaded. Returns an empty if nothing was uploaded or via a server default
file
"""
return self.getPatterFileName()
return self.getPatternFileName()
def patternstart(self):
"""[Ctb][Mythen3][Xilinx Ctb] Starts pattern. """
+15 -15
View File
@@ -1529,23 +1529,31 @@ void init_det(py::module &m) {
Detector::setNumberOfAnalogSamples,
py::arg(), py::arg() = Positions{});
CppDetectorApi.def("getADCClock",
(Result<int>(Detector::*)(sls::Positions) const) &
(Result<defs::Hz>(Detector::*)(sls::Positions) const) &
Detector::getADCClock,
py::arg() = Positions{});
CppDetectorApi.def("setADCClock",
(void (Detector::*)(int, sls::Positions)) &
(void (Detector::*)(defs::Hz, sls::Positions)) &
Detector::setADCClock,
py::arg(), py::arg() = Positions{});
CppDetectorApi.def("getRUNClock",
(Result<int>(Detector::*)(sls::Positions) const) &
(Result<defs::Hz>(Detector::*)(sls::Positions) const) &
Detector::getRUNClock,
py::arg() = Positions{});
CppDetectorApi.def("setRUNClock",
(void (Detector::*)(int, sls::Positions)) &
(void (Detector::*)(defs::Hz, sls::Positions)) &
Detector::setRUNClock,
py::arg(), py::arg() = Positions{});
CppDetectorApi.def("getDBITClock",
(Result<defs::Hz>(Detector::*)(sls::Positions) const) &
Detector::getDBITClock,
py::arg() = Positions{});
CppDetectorApi.def("setDBITClock",
(void (Detector::*)(defs::Hz, sls::Positions)) &
Detector::setDBITClock,
py::arg(), py::arg() = Positions{});
CppDetectorApi.def("getSYNCClock",
(Result<int>(Detector::*)(sls::Positions) const) &
(Result<defs::Hz>(Detector::*)(sls::Positions) const) &
Detector::getSYNCClock,
py::arg() = Positions{});
CppDetectorApi.def("getPowerList",
@@ -1646,14 +1654,6 @@ void init_det(py::module &m) {
(void (Detector::*)(defs::readoutMode, sls::Positions)) &
Detector::setReadoutMode,
py::arg(), py::arg() = Positions{});
CppDetectorApi.def("getDBITClock",
(Result<int>(Detector::*)(sls::Positions) const) &
Detector::getDBITClock,
py::arg() = Positions{});
CppDetectorApi.def("setDBITClock",
(void (Detector::*)(int, sls::Positions)) &
Detector::setDBITClock,
py::arg(), py::arg() = Positions{});
CppDetectorApi.def("getExternalSamplingSource",
(Result<int>(Detector::*)(sls::Positions) const) &
Detector::getExternalSamplingSource,
@@ -1891,9 +1891,9 @@ void init_det(py::module &m) {
Detector::configureTransceiver,
py::arg() = Positions{});
CppDetectorApi.def(
"getPatterFileName",
"getPatternFileName",
(Result<std::string>(Detector::*)(sls::Positions) const) &
Detector::getPatterFileName,
Detector::getPatternFileName,
py::arg() = Positions{});
CppDetectorApi.def(
"setPattern",
+55
View File
@@ -0,0 +1,55 @@
// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
/*
This file contains Python bindings for the Hz and for conversion to other units from and to string.
*/
#include "py_headers.h"
#include <cmath>
#include "sls/ToString.h"
#include "sls/sls_detector_defs.h"
namespace py = pybind11;
constexpr double kHz = 1e3;
constexpr double MHz = 1e6;
void init_freq(py::module &m) {
py::class_<slsDetectorDefs::Hz> Hz(m, "Hz");
Hz.def(py::init<int>());
Hz.def_readwrite("value", &slsDetectorDefs::Hz::value);
Hz.def("__repr__", [](const slsDetectorDefs::Hz &f) {
return sls::ToString(f);
});
Hz.def("__str__", [](const slsDetectorDefs::Hz &f) {
return sls::ToString(f);
});
Hz.def(py::self == py::self);
Hz.def("__mul__", [](const slsDetectorDefs::Hz &h, int x) {
return slsDetectorDefs::Hz(h.value * x);
}, py::is_operator());
Hz.def("__rmul__", [](const slsDetectorDefs::Hz &h, int x) {
return slsDetectorDefs::Hz(h.value * x);
}, py::is_operator());
Hz.def("__truediv__", [](const slsDetectorDefs::Hz &h, int x) {
return slsDetectorDefs::Hz(h.value / x);
}, py::is_operator());
Hz.def("__add__", [](const slsDetectorDefs::Hz &a,
const slsDetectorDefs::Hz &b) {
return slsDetectorDefs::Hz(a.value + b.value);
}, py::is_operator());
Hz.def("__sub__", [](const slsDetectorDefs::Hz &a,
const slsDetectorDefs::Hz &b) {
return slsDetectorDefs::Hz(a.value - b.value);
}, py::is_operator());
m.def("kHz", [](double v) {
return slsDetectorDefs::Hz(static_cast<int>(std::round(v * kHz)));
});
m.def("MHz", [](double v) {
return slsDetectorDefs::Hz(static_cast<int>(std::round(v * MHz)));
});
}
+2
View File
@@ -21,6 +21,7 @@ void init_source(py::module &);
void init_duration(py::module &);
void init_pedestal(py::module &);
void init_bit(py::module &);
void init_freq(py::module &);
PYBIND11_MODULE(_slsdet, m) {
m.doc() = R"pbdoc(
@@ -42,6 +43,7 @@ PYBIND11_MODULE(_slsdet, m) {
init_duration(m);
init_pedestal(m);
init_bit(m);
init_freq(m);
// init_experimental(m);
py::module io = m.def_submodule("io", "Submodule for io");
+189 -1
View File
@@ -396,6 +396,193 @@ def test_patternstart(session_simulator, request):
Log(LogLevel.INFOGREEN, f"{request.node.name} passed")
@pytest.mark.detectorintegration
def test_runclk(session_simulator, request):
""" Test using runclk for ctb and xilinx_ctb."""
det_type, num_interfaces, num_mods, d = session_simulator
assert d is not None
from slsdet import Hz, MHz, kHz
if det_type in ['ctb', 'xilinx_ctb']:
prev_runclk = d.getRUNClock()
d.runclk
# invalid value type
with pytest.raises(Exception) as exc_info:
d.runclk = 5e6
with pytest.raises(Exception) as exc_info:
d.runclk = 5 * 1000 * 1000
with pytest.raises(Exception) as exc_info:
d.runclk = Hz(5e6)
d.runclk = MHz(15)
assert d.runclk.value == 15_000_000
d.runclk = MHz(14.5)
assert d.runclk.value == 14_500_000
d.runclk = kHz(15000.5)
assert d.runclk.value == 15_000_500
# invalid values from server
# max is 300MHz
with pytest.raises(Exception) as exc_info:
d.runclk = MHz(301)
# min is 2MHz for ctb and 10MHz for xilinx_ctb
if det_type == 'ctb':
with pytest.raises(Exception) as exc_info:
d.runclk = MHz(1)
else:
with pytest.raises(Exception) as exc_info:
d.runclk = MHz(9)
c = MHz(2)
for rc in [5, 10, 15, 20]:
d.runclk = rc * c
assert d.runclk.value == 40_000_000
for i in range(len(d)):
d.setRUNClock(prev_runclk[i], [i])
Log(LogLevel.INFOGREEN, f"{request.node.name} passed")
@pytest.mark.detectorintegration
def test_adcclk(session_simulator, request):
""" Test using adcclk for ctb and xilinx_ctb."""
det_type, num_interfaces, num_mods, d = session_simulator
assert d is not None
from slsdet import Hz, MHz, kHz
if det_type in ['ctb', 'xilinx_ctb']:
prev_adcclk = d.getADCClock()
d.adcclk
# invalid value type
with pytest.raises(Exception) as exc_info:
d.adcclk = 5e6
with pytest.raises(Exception) as exc_info:
d.adcclk = 5 * 1000 * 1000
with pytest.raises(Exception) as exc_info:
d.adcclk = Hz(5e6)
d.adcclk = MHz(15)
assert d.adcclk.value == 15_000_000
d.adcclk = MHz(14.5)
assert d.adcclk.value == 14_500_000
d.adcclk = kHz(15000.5)
assert d.adcclk.value == 15_000_500
# invalid values from server
# max is 300MHz for xilinx and 54 MHz for ctb
if det_type == 'ctb':
with pytest.raises(Exception) as exc_info:
d.adcclk = MHz(66)
else:
with pytest.raises(Exception) as exc_info:
d.adcclk = MHz(301)
# min is 2MHz for ctb and 10MHz for xilinx_ctb
if det_type == 'ctb':
with pytest.raises(Exception) as exc_info:
d.adcclk = MHz(1)
else:
with pytest.raises(Exception) as exc_info:
d.adcclk = MHz(9)
c = MHz(2)
for rc in [5, 10, 15, 20]:
d.adcclk = rc * c
assert d.adcclk.value == 40_000_000
for i in range(len(d)):
d.setADCClock(prev_adcclk[i], [i])
Log(LogLevel.INFOGREEN, f"{request.node.name} passed")
@pytest.mark.detectorintegration
def test_dbitclk(session_simulator, request):
""" Test using dbitclk for ctb and xilinx_ctb."""
det_type, num_interfaces, num_mods, d = session_simulator
assert d is not None
from slsdet import Hz, MHz, kHz
if det_type in ['ctb', 'xilinx_ctb']:
prev_dbitclk = d.getDBITClock()
d.dbitclk
# invalid value type
with pytest.raises(Exception) as exc_info:
d.dbitclk = 5e6
with pytest.raises(Exception) as exc_info:
d.dbitclk = 5 * 1000 * 1000
with pytest.raises(Exception) as exc_info:
d.dbitclk = Hz(5e6)
d.dbitclk = MHz(15)
assert d.dbitclk.value == 15_000_000
d.dbitclk = MHz(14.5)
assert d.dbitclk.value == 14_500_000
d.dbitclk = kHz(15000.5)
assert d.dbitclk.value == 15_000_500
# invalid values from server
# max is 300MHz
with pytest.raises(Exception) as exc_info:
d.dbitclk = MHz(301)
# min is 2MHz for ctb and 10MHz for xilinx_ctb
if det_type == 'ctb':
with pytest.raises(Exception) as exc_info:
d.dbitclk = MHz(1)
else:
with pytest.raises(Exception) as exc_info:
d.dbitclk = MHz(9)
c = MHz(2)
for rc in [5, 10, 15, 20]:
d.dbitclk = rc * c
assert d.dbitclk.value == 40_000_000
for i in range(len(d)):
d.setDBITClock(prev_dbitclk[i], [i])
Log(LogLevel.INFOGREEN, f"{request.node.name} passed")
@pytest.mark.detectorintegration
def test_syncclk(session_simulator, request):
""" Test using syncclk for ctb."""
det_type, num_interfaces, num_mods, d = session_simulator
assert d is not None
if det_type in ['ctb']:
d.syncclk
Log(LogLevel.INFOGREEN, f"{request.node.name} passed")
@pytest.mark.detectorintegration
def test_v_limit(session_simulator, request):
"""Test v_limit."""
@@ -450,7 +637,7 @@ def test_v_limit(session_simulator, request):
Log(LogLevel.INFOGREEN, f"{request.node.name} passed")
@pytest.mark.detectorintegration
def test_v_abcd(session_simulator, request):
"""Test v_a, v_b, v_c, v_d, v_io are deprecated comands."""
det_type, num_interfaces, num_mods, d = session_simulator
@@ -715,3 +902,4 @@ def test_dac(session_simulator, request):
Log(LogLevel.INFOGREEN, f"{request.node.name} passed")
+48
View File
@@ -0,0 +1,48 @@
from slsdet import Hz, MHz, kHz
def test_Hz():
f = Hz(1)
assert f.value == 1
f = Hz(1 * 1000)
assert f.value == 1000
f = MHz(5)
assert f.value == 5_000_000
f = MHz(0.5)
assert f.value == 500_000
f = kHz(2.5)
assert f.value == 2500
f = kHz(5000)
assert f.value == 5_000_000
def test_rounding_exact():
f = MHz(1.234)
assert f.value == round(1.234 * 1_000_000)
def test_mul():
c = MHz(1)
assert (c * 2).value == 2_000_000
assert (c * 4).value == 4_000_000
def test_rmul():
c = MHz(1)
assert (2 * c).value == 2_000_000
assert (4 * c).value == 4_000_000
c = c * 2
assert c.value == 2_000_000
for rc in [1, 2, 4, 8]:
c = rc * c
assert c.value == 128_000_000
def test_div():
c = MHz(1)
assert (c / 2).value == 500_000
def test_eq():
assert MHz(1) == MHz(1)
assert MHz(1) != MHz(2)
assert MHz(1) == kHz(1000)
@@ -14,6 +14,7 @@
#include "communication_funcs_UDP.h"
#include "loadPattern.h"
#include <math.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
@@ -66,7 +67,8 @@ uint8_t adcEnableMask_10g = 0xFF;
uint32_t transceiverMask = DEFAULT_TRANSCEIVER_MASK;
int32_t clkPhase[NUM_CLOCKS] = {};
uint32_t clkFrequency[NUM_CLOCKS] = {DEFAULT_RUN_CLK, DEFAULT_ADC_CLK, DEFAULT_SYNC_CLK, DEFAULT_DBIT_CLK};
uint32_t clkFrequency[NUM_CLOCKS] = {DEFAULT_RUN_CLK, DEFAULT_ADC_CLK,
DEFAULT_SYNC_CLK, DEFAULT_DBIT_CLK};
int dacValues[NDAC_ONLY] = {};
int powerValues[NPWR] = {}; // powerIndex (A->IO, Chip)
@@ -1148,12 +1150,8 @@ int getNumTransceiverSamples() { return ntSamples; }
int setExpTime(int64_t val) {
setPatternWaitInterval(0, val);
// Tolerance: three clock periods in ns.
int64_t retval = getExpTime();
int64_t toleranceNs = 3 * (1000000000 / clkFrequency[RUN_CLK]);
int64_t diff = val - retval;
if (diff < -toleranceNs || diff > toleranceNs) {
if (val != retval) {
return FAIL;
}
return OK;
@@ -1167,12 +1165,12 @@ int setPeriod(int64_t val) {
return FAIL;
}
LOG(logINFO, ("Setting period %lld ns\n", (long long int)val));
val *= (1E-3 * clkFrequency[SYNC_CLK]);
val *= (NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]);
set64BitReg(val, PERIOD_LSB_REG, PERIOD_MSB_REG);
// validate for tolerance
int64_t retval = getPeriod();
val /= (1E-3 * clkFrequency[SYNC_CLK]);
val /= (NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]);
if (val != retval) {
return FAIL;
}
@@ -1181,7 +1179,7 @@ int setPeriod(int64_t val) {
int64_t getPeriod() {
return get64BitReg(PERIOD_LSB_REG, PERIOD_MSB_REG) /
(1E-3 * clkFrequency[SYNC_CLK]);
(NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]);
}
int setDelayAfterTrigger(int64_t val) {
@@ -1191,12 +1189,12 @@ int setDelayAfterTrigger(int64_t val) {
return FAIL;
}
LOG(logINFO, ("Setting delay after trigger %lld ns\n", (long long int)val));
val *= (1E-3 * clkFrequency[SYNC_CLK]);
val *= (NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]);
set64BitReg(val, DELAY_LSB_REG, DELAY_MSB_REG);
// validate for tolerance
int64_t retval = getDelayAfterTrigger();
val /= (1E-3 * clkFrequency[SYNC_CLK]);
val /= (NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]);
if (val != retval) {
return FAIL;
}
@@ -1205,7 +1203,7 @@ int setDelayAfterTrigger(int64_t val) {
int64_t getDelayAfterTrigger() {
return get64BitReg(DELAY_LSB_REG, DELAY_MSB_REG) /
(1E-3 * clkFrequency[SYNC_CLK]);
(NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]);
}
int64_t getNumFramesLeft() {
@@ -1218,12 +1216,12 @@ int64_t getNumTriggersLeft() {
int64_t getDelayAfterTriggerLeft() {
return get64BitReg(DELAY_LEFT_LSB_REG, DELAY_LEFT_MSB_REG) /
(1E-3 * clkFrequency[SYNC_CLK]);
(NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]);
}
int64_t getPeriodLeft() {
return get64BitReg(PERIOD_LEFT_LSB_REG, PERIOD_LEFT_MSB_REG) /
(1E-3 * clkFrequency[SYNC_CLK]);
(NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]);
}
int64_t getFramesFromStart() {
@@ -1232,13 +1230,14 @@ int64_t getFramesFromStart() {
}
int64_t getActualTime() {
return get64BitReg(TIME_FROM_START_LSB_REG, TIME_FROM_START_MSB_REG) /
(1E-3 * CLK_FREQ);
// reg in unit of 100ns
return get64BitReg(TIME_FROM_START_LSB_REG, TIME_FROM_START_MSB_REG) * 100;
}
int64_t getMeasurementTime() {
return get64BitReg(START_FRAME_TIME_LSB_REG, START_FRAME_TIME_MSB_REG) /
(1E-3 * CLK_FREQ);
// reg in unit of 100ns
return get64BitReg(START_FRAME_TIME_LSB_REG, START_FRAME_TIME_MSB_REG) *
100;
}
/* parameters - settings */
@@ -2224,9 +2223,8 @@ int getMaxPhase(enum CLKINDEX ind) {
MAX_PHASE_SHIFTS_STEPS;
char *clock_names[] = {CLK_NAMES};
LOG(logDEBUG1,
("Max Phase Shift (%s): %d (Clock: %d MHz, VCO:%d Hz)\n",
clock_names[ind], ret, clkFrequency[ind], PLL_VCO_FREQ_HZ));
LOG(logDEBUG1, ("Max Phase Shift (%s): %d (Clock: %d MHz, VCO:%d Hz)\n",
clock_names[ind], ret, clkFrequency[ind], PLL_VCO_FREQ_HZ));
return ret;
}
@@ -2308,16 +2306,17 @@ int getFrequency(enum CLKINDEX ind) {
LOG(logERROR, ("Unknown clock index %d to get frequency\n", ind));
return -1;
}
#ifndef VIRTUAL
// get the measured frequency from the firmware
int measuredFreqHz = ALTERA_PLL_getFrequency(ind);
#ifndef VIRTUAL
// get the measured frequency from the firmware
int measuredFreqHz = ALTERA_PLL_getFrequency(ind);
// checking against 0 here ensures compatibility with old firmware, TODO: remove this check at some point
if (measuredFreqHz != 0) {
// Round to nearest MHz. (should we round at all ?)
clkFrequency[ind] = measuredFreqHz;
}
#endif VIRTUAL
// checking against 0 here ensures compatibility with old firmware, TODO:
// remove this check at some point
if (measuredFreqHz != 0) {
// Round to nearest MHz. (should we round at all ?)
clkFrequency[ind] = measuredFreqHz;
}
#endif
return clkFrequency[ind];
}
@@ -50,13 +50,16 @@
#define DEFAULT_VLIMIT (0)
#define DEFAULT_TIMING_MODE (AUTO_TIMING)
#define DEFAULT_TX_UDP_PORT (0x7e9a)
#define DEFAULT_RUN_CLK (80000000) // 80
#define DEFAULT_ADC_CLK (40000000) // 40
#define DEFAULT_SYNC_CLK (40000000) // 40
#define DEFAULT_DBIT_CLK (200000000)
#define NS_TO_CLK_CYCLE (1E-9) // ns to MHz
#define DEFAULT_RUN_CLK (80000000) // 80 MHz
#define DEFAULT_ADC_CLK (40000000) // 40 MHz
#define DEFAULT_SYNC_CLK (40000000) // 40 MHz
#define DEFAULT_DBIT_CLK (200000000) // 200 MHz
#define NS_TO_CLK_CYCLE (1E-9) // ns to MHz
#define DEFAULT_TRANSCEIVER_MASK (0x3)
#define MIN_CLK_FREQ (2000000) // 2 MHz
#define MAX_CLK_FREQ (300000000) // 300 MHz
#define MAX_TRANSCEIVER_MASK (0xF)
#define MAX_TRANSCEIVER_SAMPLES (0xFFFF)
@@ -95,8 +98,8 @@
#define BIT32_MSK (0xFFFFFFFF)
#define BIT16_MASK (0xFFFF)
#define MAXIMUM_ADC_CLK (65000000)
#define PLL_VCO_FREQ_HZ (800000000)
#define MAXIMUM_ADC_CLK (65000000) // 65 MHz
#define PLL_VCO_FREQ_HZ (800000000) // 800MHz
/* Struct Definitions */
typedef struct udp_header_struct {
@@ -328,12 +328,12 @@ int ALTERA_PLL_SetOutputFrequency(int clkIndex, int pllVCOFreqHz, int value) {
return (int)temp;
*/
#if defined(CHIPTESTBOARDD) && !defined(VIRTUAL)
// wait for firmware to measure the actual frequency
usleep(2 * 1000 * 1000);
value = ALTERA_PLL_getFrequency(clkIndex);
LOG(logDEBUG1, ("Frequency is %d\n", value));
#endif
#if defined(CHIPTESTBOARDD) && !defined(VIRTUAL)
// wait for firmware to measure the actual frequency
usleep(2 * 1000 * 1000);
value = ALTERA_PLL_getFrequency(clkIndex);
LOG(logDEBUG1, ("Frequency is %d\n", value));
#endif
return value;
}
@@ -307,9 +307,7 @@ uint64_t getPatternWaitInterval(int level) {
LOG(logERROR, ("runclk is 0. Cannot divide by 0. Returning -1.\n"));
return -1;
}
double conv = NS_TO_CLK_CYCLE * runclk;
uint64_t waitNs = (uint64_t)(numClocks / conv + 0.5);
return waitNs;
return (double)numClocks / (NS_TO_CLK_CYCLE * runclk);
}
int validate_setPatternWaitClocksAndInterval(char *message, int level,
@@ -5717,15 +5717,34 @@ int set_clock_frequency(int file_des) {
if (getFrequency(c) == val) {
LOG(logINFO, ("Same %s: %d %s\n", modeName, val, "Hz"));
} else {
} else if (val < MIN_CLK_FREQ || val > MAX_CLK_FREQ) {
ret = FAIL;
sprintf(mess,
"Cannot set frequency to %f MHz. Frequency outside "
"limits (%f - %f MHz)\n",
val / 1e6, MIN_CLK_FREQ / 1e6, MAX_CLK_FREQ / 1e6);
LOG(logERROR, (mess));
}
#ifdef CHIPTESTBOARDD
else if (ind == ADC_CLOCK && (val > MAXIMUM_ADC_CLK)) {
ret = FAIL;
sprintf(mess,
"Cannot set ADC clock frequency to %f MHz. Frequency "
"outside limits (<= %f MHz)\n",
val / 1e6, MAXIMUM_ADC_CLK / 1e6);
LOG(logERROR, (mess));
}
#endif
else {
int ret = setFrequency(c, val);
if (ret == FAIL) {
sprintf(mess, "Could not set %s to %d %s\n", modeName, val,"Hz");
sprintf(mess, "Could not set %s to %f MHz\n", modeName,
val / 1e6);
LOG(logERROR, (mess));
} else {
int retval = getFrequency(c);
LOG(logDEBUG1,
("retval %s: %d %s\n", modeName, retval, "Hz"));
("retval %s: %f MHz\n", modeName, retval / 1e6));
// both CTB's will give the actual frequency, which is not
// 100% identical to the set frequency
validate(&ret, mess, val, retval, modeName, DEC);
@@ -5781,8 +5800,8 @@ int get_clock_frequency(int file_des) {
if (ret == OK) {
retval = getFrequency(c);
char *clock_names[] = {CLK_NAMES};
LOG(logDEBUG1,
("retval %s clock (%d) frequency: %d %s\n", clock_names[c], (int)c, retval, "Hz"));
LOG(logDEBUG1, ("retval %s clock (%d) frequency: %d %s\n",
clock_names[c], (int)c, retval, "Hz"));
}
#endif
return Server_SendResult(file_des, INT32, &retval, sizeof(retval));
@@ -768,12 +768,8 @@ int getNumTransceiverSamples() {
int setExpTime(int64_t val) {
setPatternWaitInterval(0, val);
// Tolerance: three clock periods in ns.
int64_t retval = getExpTime();
int64_t toleranceNs = 3 * (1000000000 / clkFrequency[RUN_CLK]);
int64_t diff = val - retval;
if (diff < -toleranceNs || diff > toleranceNs) {
if (val != retval) {
return FAIL;
}
return OK;
@@ -851,13 +847,14 @@ int64_t getFramesFromStart() {
}
int64_t getActualTime() {
return getU64BitReg(TIME_FROM_START_OUT_REG_1, TIME_FROM_START_OUT_REG_2) /
(NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]);
// in unit of 100ns
return getU64BitReg(TIME_FROM_START_OUT_REG_1, TIME_FROM_START_OUT_REG_2) *
100;
}
int64_t getMeasurementTime() {
return getU64BitReg(FRAME_TIME_OUT_REG_1, FRAME_TIME_OUT_REG_2) /
(NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]);
// in unit of 100ns
return getU64BitReg(FRAME_TIME_OUT_REG_1, FRAME_TIME_OUT_REG_2) * 100;
}
/* parameters - dac, adc, hv */
@@ -158,8 +158,11 @@ typedef struct udp_header_struct {
enum CLKINDEX { RUN_CLK, ADC_CLK, SYNC_CLK, DBIT_CLK, NUM_CLOCKS };
#define CLK_NAMES "run", "adc", "sync", "dbit"
#define DEFAULT_RUN_CLK (20000) // 20 MHz
#define DEFAULT_ADC_CLK (100000) // 100 MHz
#define DEFAULT_SYNC_CLK (20000) // 20 MHz
#define DEFAULT_DBIT_CLK (100000) // 100 MHz
#define NS_TO_CLK_CYCLE (1E-9) // ns to Hz
#define DEFAULT_RUN_CLK (20000000) // 20 MHz
#define DEFAULT_ADC_CLK (100000000) // 100 MHz
#define DEFAULT_SYNC_CLK (20000000) // 20 MHz
#define DEFAULT_DBIT_CLK (100000000) // 100 MHz
#define NS_TO_CLK_CYCLE (1E-9) // ns to Hz
#define MIN_CLK_FREQ (10000000) // 10 MHz
#define MAX_CLK_FREQ (300000000) // 300 MHz
@@ -16,6 +16,7 @@ type_values = {
'special::mv': ["mv", "mV"],
"special::deg": ["deg"],
"special::time_unit": ["s", "ms", "us", "ns"],
"special::freq_unit": ["Hz", "kHz", "MHz"],
"special::hard": ["hard"],
"special::force-delete-normal-file": ["--force-delete-normal-file"],
"special::currentSourceFix": ["fix", "nofix"],
@@ -40,11 +41,11 @@ def get_types(arg_types):
#list of options with a command line call that fetches them
#TODO! Rename sls_detector_get
if "defs::dacIndex" in arg_types:
return "`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
return r"`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
elif "defs::detectorSettings" in arg_types:
return "`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
return r"`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
elif "defs::timingMode" in arg_types:
return "`sls_detector_get timinglist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
return r"`sls_detector_get timinglist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
return ret
@@ -96,10 +96,18 @@ return 0
}
__adcclk() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="Hz MHz kHz"
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN="Hz MHz kHz"
fi
fi
return 0
}
@@ -565,12 +573,12 @@ __dacname() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
@@ -611,10 +619,18 @@ return 0
}
__dbitclk() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="Hz MHz kHz"
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN="Hz MHz kHz"
fi
fi
return 0
}
@@ -648,21 +664,21 @@ __defaultdac() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "4" ]]; then
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
fi
return 0
@@ -671,13 +687,13 @@ __defaultpattern() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "4" ]]; then
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
fi
return 0
@@ -2120,10 +2136,18 @@ return 0
}
__runclk() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="Hz MHz kHz"
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN="Hz MHz kHz"
fi
fi
return 0
}
@@ -2408,7 +2432,7 @@ __scan() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
@@ -2461,7 +2485,7 @@ __settings() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
fi
return 0
@@ -2571,12 +2595,12 @@ __slowadcname() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
@@ -2680,6 +2704,16 @@ return 0
}
__syncclk() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="Hz MHz kHz"
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="Hz MHz kHz"
fi
fi
return 0
}
__temp_10ge() {
@@ -2773,13 +2807,13 @@ if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
if [[ "${cword}" == "4" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "5" ]]; then
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
fi
return 0
@@ -2791,13 +2825,13 @@ if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
if [[ "${cword}" == "4" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "5" ]]; then
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
fi
return 0
@@ -2806,7 +2840,7 @@ __timing() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="`sls_detector_get timinglist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get timinglist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
fi
return 0
@@ -20,10 +20,18 @@ return 0
}
__adcclk() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="Hz MHz kHz"
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN="Hz MHz kHz"
fi
fi
return 0
}
@@ -489,12 +497,12 @@ __dacname() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
@@ -535,10 +543,18 @@ return 0
}
__dbitclk() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="Hz MHz kHz"
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN="Hz MHz kHz"
fi
fi
return 0
}
@@ -572,21 +588,21 @@ __defaultdac() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "4" ]]; then
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
fi
return 0
@@ -595,13 +611,13 @@ __defaultpattern() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "4" ]]; then
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
fi
return 0
@@ -2044,10 +2060,18 @@ return 0
}
__runclk() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="Hz MHz kHz"
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN="Hz MHz kHz"
fi
fi
return 0
}
@@ -2332,7 +2356,7 @@ __scan() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
@@ -2385,7 +2409,7 @@ __settings() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
fi
return 0
@@ -2495,12 +2519,12 @@ __slowadcname() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get daclist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
@@ -2604,6 +2628,16 @@ return 0
}
__syncclk() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="Hz MHz kHz"
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="Hz MHz kHz"
fi
fi
return 0
}
__temp_10ge() {
@@ -2697,13 +2731,13 @@ if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
if [[ "${cword}" == "4" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "5" ]]; then
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
fi
return 0
@@ -2715,13 +2749,13 @@ if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
if [[ "${cword}" == "4" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "5" ]]; then
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get settingslist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
fi
return 0
@@ -2730,7 +2764,7 @@ __timing() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN="`sls_detector_get timinglist | sed -e 's/.*\[\(.*\)\].*/\1/' | sed 's/,//g'`"
FCN_RETURN="`sls_detector_get timinglist | sed -e 's/.*\[\(.*\)\].*/\\1/' | sed 's/,//g'`"
fi
fi
return 0
+89 -34
View File
@@ -2,6 +2,56 @@
# detectors: MYTHEN3
################# TEMPLATES #################
FREQ_COMMAND:
infer_action: true
help: ""
template: true
actions:
GET:
require_det_id: true
function: ''
args:
- argc: 0
output: [ OutString(t) ]
- argc: 1
arg_types: [ special::freq_unit ]
output: [ "OutString(t , args[0])" ]
PUT:
function: ''
require_det_id: true
input: [ converted_freq ]
input_types: [ defs::Hz ]
args:
- argc: 1
arg_types: [ std::string ]
separate_freq_units:
input: 'args[0]'
output: [ converted_freq, unit ]
output: [ 'args[0]' ]
- argc: 2
arg_types: [ int, special::freq_unit ]
convert_to_freq:
input: [ 'args[0]', 'args[1]' ]
output: converted_freq
output: [ 'args[0]', 'args[1]' ]
FREQ_GET_COMMAND:
infer_action: true
help: ""
template: true
actions:
GET:
require_det_id: true
function: ''
args:
- argc: 0
output: [ OutString(t) ]
- argc: 1
arg_types: [ special::freq_unit ]
output: [ "OutString(t , args[0])" ]
TIME_COMMAND:
infer_action: true
help: ""
@@ -401,6 +451,44 @@ CTB_GET_INDEX:
################# COMMANDS ##################################
################# FREQ_COMMAND #############
adcclk:
help: "[n_clk] [(optional unit) Hz(default)|kHz|MHz]\n\t[Ctb][Xilinx Ctb] ADC clock frequency."
inherit_actions: FREQ_COMMAND
actions:
GET:
function: getADCClock
PUT:
function: setADCClock
runclk:
help: "[n_clk] [(optional unit) Hz(default)|kHz|MHz]\n\t[Ctb][Xilinx Ctb] Run clock frequency."
inherit_actions: FREQ_COMMAND
actions:
GET:
function: getRUNClock
PUT:
function: setRUNClock
dbitclk:
help: "[n_clk] [(optional unit) Hz(default)|kHz|MHz]\n\t[Ctb][Xilinx Ctb] Clock for latching the digital bits."
inherit_actions: FREQ_COMMAND
actions:
GET:
function: getDBITClock
PUT:
function: setDBITClock
################# FREQ_GET_COMMAND #############
syncclk:
inherit_actions: FREQ_GET_COMMAND
help: "[n_clk] [(optional unit) Hz(default)|kHz|MHz]\n\t[Ctb] Sync clock."
actions:
GET:
function: getSYNCClock
################# TIME_COMMAND #############
period:
@@ -1243,23 +1331,6 @@ asamples:
PUT:
function: setNumberOfAnalogSamples
adcclk:
help: "[n_clk in MHz]\n\t[Ctb][xilinx Ctb] ADC clock frequency in MHz."
inherit_actions: INTEGER_COMMAND_VEC_ID
actions:
GET:
function: getADCClock
PUT:
function: setADCClock
runclk:
help: "[n_clk in MHz]\n\t[Ctb][xilinx Ctb] Run clock in MHz."
inherit_actions: INTEGER_COMMAND_VEC_ID
actions:
GET:
function: getRUNClock
PUT:
function: setRUNClock
dsamples:
help: "[n_value]\n\t[Ctb] Number of digital samples expected."
@@ -1289,15 +1360,6 @@ romode:
function: setReadoutMode
input_types: [ defs::readoutMode ]
dbitclk:
help: "[n_clk in MHz]\n\t[Ctb][xilinx Ctb] Clock for latching the digital bits in MHz."
inherit_actions: INTEGER_COMMAND_VEC_ID
actions:
GET:
function: getDBITClock
PUT:
function: setDBITClock
extsampling:
help: "[0, 1]\n\t[Ctb] Enable for external sampling signal for digital data to signal by extsampling src command. For advanced users only."
inherit_actions: INTEGER_COMMAND_VEC_ID
@@ -1912,19 +1974,12 @@ burstsl:
GET:
function: getNumberOfBurstsLeft
syncclk:
inherit_actions: GET_COMMAND
help: "[n_clk in MHz]\n\t[Ctb] Sync clock in MHz."
actions:
GET:
function: getSYNCClock
patfname:
inherit_actions: GET_COMMAND
help: "\n\t[Ctb][Mythen3][Xilinx Ctb] Gets the pattern file name including path of the last pattern uploaded. Returns an empty if nothing was uploaded or via a server default file"
actions:
GET:
function: getPatterFileName
function: getPatternFileName
lastclient:
inherit_actions: GET_COMMAND
@@ -50,7 +50,6 @@ class CommandParser:
if len(arg['input_types']) != len(arg['input']):
raise ValueError(f'Argument {arg} does not have the correct number of inputs')
if 'separate_time_units' in arg:
if arg['separate_time_units']['input'] == "":
raise ValueError(f'Argument {arg} does not have the correct number of inputs for separate_time_units')
if len(arg['separate_time_units']['output']) != 2:
@@ -60,6 +59,16 @@ class CommandParser:
raise ValueError(f'Argument {arg} does not have the correct number of inputs for convert_to_time')
if len(arg['convert_to_time']['output']) == "":
raise ValueError(f'Argument {arg} does not have the correct number of outputs for convert_to_time')
if 'separate_freq_units' in arg:
if arg['separate_freq_units']['input'] == "":
raise ValueError(f'Argument {arg} does not have the correct number of inputs for separate_freq_units')
if len(arg['separate_freq_units']['output']) != 2:
raise ValueError(f'Argument {arg} does not have the correct number of outputs for separate_freq_units')
if 'convert_to_freq' in arg:
if len(arg['convert_to_freq']['input']) != 2:
raise ValueError(f'Argument {arg} does not have the correct number of inputs for convert_to_freq')
if len(arg['convert_to_freq']['output']) == "":
raise ValueError(f'Argument {arg} does not have the correct number of outputs for convert_to_freq')
# if infer_action:
# if arg['argc'] in self.argc_set:
# raise ValueError(f'Argument {arg} has a duplicate argc')
@@ -142,6 +142,16 @@ class CodeGenerator:
if 'convert_to_time' in arg and arg['convert_to_time']:
self.write_line(f'auto {arg["convert_to_time"]["output"]} = '
f'StringTo < time::ns > ({", ".join(arg["convert_to_time"]["input"])});')
if 'separate_freq_units' in arg and arg['separate_freq_units']:
self.write_line(f'std::string tmp_freq({arg["separate_freq_units"]["input"]});')
self.write_line(f'std::string {arg["separate_freq_units"]["output"][1]}'
f' = RemoveUnit(tmp_freq);')
self.write_line(f'auto {arg["separate_freq_units"]["output"][0]} = '
f'StringTo < defs::Hz > (tmp_freq,'
f' {arg["separate_freq_units"]["output"][1]});')
if 'convert_to_freq' in arg and arg['convert_to_freq']:
self.write_line(f'auto {arg["convert_to_freq"]["output"]} = '
f'StringTo < defs::Hz > ({", ".join(arg["convert_to_freq"]["input"])});')
input_arguments = []
if 'exceptions' in arg:
for exception in arg['exceptions']:
@@ -86,27 +86,69 @@ adcclk:
- OutString(t)
require_det_id: true
store_result_in_t: true
- arg_types:
- special::freq_unit
argc: 1
cast_input: []
check_det_id: false
convert_det_id: true
function: getADCClock
input: []
input_types: []
output:
- OutString(t , args[0])
require_det_id: true
store_result_in_t: true
PUT:
args:
- arg_types:
- int
- std::string
argc: 1
cast_input:
- true
- false
check_det_id: false
convert_det_id: true
function: setADCClock
input:
- args[0]
- converted_freq
input_types:
- int
- defs::Hz
output:
- args.front()
- args[0]
require_det_id: true
separate_freq_units:
input: args[0]
output:
- converted_freq
- unit
store_result_in_t: false
- arg_types:
- int
- special::freq_unit
argc: 2
cast_input:
- false
check_det_id: false
convert_det_id: true
convert_to_freq:
input:
- args[0]
- args[1]
output: converted_freq
function: setADCClock
input:
- converted_freq
input_types:
- defs::Hz
output:
- args[0]
- args[1]
require_det_id: true
store_result_in_t: false
command_name: adcclk
function_alias: adcclk
help: "[n_clk in MHz]\n\t[Ctb][xilinx Ctb] ADC clock frequency in MHz."
help: "[n_clk] [(optional unit) Hz(default)|kHz|MHz]\n\t[Ctb][Xilinx Ctb] ADC clock\
\ frequency."
infer_action: true
template: true
adcenable:
@@ -2059,27 +2101,69 @@ dbitclk:
- OutString(t)
require_det_id: true
store_result_in_t: true
- arg_types:
- special::freq_unit
argc: 1
cast_input: []
check_det_id: false
convert_det_id: true
function: getDBITClock
input: []
input_types: []
output:
- OutString(t , args[0])
require_det_id: true
store_result_in_t: true
PUT:
args:
- arg_types:
- int
- std::string
argc: 1
cast_input:
- true
- false
check_det_id: false
convert_det_id: true
function: setDBITClock
input:
- args[0]
- converted_freq
input_types:
- int
- defs::Hz
output:
- args.front()
- args[0]
require_det_id: true
separate_freq_units:
input: args[0]
output:
- converted_freq
- unit
store_result_in_t: false
- arg_types:
- int
- special::freq_unit
argc: 2
cast_input:
- false
check_det_id: false
convert_det_id: true
convert_to_freq:
input:
- args[0]
- args[1]
output: converted_freq
function: setDBITClock
input:
- converted_freq
input_types:
- defs::Hz
output:
- args[0]
- args[1]
require_det_id: true
store_result_in_t: false
command_name: dbitclk
function_alias: dbitclk
help: "[n_clk in MHz]\n\t[Ctb][xilinx Ctb] Clock for latching the digital bits in MHz."
help: "[n_clk] [(optional unit) Hz(default)|kHz|MHz]\n\t[Ctb][Xilinx Ctb] Clock\
\ for latching the digital bits."
infer_action: true
template: true
dbitphase:
@@ -5786,7 +5870,7 @@ patfname:
cast_input: []
check_det_id: false
convert_det_id: true
function: getPatterFileName
function: getPatternFileName
input: []
input_types: []
output:
@@ -8138,27 +8222,69 @@ runclk:
- OutString(t)
require_det_id: true
store_result_in_t: true
- arg_types:
- special::freq_unit
argc: 1
cast_input: []
check_det_id: false
convert_det_id: true
function: getRUNClock
input: []
input_types: []
output:
- OutString(t , args[0])
require_det_id: true
store_result_in_t: true
PUT:
args:
- arg_types:
- int
- std::string
argc: 1
cast_input:
- true
- false
check_det_id: false
convert_det_id: true
function: setRUNClock
input:
- args[0]
- converted_freq
input_types:
- int
- defs::Hz
output:
- args.front()
- args[0]
require_det_id: true
separate_freq_units:
input: args[0]
output:
- converted_freq
- unit
store_result_in_t: false
- arg_types:
- int
- special::freq_unit
argc: 2
cast_input:
- false
check_det_id: false
convert_det_id: true
convert_to_freq:
input:
- args[0]
- args[1]
output: converted_freq
function: setRUNClock
input:
- converted_freq
input_types:
- defs::Hz
output:
- args[0]
- args[1]
require_det_id: true
store_result_in_t: false
command_name: runclk
function_alias: runclk
help: "[n_clk in MHz]\n\t[Ctb][xilinx Ctb] Run clock in MHz."
help: "[n_clk] [(optional unit) Hz(default)|kHz|MHz]\n\t[Ctb][Xilinx Ctb] Run clock\
\ frequency."
infer_action: true
template: true
runtime:
@@ -10573,9 +10699,22 @@ syncclk:
- OutString(t)
require_det_id: true
store_result_in_t: true
- arg_types:
- special::freq_unit
argc: 1
cast_input: []
check_det_id: false
convert_det_id: true
function: getSYNCClock
input: []
input_types: []
output:
- OutString(t , args[0])
require_det_id: true
store_result_in_t: true
command_name: syncclk
function_alias: syncclk
help: "[n_clk in MHz]\n\t[Ctb] Sync clock in MHz."
help: "[n_clk] [(optional unit) Hz(default)|kHz|MHz]\n\t[Ctb] Sync clock."
infer_action: true
template: true
temp_10ge:
@@ -122,7 +122,25 @@ def generate(
f'StringTo < time::ns > ({", ".join(arg["convert_to_time"]["input"])});')
codegen.write_line(
f'}} catch (...) {{ throw RuntimeError("Could not convert arguments to time::ns");}}')
elif 'separate_freq_units' in arg and arg['separate_freq_units']:
codegen.write_line(f'try {{')
# TODO: refactor this repeating code
codegen.write_line(f'std::string tmp_freq({arg["separate_freq_units"]["input"]});')
codegen.write_line(f'std::string {arg["separate_freq_units"]["output"][1]}'
f' = RemoveUnit(tmp_freq);')
codegen.write_line(f'auto {arg["separate_freq_units"]["output"][0]} = '
f'StringTo < defs::Hz > (tmp_freq,'
f' {arg["separate_freq_units"]["output"][1]});')
codegen.write_line(
f'}} catch (...) {{ throw RuntimeError("Could not convert argument to defs::Hz");}}')
elif 'convert_to_freq' in arg and arg['convert_to_freq']:
codegen.write_line(f'try {{')
codegen.write_line(
f'StringTo < defs::Hz > ({", ".join(arg["convert_to_freq"]["input"])});')
codegen.write_line(
f'}} catch (...) {{ throw RuntimeError("Could not convert arguments to defs::Hz");}}')
for i in range(len(arg['input'])):
if not arg['cast_input'][i]:
continue
+7 -1
View File
@@ -302,7 +302,13 @@ write_arg in codegen reads the argument fields and generate c++ code accordingly
std::string $output[1]$ = RemoveUnit(tmp_time);
auto $output[0]$ = StringTo<time::ns>(tmp_time, $output[1]$);
```
- convert_to_time: takes three parameters: input[0], input[1], output
- separate_freq_units: takes three parameters: input, output[0], output[1] each one is a variable name
```cpp
std::string tmp_freq($input$);
std::string $output[1]$ = RemoveUnit(tmp_freq);
auto $output[0]$ = StringTo<defs::Hz>(tmp_freq, $output[1]$);
```
- convert_to_time and convert_to_freq: takes three parameters: input[0], input[1], output
```cpp
auto output = StringTo<time::ns>(input[0], input[1]);
```
+17 -17
View File
@@ -1613,20 +1613,26 @@ class Detector {
/** [CTB] */
void setNumberOfAnalogSamples(int value, Positions pos = {});
/** [CTB] in Hz, [XCTB] in Hz */
Result<int> getADCClock(Positions pos = {}) const;
/** [CTB][XCTB] */
Result<defs::Hz> getADCClock(Positions pos = {}) const;
/** [CTB] in Hz, [XCTB] in Hz */
void setADCClock(int value_in_Hz, Positions pos = {});
/** [CTB][XCTB] */
void setADCClock(defs::Hz val, Positions pos = {});
/** [CTB] in Hz, [XCTB] in Hz */
Result<int> getRUNClock(Positions pos = {}) const;
/** [CTB][XCTB] */
Result<defs::Hz> getRUNClock(Positions pos = {}) const;
/** [CTB] in Hz, [XCTB] in Hz */
void setRUNClock(int value_in_Hz, Positions pos = {});
/** [CTB][XCTB] */
void setRUNClock(defs::Hz val, Positions pos = {});
/** [CTB] in MHZ */
Result<int> getSYNCClock(Positions pos = {}) const;
/** [CTB][XCTB] */
Result<defs::Hz> getDBITClock(Positions pos = {}) const;
/** [CTB][XCTB] */
void setDBITClock(defs::Hz val, Positions pos = {});
/** [CTB][XCTB] */
Result<defs::Hz> getSYNCClock(Positions pos = {}) const;
/** gets list of power enums */
std::vector<defs::powerIndex> getPowerList() const;
@@ -1721,12 +1727,6 @@ class Detector {
*/
void setReadoutMode(defs::readoutMode value, Positions pos = {});
/** [CTB] in Hz, [XCTB] in Hz */
Result<int> getDBITClock(Positions pos = {}) const;
/** [CTB] in Hz, [XCTB] in Hz */
void setDBITClock(int value_in_Hz, Positions pos = {});
/** [CTB] */
Result<int> getExternalSamplingSource(Positions pos = {}) const;
@@ -1934,7 +1934,7 @@ class Detector {
/** [CTB][Mythen3][Xilinx CTB] Gets the pattern file name including path of
* the last pattern uploaded. \n Returns an empty if nothing was uploaded or
* via a server default file*/
Result<std::string> getPatterFileName(Positions pos = {}) const;
Result<std::string> getPatternFileName(Positions pos = {}) const;
/** [CTB][Mythen3][Xilinx CTB] Loads ASCII pattern file directly to server
* (instead of executing line by line)*/
+3
View File
@@ -38,6 +38,7 @@ template <class T, class Allocator = std::allocator<T>> class Result {
template <typename V, typename = typename std::enable_if<
std::is_integral<V>::value &&
(std::is_same<T, time::ns>::value ||
std::is_same<T, defs::Hz>::value ||
std::is_same<T, bool>::value)>::type>
Result(const Result<V> &from) {
vec.reserve(from.size());
@@ -49,6 +50,7 @@ template <class T, class Allocator = std::allocator<T>> class Result {
template <typename V, typename = typename std::enable_if<
std::is_integral<V>::value &&
(std::is_same<T, time::ns>::value ||
std::is_same<T, defs::Hz>::value ||
std::is_same<T, bool>::value)>::type>
Result(Result<V> &from) {
vec.reserve(from.size());
@@ -60,6 +62,7 @@ template <class T, class Allocator = std::allocator<T>> class Result {
template <typename V, typename = typename std::enable_if<
std::is_integral<V>::value &&
(std::is_same<T, time::ns>::value ||
std::is_same<T, defs::Hz>::value ||
std::is_same<T, bool>::value)>::type>
Result(Result<V> &&from) {
vec.reserve(from.size());
+69 -34
View File
@@ -72,20 +72,24 @@ std::string Caller::adcclk(int action) {
std::ostringstream os;
// print help
if (action == slsDetectorDefs::HELP_ACTION) {
os << R"V0G0N([ADC clock frequency] [(optional unit) MHz|kHz|Hz])V0G0N"
os << R"V0G0N([n_clk] [(optional unit) Hz(default)|kHz|MHz]
[Ctb][Xilinx Ctb] ADC clock frequency. )V0G0N"
<< std::endl;
return os.str();
}
// check if action and arguments are valid
if (action == slsDetectorDefs::GET_ACTION) {
if (1 && args.size() != 0) {
if (1 && args.size() != 0 && args.size() != 1) {
throw RuntimeError("Wrong number of arguments for action GET");
}
if (args.size() == 0) {
}
if (args.size() == 1) {
}
}
else if (action == slsDetectorDefs::PUT_ACTION) {
@@ -97,17 +101,17 @@ std::string Caller::adcclk(int action) {
try {
std::string tmp_freq(args[0]);
std::string unit = RemoveUnit(tmp_freq);
StringToHz(tmp_freq, unit);
auto converted_freq = StringTo<defs::Hz>(tmp_freq, unit);
} catch (...) {
throw RuntimeError("Could not convert argument to frequency");
throw RuntimeError("Could not convert argument to defs::Hz");
}
}
if (args.size() == 2) {
try {
StringToHz(args[0], args[1]);
StringTo<defs::Hz>(args[0], args[1]);
} catch (...) {
throw RuntimeError("Could not convert arguments to frequency");
throw RuntimeError("Could not convert arguments to defs::Hz");
}
}
@@ -125,20 +129,25 @@ std::string Caller::adcclk(int action) {
auto t = det->getADCClock(std::vector<int>{det_id});
os << OutString(t) << '\n';
}
if (args.size() == 1) {
auto t = det->getADCClock(std::vector<int>{det_id});
os << OutString(t, args[0]) << '\n';
}
}
if (action == slsDetectorDefs::PUT_ACTION) {
if (args.size() == 1) {
std::string tmp_freq(args[0]);
std::string unit = RemoveUnit(tmp_freq);
auto converted_freq_hz = StringToHz(tmp_freq, unit);
det->setADCClock(converted_freq_hz, std::vector<int>{det_id});
auto converted_freq = StringTo<defs::Hz>(tmp_freq, unit);
det->setADCClock(converted_freq, std::vector<int>{det_id});
os << args[0] << '\n';
}
if (args.size() == 2) {
auto converted_freq_hz = StringToHz(args[0], args[1]);
det->setADCClock(converted_freq_hz, std::vector<int>{det_id});
auto converted_freq = StringTo<defs::Hz>(args[0], args[1]);
det->setADCClock(converted_freq, std::vector<int>{det_id});
os << args[0] << args[1] << '\n';
}
}
@@ -2498,20 +2507,24 @@ std::string Caller::dbitclk(int action) {
std::ostringstream os;
// print help
if (action == slsDetectorDefs::HELP_ACTION) {
os << R"V0G0N([dbit clock frequency] [(optional unit) MHz|kHz|Hz])V0G0N"
os << R"V0G0N([n_clk] [(optional unit) Hz(default)|kHz|MHz]
[Ctb][Xilinx Ctb] Clock for latching the digital bits. )V0G0N"
<< std::endl;
return os.str();
}
// check if action and arguments are valid
if (action == slsDetectorDefs::GET_ACTION) {
if (1 && args.size() != 0) {
if (1 && args.size() != 0 && args.size() != 1) {
throw RuntimeError("Wrong number of arguments for action GET");
}
if (args.size() == 0) {
}
if (args.size() == 1) {
}
}
else if (action == slsDetectorDefs::PUT_ACTION) {
@@ -2523,17 +2536,17 @@ std::string Caller::dbitclk(int action) {
try {
std::string tmp_freq(args[0]);
std::string unit = RemoveUnit(tmp_freq);
StringToHz(tmp_freq, unit);
auto converted_freq = StringTo<defs::Hz>(tmp_freq, unit);
} catch (...) {
throw RuntimeError("Could not convert argument to frequency");
throw RuntimeError("Could not convert argument to defs::Hz");
}
}
if (args.size() == 2) {
try {
StringToHz(args[0], args[1]);
StringTo<defs::Hz>(args[0], args[1]);
} catch (...) {
throw RuntimeError("Could not convert arguments to frequency");
throw RuntimeError("Could not convert arguments to defs::Hz");
}
}
@@ -2551,20 +2564,25 @@ std::string Caller::dbitclk(int action) {
auto t = det->getDBITClock(std::vector<int>{det_id});
os << OutString(t) << '\n';
}
if (args.size() == 1) {
auto t = det->getDBITClock(std::vector<int>{det_id});
os << OutString(t, args[0]) << '\n';
}
}
if (action == slsDetectorDefs::PUT_ACTION) {
if (args.size() == 1) {
std::string tmp_freq(args[0]);
std::string unit = RemoveUnit(tmp_freq);
auto converted_freq_hz = StringToHz(tmp_freq, unit);
det->setDBITClock(converted_freq_hz, std::vector<int>{det_id});
auto converted_freq = StringTo<defs::Hz>(tmp_freq, unit);
det->setDBITClock(converted_freq, std::vector<int>{det_id});
os << args[0] << '\n';
}
if (args.size() == 2) {
auto converted_freq_hz = StringToHz(args[0], args[1]);
det->setDBITClock(converted_freq_hz, std::vector<int>{det_id});
auto converted_freq = StringTo<defs::Hz>(args[0], args[1]);
det->setDBITClock(converted_freq, std::vector<int>{det_id});
os << args[0] << args[1] << '\n';
}
}
@@ -7344,7 +7362,7 @@ std::string Caller::patfname(int action) {
// generate code for each action
if (action == slsDetectorDefs::GET_ACTION) {
if (args.size() == 0) {
auto t = det->getPatterFileName(std::vector<int>{det_id});
auto t = det->getPatternFileName(std::vector<int>{det_id});
os << OutString(t) << '\n';
}
}
@@ -9941,20 +9959,24 @@ std::string Caller::runclk(int action) {
std::ostringstream os;
// print help
if (action == slsDetectorDefs::HELP_ACTION) {
os << R"V0G0N([Run clock frequency] [(optional unit) MHz|kHz|Hz])V0G0N"
os << R"V0G0N([n_clk] [(optional unit) Hz(default)|kHz|MHz]
[Ctb][Xilinx Ctb] Run clock frequency. )V0G0N"
<< std::endl;
return os.str();
}
// check if action and arguments are valid
if (action == slsDetectorDefs::GET_ACTION) {
if (1 && args.size() != 0) {
if (1 && args.size() != 0 && args.size() != 1) {
throw RuntimeError("Wrong number of arguments for action GET");
}
if (args.size() == 0) {
}
if (args.size() == 1) {
}
}
else if (action == slsDetectorDefs::PUT_ACTION) {
@@ -9966,17 +9988,17 @@ std::string Caller::runclk(int action) {
try {
std::string tmp_freq(args[0]);
std::string unit = RemoveUnit(tmp_freq);
StringToHz(tmp_freq, unit);
auto converted_freq = StringTo<defs::Hz>(tmp_freq, unit);
} catch (...) {
throw RuntimeError("Could not convert argument to frequency");
throw RuntimeError("Could not convert argument to defs::Hz");
}
}
if (args.size() == 2) {
try {
StringToHz(args[0], args[1]);
StringTo<defs::Hz>(args[0], args[1]);
} catch (...) {
throw RuntimeError("Could not convert arguments to frequency");
throw RuntimeError("Could not convert arguments to defs::Hz");
}
}
@@ -9994,20 +10016,25 @@ std::string Caller::runclk(int action) {
auto t = det->getRUNClock(std::vector<int>{det_id});
os << OutString(t) << '\n';
}
if (args.size() == 1) {
auto t = det->getRUNClock(std::vector<int>{det_id});
os << OutString(t, args[0]) << '\n';
}
}
if (action == slsDetectorDefs::PUT_ACTION) {
if (args.size() == 1) {
std::string tmp_freq(args[0]);
std::string unit = RemoveUnit(tmp_freq);
auto converted_freq_hz = StringToHz(tmp_freq, unit);
det->setRUNClock(converted_freq_hz, std::vector<int>{det_id});
auto converted_freq = StringTo<defs::Hz>(tmp_freq, unit);
det->setRUNClock(converted_freq, std::vector<int>{det_id});
os << args[0] << '\n';
}
if (args.size() == 2) {
auto converted_freq_hz = StringToHz(args[0], args[1]);
det->setRUNClock(converted_freq_hz, std::vector<int>{det_id});
auto converted_freq = StringTo<defs::Hz>(args[0], args[1]);
det->setRUNClock(converted_freq, std::vector<int>{det_id});
os << args[0] << args[1] << '\n';
}
}
@@ -13110,21 +13137,24 @@ std::string Caller::syncclk(int action) {
std::ostringstream os;
// print help
if (action == slsDetectorDefs::HELP_ACTION) {
os << R"V0G0N([n_clk in MHz]
[Ctb] Sync clock in MHz. )V0G0N"
os << R"V0G0N([n_clk] [(optional unit) Hz(default)|kHz|MHz]
[Ctb] Sync clock. )V0G0N"
<< std::endl;
return os.str();
}
// check if action and arguments are valid
if (action == slsDetectorDefs::GET_ACTION) {
if (1 && args.size() != 0) {
if (1 && args.size() != 0 && args.size() != 1) {
throw RuntimeError("Wrong number of arguments for action GET");
}
if (args.size() == 0) {
}
if (args.size() == 1) {
}
}
else {
@@ -13139,6 +13169,11 @@ std::string Caller::syncclk(int action) {
auto t = det->getSYNCClock(std::vector<int>{det_id});
os << OutString(t) << '\n';
}
if (args.size() == 1) {
auto t = det->getSYNCClock(std::vector<int>{det_id});
os << OutString(t, args[0]) << '\n';
}
}
return os.str();
+18 -18
View File
@@ -2144,25 +2144,34 @@ void Detector::setNumberOfAnalogSamples(int value, Positions pos) {
pimpl->Parallel(&Module::setNumberOfAnalogSamples, pos, value);
}
Result<int> Detector::getADCClock(Positions pos) const {
Result<defs::Hz> Detector::getADCClock(Positions pos) const {
return pimpl->Parallel(&Module::getClockFrequency, pos, defs::ADC_CLOCK);
}
void Detector::setADCClock(int value_in_Hz, Positions pos) {
void Detector::setADCClock(defs::Hz val, Positions pos) {
pimpl->Parallel(&Module::setClockFrequency, pos, defs::ADC_CLOCK,
value_in_Hz);
val.value);
}
Result<int> Detector::getRUNClock(Positions pos) const {
Result<defs::Hz> Detector::getRUNClock(Positions pos) const {
return pimpl->Parallel(&Module::getClockFrequency, pos, defs::RUN_CLOCK);
}
void Detector::setRUNClock(int value_in_Hz, Positions pos) {
void Detector::setRUNClock(defs::Hz val, Positions pos) {
pimpl->Parallel(&Module::setClockFrequency, pos, defs::RUN_CLOCK,
value_in_Hz);
val.value);
}
Result<int> Detector::getSYNCClock(Positions pos) const {
Result<defs::Hz> Detector::getDBITClock(Positions pos) const {
return pimpl->Parallel(&Module::getClockFrequency, pos, defs::DBIT_CLOCK);
}
void Detector::setDBITClock(defs::Hz val, Positions pos) {
pimpl->Parallel(&Module::setClockFrequency, pos, defs::DBIT_CLOCK,
val.value);
}
Result<defs::Hz> Detector::getSYNCClock(Positions pos) const {
return pimpl->Parallel(&Module::getClockFrequency, pos, defs::SYNC_CLOCK);
}
@@ -2310,15 +2319,6 @@ void Detector::setReadoutMode(defs::readoutMode value, Positions pos) {
pimpl->Parallel(&Module::setReadoutMode, pos, value);
}
Result<int> Detector::getDBITClock(Positions pos) const {
return pimpl->Parallel(&Module::getClockFrequency, pos, defs::DBIT_CLOCK);
}
void Detector::setDBITClock(int value_in_Hz, Positions pos) {
pimpl->Parallel(&Module::setClockFrequency, pos, defs::DBIT_CLOCK,
value_in_Hz);
}
Result<int> Detector::getSlowADC(defs::dacIndex index, Positions pos) const {
if (index < defs::SLOW_ADC0 || index > defs::SLOW_ADC7) {
throw RuntimeError("Unknown Slow ADC Index");
@@ -2609,8 +2609,8 @@ void Detector::configureTransceiver(Positions pos) {
// Pattern
Result<std::string> Detector::getPatterFileName(Positions pos) const {
return pimpl->Parallel(&Module::getPatterFileName, pos);
Result<std::string> Detector::getPatternFileName(Positions pos) const {
return pimpl->Parallel(&Module::getPatternFileName, pos);
}
void Detector::setPattern(const std::string &fname, Positions pos) {
+1 -1
View File
@@ -2669,7 +2669,7 @@ void Module::configureTransceiver() {
}
// Pattern
std::string Module::getPatterFileName() const {
std::string Module::getPatternFileName() const {
char retval[MAX_STR_LENGTH]{};
sendToDetector(F_GET_PATTERN_FILE_NAME, nullptr, retval);
return retval;
+1 -1
View File
@@ -536,7 +536,7 @@ class Module : public virtual slsDetectorDefs {
* Pattern *
* *
* ************************************************/
std::string getPatterFileName() const;
std::string getPatternFileName() const;
void setPattern(const Pattern &pat, const std::string &fname);
Pattern getPattern();
void loadDefaultPattern();
+22
View File
@@ -63,6 +63,12 @@ int InferAction::adcclk() {
}
if (args.size() == 1) {
throw RuntimeError(
"sls_detector is disabled for command: adcclk with number of "
"arguments 1. Use sls_detector_get or sls_detector_put");
}
if (args.size() == 2) {
return slsDetectorDefs::PUT_ACTION;
}
@@ -711,6 +717,12 @@ int InferAction::dbitclk() {
}
if (args.size() == 1) {
throw RuntimeError(
"sls_detector is disabled for command: dbitclk with number of "
"arguments 1. Use sls_detector_get or sls_detector_put");
}
if (args.size() == 2) {
return slsDetectorDefs::PUT_ACTION;
}
@@ -2595,6 +2607,12 @@ int InferAction::runclk() {
}
if (args.size() == 1) {
throw RuntimeError(
"sls_detector is disabled for command: runclk with number of "
"arguments 1. Use sls_detector_get or sls_detector_put");
}
if (args.size() == 2) {
return slsDetectorDefs::PUT_ACTION;
}
@@ -3477,6 +3495,10 @@ int InferAction::syncclk() {
return slsDetectorDefs::GET_ACTION;
}
if (args.size() == 1) {
return slsDetectorDefs::GET_ACTION;
}
else {
throw RuntimeError("Could not infer action: Wrong number of arguments");
@@ -921,22 +921,42 @@ TEST_CASE("adcclk", "[.detectorintegration]") {
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::CHIPTESTBOARD) {
if (det_type == defs::CHIPTESTBOARD ||
det_type == defs::XILINX_CHIPTESTBOARD) {
auto prev_val = det.getADCClock();
REQUIRE_NOTHROW(caller.call("adcclk", {"MHZ"}, -1, GET));
REQUIRE_NOTHROW(caller.call("adcclk", {"mhz"}, -1, GET));
REQUIRE_NOTHROW(caller.call("adcclk", {"MHz"}, -1, GET));
REQUIRE_NOTHROW(caller.call("adcclk", {"kHz"}, -1, GET));
REQUIRE_NOTHROW(caller.call("adcclk", {"Hz"}, -1, GET));
REQUIRE_NOTHROW(caller.call("adcclk", {}, -1, GET));
// min
if (det_type == defs::CHIPTESTBOARD)
REQUIRE_THROWS(caller.call("adcclk", {"1", "MHz"}, -1, PUT));
else
REQUIRE_THROWS(caller.call("adcclk", {"9", "MHz"}, -1, PUT));
// max
if (det_type == defs::CHIPTESTBOARD)
REQUIRE_THROWS(caller.call("adcclk", {"66", "MHz"}, -1, PUT));
else
REQUIRE_THROWS(caller.call("adcclk", {"301", "MHz"}, -1, PUT));
{
std::ostringstream oss;
caller.call("adcclk", {"20"}, -1, PUT, oss);
REQUIRE(oss.str() == "adcclk 20\n");
caller.call("adcclk", {"20MHz"}, -1, PUT, oss);
REQUIRE(oss.str() == "adcclk 20MHz\n");
}
{
std::ostringstream oss;
caller.call("adcclk", {"10"}, -1, PUT, oss);
REQUIRE(oss.str() == "adcclk 10\n");
caller.call("adcclk", {"10000000"}, -1, PUT, oss);
REQUIRE(oss.str() == "adcclk 10000000\n");
}
{
std::ostringstream oss;
caller.call("adcclk", {}, -1, GET, oss);
REQUIRE(oss.str() == "adcclk 10000000\n");
REQUIRE(oss.str() == "adcclk 10MHz\n");
}
{
std::ostringstream oss;
@@ -946,18 +966,20 @@ TEST_CASE("adcclk", "[.detectorintegration]") {
{
std::ostringstream oss;
caller.call("adcclk", {}, -1, GET, oss);
REQUIRE(oss.str() == "adcclk 15000000\n");
REQUIRE(oss.str() == "adcclk 15MHz\n");
}
{
std::ostringstream oss;
caller.call("adcclk", {"5.75", "MHz"}, -1, PUT, oss);
REQUIRE(oss.str() == "adcclk 5.75MHz\n");
caller.call("adcclk", {"15.75", "MHz"}, -1, PUT, oss);
REQUIRE(oss.str() == "adcclk 15.75MHz\n");
}
{
std::ostringstream oss;
caller.call("adcclk", {}, -1, GET, oss);
REQUIRE(oss.str() == "adcclk 5750000\n");
REQUIRE(oss.str() == "adcclk 15.75MHz\n");
}
std::cout << "Resetting adc clock to :" << ToString(prev_val)
<< std::endl;
for (int i = 0; i != det.size(); ++i) {
det.setADCClock(prev_val[i], {i});
}
@@ -972,22 +994,39 @@ TEST_CASE("runclk", "[.detectorintegration]") {
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::CHIPTESTBOARD) {
if (det_type == defs::CHIPTESTBOARD ||
det_type == defs::XILINX_CHIPTESTBOARD) {
auto prev_val = det.getRUNClock();
REQUIRE_NOTHROW(caller.call("runclk", {"MHZ"}, -1, GET));
REQUIRE_NOTHROW(caller.call("runclk", {"mhz"}, -1, GET));
REQUIRE_NOTHROW(caller.call("runclk", {"MHz"}, -1, GET));
REQUIRE_NOTHROW(caller.call("runclk", {"kHz"}, -1, GET));
REQUIRE_NOTHROW(caller.call("runclk", {"Hz"}, -1, GET));
REQUIRE_NOTHROW(caller.call("runclk", {}, -1, GET));
// min
if (det_type == defs::CHIPTESTBOARD)
REQUIRE_THROWS(caller.call("runclk", {"1", "MHz"}, -1, PUT));
else
REQUIRE_THROWS(caller.call("runclk", {"9", "MHz"}, -1, PUT));
// max
REQUIRE_THROWS(caller.call("runclk", {"301", "MHz"}, -1, PUT));
{
std::ostringstream oss;
caller.call("runclk", {"20"}, -1, PUT, oss);
REQUIRE(oss.str() == "runclk 20\n");
caller.call("runclk", {"20MHz"}, -1, PUT, oss);
REQUIRE(oss.str() == "runclk 20MHz\n");
}
{
std::ostringstream oss;
caller.call("runclk", {"10"}, -1, PUT, oss);
REQUIRE(oss.str() == "runclk 10\n");
caller.call("runclk", {"10000000"}, -1, PUT, oss);
REQUIRE(oss.str() == "runclk 10000000\n");
}
{
std::ostringstream oss;
caller.call("runclk", {}, -1, GET, oss);
REQUIRE(oss.str() == "runclk 10000000\n");
REQUIRE(oss.str() == "runclk 10MHz\n");
}
{
std::ostringstream oss;
@@ -997,17 +1036,17 @@ TEST_CASE("runclk", "[.detectorintegration]") {
{
std::ostringstream oss;
caller.call("runclk", {}, -1, GET, oss);
REQUIRE(oss.str() == "runclk 15000000\n");
REQUIRE(oss.str() == "runclk 15MHz\n");
}
{
std::ostringstream oss;
caller.call("runclk", {"5.75", "MHz"}, -1, PUT, oss);
REQUIRE(oss.str() == "runclk 5.75MHz\n");
caller.call("runclk", {"15.75", "MHz"}, -1, PUT, oss);
REQUIRE(oss.str() == "runclk 15.75MHz\n");
}
{
std::ostringstream oss;
caller.call("runclk", {}, -1, GET, oss);
REQUIRE(oss.str() == "runclk 5750000\n");
REQUIRE(oss.str() == "runclk 15.75MHz\n");
}
for (int i = 0; i != det.size(); ++i) {
det.setRUNClock(prev_val[i], {i});
@@ -1023,6 +1062,11 @@ TEST_CASE("syncclk", "[.detectorintegration]") {
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::CHIPTESTBOARD) {
REQUIRE_NOTHROW(caller.call("syncclk", {"MHZ"}, -1, GET));
REQUIRE_NOTHROW(caller.call("syncclk", {"mhz"}, -1, GET));
REQUIRE_NOTHROW(caller.call("syncclk", {"MHz"}, -1, GET));
REQUIRE_NOTHROW(caller.call("syncclk", {"kHz"}, -1, GET));
REQUIRE_NOTHROW(caller.call("syncclk", {"Hz"}, -1, GET));
REQUIRE_NOTHROW(caller.call("syncclk", {}, -1, GET));
} else {
// clock index might work
@@ -1289,22 +1333,39 @@ TEST_CASE("dbitclk", "[.detectorintegration]") {
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::CHIPTESTBOARD) {
if (det_type == defs::CHIPTESTBOARD ||
det_type == defs::XILINX_CHIPTESTBOARD) {
auto prev_val = det.getDBITClock();
REQUIRE_NOTHROW(caller.call("dbitclk", {"MHZ"}, -1, GET));
REQUIRE_NOTHROW(caller.call("dbitclk", {"mhz"}, -1, GET));
REQUIRE_NOTHROW(caller.call("dbitclk", {"MHz"}, -1, GET));
REQUIRE_NOTHROW(caller.call("dbitclk", {"kHz"}, -1, GET));
REQUIRE_NOTHROW(caller.call("dbitclk", {"Hz"}, -1, GET));
REQUIRE_NOTHROW(caller.call("dbitclk", {}, -1, GET));
// min
if (det_type == defs::CHIPTESTBOARD)
REQUIRE_THROWS(caller.call("dbitclk", {"1", "MHz"}, -1, PUT));
else
REQUIRE_THROWS(caller.call("dbitclk", {"9", "MHz"}, -1, PUT));
// max
REQUIRE_THROWS(caller.call("dbitclk", {"301", "MHz"}, -1, PUT));
{
std::ostringstream oss;
caller.call("dbitclk", {"20"}, -1, PUT, oss);
REQUIRE(oss.str() == "dbitclk 20\n");
caller.call("dbitclk", {"20MHz"}, -1, PUT, oss);
REQUIRE(oss.str() == "dbitclk 20MHz\n");
}
{
std::ostringstream oss;
caller.call("dbitclk", {"10"}, -1, PUT, oss);
REQUIRE(oss.str() == "dbitclk 10\n");
caller.call("dbitclk", {"10000000"}, -1, PUT, oss);
REQUIRE(oss.str() == "dbitclk 10000000\n");
}
{
std::ostringstream oss;
caller.call("dbitclk", {}, -1, GET, oss);
REQUIRE(oss.str() == "dbitclk 10000000\n");
REQUIRE(oss.str() == "dbitclk 10MHz\n");
}
{
std::ostringstream oss;
@@ -1314,17 +1375,17 @@ TEST_CASE("dbitclk", "[.detectorintegration]") {
{
std::ostringstream oss;
caller.call("dbitclk", {}, -1, GET, oss);
REQUIRE(oss.str() == "dbitclk 15000000\n");
REQUIRE(oss.str() == "dbitclk 15MHz\n");
}
{
std::ostringstream oss;
caller.call("dbitclk", {"5.75", "MHz"}, -1, PUT, oss);
REQUIRE(oss.str() == "dbitclk 5.75MHz\n");
caller.call("dbitclk", {"15.75", "MHz"}, -1, PUT, oss);
REQUIRE(oss.str() == "dbitclk 15.75MHz\n");
}
{
std::ostringstream oss;
caller.call("dbitclk", {}, -1, GET, oss);
REQUIRE(oss.str() == "dbitclk 5750000\n");
REQUIRE(oss.str() == "dbitclk 15.75MHz\n");
}
for (int i = 0; i != det.size(); ++i) {
det.setDBITClock(prev_val[i], {i});
+66 -4
View File
@@ -108,6 +108,44 @@ ToString(From t) {
}
}
/** Convert frequency with specified output unit */
template <typename T, typename Rep = double>
typename std::enable_if<is_frequency<T>::value, std::string>::type
ToString(T f, const std::string &unit) {
double val = static_cast<double>(f.value);
auto unitLower = [&] {
std::string result = unit;
std::transform(result.begin(), result.end(), result.begin(),
[](unsigned char c) { return std::tolower(c); });
return result;
}();
std::ostringstream os;
if (unitLower == "hz")
os << val << unit;
else if (unitLower == "khz")
os << val / (static_cast<double>(1e3)) << unit;
else if (unitLower == "mhz")
os << val / (static_cast<double>(1e6)) << unit;
else
throw std::runtime_error("Unknown unit: " + unit);
return os.str();
}
/** Convert frequency automatically selecting the unit */
template <typename From>
typename std::enable_if<is_frequency<From>::value, std::string>::type
ToString(From f) {
int val = f.value;
if (val < 1e3) {
return ToString(f, "Hz");
} else if (val < 1e6) {
return ToString(f, "kHz");
} else {
return ToString(f, "MHz");
}
}
/** Conversion of floating point values, removes trailing zeros*/
template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, std::string>::type
@@ -279,7 +317,7 @@ ToString(const T &container, const std::string &unit) {
return os.str();
}
template <typename T>
template <typename T, std::enable_if_t<sls::is_duration<T>::value, int> = 0>
T StringTo(const std::string &t, const std::string &unit) {
double tval{0};
try {
@@ -304,6 +342,33 @@ T StringTo(const std::string &t, const std::string &unit) {
}
}
template <typename T, std::enable_if_t<sls::is_frequency<T>::value, int> = 0>
T StringTo(const std::string &f, const std::string &unit) {
double fval{0};
try {
fval = std::stod(f);
} catch (const std::invalid_argument &e) {
throw RuntimeError("Could not convert string to frequency");
}
auto unitLower = [&] {
std::string result = unit;
std::transform(result.begin(), result.end(), result.begin(),
[](unsigned char c) { return std::tolower(c); });
return result;
}();
if (unitLower == "mhz") {
return T(static_cast<int>(fval * 1e6));
} else if (unitLower == "khz") {
return T(static_cast<int>(fval * 1e3));
} else if (unitLower.empty() || unitLower == "hz") {
return T(static_cast<int>(fval));
} else {
throw RuntimeError(
"Invalid unit in conversion from string to frequency");
}
}
template <typename T> T StringTo(const std::string &t) {
std::string tmp{t};
auto unit = RemoveUnit(tmp);
@@ -358,7 +423,4 @@ std::vector<T> StringTo(const std::vector<std::string> &strings) {
return result;
}
/** Convert frequency string with unit (MHz, kHz, Hz) to Hz */
int StringToHz(const std::string &s, const std::string &unit);
} // namespace sls
+7
View File
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
#pragma once
#include "sls/sls_detector_defs.h"
#include <type_traits>
#include <vector>
@@ -120,4 +122,9 @@ struct has_bool_isValid : std::false_type {};
template <typename T>
struct has_bool_isValid<T, std::void_t<decltype(std::declval<T>().isValid)>>
: std::is_same<decltype(std::declval<T>().isValid), bool> {};
template <typename T> struct is_frequency : std::false_type {};
template <> struct is_frequency<defs::Hz> : std::true_type {};
} // namespace sls
@@ -211,6 +211,14 @@ class slsDetectorDefs {
std::map<std::string, std::string> addJsonHeader;
};
struct Hz {
int value{0};
explicit Hz(int v) : value(v){};
constexpr bool operator==(const Hz &other) const {
return (value == other.value);
}
};
#endif
enum frameDiscardPolicy {
NO_DISCARD,
@@ -837,7 +845,6 @@ typedef struct {
#endif
#ifdef __cplusplus
// TODO! discuss this
#include <vector> //hmm... but currently no way around
namespace sls {
-19
View File
@@ -1264,23 +1264,4 @@ template <> int64_t StringTo(const std::string &s) {
return std::stol(s, nullptr, base);
}
int StringToHz(const std::string &s, const std::string &unit) {
double fval{0};
try {
fval = std::stod(s);
} catch (const std::invalid_argument &e) {
throw RuntimeError("Could not convert string to frequency");
}
if (unit.empty() || unit == "MHz") {
return static_cast<int>(fval * 1000000.0);
} else if (unit == "kHz") {
return static_cast<int>(fval * 1000.0);
} else if (unit == "Hz") {
return static_cast<int>(fval);
} else {
throw RuntimeError("Unknown unit: " + unit +
". Supported units: MHz, kHz, Hz");
}
}
} // namespace sls
+18
View File
@@ -76,6 +76,15 @@ TEST_CASE("conversion from duration to string", "[support]") {
REQUIRE(ToString(us(-100)) == "-100us");
}
TEST_CASE("conversion from frequency to string", "[support]") {
REQUIRE(ToString(defs::Hz(150)) == "150Hz");
REQUIRE(ToString(defs::Hz(1500)) == "1.5kHz");
REQUIRE(ToString(defs::Hz(1500000)) == "1.5MHz");
REQUIRE(ToString(defs::Hz(150), "Hz") == "150Hz");
REQUIRE(ToString(defs::Hz(150), "kHz") == "0.15kHz");
REQUIRE(ToString(defs::Hz(150), "MHz") == "0.00015MHz");
}
TEST_CASE("Convert vector of time", "[support]") {
std::vector<ns> vec{ns(150), us(10), ns(600)};
REQUIRE(ToString(vec) == "[150ns, 10us, 600ns]");
@@ -155,6 +164,15 @@ TEST_CASE("string to std::chrono::duration", "[support]") {
REQUIRE_THROWS(StringTo<ns>("asvn"));
}
TEST_CASE("string to frequency", "[support]") {
REQUIRE(StringTo<defs::Hz>("150") == defs::Hz(150));
REQUIRE(StringTo<defs::Hz>("150Hz") == defs::Hz(150));
REQUIRE(StringTo<defs::Hz>("1.5kHz") == defs::Hz(1500));
REQUIRE(StringTo<defs::Hz>("1.5MHz") == defs::Hz(1500000));
REQUIRE_THROWS(StringTo<defs::Hz>("5xs"));
REQUIRE_THROWS(StringTo<defs::Hz>("asvn"));
}
TEST_CASE("string to detectorType") {
using dt = slsDetectorDefs::detectorType;
REQUIRE(StringTo<dt>("Eiger") == dt::EIGER);