CTB frequency rounding, CTB frequency measurement, CTB frequency units (#1423)

* round CTB clocks to next closest possible value, added freq measurement

* added time for firmware to measrue actual value after frequency change

* add check for backwards compatibility

* change CTB and XCTB clock values to MHz, TODO: units and validation errors

* changed runclk command to use units and float, TODO: dbit, adcclk, why is everything called StringTo ?

* do the same for dbit and adcclk

* added tolerance to exptime, fixed test

* update default values in server defs

* added virtual check in Altera_PLL, update testcases

* change python and pyctbgui to accept and return floating point MHz

* update help and comments

* Dev/ctb clocks fix (#1434)

* 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

* insert tolerance check again

* also added tolerance check for patwaittime

* formatting

* minor: rounding test

* removed Rep redundant in ToString for freq

* intro frequency unit enums, removed unnecessary template behavior for ToString with freq unit, switching from parsing string unit argument to the enum argument for ToString, adding parsing string to unit at CLI boundary

* minor, and binaries

* minor, default clk vals are 0 but set up at detector setup

* get frequency only for that unit

* tolerance process

* missed in previous commit

* some more changes to exptime and validations

* ctb is probably done

* periodleft and delayleft

* fixed xilinx freq conv as well

* fixed m3 bug, binaries

* xilinx: setup also done in stop server so that the clk is not 0

* missed a test marker

* binaries in

* review fixes, simpler validation of timers in ctb and xilinx ctb

* typo fix

* format

* fix tests

---------

Co-authored-by: Martin Mueller <martin.mueller@psi.ch>
Co-authored-by: Dhanya Thattil <dhanya.thattil@psi.ch>
This commit is contained in:
Martin Mueller
2026-05-06 15:52:13 +02:00
committed by GitHub
parent bb1a73d718
commit 0837de2a5a
57 changed files with 2239 additions and 706 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:
+42 -40
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
@@ -58,12 +58,6 @@ class AcquisitionTab(QtWidgets.QWidget):
self.view.spinBoxADCPipeline.setDisabled(True)
self.view.spinBoxDBITPhase.setDisabled(True)
self.view.spinBoxDBITPipeline.setDisabled(True)
self.view.labelRunF.setText("Run Clock Frequency (kHz):")
self.view.labelDBITF.setText("DBIT Clock Frequency (kHz):")
self.view.labelADCF.setText("ADC Clock Frequency (kHz):")
self.view.spinBoxRunF.setMaximum(250000)
self.view.spinBoxDBITF.setMaximum(250000)
self.view.spinBoxADCF.setMaximum(250000)
def connect_ui(self):
# For Acquistions Tab
@@ -74,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.getRunFrequency)
self.view.spinBoxADCF.editingFinished.connect(self.setADCFrequency)
self.view.comboBoxADCF.currentIndexChanged.connect(self.getADCFrequency)
self.view.spinBoxDBITF.editingFinished.connect(self.setDBITFrequency)
self.view.comboBoxDBITF.currentIndexChanged.connect(self.getDBITFrequency)
if self.det.type == detectorType.CHIPTESTBOARD:
self.view.spinBoxADCPhase.editingFinished.connect(self.setADCPhase)
self.view.spinBoxADCPipeline.editingFinished.connect(self.setADCPipeline)
@@ -195,20 +192,43 @@ class AcquisitionTab(QtWidgets.QWidget):
self.view.comboBoxROMode.currentIndexChanged.connect(self.setReadOut)
self.getReadout()
def _getFrequency(self, det_attr, spinbox, spinSetter, combobox):
spinbox.editingFinished.disconnect()
f = getattr(self.det, det_attr).value
unit = combobox.currentIndex()
if unit == 2: #Hz
spinbox.setValue(f)
elif unit == 1: #kHz
spinbox.setValue(f / 1e3)
else:
spinbox.setValue(f / 1e6)
spinbox.editingFinished.connect(spinSetter)
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.setRunFrequency, self.view.comboBoxRunF)
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()
@@ -260,19 +280,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.setADCFrequency, self.view.comboBoxADCF)
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()
@@ -305,19 +316,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.setDBITFrequency, self.view.comboBoxDBITF)
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()
+377 -238
View File
@@ -36,7 +36,7 @@
</property>
<layout class="QGridLayout" name="gridLayout_19">
<item row="1" column="5">
<widget class="QSpinBox" name="spinBoxRunF">
<widget class="QDoubleSpinBox" name="spinBoxRunF">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
@@ -45,13 +45,13 @@
</property>
<property name="minimumSize">
<size>
<width>125</width>
<width>120</width>
<height>31</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>125</width>
<width>120</width>
<height>31</height>
</size>
</property>
@@ -61,18 +61,17 @@
<property name="buttonSymbols">
<enum>QAbstractSpinBox::UpDownArrows</enum>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="maximum">
<number>1000</number>
<double>999999999.000000000000000</double>
</property>
<property name="singleStep">
<double>1.000000000000000</double>
</property>
<property name="value">
<number>0</number>
</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>
@@ -117,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">
@@ -152,13 +205,13 @@
</property>
<property name="minimumSize">
<size>
<width>125</width>
<width>185</width>
<height>32</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>125</width>
<width>185</width>
<height>32</height>
</size>
</property>
@@ -210,6 +263,12 @@
<height>201</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>190</width>
<height>0</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
@@ -217,16 +276,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>120</width>
<height>31</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>120</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>999999999.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>120</width>
<height>31</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>120</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>999999999.000000000000000</double>
</property>
<property name="singleStep">
<double>1.000000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
</widget>
</item>
@@ -245,213 +416,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="QSpinBox" 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="maximum">
<number>1000</number>
</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="QSpinBox" 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="maximum">
<number>1000</number>
</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>
@@ -462,7 +427,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">
@@ -472,13 +481,13 @@
</property>
<property name="minimumSize">
<size>
<width>125</width>
<width>185</width>
<height>32</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>125</width>
<width>185</width>
<height>32</height>
</size>
</property>
@@ -493,14 +502,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>185</width>
<height>31</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>185</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>185</width>
<height>31</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>185</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">
@@ -510,13 +565,13 @@
</property>
<property name="minimumSize">
<size>
<width>125</width>
<width>185</width>
<height>32</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>125</width>
<width>185</width>
<height>32</height>
</size>
</property>
@@ -534,6 +589,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>185</width>
<height>31</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>185</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>185</width>
<height>31</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>185</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():
+32 -13
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,15 +3442,21 @@ class Detector(CppDetectorApi):
@element
def runclk(self):
"""
[Ctb] Sets Run clock frequency in MHz. \n
[Xilinx Ctb] Sets Run clock frequency in kHz.
"""
[Ctb][Xilinx Ctb] Sets Run clock frequency.
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):
ut.set_using_dict(self.setRUNClock, freq)
ut.set_using_dict(self.setRUNClock, freq)
@property
@element
@@ -3526,10 +3533,16 @@ class Detector(CppDetectorApi):
@element
def dbitclk(self):
"""
[Ctb] Sets clock for latching the digital bits in MHz. \n
[Xilinx Ctb] clock for latching the digital bits in kHz.
"""
[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)
"""
return self.getDBITClock()
@dbitclk.setter
@@ -3657,10 +3670,16 @@ class Detector(CppDetectorApi):
@element
def adcclk(self):
"""
[Ctb] Sets ADC clock frequency in MHz. \n
[Xilinx Ctb] Sets ADC clock frequency in kHz.
"""
[Ctb][Xilinx Ctb] Sets ADC clock frequency.
Example
--------
>>> d.adcclk
>>> 10MHz
>>> d.adcclk = MHz(5)
>>> d.adcclk = Hz(5 * 1000 * 1000)
>>> d.adcclk = kHz(2000)
"""
return self.getADCClock()
@adcclk.setter
@@ -3671,7 +3690,7 @@ class Detector(CppDetectorApi):
@element
def syncclk(self):
"""
[Ctb] Sync clock in MHz.
[Ctb] Sync clock.
:setter: Not implemented
"""
@@ -3704,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");
+188
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."""
@@ -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_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)
@@ -628,11 +628,14 @@
#define ADC_SLOW_CTRL_DONE_OFST (1)
#define ADC_SLOW_CTRL_DONE_MSK (0x00000001 << ADC_SLOW_CTRL_DONE_OFST)
/* Clock Measurement base reg */
#define PLL_FREQ_MEASURE_REG (0x44 << MEM_MAP_SHIFT)
/* SPI */
#define SPI_CTRL_REG (0x48 << MEM_MAP_SHIFT)
#define SPI_CTRL_RX_EMPTY_BIT 2
#define SPI_CTRL_CHIPSELECT_BIT 4
#define SPI_CTRL_NBIT_OFST 16
#define SPI_CTRL_RX_EMPTY_BIT 2
#define SPI_CTRL_CHIPSELECT_BIT 4
#define SPI_CTRL_NBIT_OFST 16
#define SPI_WRITEDATA_REG (0x49 << MEM_MAP_SHIFT)
#define SPI_READDATA_REG (0x4A << MEM_MAP_SHIFT)
@@ -13,6 +13,7 @@
#include "communication_funcs_UDP.h"
#include "loadPattern.h"
#include <math.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
@@ -65,7 +66,7 @@ uint8_t adcEnableMask_10g = 0xFF;
uint32_t transceiverMask = DEFAULT_TRANSCEIVER_MASK;
int32_t clkPhase[NUM_CLOCKS] = {};
uint32_t clkFrequency[NUM_CLOCKS] = {40, 20, 20, 200};
uint32_t clkFrequency[NUM_CLOCKS] = {};
int dacValues[NDAC_ONLY] = {};
int powerValues[NPWR] = {}; // powerIndex (A->IO, Chip)
@@ -557,7 +558,7 @@ void setupDetector() {
ALTERA_PLL_SetDefines(PLL_CNTRL_REG, PLL_PARAM_REG,
PLL_CNTRL_RCNFG_PRMTR_RST_MSK, PLL_CNTRL_WR_PRMTR_MSK,
PLL_CNTRL_PLL_RST_MSK, PLL_CNTRL_ADDR_MSK,
PLL_CNTRL_ADDR_OFST);
PLL_CNTRL_ADDR_OFST, PLL_FREQ_MEASURE_REG);
ALTERA_PLL_ResetPLLAndReconfiguration();
resetCore();
@@ -632,10 +633,16 @@ void setupDetector() {
DEFAULT_NUM_SAMPLES); // update databytes and allocate ram
setNumTransceiverSamples(DEFAULT_NUM_SAMPLES);
setNumFrames(DEFAULT_NUM_FRAMES);
setExpTime(DEFAULT_EXPTIME);
initError = setExpTime(DEFAULT_EXPTIME, initErrorMessage);
if (initError == FAIL)
return;
setNumTriggers(DEFAULT_NUM_CYCLES);
setPeriod(DEFAULT_PERIOD);
setDelayAfterTrigger(DEFAULT_DELAY);
initError = setPeriod(DEFAULT_PERIOD, initErrorMessage);
if (initError == FAIL)
return;
initError = setDelayAfterTrigger(DEFAULT_DELAY, initErrorMessage);
if (initError == FAIL)
return;
setTiming(DEFAULT_TIMING_MODE);
setADCEnableMask(BIT32_MSK);
setADCEnableMask_10G(BIT32_MSK);
@@ -1134,64 +1141,132 @@ int setNumTransceiverSamples(int val) {
int getNumTransceiverSamples() { return ntSamples; }
int setExpTime(int64_t val) {
int setExpTime(int64_t val, char *mess) {
setPatternWaitInterval(0, val);
// validate for tolerance
int64_t retval = getExpTime();
// validate
uint64_t arg_clocks = ns_to_clocks(val, clkFrequency[RUN_CLK]);
uint64_t retval_clocks = getPatternWaitClocks(0);
if (arg_clocks != retval_clocks) {
sprintf(mess,
"Failed to set exposure time. Could not set number of clocks "
"to %lld, read %lld\n",
(long long int)arg_clocks, (long long int)retval_clocks);
LOG(logERROR, (mess));
return FAIL;
}
// log rounding if any
int64_t retval = getPatternWaitInterval(0);
if (val != retval) {
LOG(logWARNING, ("Rounding to %lld ns due to clock frequency\n",
(long long int)retval));
}
return OK;
}
int getExpTime(int64_t *retval, char *mess) {
*retval = getPatternWaitInterval(0);
if (*retval == -1) {
sprintf(mess, "Failed to get exposure time.\n");
LOG(logERROR, (mess));
return FAIL;
}
return OK;
}
int64_t getExpTime() { return getPatternWaitInterval(0); }
int setPeriod(int64_t val) {
int setPeriod(int64_t val, char *mess) {
if (val < 0) {
LOG(logERROR, ("Invalid period: %lld ns\n", (long long int)val));
sprintf(mess, "Invalid period: %lld ns\n", (long long int)val);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("Setting period %lld ns\n", (long long int)val));
val *= (1E-3 * clkFrequency[SYNC_CLK]);
set64BitReg(val, PERIOD_LSB_REG, PERIOD_MSB_REG);
uint64_t arg_clocks = ns_to_clocks(val, clkFrequency[SYNC_CLK]);
set64BitReg(arg_clocks, PERIOD_LSB_REG, PERIOD_MSB_REG);
// validate for tolerance
int64_t retval = getPeriod();
val /= (1E-3 * clkFrequency[SYNC_CLK]);
if (val != retval) {
// validate
uint64_t retval_clocks = get64BitReg(PERIOD_LSB_REG, PERIOD_MSB_REG);
if (arg_clocks != retval_clocks) {
sprintf(mess,
"Failed to set period. Could not set number of clocks "
"to %lld, red %lld\n",
(long long int)arg_clocks, (long long int)retval_clocks);
LOG(logERROR, (mess));
return FAIL;
}
// log rounding if any
int64_t retval = 0;
if (getPeriod(&retval, mess) == FAIL) {
return FAIL;
}
if (val != retval) {
LOG(logWARNING, ("Rounding to %lld ns due to clock frequency\n",
(long long int)retval));
}
return OK;
}
int64_t getPeriod() {
return get64BitReg(PERIOD_LSB_REG, PERIOD_MSB_REG) /
(1E-3 * clkFrequency[SYNC_CLK]);
int getPeriod(int64_t *retval, char *mess) {
if (clkFrequency[SYNC_CLK] == 0) {
sprintf(mess, "Cannot get period. Sync clock frequency is 0.\n");
LOG(logERROR, (mess));
return FAIL;
}
uint64_t numClocks = get64BitReg(PERIOD_LSB_REG, PERIOD_MSB_REG);
*retval = clocks_to_ns(numClocks, clkFrequency[SYNC_CLK]);
return OK;
}
int setDelayAfterTrigger(int64_t val) {
int setDelayAfterTrigger(int64_t val, char *mess) {
if (val < 0) {
LOG(logERROR,
("Invalid delay after trigger: %lld ns\n", (long long int)val));
sprintf(mess, "Invalid delay after trigger: %lld ns\n",
(long long int)val);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("Setting delay after trigger %lld ns\n", (long long int)val));
val *= (1E-3 * clkFrequency[SYNC_CLK]);
set64BitReg(val, DELAY_LSB_REG, DELAY_MSB_REG);
uint64_t arg_clocks = ns_to_clocks(val, clkFrequency[SYNC_CLK]);
set64BitReg(arg_clocks, DELAY_LSB_REG, DELAY_MSB_REG);
// validate for tolerance
int64_t retval = getDelayAfterTrigger();
val /= (1E-3 * clkFrequency[SYNC_CLK]);
if (val != retval) {
// validate
uint64_t retval_clocks = get64BitReg(DELAY_LSB_REG, DELAY_MSB_REG);
if (arg_clocks != retval_clocks) {
sprintf(
mess,
"Failed to set delay after trigger. Could not set number of clocks "
"to %lld, read %lld\n",
(long long int)arg_clocks, (long long int)retval_clocks);
LOG(logERROR, (mess));
return FAIL;
}
// log rounding if any
int64_t retval = 0;
if (getDelayAfterTrigger(&retval, mess) == FAIL) {
return FAIL;
}
if (val != retval) {
LOG(logWARNING, ("Rounding to %lld ns due to clock frequency\n",
(long long int)retval));
}
return OK;
}
int64_t getDelayAfterTrigger() {
return get64BitReg(DELAY_LSB_REG, DELAY_MSB_REG) /
(1E-3 * clkFrequency[SYNC_CLK]);
int getDelayAfterTrigger(int64_t *retval, char *mess) {
if (clkFrequency[SYNC_CLK] == 0) {
sprintf(mess,
"Cannot get delay after trigger. Sync clock frequency is 0.\n");
LOG(logERROR, (mess));
return FAIL;
}
uint64_t numClocks = get64BitReg(DELAY_LSB_REG, DELAY_MSB_REG);
*retval = clocks_to_ns(numClocks, clkFrequency[SYNC_CLK]);
return OK;
}
int64_t getNumFramesLeft() {
@@ -1202,14 +1277,27 @@ int64_t getNumTriggersLeft() {
return get64BitReg(CYCLES_LEFT_LSB_REG, CYCLES_LEFT_MSB_REG);
}
int64_t getDelayAfterTriggerLeft() {
return get64BitReg(DELAY_LEFT_LSB_REG, DELAY_LEFT_MSB_REG) /
(1E-3 * clkFrequency[SYNC_CLK]);
int getDelayAfterTriggerLeft(int64_t *retval, char *mess) {
if (clkFrequency[SYNC_CLK] == 0) {
sprintf(mess, "Cannot get delay after trigger left. Sync clock "
"frequency is 0.\n");
LOG(logERROR, (mess));
return FAIL;
}
uint64_t numClocks = get64BitReg(DELAY_LEFT_LSB_REG, DELAY_LEFT_MSB_REG);
*retval = clocks_to_ns(numClocks, clkFrequency[SYNC_CLK]);
return OK;
}
int64_t getPeriodLeft() {
return get64BitReg(PERIOD_LEFT_LSB_REG, PERIOD_LEFT_MSB_REG) /
(1E-3 * clkFrequency[SYNC_CLK]);
int getPeriodLeft(int64_t *retval, char *mess) {
if (clkFrequency[SYNC_CLK] == 0) {
sprintf(mess, "Cannot get period left. Sync clock frequency is 0.\n");
LOG(logERROR, (mess));
return FAIL;
}
uint64_t numClocks = get64BitReg(PERIOD_LEFT_LSB_REG, PERIOD_LEFT_MSB_REG);
*retval = clocks_to_ns(numClocks, clkFrequency[SYNC_CLK]);
return OK;
}
int64_t getFramesFromStart() {
@@ -1218,13 +1306,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 */
@@ -2206,13 +2295,12 @@ int getMaxPhase(enum CLKINDEX ind) {
LOG(logERROR, ("Unknown clock index %d to get max phase\n", ind));
return -1;
}
int ret = ((double)PLL_VCO_FREQ_MHZ / (double)clkFrequency[ind]) *
int ret = ((double)PLL_VCO_FREQ_HZ / (double)clkFrequency[ind]) *
MAX_PHASE_SHIFTS_STEPS;
char *clock_names[] = {CLK_NAMES};
LOG(logDEBUG1,
("Max Phase Shift (%s): %d (Clock: %d MHz, VCO:%d MHz)\n",
clock_names[ind], ret, clkFrequency[ind], PLL_VCO_FREQ_MHZ));
LOG(logDEBUG1, ("Max Phase Shift (%s): %d (Clock: %d Hz, VCO:%d Hz)\n",
clock_names[ind], ret, clkFrequency[ind], PLL_VCO_FREQ_HZ));
return ret;
}
@@ -2248,12 +2336,12 @@ int setFrequency(enum CLKINDEX ind, int val) {
return FAIL;
}
char *clock_names[] = {CLK_NAMES};
LOG(logINFO, ("\tSetting %s clock (%d) frequency to %d MHz\n",
LOG(logINFO, ("\tSetting %s clock (%d) frequency to %d Hz\n",
clock_names[ind], ind, val));
// check adc clk too high
if (ind == ADC_CLK && val > MAXIMUM_ADC_CLK) {
LOG(logERROR, ("Frequency %d MHz too high for ADC\n", val));
LOG(logERROR, ("Frequency %d Hz too high for ADC\n", val));
return FAIL;
}
@@ -2265,8 +2353,8 @@ int setFrequency(enum CLKINDEX ind, int val) {
// Calculate and set output frequency
clkFrequency[ind] =
ALTERA_PLL_SetOuputFrequency(ind, PLL_VCO_FREQ_MHZ, val);
LOG(logINFO, ("\t%s clock (%d) frequency set to %d MHz\n", clock_names[ind],
ALTERA_PLL_SetOutputFrequency(ind, PLL_VCO_FREQ_HZ, val);
LOG(logINFO, ("\t%s clock (%d) frequency set to %d Hz\n", clock_names[ind],
ind, clkFrequency[ind]));
// phase reset by pll (when setting output frequency)
@@ -2294,6 +2382,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);
// checking against 0 here ensures compatibility with old firmware, TODO:
// remove this check at some point
if (measuredFreqHz != 0) {
// Round to nearest Hz. (should we round at all ?)
clkFrequency[ind] = measuredFreqHz;
}
#endif
return clkFrequency[ind];
}
@@ -2507,10 +2606,21 @@ void *start_timer(void *arg) {
return NULL;
}
int64_t periodNs = getPeriod();
int64_t periodNs = 0;
int64_t expUs = 0;
{
char mess[MAX_STR_LENGTH] = {0};
if (getPeriod(&periodNs, mess) == FAIL) {
LOG(logERROR, ("Failed to get period.\n"));
return NULL;
}
if (getExpTime(&expUs, mess) == FAIL) {
LOG(logERROR, ("Failed to get exposure time.\n"));
return NULL;
}
expUs /= 1000;
}
int numFrames = (getNumFrames() * getNumTriggers());
int64_t expUs = getExpTime() / 1000;
int imageSize = dataBytes;
int dataSize = UDP_PACKET_DATA_BYTES;
int packetSize = sizeof(sls_detector_header) + dataSize;
@@ -98,10 +98,10 @@ void setNumFrames(int64_t val);
int64_t getNumFrames();
void setNumTriggers(int64_t val);
int64_t getNumTriggers();
int setExpTime(int64_t val);
int64_t getExpTime();
int setPeriod(int64_t val);
int64_t getPeriod();
int setExpTime(int64_t val, char *mess);
int getExpTime(int64_t *retval, char *mess);
int setPeriod(int64_t val, char *mess);
int getPeriod(int64_t *retval, char *mess);
int setNumAnalogSamples(int val);
int getNumAnalogSamples();
int setNumDigitalSamples(int val);
@@ -111,10 +111,10 @@ int getNumTransceiverSamples();
int64_t getNumFramesLeft();
int64_t getNumTriggersLeft();
int setDelayAfterTrigger(int64_t val);
int64_t getDelayAfterTrigger();
int64_t getDelayAfterTriggerLeft();
int64_t getPeriodLeft();
int setDelayAfterTrigger(int64_t val, char *mess);
int getDelayAfterTrigger(int64_t *retval, char *mess);
int getDelayAfterTriggerLeft(int64_t *retval, char *mess);
int getPeriodLeft(int64_t *retval, char *mess);
int64_t getFramesFromStart();
int64_t getActualTime();
int64_t getMeasurementTime();
@@ -44,13 +44,16 @@
#define DEFAULT_VLIMIT (0)
#define DEFAULT_TIMING_MODE (AUTO_TIMING)
#define DEFAULT_TX_UDP_PORT (0x7e9a)
#define DEFAULT_RUN_CLK (200) // 40
#define DEFAULT_ADC_CLK (40) // 20
#define DEFAULT_SYNC_CLK (40) // 20
#define DEFAULT_DBIT_CLK (200)
#define NS_TO_CLK_CYCLE (1E-3) // 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)
@@ -89,8 +92,8 @@
#define BIT32_MSK (0xFFFFFFFF)
#define BIT16_MASK (0xFFFF)
#define MAXIMUM_ADC_CLK (65)
#define PLL_VCO_FREQ_MHZ (800)
#define MAXIMUM_ADC_CLK (65000000) // 65 MHz
#define PLL_VCO_FREQ_HZ (800000000) // 800MHz
/* Struct Definitions */
typedef struct udp_header_struct {
@@ -163,7 +163,6 @@ int setPhase(enum CLKINDEX ind, int val, int degrees);
int getPhase(enum CLKINDEX ind, int degrees);
int getMaxPhase(enum CLKINDEX ind);
int validatePhaseinDegrees(enum CLKINDEX ind, int val, int retval);
// void setFrequency(enum CLKINDEX ind, int val);
int getFrequency(enum CLKINDEX ind);
int getVCOFrequency(enum CLKINDEX ind);
int setReadoutSpeed(int val);
@@ -195,7 +195,6 @@ int setPhase(enum CLKINDEX ind, int val, int degrees);
int getPhase(enum CLKINDEX ind, int degrees);
int getMaxPhase(enum CLKINDEX ind);
int validatePhaseinDegrees(enum CLKINDEX ind, int val, int retval);
// void setFrequency(enum CLKINDEX ind, int val);
int getFrequency(enum CLKINDEX ind);
int getVCOFrequency(enum CLKINDEX ind);
int getMaxClockDivider();
@@ -20,6 +20,10 @@
void ALTERA_PLL_SetDefines(uint32_t creg, uint32_t preg, uint32_t rprmsk,
uint32_t wpmsk, uint32_t prmsk, uint32_t amsk,
int aofst, uint32_t wd2msk, int clk2Index);
#elif defined(CHIPTESTBOARDD)
void ALTERA_PLL_SetDefines(uint32_t creg, uint32_t preg, uint32_t rprmsk,
uint32_t wpmsk, uint32_t prmsk, uint32_t amsk,
int aofst, uint32_t freqreg);
#else
/**
* Set Defines
@@ -71,8 +75,15 @@ void ALTERA_PLL_SetModePolling();
/**
* Calculate and write output frequency
* @param clkIndex clock index
* @param pllVCOFreqMhz PLL VCO Frequency in Mhz
* @param pllVCOFreqHz PLL VCO Frequency in Hz
* @param value frequency to set to
* @param frequency set
*/
int ALTERA_PLL_SetOuputFrequency(int clkIndex, int pllVCOFreqMhz, int value);
int ALTERA_PLL_SetOutputFrequency(int clkIndex, int pllVCOFreqHz, int value);
/**
* get measured clock frequency
*/
#if defined(CHIPTESTBOARDD)
uint32_t ALTERA_PLL_getFrequency(uint32_t clkIDX);
#endif
@@ -2,6 +2,7 @@
// Copyright (C) 2021 Contributors to the SLS Detector Package
#pragma once
#include "clogger.h"
#include "sls/md5.h"
#include <stdint.h> // int64_t
#include <stdio.h>
@@ -21,6 +22,19 @@
enum numberMode { DEC, HEX };
enum PROGRAM_INDEX { PROGRAM_FPGA, PROGRAM_KERNEL, PROGRAM_SERVER };
#define NS_PER_SEC 1000000000ULL
#define HALF_NS_PER_SEC (NS_PER_SEC / 2)
static inline uint64_t ns_to_clocks(uint64_t t, uint32_t freq_hz) {
return (t * (uint64_t)freq_hz + HALF_NS_PER_SEC) / NS_PER_SEC;
}
static inline uint64_t clocks_to_ns(uint64_t clocks, uint32_t freq_hz) {
if (freq_hz == 0) {
LOG(logERROR, ("Frequency is 0, cannot convert clocks to ns\n"));
return (uint64_t)-1;
}
return (clocks * (uint64_t)NS_PER_SEC + freq_hz / 2) / freq_hz;
}
/**
* Convert a value from a range to a different range (eg voltage to dac or vice
* versa)
@@ -130,7 +130,8 @@ uint32_t ALTERA_PLL_Cntrl_WrPrmtrMask = 0x0;
#if defined(JUNGFRAUD)
uint32_t ALTERA_PLL_Cntrl_DBIT_PLL_WrPrmtrMask = 0x0;
int ALTERA_PLL_Cntrl_DBIT_ClkIndex = 0;
#elif defined(CHIPTESTBOARDD)
uint32_t ALTERA_PLL_FREQ_MEASURE_BASE = 0x0;
#endif
uint32_t ALTERA_PLL_Cntrl_PLLRstMask = 0x0;
uint32_t ALTERA_PLL_Cntrl_AddrMask = 0x0;
@@ -150,6 +151,19 @@ void ALTERA_PLL_SetDefines(uint32_t creg, uint32_t preg, uint32_t rprmsk,
ALTERA_PLL_Cntrl_DBIT_PLL_WrPrmtrMask = wd2msk;
ALTERA_PLL_Cntrl_DBIT_ClkIndex = clk2Index;
}
#elif defined(CHIPTESTBOARDD)
void ALTERA_PLL_SetDefines(uint32_t creg, uint32_t preg, uint32_t rprmsk,
uint32_t wpmsk, uint32_t prmsk, uint32_t amsk,
int aofst, uint32_t freqreg) {
ALTERA_PLL_Cntrl_Reg = creg;
ALTERA_PLL_Param_Reg = preg;
ALTERA_PLL_Cntrl_RcnfgPrmtrRstMask = rprmsk;
ALTERA_PLL_Cntrl_WrPrmtrMask = wpmsk;
ALTERA_PLL_Cntrl_PLLRstMask = prmsk;
ALTERA_PLL_Cntrl_AddrMask = amsk;
ALTERA_PLL_Cntrl_AddrOfst = aofst;
ALTERA_PLL_FREQ_MEASURE_BASE = freqreg;
}
#else
void ALTERA_PLL_SetDefines(uint32_t creg, uint32_t preg, uint32_t rprmsk,
uint32_t wpmsk, uint32_t prmsk, uint32_t amsk,
@@ -269,12 +283,12 @@ void ALTERA_PLL_SetModePolling() {
ALTERA_PLL_MODE_PLLNG_MD_VAL, 0);
}
int ALTERA_PLL_SetOuputFrequency(int clkIndex, int pllVCOFreqMhz, int value) {
LOG(logDEBUG1, ("C%d: Setting output frequency to %d (pllvcofreq: %dMhz)\n",
clkIndex, value, pllVCOFreqMhz));
int ALTERA_PLL_SetOutputFrequency(int clkIndex, int pllVCOFreqHz, int value) {
LOG(logDEBUG1, ("C%d: Setting output frequency to %d (pllvcofreq: %dHz)\n",
clkIndex, value, pllVCOFreqHz));
// calculate output frequency
uint32_t total_div = (float)pllVCOFreqMhz / (float)value;
// calculate output frequency, round to next closest integer division
uint32_t total_div = (pllVCOFreqHz + value / 2) / value;
// assume 50% duty cycle
uint32_t low_count = total_div / 2;
@@ -307,11 +321,24 @@ int ALTERA_PLL_SetOuputFrequency(int clkIndex, int pllVCOFreqMhz, int value) {
// as adc clock is stopped temporarily when resetting pll)
ALTERA_PLL_ResetPLL();
/*double temp = ((double)pllVCOFreqMhz / (double)(low_count + high_count));
/*double temp = ((double)pllVCOFreqHz / (double)(low_count + high_count));
if ((temp - (int)temp) > 0.0001) {
temp += 0.5;
}
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
return value;
}
#if defined(CHIPTESTBOARDD)
uint32_t ALTERA_PLL_getFrequency(uint32_t clk_index) {
return bus_r(ALTERA_PLL_FREQ_MEASURE_BASE + clk_index * 2);
}
#endif
@@ -11,9 +11,9 @@
// leave some things away)
// clang-format off
#define XILINX_PLL_INPUT_FREQ (100000) // 100 MHz
#define XILINX_PLL_MIN_FREQ (10000)
#define XILINX_PLL_MAX_FREQ (250000)
#define XILINX_PLL_INPUT_FREQ (100000000) // 100 MHz
#define XILINX_PLL_MIN_FREQ (10000000)
#define XILINX_PLL_MAX_FREQ (250000000)
#define XILINX_PLL_MAX_CLK_DIV (256)
#define XILINX_PLL_NUM_CLKS (7)
#define XILINX_PLL_MAX_NUM_CLKS_FOR_GET (3)
@@ -71,14 +71,14 @@
// clang-format on
// freq in kHz !!
// freq in Hz !!
int XILINX_PLL_setFrequency(uint32_t clk_index, uint32_t freq) {
if (clk_index >= XILINX_PLL_NUM_CLKS) {
LOG(logERROR, ("XILINX_PLL: Invalid clock index %d\n", clk_index));
return 1;
}
if (freq < XILINX_PLL_MIN_FREQ || freq > XILINX_PLL_MAX_FREQ) {
LOG(logERROR, ("XILINX_PLL: Frequency %d kHz is out of range\n", freq));
LOG(logERROR, ("XILINX_PLL: Frequency %d Hz is out of range\n", freq));
return 1;
}
@@ -160,11 +160,7 @@ uint32_t XILINX_PLL_getFrequency(uint32_t clk_index) {
clk_index -= XILINX_PLL_MEASURE_BASE_ADDR0_MAX_CLKS;
base_addr = XILINX_PLL_MEASURE_BASE_ADDR1;
}
uint32_t addr = base_addr + clk_index * XILINX_PLL_MEASURE_WIDTH;
uint32_t counter_val = bus_r_csp2(addr);
// Hz => round to nearest kHz
uint32_t freq_kHz = (counter_val + 500) / 1000; // round to nearest kHz
return freq_kHz;
return bus_r_csp2(base_addr + clk_index * XILINX_PLL_MEASURE_WIDTH);
}
bool XILINX_PLL_isLocked() {
@@ -11,7 +11,7 @@
#ifdef MYTHEN3D
extern enum TLogLevel trimmingPrint;
extern uint32_t clkDivider[];
extern int getFrequency(enum CLKINDEX ind);
#endif
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
extern uint32_t clkFrequency[];
@@ -277,6 +277,14 @@ int validate_getPatternWaitClocksAndInterval(char *message, int level,
*waittime = getPatternWaitClocks(level);
} else {
*waittime = getPatternWaitInterval(level);
if (*waittime == (uint64_t)-1) {
sprintf(
message,
"Cannot get pattern wait interval for level %d. runclk is 0.\n",
level);
LOG(logERROR, (message));
return FAIL;
}
}
return OK;
}
@@ -297,17 +305,17 @@ uint64_t getPatternWaitClocks(int level) {
uint64_t getPatternWaitInterval(int level) {
uint64_t numClocks = getPatternWaitClocks(level);
int runclk = 0;
uint32_t runclk = 0;
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
runclk = clkFrequency[RUN_CLK];
#elif MYTHEN3D
runclk = clkDivider[SYSTEM_C0];
runclk = getFrequency(SYSTEM_C0);
#endif
if (runclk == 0) {
LOG(logERROR, ("runclk is 0. Cannot divide by 0. Returning -1.\n"));
return -1;
}
return numClocks / (NS_TO_CLK_CYCLE * runclk);
return clocks_to_ns(numClocks, runclk);
}
int validate_setPatternWaitClocksAndInterval(char *message, int level,
@@ -321,27 +329,50 @@ int validate_setPatternWaitClocksAndInterval(char *message, int level,
return FAIL;
}
uint64_t retval = 0;
if (clocks) {
setPatternWaitClocks(level, waittime);
// validate result
retval = getPatternWaitClocks(level);
uint64_t retval = getPatternWaitClocks(level);
LOG(logDEBUG1, ("Pattern wait time in clocks (level:%d) retval: %d\n",
level, (long long int)retval));
} else {
setPatternWaitInterval(level, waittime);
// validate result
retval = getPatternWaitInterval(level);
LOG(logDEBUG1, ("Pattern wait time (level:%d) retval: %d\n", level,
(long long int)retval));
int ret = OK;
char mode[128];
memset(mode, 0, sizeof(mode));
sprintf(mode, "set pattern Loop %d wait time (clocks)", level);
validate64(&ret, message, waittime, retval, mode, DEC);
return ret;
}
int ret = OK;
char mode[128];
memset(mode, 0, sizeof(mode));
sprintf(mode, "set pattern Loop %d wait time", level);
validate64(&ret, message, waittime, retval, mode, DEC);
return ret;
// interval
setPatternWaitInterval(level, waittime);
// validate
uint32_t runclk = 0;
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
runclk = clkFrequency[RUN_CLK];
#elif MYTHEN3D
runclk = getFrequency(SYSTEM_C0);
#endif
uint64_t arg_clocks = ns_to_clocks(waittime, runclk);
uint64_t retval_clocks = getPatternWaitClocks(level);
if (arg_clocks != retval_clocks) {
sprintf(message,
"Failed to set pattern loop %d wait interval. Could not set "
"number of clocks to %lld, read %lld\n",
level, (long long int)arg_clocks, (long long int)retval_clocks);
LOG(logERROR, (message));
return FAIL;
}
// log rounding if any
uint64_t retval = getPatternWaitInterval(level);
if (waittime != retval) {
LOG(logWARNING, ("Rounding to %lld ns due to clock frequency\n",
(long long int)retval));
}
return OK;
}
void setPatternWaitClocks(int level, uint64_t t) {
@@ -375,13 +406,13 @@ void setPatternWaitInterval(int level, uint64_t t) {
#endif
("Setting Pattern Wait Time (level:%d) :%lld ns\n", level,
(long long int)t));
int runclk = 0;
uint32_t runclk = 0;
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
runclk = clkFrequency[RUN_CLK];
#elif MYTHEN3D
runclk = clkDivider[SYSTEM_C0];
runclk = getFrequency(SYSTEM_C0);
#endif
uint64_t numClocks = t * (NS_TO_CLK_CYCLE * runclk);
uint64_t numClocks = ns_to_clocks(t, runclk);
setPatternWaitClocks(level, numClocks);
}
@@ -2402,7 +2402,11 @@ int get_exptime(int file_des) {
"for this detector\n");
LOG(logERROR, (mess));
} else {
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
ret = getExpTime(&retval, mess);
#else
retval = getExpTime();
#endif
LOG(logDEBUG1, ("retval exptime %lld ns\n", (long long int)retval));
}
#endif
@@ -2472,6 +2476,9 @@ int set_exptime(int file_des) {
"for this detector\n");
LOG(logERROR, (mess));
} else {
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
ret = setExpTime(val, mess);
#else
ret = setExpTime(val);
int64_t retval = getExpTime();
LOG(logDEBUG1, ("retval exptime %lld ns\n", (long long int)retval));
@@ -2482,6 +2489,7 @@ int set_exptime(int file_des) {
(long long int)val, (long long int)retval);
LOG(logERROR, (mess));
}
#endif
}
#endif
}
@@ -2494,7 +2502,11 @@ int get_period(int file_des) {
int64_t retval = -1;
// get only
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
ret = getPeriod(&retval, mess);
#else
retval = getPeriod();
#endif
LOG(logDEBUG1, ("retval period %lld ns\n", (long long int)retval));
return Server_SendResult(file_des, INT64, &retval, sizeof(retval));
}
@@ -2510,6 +2522,9 @@ int set_period(int file_des) {
// only set
if (Server_VerifyLock() == OK) {
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
ret = setPeriod(arg, mess);
#else
ret = setPeriod(arg);
int64_t retval = getPeriod();
LOG(logDEBUG1, ("retval period %lld ns\n", (long long int)retval));
@@ -2518,6 +2533,7 @@ int set_period(int file_des) {
(long long int)arg, (long long int)retval);
LOG(logERROR, (mess));
}
#endif
}
return Server_SendResult(file_des, INT64, NULL, 0);
}
@@ -2533,7 +2549,11 @@ int get_delay_after_trigger(int file_des) {
functionNotImplemented();
#else
// get only
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
ret = getDelayAfterTrigger(&retval, mess);
#else
retval = getDelayAfterTrigger();
#endif
LOG(logDEBUG1,
("retval delay after trigger %lld ns\n", (long long int)retval));
#endif
@@ -2557,6 +2577,9 @@ int set_delay_after_trigger(int file_des) {
#else
// only set
if (Server_VerifyLock() == OK) {
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
ret = setDelayAfterTrigger(arg, mess);
#else
ret = setDelayAfterTrigger(arg);
int64_t retval = getDelayAfterTrigger();
LOG(logDEBUG1,
@@ -2568,6 +2591,7 @@ int set_delay_after_trigger(int file_des) {
(long long int)arg, (long long int)retval);
LOG(logERROR, (mess));
}
#endif
}
#endif
return Server_SendResult(file_des, INT64, NULL, 0);
@@ -2802,7 +2826,11 @@ int get_period_left(int file_des) {
functionNotImplemented();
#else
// get only
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
ret = getPeriodLeft(&retval, mess);
#else
retval = getPeriodLeft();
#endif
LOG(logDEBUG1, ("retval period left %lld ns\n", (long long int)retval));
#endif
return Server_SendResult(file_des, INT64, &retval, sizeof(retval));
@@ -2819,7 +2847,11 @@ int get_delay_after_trigger_left(int file_des) {
functionNotImplemented();
#else
// get only
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
ret = getDelayAfterTriggerLeft(&retval, mess);
#else
retval = getDelayAfterTriggerLeft();
#endif
LOG(logDEBUG1,
("retval delay after trigger left %lld ns\n", (long long int)retval));
#endif
@@ -3306,10 +3338,6 @@ int set_pattern_wait_clocks(int file_des) {
if (ret == OK) {
ret = validate_getPatternWaitClocksAndInterval(mess, loopLevel,
&retval, 1);
if ((int64_t)timeval != GET_FLAG) {
validate64(&ret, mess, (int64_t)timeval, retval,
"set pattern wait clocks", DEC);
}
}
}
#endif
@@ -5693,11 +5721,9 @@ int set_clock_frequency(int file_des) {
case ADC_CLOCK:
c = ADC_CLK;
break;
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
case DBIT_CLOCK:
c = DBIT_CLK;
break;
#endif
case RUN_CLOCK:
c = RUN_CLK;
break;
@@ -5718,26 +5744,38 @@ int set_clock_frequency(int file_des) {
(int)c);
if (getFrequency(c) == val) {
LOG(logINFO, ("Same %s: %d %s\n", modeName, val,
myDetectorType == GOTTHARD2 ? "Hz" : "MHz"));
} else {
LOG(logINFO, ("Same %s: %d %s\n", modeName, val, "Hz"));
} 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,
myDetectorType == XILINX_CHIPTESTBOARD ? "kHz"
: "MHz");
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,
myDetectorType == XILINX_CHIPTESTBOARD ? "kHz"
: "MHz"));
#if !defined(XILINX_CHIPTESTBOARDD)
// XCTB will give the actual frequency, which is not
("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);
#endif
}
}
}
@@ -5790,14 +5828,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,
myDetectorType == XILINX_CHIPTESTBOARD
? "kHz"
: (myDetectorType == GOTTHARD2 || myDetectorType == MYTHEN3
? "Hz"
: "MHz")));
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));
@@ -7029,6 +7061,11 @@ int get_receiver_parameters(int file_des) {
// exptime
#ifdef MYTHEN3D
i64 = 0;
#elif defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
if (getExpTime(&i64, mess) == FAIL) {
sprintf(mess, "Could not get exposure time.\n");
return sendError(file_des);
}
#else
i64 = getExpTime();
#endif
@@ -7037,7 +7074,15 @@ int get_receiver_parameters(int file_des) {
return printSocketReadError();
// period
i64 = 0;
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
if (getPeriod(&i64, mess) == FAIL) {
sprintf(mess, "Could not get period.\n");
return sendError(file_des);
}
#else
i64 = getPeriod();
#endif
n += sendData(file_des, &i64, sizeof(i64), INT64);
if (n < 0)
return printSocketReadError();
@@ -10894,13 +10939,6 @@ int set_pattern_wait_interval(int file_des) {
if (Server_VerifyLock() == OK) {
ret = validate_setPatternWaitClocksAndInterval(mess, loopLevel, timeval,
0);
if (ret == OK) {
uint64_t retval = 0;
ret = validate_getPatternWaitClocksAndInterval(mess, loopLevel,
&retval, 0);
validate64(&ret, mess, (int64_t)timeval, retval,
"set pattern wait interval", DEC);
}
}
#endif
@@ -363,7 +363,7 @@ void initStopServer() {
return;
}
#ifdef VIRTUAL
sharedMemory_setStop(0);
setupDetector();
#endif
}
initCheckDone = 1;
@@ -389,9 +389,13 @@ void setupDetector() {
vLimit = DEFAULT_VLIMIT;
#ifdef VIRTUAL
sharedMemory_setStatus(IDLE);
setupUDPCommParameters();
initializePatternWord();
if (isControlServer) {
sharedMemory_setStatus(IDLE);
setupUDPCommParameters();
initializePatternWord();
} else {
sharedMemory_setStop(0);
}
#endif
// initialization only at start up (restart fpga)
initError = waitTransceiverReset(initErrorMessage);
@@ -444,9 +448,15 @@ void setupDetector() {
setNumFrames(DEFAULT_NUM_FRAMES);
setNumTriggers(DEFAULT_NUM_CYCLES);
setTiming(DEFAULT_TIMING_MODE);
setExpTime(DEFAULT_EXPTIME);
setPeriod(DEFAULT_PERIOD);
setDelayAfterTrigger(DEFAULT_DELAY);
initError = setExpTime(DEFAULT_EXPTIME, initErrorMessage);
if (initError == FAIL)
return;
initError = setPeriod(DEFAULT_PERIOD, initErrorMessage);
if (initError == FAIL)
return;
initError = setDelayAfterTrigger(DEFAULT_DELAY, initErrorMessage);
if (initError == FAIL)
return;
setNextFrameNumber(DEFAULT_STARTING_FRAME_NUMBER);
}
@@ -766,63 +776,132 @@ int getNumTransceiverSamples() {
return ((bus_r(NO_SAMPLES_X_REG) & NO_SAMPLES_X_MSK) >> NO_SAMPLES_X_OFST);
}
int setExpTime(int64_t val) {
int setExpTime(int64_t val, char *mess) {
setPatternWaitInterval(0, val);
// validate for tolerance
int64_t retval = getExpTime();
// validate
uint64_t arg_clocks = ns_to_clocks(val, clkFrequency[RUN_CLK]);
uint64_t retval_clocks = getPatternWaitClocks(0);
if (arg_clocks != retval_clocks) {
sprintf(mess,
"Failed to set exposure time. Could not set number of clocks "
"to %lld, read %lld\n",
(long long int)arg_clocks, (long long int)retval_clocks);
LOG(logERROR, (mess));
return FAIL;
}
// log rounding if any
int64_t retval = getPatternWaitInterval(0);
if (val != retval) {
LOG(logWARNING, ("Rounding to %lld ns due to clock frequency\n",
(long long int)retval));
}
return OK;
}
int getExpTime(int64_t *retval, char *mess) {
*retval = getPatternWaitInterval(0);
if (*retval == -1) {
sprintf(mess, "Failed to get exposure time.\n");
LOG(logERROR, (mess));
return FAIL;
}
return OK;
}
int64_t getExpTime() { return getPatternWaitInterval(0); }
int setPeriod(int64_t val) {
int setPeriod(int64_t val, char *mess) {
if (val < 0) {
LOG(logERROR, ("Invalid period: %lld ns\n", (long long int)val));
sprintf(mess, "Invalid period: %lld ns\n", (long long int)val);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("Setting period %lld ns\n", (long long int)val));
val *= (NS_TO_CLK_CYCLE * clkFrequency[RUN_CLK]);
setU64BitReg(val, PERIOD_IN_REG_1, PERIOD_IN_REG_2);
uint64_t arg_clocks = ns_to_clocks(val, clkFrequency[RUN_CLK]);
setU64BitReg(arg_clocks, PERIOD_IN_REG_1, PERIOD_IN_REG_2);
// validate for tolerance
int64_t retval = getPeriod();
val /= (NS_TO_CLK_CYCLE * clkFrequency[RUN_CLK]);
if (val != retval) {
// validate
uint64_t retval_clocks = getU64BitReg(PERIOD_IN_REG_1, PERIOD_IN_REG_2);
if (arg_clocks != retval_clocks) {
sprintf(mess,
"Failed to set period. Could not set number of clocks "
"to %lld, red %lld\n",
(long long int)arg_clocks, (long long int)retval_clocks);
LOG(logERROR, (mess));
return FAIL;
}
// log rounding if any
int64_t retval = 0;
if (getPeriod(&retval, mess) == FAIL) {
return FAIL;
}
if (val != retval) {
LOG(logWARNING, ("Rounding to %lld ns due to clock frequency\n",
(long long int)retval));
}
return OK;
}
int64_t getPeriod() {
return getU64BitReg(PERIOD_IN_REG_1, PERIOD_IN_REG_2) /
(NS_TO_CLK_CYCLE * clkFrequency[RUN_CLK]);
int getPeriod(int64_t *retval, char *mess) {
if (clkFrequency[RUN_CLK] == 0) {
sprintf(mess, "Cannot get period. Run clock frequency is 0.\n");
LOG(logERROR, (mess));
return FAIL;
}
uint64_t numClocks = getU64BitReg(PERIOD_IN_REG_1, PERIOD_IN_REG_2);
*retval = clocks_to_ns(numClocks, clkFrequency[RUN_CLK]);
return OK;
}
int setDelayAfterTrigger(int64_t val) {
int setDelayAfterTrigger(int64_t val, char *mess) {
if (val < 0) {
LOG(logERROR, ("Invalid delay after trigger: %ld ns\n", val));
sprintf(mess, "Invalid delay after trigger: %lld ns\n",
(long long int)val);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("Setting delay after trigger %ld ns\n", val));
val *= (NS_TO_CLK_CYCLE * clkFrequency[RUN_CLK]);
setU64BitReg(val, DELAY_IN_REG_1, DELAY_IN_REG_2);
LOG(logINFO, ("Setting delay after trigger %lld ns\n", (long long int)val));
uint64_t arg_clocks = ns_to_clocks(val, clkFrequency[RUN_CLK]);
setU64BitReg(arg_clocks, DELAY_IN_REG_1, DELAY_IN_REG_2);
// validate for tolerance
int64_t retval = getDelayAfterTrigger();
val /= (NS_TO_CLK_CYCLE * clkFrequency[RUN_CLK]);
if (val != retval) {
// validate
uint64_t retval_clocks = getU64BitReg(DELAY_IN_REG_1, DELAY_IN_REG_2);
if (arg_clocks != retval_clocks) {
sprintf(
mess,
"Failed to set delay after trigger. Could not set number of clocks "
"to %lld, read %lld\n",
(long long int)arg_clocks, (long long int)retval_clocks);
LOG(logERROR, (mess));
return FAIL;
}
// log rounding if any
int64_t retval = 0;
if (getDelayAfterTrigger(&retval, mess) == FAIL) {
return FAIL;
}
if (val != retval) {
LOG(logWARNING, ("Rounding to %lld ns due to clock frequency\n",
(long long int)retval));
}
return OK;
}
int64_t getDelayAfterTrigger() {
return getU64BitReg(DELAY_IN_REG_1, DELAY_IN_REG_2) /
(NS_TO_CLK_CYCLE * clkFrequency[RUN_CLK]);
int getDelayAfterTrigger(int64_t *retval, char *mess) {
if (clkFrequency[RUN_CLK] == 0) {
sprintf(mess,
"Cannot get delay after trigger. Run clock frequency is 0.\n");
LOG(logERROR, (mess));
return FAIL;
}
uint64_t numClocks = getU64BitReg(DELAY_IN_REG_1, DELAY_IN_REG_2);
*retval = clocks_to_ns(numClocks, clkFrequency[RUN_CLK]);
return OK;
}
int64_t getNumFramesLeft() {
@@ -833,14 +912,27 @@ int64_t getNumTriggersLeft() {
return getU64BitReg(CYCLES_OUT_REG_1, CYCLES_OUT_REG_2);
}
int64_t getDelayAfterTriggerLeft() {
return getU64BitReg(DELAY_OUT_REG_1, DELAY_OUT_REG_2) /
(NS_TO_CLK_CYCLE * clkFrequency[RUN_CLK]);
int getDelayAfterTriggerLeft(int64_t *retval, char *mess) {
if (clkFrequency[RUN_CLK] == 0) {
sprintf(mess, "Cannot get delay after trigger left. Run clock "
"frequency is 0.\n");
LOG(logERROR, (mess));
return FAIL;
}
uint64_t numClocks = getU64BitReg(DELAY_OUT_REG_1, DELAY_OUT_REG_2);
*retval = clocks_to_ns(numClocks, clkFrequency[RUN_CLK]);
return OK;
}
int64_t getPeriodLeft() {
return getU64BitReg(PERIOD_OUT_REG_1, PERIOD_OUT_REG_2) /
(NS_TO_CLK_CYCLE * clkFrequency[RUN_CLK]);
int getPeriodLeft(int64_t *retval, char *mess) {
if (clkFrequency[RUN_CLK] == 0) {
sprintf(mess, "Cannot get period left. Run clock frequency is 0.\n");
LOG(logERROR, (mess));
return FAIL;
}
uint64_t numClocks = getU64BitReg(PERIOD_OUT_REG_1, PERIOD_OUT_REG_2);
*retval = clocks_to_ns(numClocks, clkFrequency[RUN_CLK]);
return OK;
}
int64_t getFramesFromStart() {
@@ -849,13 +941,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 */
@@ -1447,11 +1540,22 @@ void *start_timer(void *arg) {
if (!isControlServer) {
return NULL;
}
int64_t periodNs = 0;
int64_t expUs = 0;
{
char mess[MAX_STR_LENGTH] = {0};
if (getPeriod(&periodNs, mess) == FAIL) {
LOG(logERROR, ("Failed to get period.\n"));
return NULL;
}
if (getExpTime(&expUs, mess) == FAIL) {
LOG(logERROR, ("Failed to get exposure time.\n"));
return NULL;
}
expUs /= 1000;
}
int64_t periodNs = getPeriod();
int numFrames = (getNumFrames() * getNumTriggers());
int64_t expUs = getExpTime() / 1000;
int imageSize = calculateDataBytes();
int maxDataSize = MAX_DATA_SIZE_IN_PACKET;
int packetSize = sizeof(sls_detector_header) + maxDataSize;
@@ -1716,11 +1820,11 @@ int setFrequency(enum CLKINDEX ind, int val) {
}
char *clock_names[] = {CLK_NAMES};
LOG(logINFO, ("\tSetting %s clock (%d) frequency to %d kHz\n",
LOG(logINFO, ("\tSetting %s clock (%d) frequency to %d Hz\n",
clock_names[ind], ind, val));
if (XILINX_PLL_setFrequency(ind, val) == FAIL) {
LOG(logERROR, ("\tCould not set %s clock (%d) frequency to %d kHz\n",
LOG(logERROR, ("\tCould not set %s clock (%d) frequency to %d Hz\n",
clock_names[ind], ind, val));
return FAIL;
}
@@ -84,10 +84,10 @@ void setNumFrames(int64_t val);
int64_t getNumFrames();
void setNumTriggers(int64_t val);
int64_t getNumTriggers();
int setExpTime(int64_t val);
int64_t getExpTime();
int setPeriod(int64_t val);
int64_t getPeriod();
int setExpTime(int64_t val, char *mess);
int getExpTime(int64_t *retval, char *mess);
int setPeriod(int64_t val, char *mess);
int getPeriod(int64_t *retval, char *mess);
int setNumAnalogSamples(int val);
int getNumAnalogSamples();
int setNumDigitalSamples(int val);
@@ -97,10 +97,10 @@ int getNumTransceiverSamples();
int64_t getNumFramesLeft();
int64_t getNumTriggersLeft();
int setDelayAfterTrigger(int64_t val);
int64_t getDelayAfterTrigger();
int64_t getDelayAfterTriggerLeft();
int64_t getPeriodLeft();
int setDelayAfterTrigger(int64_t val, char *mess);
int getDelayAfterTrigger(int64_t *retval, char *mess);
int getDelayAfterTriggerLeft(int64_t *retval, char *mess);
int getPeriodLeft(int64_t *retval, char *mess);
int64_t getFramesFromStart();
int64_t getActualTime();
int64_t getMeasurementTime();
@@ -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-6) // ns to kHz
#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
@@ -54,6 +54,9 @@ class Caller {
return ToString(value, unit);
}
std::string OutString(const Result<defs::Hz> &value,
const std::string &unit);
std::vector<std::string> getAllCommands();
std::map<std::string, std::string> GetDeprecatedCommands();
std::string list(int action);
@@ -96,6 +99,7 @@ class Caller {
defs::dacIndex parseDacIndex(int argIndex, bool isCtb);
bool parseMV(int argIndex);
defs::powerIndex parsePowerIndex(int argIndex);
defs::FrequencyUnit parseFrequencyUnit(const std::string &s);
FunctionMap functions{
{"list", &Caller::list},
@@ -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] ADC clock frequency in MHz.\n\t[xilinx Ctb] ADC clock frequency in kHz."
inherit_actions: INTEGER_COMMAND_VEC_ID
actions:
GET:
function: getADCClock
PUT:
function: setADCClock
runclk:
help: "[n_clk in MHz]\n\t[Ctb] Run clock in MHz.\n\t[xilinx Ctb] Run clock in kHz."
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] Clock for latching the digital bits in MHz.\n\t[xilinx Ctb] Clock for latching the digital bits in kHz."
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,28 +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] ADC clock frequency in MHz.\n\t[xilinx Ctb] ADC clock\
\ frequency in kHz."
help: "[n_clk] [(optional unit) Hz(default)|kHz|MHz]\n\t[Ctb][Xilinx Ctb] ADC clock\
\ frequency."
infer_action: true
template: true
adcenable:
@@ -2060,28 +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] Clock for latching the digital bits in MHz.\n\t[xilinx\
\ Ctb] Clock for latching the digital bits in kHz."
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:
@@ -5788,7 +5870,7 @@ patfname:
cast_input: []
check_det_id: false
convert_det_id: true
function: getPatterFileName
function: getPatternFileName
input: []
input_types: []
output:
@@ -8140,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] Run clock in MHz.\n\t[xilinx Ctb] Run clock in kHz."
help: "[n_clk] [(optional unit) Hz(default)|kHz|MHz]\n\t[Ctb][Xilinx Ctb] Run clock\
\ frequency."
infer_action: true
template: true
runtime:
@@ -10575,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 MHz, [XCTB] in kHz */
Result<int> getADCClock(Positions pos = {}) const;
/** [CTB][XCTB] */
Result<defs::Hz> getADCClock(Positions pos = {}) const;
/** [CTB] in MHz, [XCTB] in kHz */
void setADCClock(int value_in_MHz, Positions pos = {});
/** [CTB][XCTB] */
void setADCClock(defs::Hz val, Positions pos = {});
/** [CTB] in MHz, [XCTB] in kHz */
Result<int> getRUNClock(Positions pos = {}) const;
/** [CTB][XCTB] */
Result<defs::Hz> getRUNClock(Positions pos = {}) const;
/** [CTB] in MHz, [XCTB] in kHz */
void setRUNClock(int value_in_MHz, 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 MHz, [XCTB] in kHz */
Result<int> getDBITClock(Positions pos = {}) const;
/** [CTB] in MHz, [XCTB] in kHz */
void setDBITClock(int value_in_MHz, 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());
+117 -34
View File
@@ -72,34 +72,46 @@ std::string Caller::adcclk(int action) {
std::ostringstream os;
// print help
if (action == slsDetectorDefs::HELP_ACTION) {
os << R"V0G0N([n_clk in MHz]
[Ctb] ADC clock frequency in MHz.
[xilinx Ctb] ADC clock frequency in kHz. )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) {
if (1 && args.size() != 1) {
if (1 && args.size() != 1 && args.size() != 2) {
throw RuntimeError("Wrong number of arguments for action PUT");
}
if (args.size() == 1) {
try {
StringTo<int>(args[0]);
std::string tmp_freq(args[0]);
std::string unit = RemoveUnit(tmp_freq);
auto converted_freq = StringTo<defs::Hz>(tmp_freq, unit);
} catch (...) {
throw RuntimeError("Could not convert argument 0 to int");
throw RuntimeError("Could not convert argument to defs::Hz");
}
}
if (args.size() == 2) {
try {
StringTo<defs::Hz>(args[0], args[1]);
} catch (...) {
throw RuntimeError("Could not convert arguments to defs::Hz");
}
}
@@ -117,13 +129,26 @@ 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) {
auto arg0 = StringTo<int>(args[0]);
det->setADCClock(arg0, std::vector<int>{det_id});
os << args.front() << '\n';
std::string tmp_freq(args[0]);
std::string unit = RemoveUnit(tmp_freq);
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 = StringTo<defs::Hz>(args[0], args[1]);
det->setADCClock(converted_freq, std::vector<int>{det_id});
os << args[0] << args[1] << '\n';
}
}
@@ -2482,34 +2507,46 @@ std::string Caller::dbitclk(int action) {
std::ostringstream os;
// print help
if (action == slsDetectorDefs::HELP_ACTION) {
os << R"V0G0N([n_clk in MHz]
[Ctb] Clock for latching the digital bits in MHz.
[xilinx Ctb] Clock for latching the digital bits in kHz. )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) {
if (1 && args.size() != 1) {
if (1 && args.size() != 1 && args.size() != 2) {
throw RuntimeError("Wrong number of arguments for action PUT");
}
if (args.size() == 1) {
try {
StringTo<int>(args[0]);
std::string tmp_freq(args[0]);
std::string unit = RemoveUnit(tmp_freq);
auto converted_freq = StringTo<defs::Hz>(tmp_freq, unit);
} catch (...) {
throw RuntimeError("Could not convert argument 0 to int");
throw RuntimeError("Could not convert argument to defs::Hz");
}
}
if (args.size() == 2) {
try {
StringTo<defs::Hz>(args[0], args[1]);
} catch (...) {
throw RuntimeError("Could not convert arguments to defs::Hz");
}
}
@@ -2527,13 +2564,26 @@ 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) {
auto arg0 = StringTo<int>(args[0]);
det->setDBITClock(arg0, std::vector<int>{det_id});
os << args.front() << '\n';
std::string tmp_freq(args[0]);
std::string unit = RemoveUnit(tmp_freq);
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 = StringTo<defs::Hz>(args[0], args[1]);
det->setDBITClock(converted_freq, std::vector<int>{det_id});
os << args[0] << args[1] << '\n';
}
}
@@ -7312,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';
}
}
@@ -9909,34 +9959,46 @@ std::string Caller::runclk(int action) {
std::ostringstream os;
// print help
if (action == slsDetectorDefs::HELP_ACTION) {
os << R"V0G0N([n_clk in MHz]
[Ctb] Run clock in MHz.
[xilinx Ctb] Run clock in kHz. )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) {
if (1 && args.size() != 1) {
if (1 && args.size() != 1 && args.size() != 2) {
throw RuntimeError("Wrong number of arguments for action PUT");
}
if (args.size() == 1) {
try {
StringTo<int>(args[0]);
std::string tmp_freq(args[0]);
std::string unit = RemoveUnit(tmp_freq);
auto converted_freq = StringTo<defs::Hz>(tmp_freq, unit);
} catch (...) {
throw RuntimeError("Could not convert argument 0 to int");
throw RuntimeError("Could not convert argument to defs::Hz");
}
}
if (args.size() == 2) {
try {
StringTo<defs::Hz>(args[0], args[1]);
} catch (...) {
throw RuntimeError("Could not convert arguments to defs::Hz");
}
}
@@ -9954,13 +10016,26 @@ 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) {
auto arg0 = StringTo<int>(args[0]);
det->setRUNClock(arg0, std::vector<int>{det_id});
os << args.front() << '\n';
std::string tmp_freq(args[0]);
std::string unit = RemoveUnit(tmp_freq);
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 = StringTo<defs::Hz>(args[0], args[1]);
det->setRUNClock(converted_freq, std::vector<int>{det_id});
os << args[0] << args[1] << '\n';
}
}
@@ -13062,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 {
@@ -13091,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();
+4
View File
@@ -54,6 +54,9 @@ class Caller {
return ToString(value, unit);
}
std::string OutString(const Result<defs::Hz> &value,
const std::string &unit);
std::vector<std::string> getAllCommands();
std::map<std::string, std::string> GetDeprecatedCommands();
std::string list(int action);
@@ -421,6 +424,7 @@ class Caller {
defs::dacIndex parseDacIndex(int argIndex, bool isCtb);
bool parseMV(int argIndex);
defs::powerIndex parsePowerIndex(int argIndex);
defs::FrequencyUnit parseFrequencyUnit(const std::string &s);
FunctionMap functions{
{"list", &Caller::list},
+25
View File
@@ -11,6 +11,14 @@
namespace sls {
// some helper functions to print
std::string Caller::OutString(const Result<defs::Hz> &value,
const std::string &unit) {
auto u = parseFrequencyUnit(unit);
if (value.equal())
return ToString(value.front(), u);
return ToString(value, u);
}
std::vector<std::string> Caller::getAllCommands() {
std::vector<std::string> ret;
for (auto it : functions)
@@ -2105,4 +2113,21 @@ std::string Caller::powervalues(int action) {
return os.str();
}
defs::FrequencyUnit Caller::parseFrequencyUnit(const std::string &unit) {
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 == "hz")
return defs::FrequencyUnit::Hz;
if (unitLower == "khz")
return defs::FrequencyUnit::kHz;
if (unitLower == "mhz")
return defs::FrequencyUnit::MHz;
throw std::runtime_error("Unknown frequency unit: " + unit);
}
} // namespace sls
+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_MHz, Positions pos) {
void Detector::setADCClock(defs::Hz val, Positions pos) {
pimpl->Parallel(&Module::setClockFrequency, pos, defs::ADC_CLOCK,
value_in_MHz);
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_MHz, Positions pos) {
void Detector::setRUNClock(defs::Hz val, Positions pos) {
pimpl->Parallel(&Module::setClockFrequency, pos, defs::RUN_CLOCK,
value_in_MHz);
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_MHz, Positions pos) {
pimpl->Parallel(&Module::setClockFrequency, pos, defs::DBIT_CLOCK,
value_in_MHz);
}
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
@@ -2668,7 +2668,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,23 +921,65 @@ 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 10MHz\n");
}
{
std::ostringstream oss;
caller.call("adcclk", {"15000", "kHz"}, -1, PUT, oss);
REQUIRE(oss.str() == "adcclk 15000kHz\n");
}
{
std::ostringstream oss;
caller.call("adcclk", {}, -1, GET, oss);
REQUIRE(oss.str() == "adcclk 10\n");
REQUIRE(oss.str() == "adcclk 15MHz\n");
}
{
std::ostringstream oss;
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 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});
}
@@ -952,25 +994,119 @@ 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 10MHz\n");
}
{
std::ostringstream oss;
caller.call("runclk", {"15000", "kHz"}, -1, PUT, oss);
REQUIRE(oss.str() == "runclk 15000kHz\n");
}
{
std::ostringstream oss;
caller.call("runclk", {}, -1, GET, oss);
REQUIRE(oss.str() == "runclk 10\n");
REQUIRE(oss.str() == "runclk 15MHz\n");
}
{
std::ostringstream oss;
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 15.75MHz\n");
}
// tolerance
auto prev_exptime = det.getExptime();
auto prev_period = det.getPeriod();
auto prev_delay = det.getDelayAfterTrigger();
{
caller.call("runclk", {"80", "MHz"}, -1, PUT);
{
std::ostringstream oss;
REQUIRE_NOTHROW(
caller.call("exptime", {"10012", "ns"}, -1, PUT));
REQUIRE_NOTHROW(caller.call("exptime", {"ns"}, -1, GET, oss));
REQUIRE(oss.str() == "exptime 10013ns\n");
}
{
std::ostringstream oss;
REQUIRE_NOTHROW(
caller.call("exptime", {"10013", "ns"}, -1, PUT));
REQUIRE_NOTHROW(caller.call("exptime", {"ns"}, -1, GET, oss));
REQUIRE(oss.str() == "exptime 10013ns\n");
}
{
std::ostringstream oss;
REQUIRE_NOTHROW(
caller.call("exptime", {"10019", "ns"}, -1, PUT));
REQUIRE_NOTHROW(caller.call("exptime", {"ns"}, -1, GET, oss));
REQUIRE(oss.str() == "exptime 10025ns\n");
}
{
std::ostringstream oss;
REQUIRE_NOTHROW(
caller.call("period", {"10125", "ns"}, -1, PUT));
REQUIRE_NOTHROW(caller.call("period", {"ns"}, -1, GET, oss));
REQUIRE(oss.str() == "period 10125ns\n");
}
{
std::ostringstream oss;
REQUIRE_NOTHROW(
caller.call("period", {"10124", "ns"}, -1, PUT));
REQUIRE_NOTHROW(caller.call("period", {"ns"}, -1, GET, oss));
REQUIRE(oss.str() == "period 10125ns\n");
}
{
std::ostringstream oss;
REQUIRE_NOTHROW(caller.call("delay", {"10125", "ns"}, -1, PUT));
REQUIRE_NOTHROW(caller.call("delay", {"ns"}, -1, GET, oss));
REQUIRE(oss.str() == "delay 10125ns\n");
}
{
std::ostringstream oss;
REQUIRE_NOTHROW(caller.call("delay", {"10124", "ns"}, -1, PUT));
REQUIRE_NOTHROW(caller.call("delay", {"ns"}, -1, GET, oss));
REQUIRE(oss.str() == "delay 10125ns\n");
}
}
for (int i = 0; i != det.size(); ++i) {
det.setRUNClock(prev_val[i], {i});
det.setExptime(prev_exptime[i], {i});
det.setPeriod(prev_period[i], {i});
det.setDelayAfterTrigger(prev_delay[i], {i});
}
} else {
// clock index might work
@@ -983,6 +1119,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
@@ -1249,22 +1390,59 @@ 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 10MHz\n");
}
{
std::ostringstream oss;
caller.call("dbitclk", {"15000", "kHz"}, -1, PUT, oss);
REQUIRE(oss.str() == "dbitclk 15000kHz\n");
}
{
std::ostringstream oss;
caller.call("dbitclk", {}, -1, GET, oss);
REQUIRE(oss.str() == "dbitclk 10\n");
REQUIRE(oss.str() == "dbitclk 15MHz\n");
}
{
std::ostringstream oss;
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 15.75MHz\n");
}
for (int i = 0; i != det.size(); ++i) {
det.setDBITClock(prev_val[i], {i});
+49
View File
@@ -108,6 +108,12 @@ ToString(From t) {
}
}
/** Convert frequency with specified output unit */
std::string ToString(defs::Hz f, defs::FrequencyUnit unit);
/** Convert frequency automatically selecting the unit */
std::string ToString(defs::Hz f);
/** 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 +285,23 @@ ToString(const T &container, const std::string &unit) {
return os.str();
}
/** Container and specified unit, call ToString(value, FrequencyUnit) */
template <typename T>
typename std::enable_if<is_container<T>::value, std::string>::type
ToString(const T &container, defs::FrequencyUnit unit) {
std::ostringstream os;
os << '[';
if (!container.empty()) {
auto it = container.cbegin();
os << ToString(*it++, unit);
while (it != container.cend())
os << ", " << ToString(*it++, unit);
}
os << ']';
return os.str();
}
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 +326,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);
+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
+10 -1
View File
@@ -221,6 +221,16 @@ 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);
}
};
enum class FrequencyUnit { Hz, kHz, MHz };
#endif
enum frameDiscardPolicy {
NO_DISCARD,
@@ -854,7 +864,6 @@ typedef struct {
#endif
#ifdef __cplusplus
// TODO! discuss this
#include <vector> //hmm... but currently no way around
namespace sls {
+4 -4
View File
@@ -3,11 +3,11 @@
/** API versions */
#define APILIB "0.0.0 0x250909"
#define APIRECEIVER "0.0.0 0x250822"
#define APICTB "0.0.0 0x260427"
#define APICTB "0.0.0 0x260506"
#define APIGOTTHARD2 "0.0.0 0x260427"
#define APIMOENCH "0.0.0 0x260424"
#define APIEIGER "0.0.0 0x260424"
#define APIXILINXCTB "0.0.0 0x260427"
#define APIXILINXCTB "0.0.0 0x260506"
#define APIJUNGFRAU "0.0.0 0x260424"
#define APIMYTHEN3 "0.0.0 0x260427"
#define APIMATTERHORN "0.0.0 0x260212"
#define APIMYTHEN3 "0.0.0 0x260506"
#define APIMATTERHORN "0.0.0 0x260212"
+30
View File
@@ -741,6 +741,36 @@ std::string ToString(const defs::collectionMode s) {
const std::string &ToString(const std::string &s) { return s; }
std::string ToString(defs::Hz f, defs::FrequencyUnit unit) {
double val = static_cast<double>(f.value);
std::ostringstream os;
switch (unit) {
case defs::FrequencyUnit::Hz:
os << val << "Hz";
break;
case defs::FrequencyUnit::kHz:
os << val / (static_cast<double>(1e3)) << "kHz";
break;
case defs::FrequencyUnit::MHz:
os << val / (static_cast<double>(1e6)) << "MHz";
break;
default:
throw std::runtime_error("Unknown frequency unit");
}
return os.str();
}
std::string ToString(defs::Hz f) {
int val = f.value;
if (val < 1e3) {
return ToString(f, defs::FrequencyUnit::Hz);
} else if (val < 1e6) {
return ToString(f, defs::FrequencyUnit::kHz);
} else {
return ToString(f, defs::FrequencyUnit::MHz);
}
}
template <> defs::detectorType StringTo(const std::string &s) {
if (s == "Eiger")
return defs::EIGER;
+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), defs::FrequencyUnit::Hz) == "150Hz");
REQUIRE(ToString(defs::Hz(150), defs::FrequencyUnit::kHz) == "0.15kHz");
REQUIRE(ToString(defs::Hz(150), defs::FrequencyUnit::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);