diff --git a/.gitea/workflows/docker-rh8-build-test.yml b/.gitea/workflows/docker-rh8-build-test.yml index ed569282d..3d070f71e 100644 --- a/.gitea/workflows/docker-rh8-build-test.yml +++ b/.gitea/workflows/docker-rh8-build-test.yml @@ -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}} diff --git a/.gitea/workflows/docker-rh9-build-test.yml b/.gitea/workflows/docker-rh9-build-test.yml index 9c2e392fd..2783d69ec 100644 --- a/.gitea/workflows/docker-rh9-build-test.yml +++ b/.gitea/workflows/docker-rh9-build-test.yml @@ -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}} diff --git a/.github/workflows/run_tests.yaml b/.github/workflows/run_tests.yaml index 215efb8a3..fbf55c240 100644 --- a/.github/workflows/run_tests.yaml +++ b/.github/workflows/run_tests.yaml @@ -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: diff --git a/pyctbgui/pyctbgui/services/Acquisition.py b/pyctbgui/pyctbgui/services/Acquisition.py index 10bb1c5c8..d7b826138 100644 --- a/pyctbgui/pyctbgui/services/Acquisition.py +++ b/pyctbgui/pyctbgui/services/Acquisition.py @@ -7,7 +7,7 @@ import zmq from PyQt5 import QtWidgets, uic import logging -from slsdet import readoutMode, runStatus, detectorType +from slsdet import readoutMode, runStatus, detectorType, Hz, MHz, kHz from pyctbgui.utils.defines import Defines from pyctbgui.utils.numpyWriter.npy_writer import NumpyFileManager from pyctbgui.utils.numpyWriter.npz_writer import NpzFileWriter @@ -68,8 +68,11 @@ class AcquisitionTab(QtWidgets.QWidget): if self.det.type in [detectorType.CHIPTESTBOARD, detectorType.XILINX_CHIPTESTBOARD]: self.view.spinBoxRunF.editingFinished.connect(self.setRunFrequency) + self.view.comboBoxRunF.currentIndexChanged.connect(self.setRunFrequency) self.view.spinBoxADCF.editingFinished.connect(self.setADCFrequency) + self.view.comboBoxADCF.currentIndexChanged.connect(self.setADCFrequency) self.view.spinBoxDBITF.editingFinished.connect(self.setDBITFrequency) + self.view.comboBoxDBITF.currentIndexChanged.connect(self.setDBITFrequency) if self.det.type == detectorType.CHIPTESTBOARD: self.view.spinBoxADCPhase.editingFinished.connect(self.setADCPhase) self.view.spinBoxADCPipeline.editingFinished.connect(self.setADCPipeline) @@ -189,20 +192,49 @@ class AcquisitionTab(QtWidgets.QWidget): self.view.comboBoxROMode.currentIndexChanged.connect(self.setReadOut) self.getReadout() + + def _getFrequency(self, det_attr, spinbox, combobox, setter): + spinbox.editingFinished.disconnect() + combobox.currentIndexChanged.disconnect() + f = getattr(self.det, det_attr).value + + if f < 1e3: + combobox.setCurrentIndex(2) #Hz + spinbox.setValue(f) + elif f < 1e6: + combobox.setCurrentIndex(1) #kHz + spinbox.setValue(f / 1e3) + else: + combobox.setCurrentIndex(0) #MHz + spinbox.setValue(f / 1e6) + + spinbox.editingFinished.connect(setter) + combobox.currentIndexChanged.connect(setter) + + + def _setFrequency(self, det_attr, spinbox, combobox, title, getter): + value = spinbox.value() + idx = combobox.currentIndex() + + if idx == 0: + val = MHz(value) + elif idx == 1: + val = kHz(value) + else: + val = Hz((int)(value)) + + try: + setattr(self.det, det_attr, val) + except Exception as e: + QtWidgets.QMessageBox.warning(self.mainWindow, title + " Fail", str(e), QtWidgets.QMessageBox.Ok) + getter() + + def getRunFrequency(self): - self.view.spinBoxRunF.editingFinished.disconnect() - self.view.spinBoxRunF.setValue(self.det.runclk) - self.view.spinBoxRunF.editingFinished.connect(self.setRunFrequency) + self._getFrequency('runclk', self.view.spinBoxRunF, self.view.comboBoxRunF, self.setRunFrequency) def setRunFrequency(self): - self.view.spinBoxRunF.editingFinished.disconnect() - try: - self.det.runclk = self.view.spinBoxRunF.value() - except Exception as e: - QtWidgets.QMessageBox.warning(self.mainWindow, "Run Frequency Fail", str(e), QtWidgets.QMessageBox.Ok) - # TODO: handling double event exceptions - self.view.spinBoxRunF.editingFinished.connect(self.setRunFrequency) - self.getRunFrequency() + self._setFrequency('runclk', self.view.spinBoxRunF, self.view.comboBoxRunF, "Run Frequency Fail", self.getRunFrequency) def getTransceiver(self): self.view.spinBoxTransceiver.editingFinished.disconnect() @@ -254,19 +286,10 @@ class AcquisitionTab(QtWidgets.QWidget): self.getDigital() def getADCFrequency(self): - self.view.spinBoxADCF.editingFinished.disconnect() - self.view.spinBoxADCF.setValue(self.det.adcclk) - self.view.spinBoxADCF.editingFinished.connect(self.setADCFrequency) + self._getFrequency('adcclk', self.view.spinBoxADCF, self.view.comboBoxADCF, self.setADCFrequency) def setADCFrequency(self): - self.view.spinBoxADCF.editingFinished.disconnect() - try: - self.det.adcclk = self.view.spinBoxADCF.value() - except Exception as e: - QtWidgets.QMessageBox.warning(self.mainWindow, "ADC Frequency Fail", str(e), QtWidgets.QMessageBox.Ok) - # TODO: handling double event exceptions - self.view.spinBoxADCF.editingFinished.connect(self.setADCFrequency) - self.getADCFrequency() + self._setFrequency('adcclk', self.view.spinBoxADCF, self.view.comboBoxADCF, "ADC Frequency Fail", self.getADCFrequency) def getADCPhase(self): self.view.spinBoxADCPhase.editingFinished.disconnect() @@ -299,19 +322,10 @@ class AcquisitionTab(QtWidgets.QWidget): self.getADCPipeline() def getDBITFrequency(self): - self.view.spinBoxDBITF.editingFinished.disconnect() - self.view.spinBoxDBITF.setValue(self.det.dbitclk) - self.view.spinBoxDBITF.editingFinished.connect(self.setDBITFrequency) + self._getFrequency('dbitclk', self.view.spinBoxDBITF, self.view.comboBoxDBITF, self.setDBITFrequency) def setDBITFrequency(self): - self.view.spinBoxDBITF.editingFinished.disconnect() - try: - self.det.dbitclk = self.view.spinBoxDBITF.value() - except Exception as e: - QtWidgets.QMessageBox.warning(self.mainWindow, "DBit Frequency Fail", str(e), QtWidgets.QMessageBox.Ok) - # TODO: handling double event exceptions - self.view.spinBoxDBITF.editingFinished.connect(self.setDBITFrequency) - self.getDBITFrequency() + self._setFrequency('dbitclk', self.view.spinBoxDBITF, self.view.comboBoxDBITF, "DBit Frequency Fail", self.getDBITFrequency) def getDBITPhase(self): self.view.spinBoxDBITPhase.editingFinished.disconnect() diff --git a/pyctbgui/pyctbgui/ui/acquisition.ui b/pyctbgui/pyctbgui/ui/acquisition.ui index ba0eddbaa..0dd533436 100644 --- a/pyctbgui/pyctbgui/ui/acquisition.ui +++ b/pyctbgui/pyctbgui/ui/acquisition.ui @@ -45,13 +45,13 @@ - 125 + 90 31 - 125 + 90 31 @@ -61,24 +61,17 @@ QAbstractSpinBox::UpDownArrows - - 6 - - - 0.100000000000000 - + + 3 + - 1000.000000000000000 + 10000.000000000000000 + + + 1.000000000000000 - 0.000000000000000 - - - - - - - Read Out Mode: + 0.000000000000000 @@ -123,13 +116,67 @@ + + + + Read Out Mode: + + + - Run Clock Frequency (MHz): + Run Clock Frequency: + + + + + 60 + 31 + + + + + 60 + 16777215 + + + + + MHz + + + + + kHz + + + + + Hz + + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 10 + 20 + + + + @@ -223,16 +270,128 @@ QFrame::Sunken - - - + + + + ADC Pipeline: + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + - 200 - 0 + 10 + 20 + + + + - DBIT Clock Frequency (MHz): + DBIT Clock Phase (a.u.): + + + + + + + + 0 + 0 + + + + + 90 + 31 + + + + + 90 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 3 + + + 10000.000000000000000 + + + 1.000000000000000 + + + 0.000000000000000 + + + + + + + ADC Clock Phase (a.u.): + + + + + + + DBIT Pipeline: + + + + + + + Digital Samples: + + + + + + + + 0 + 0 + + + + + 90 + 31 + + + + + 90 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 3 + + + 10000.000000000000000 + + + 1.000000000000000 + + + 0.000000000000000 @@ -251,225 +410,7 @@ - ADC Clock Frequency (MHz): - - - - - - - - 0 - 0 - - - - - 125 - 31 - - - - - 125 - 31 - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 9999 - - - - - - - DBIT Pipeline: - - - - - - - - 0 - 0 - - - - - 125 - 31 - - - - - 125 - 31 - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 6 - - - 0.100000000000000 - - - 1000.000000000000000 - - - - - - - - 0 - 0 - - - - - 125 - 31 - - - - - 125 - 31 - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - ADC Pipeline: - - - - - - - ADC Clock Phase (a.u.): - - - - - - - DBIT Clock Phase (a.u.): - - - - - - - Qt::Horizontal - - - QSizePolicy::Expanding - - - - 10 - 20 - - - - - - - - - 0 - 0 - - - - - 125 - 31 - - - - - 125 - 31 - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 6 - - - 0.100000000000000 - - - 1000.000000000000000 - - - - - - - - 0 - 0 - - - - - 125 - 31 - - - - - 125 - 31 - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - 125 - 31 - - - - - 125 - 31 - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 9999 + ADC Clock Frequency: @@ -480,7 +421,51 @@ - + + + + + 200 + 0 + + + + DBIT Clock Frequency: + + + + + + + + 60 + 31 + + + + + 60 + 16777215 + + + + + MHz + + + + + kHz + + + + + Hz + + + + + @@ -490,13 +475,13 @@ - 125 + 155 32 - 125 + 155 32 @@ -511,14 +496,60 @@ - - - - Digital Samples: + + + + + 0 + 0 + + + + + 155 + 31 + + + + + 155 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 9999 - + + + + + 0 + 0 + + + + + 155 + 31 + + + + + 155 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + @@ -528,13 +559,13 @@ - 125 + 155 32 - 125 + 155 32 @@ -552,6 +583,90 @@ + + + + + 0 + 0 + + + + + 155 + 31 + + + + + 155 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 9999 + + + + + + + + 0 + 0 + + + + + 155 + 31 + + + + + 155 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 60 + 31 + + + + + 60 + 16777215 + + + + + MHz + + + + + kHz + + + + + Hz + + + + diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 13e6abb3d..ffec1ac60 100755 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -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 diff --git a/python/slsdet/__init__.py b/python/slsdet/__init__.py index 753267d81..f08e8acab 100755 --- a/python/slsdet/__init__.py +++ b/python/slsdet/__init__.py @@ -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(): diff --git a/python/slsdet/detector.py b/python/slsdet/detector.py index af98c0d30..56e29800f 100755 --- a/python/slsdet/detector.py +++ b/python/slsdet/detector.py @@ -14,11 +14,12 @@ powerIndex = slsDetectorDefs.powerIndex detectorType = slsDetectorDefs.detectorType streamingInterface = slsDetectorDefs.streamingInterface + defs = slsDetectorDefs from .utils import element_if_equal, all_equal, get_set_bits, list_to_bitmask from .utils import Geometry, to_geo, element, reduce_time, is_iterable, hostname_list -from ._slsdet import xy, freeSharedMemory, getUserDetails +from ._slsdet import xy, Hz, freeSharedMemory, getUserDetails from .gaincaps import Mythen3GainCapsWrapper from . import utils as ut from .proxy import JsonProxy, ClkDivProxy, MaxPhaseProxy, ClkFreqProxy, PatLoopProxy, PatNLoopProxy, PatWaitProxy, PatWaitTimeProxy @@ -3441,22 +3442,21 @@ class Detector(CppDetectorApi): @element def runclk(self): """ - [Ctb][Xilinx Ctb] Sets Run clock frequency in MHz. \n - Accepts decimal inputs - """ + [Ctb][Xilinx Ctb] Sets Run clock frequency. - freq_hz = element_if_equal(self.getRUNClock()) - if isinstance(freq_hz, list): - return [value / 1e6 for value in freq_hz] - return freq_hz / 1e6 + Example + -------- + >>> d.runclk + >>> 10MHz + >>> d.runclk = MHz(5) + >>> d.runclk = Hz(5 * 1000 * 1000) + >>> d.runclk = kHz(2000) + """ + return self.getRUNClock() @runclk.setter def runclk(self, freq): - if isinstance(freq, dict): - freq_hz = {key: int(round(value * 1e6)) for key, value in freq.items()} - else: - freq_hz = int(round(freq * 1e6)) - ut.set_using_dict(self.setRUNClock, freq_hz) + ut.set_using_dict(self.setRUNClock, freq) @property @element @@ -3533,21 +3533,21 @@ class Detector(CppDetectorApi): @element def dbitclk(self): """ - [Ctb][Xilinx Ctb] Sets clock for latching the digital bits in MHz. \n - Accepts decimal inputs + [Ctb][Xilinx Ctb] Sets clock for latching the digital bits. + + Example + -------- + >>> d.dbitclk + >>> 10MHz + >>> d.dbitclk = MHz(5) + >>> d.dbitclk = Hz(5 * 1000 * 1000) + >>> d.dbitclk = kHz(2000) """ - freq_hz = element_if_equal(self.getDBITClock()) - if isinstance(freq_hz, list): - return [value / 1e6 for value in freq_hz] - return freq_hz / 1e6 + return self.getDBITClock() @dbitclk.setter def dbitclk(self, value): - if isinstance(value, dict): - value_hz = {key: int(round(item * 1e6)) for key, item in value.items()} - else: - value_hz = int(round(value * 1e6)) - ut.set_using_dict(self.setDBITClock, value_hz) + ut.set_using_dict(self.setDBITClock, value) @property @element @@ -3670,28 +3670,27 @@ class Detector(CppDetectorApi): @element def adcclk(self): """ - [Ctb][Xilinx Ctb] Sets ADC clock frequency in MHz. \n - Accepts decimal inputs - """ + [Ctb][Xilinx Ctb] Sets ADC clock frequency. - freq_hz = element_if_equal(self.getADCClock()) - if isinstance(freq_hz, list): - return [value / 1e6 for value in freq_hz] - return freq_hz / 1e6 + Example + -------- + >>> d.adcclk + >>> 10MHz + >>> d.adcclk = MHz(5) + >>> d.adcclk = Hz(5 * 1000 * 1000) + >>> d.adcclk = kHz(2000) + """ + return self.getADCClock() @adcclk.setter def adcclk(self, value): - if isinstance(value, dict): - value_hz = {key: int(round(item * 1e6)) for key, item in value.items()} - else: - value_hz = int(round(value * 1e6)) - ut.set_using_dict(self.setADCClock, value_hz) + ut.set_using_dict(self.setADCClock, value) @property @element def syncclk(self): """ - [Ctb] Sync clock in MHz. + [Ctb] Sync clock. :setter: Not implemented """ @@ -3724,7 +3723,7 @@ class Detector(CppDetectorApi): [Ctb][Mythen3][Xilinx Ctb] Gets the pattern file name including path of the last pattern uploaded. Returns an empty if nothing was uploaded or via a server default file """ - return self.getPatterFileName() + return self.getPatternFileName() def patternstart(self): """[Ctb][Mythen3][Xilinx Ctb] Starts pattern. """ diff --git a/python/src/detector.cpp b/python/src/detector.cpp index 3d2b3a049..ff14eaafa 100644 --- a/python/src/detector.cpp +++ b/python/src/detector.cpp @@ -1529,23 +1529,31 @@ void init_det(py::module &m) { Detector::setNumberOfAnalogSamples, py::arg(), py::arg() = Positions{}); CppDetectorApi.def("getADCClock", - (Result(Detector::*)(sls::Positions) const) & + (Result(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(Detector::*)(sls::Positions) const) & + (Result(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(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(Detector::*)(sls::Positions) const) & + (Result(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(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(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(Detector::*)(sls::Positions) const) & - Detector::getPatterFileName, + Detector::getPatternFileName, py::arg() = Positions{}); CppDetectorApi.def( "setPattern", diff --git a/python/src/frequency.cpp b/python/src/frequency.cpp new file mode 100644 index 000000000..ff08cf878 --- /dev/null +++ b/python/src/frequency.cpp @@ -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 + +#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_ Hz(m, "Hz"); + Hz.def(py::init()); + 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(std::round(v * kHz))); + }); + + m.def("MHz", [](double v) { + return slsDetectorDefs::Hz(static_cast(std::round(v * MHz))); + }); +} \ No newline at end of file diff --git a/python/src/main.cpp b/python/src/main.cpp index 214f2b81c..6bc583cbd 100644 --- a/python/src/main.cpp +++ b/python/src/main.cpp @@ -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"); diff --git a/python/tests/test_det_api.py b/python/tests/test_det_api.py index e8d89560b..551562820 100644 --- a/python/tests/test_det_api.py +++ b/python/tests/test_det_api.py @@ -396,6 +396,193 @@ def test_patternstart(session_simulator, request): Log(LogLevel.INFOGREEN, f"✅ {request.node.name} passed") + +@pytest.mark.detectorintegration +def test_runclk(session_simulator, request): + """ Test using runclk for ctb and xilinx_ctb.""" + det_type, num_interfaces, num_mods, d = session_simulator + assert d is not None + + from slsdet import Hz, MHz, kHz + + if det_type in ['ctb', 'xilinx_ctb']: + prev_runclk = d.getRUNClock() + + d.runclk + + # invalid value type + with pytest.raises(Exception) as exc_info: + d.runclk = 5e6 + + with pytest.raises(Exception) as exc_info: + d.runclk = 5 * 1000 * 1000 + + with pytest.raises(Exception) as exc_info: + d.runclk = Hz(5e6) + + d.runclk = MHz(15) + assert d.runclk.value == 15_000_000 + + d.runclk = MHz(14.5) + assert d.runclk.value == 14_500_000 + + d.runclk = kHz(15000.5) + assert d.runclk.value == 15_000_500 + + # invalid values from server + # max is 300MHz + with pytest.raises(Exception) as exc_info: + d.runclk = MHz(301) + + # min is 2MHz for ctb and 10MHz for xilinx_ctb + if det_type == 'ctb': + with pytest.raises(Exception) as exc_info: + d.runclk = MHz(1) + else: + with pytest.raises(Exception) as exc_info: + d.runclk = MHz(9) + + c = MHz(2) + for rc in [5, 10, 15, 20]: + d.runclk = rc * c + assert d.runclk.value == 40_000_000 + + for i in range(len(d)): + d.setRUNClock(prev_runclk[i], [i]) + + Log(LogLevel.INFOGREEN, f"✅ {request.node.name} passed") + + +@pytest.mark.detectorintegration +def test_adcclk(session_simulator, request): + """ Test using adcclk for ctb and xilinx_ctb.""" + det_type, num_interfaces, num_mods, d = session_simulator + assert d is not None + + from slsdet import Hz, MHz, kHz + + if det_type in ['ctb', 'xilinx_ctb']: + prev_adcclk = d.getADCClock() + + d.adcclk + + # invalid value type + with pytest.raises(Exception) as exc_info: + d.adcclk = 5e6 + + with pytest.raises(Exception) as exc_info: + d.adcclk = 5 * 1000 * 1000 + + with pytest.raises(Exception) as exc_info: + d.adcclk = Hz(5e6) + + d.adcclk = MHz(15) + assert d.adcclk.value == 15_000_000 + + d.adcclk = MHz(14.5) + assert d.adcclk.value == 14_500_000 + + d.adcclk = kHz(15000.5) + assert d.adcclk.value == 15_000_500 + + # invalid values from server + # max is 300MHz for xilinx and 54 MHz for ctb + if det_type == 'ctb': + with pytest.raises(Exception) as exc_info: + d.adcclk = MHz(66) + else: + with pytest.raises(Exception) as exc_info: + d.adcclk = MHz(301) + + # min is 2MHz for ctb and 10MHz for xilinx_ctb + if det_type == 'ctb': + with pytest.raises(Exception) as exc_info: + d.adcclk = MHz(1) + else: + with pytest.raises(Exception) as exc_info: + d.adcclk = MHz(9) + + c = MHz(2) + for rc in [5, 10, 15, 20]: + d.adcclk = rc * c + assert d.adcclk.value == 40_000_000 + + for i in range(len(d)): + d.setADCClock(prev_adcclk[i], [i]) + + Log(LogLevel.INFOGREEN, f"✅ {request.node.name} passed") + + +@pytest.mark.detectorintegration +def test_dbitclk(session_simulator, request): + """ Test using dbitclk for ctb and xilinx_ctb.""" + det_type, num_interfaces, num_mods, d = session_simulator + assert d is not None + + from slsdet import Hz, MHz, kHz + + if det_type in ['ctb', 'xilinx_ctb']: + prev_dbitclk = d.getDBITClock() + + d.dbitclk + + # invalid value type + with pytest.raises(Exception) as exc_info: + d.dbitclk = 5e6 + + with pytest.raises(Exception) as exc_info: + d.dbitclk = 5 * 1000 * 1000 + + with pytest.raises(Exception) as exc_info: + d.dbitclk = Hz(5e6) + + d.dbitclk = MHz(15) + assert d.dbitclk.value == 15_000_000 + + d.dbitclk = MHz(14.5) + assert d.dbitclk.value == 14_500_000 + + d.dbitclk = kHz(15000.5) + assert d.dbitclk.value == 15_000_500 + + # invalid values from server + # max is 300MHz + with pytest.raises(Exception) as exc_info: + d.dbitclk = MHz(301) + + # min is 2MHz for ctb and 10MHz for xilinx_ctb + if det_type == 'ctb': + with pytest.raises(Exception) as exc_info: + d.dbitclk = MHz(1) + else: + with pytest.raises(Exception) as exc_info: + d.dbitclk = MHz(9) + + c = MHz(2) + for rc in [5, 10, 15, 20]: + d.dbitclk = rc * c + assert d.dbitclk.value == 40_000_000 + + for i in range(len(d)): + d.setDBITClock(prev_dbitclk[i], [i]) + + Log(LogLevel.INFOGREEN, f"✅ {request.node.name} passed") + + + +@pytest.mark.detectorintegration +def test_syncclk(session_simulator, request): + """ Test using syncclk for ctb.""" + det_type, num_interfaces, num_mods, d = session_simulator + assert d is not None + + if det_type in ['ctb']: + d.syncclk + + Log(LogLevel.INFOGREEN, f"✅ {request.node.name} passed") + + + @pytest.mark.detectorintegration def test_v_limit(session_simulator, request): """Test v_limit.""" @@ -450,7 +637,7 @@ def test_v_limit(session_simulator, request): Log(LogLevel.INFOGREEN, f"✅ {request.node.name} passed") -@pytest.mark.detectorintegration + def test_v_abcd(session_simulator, request): """Test v_a, v_b, v_c, v_d, v_io are deprecated comands.""" det_type, num_interfaces, num_mods, d = session_simulator @@ -715,3 +902,4 @@ def test_dac(session_simulator, request): Log(LogLevel.INFOGREEN, f"✅ {request.node.name} passed") + diff --git a/python/tests/test_freq.py b/python/tests/test_freq.py new file mode 100644 index 000000000..c9a1c4649 --- /dev/null +++ b/python/tests/test_freq.py @@ -0,0 +1,48 @@ +from slsdet import Hz, MHz, kHz + +def test_Hz(): + f = Hz(1) + assert f.value == 1 + f = Hz(1 * 1000) + assert f.value == 1000 + f = MHz(5) + assert f.value == 5_000_000 + f = MHz(0.5) + assert f.value == 500_000 + f = kHz(2.5) + assert f.value == 2500 + f = kHz(5000) + assert f.value == 5_000_000 + +def test_rounding_exact(): + f = MHz(1.234) + assert f.value == round(1.234 * 1_000_000) + + +def test_mul(): + c = MHz(1) + assert (c * 2).value == 2_000_000 + assert (c * 4).value == 4_000_000 + + +def test_rmul(): + c = MHz(1) + assert (2 * c).value == 2_000_000 + assert (4 * c).value == 4_000_000 + + c = c * 2 + assert c.value == 2_000_000 + + for rc in [1, 2, 4, 8]: + c = rc * c + assert c.value == 128_000_000 + + +def test_div(): + c = MHz(1) + assert (c / 2).value == 500_000 + +def test_eq(): + assert MHz(1) == MHz(1) + assert MHz(1) != MHz(2) + assert MHz(1) == kHz(1000) \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c index 89338fa54..1d849c9a7 100644 --- a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c @@ -14,6 +14,7 @@ #include "communication_funcs_UDP.h" #include "loadPattern.h" +#include #include #include #include @@ -66,7 +67,8 @@ uint8_t adcEnableMask_10g = 0xFF; uint32_t transceiverMask = DEFAULT_TRANSCEIVER_MASK; int32_t clkPhase[NUM_CLOCKS] = {}; -uint32_t clkFrequency[NUM_CLOCKS] = {DEFAULT_RUN_CLK, DEFAULT_ADC_CLK, DEFAULT_SYNC_CLK, DEFAULT_DBIT_CLK}; +uint32_t clkFrequency[NUM_CLOCKS] = {DEFAULT_RUN_CLK, DEFAULT_ADC_CLK, + DEFAULT_SYNC_CLK, DEFAULT_DBIT_CLK}; int dacValues[NDAC_ONLY] = {}; int powerValues[NPWR] = {}; // powerIndex (A->IO, Chip) @@ -1148,12 +1150,8 @@ int getNumTransceiverSamples() { return ntSamples; } int setExpTime(int64_t val) { setPatternWaitInterval(0, val); - - // Tolerance: three clock periods in ns. int64_t retval = getExpTime(); - int64_t toleranceNs = 3 * (1000000000 / clkFrequency[RUN_CLK]); - int64_t diff = val - retval; - if (diff < -toleranceNs || diff > toleranceNs) { + if (val != retval) { return FAIL; } return OK; @@ -1167,12 +1165,12 @@ int setPeriod(int64_t val) { return FAIL; } LOG(logINFO, ("Setting period %lld ns\n", (long long int)val)); - val *= (1E-3 * clkFrequency[SYNC_CLK]); + val *= (NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]); set64BitReg(val, PERIOD_LSB_REG, PERIOD_MSB_REG); // validate for tolerance int64_t retval = getPeriod(); - val /= (1E-3 * clkFrequency[SYNC_CLK]); + val /= (NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]); if (val != retval) { return FAIL; } @@ -1181,7 +1179,7 @@ int setPeriod(int64_t val) { int64_t getPeriod() { return get64BitReg(PERIOD_LSB_REG, PERIOD_MSB_REG) / - (1E-3 * clkFrequency[SYNC_CLK]); + (NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]); } int setDelayAfterTrigger(int64_t val) { @@ -1191,12 +1189,12 @@ int setDelayAfterTrigger(int64_t val) { return FAIL; } LOG(logINFO, ("Setting delay after trigger %lld ns\n", (long long int)val)); - val *= (1E-3 * clkFrequency[SYNC_CLK]); + val *= (NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]); set64BitReg(val, DELAY_LSB_REG, DELAY_MSB_REG); // validate for tolerance int64_t retval = getDelayAfterTrigger(); - val /= (1E-3 * clkFrequency[SYNC_CLK]); + val /= (NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]); if (val != retval) { return FAIL; } @@ -1205,7 +1203,7 @@ int setDelayAfterTrigger(int64_t val) { int64_t getDelayAfterTrigger() { return get64BitReg(DELAY_LSB_REG, DELAY_MSB_REG) / - (1E-3 * clkFrequency[SYNC_CLK]); + (NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]); } int64_t getNumFramesLeft() { @@ -1218,12 +1216,12 @@ int64_t getNumTriggersLeft() { int64_t getDelayAfterTriggerLeft() { return get64BitReg(DELAY_LEFT_LSB_REG, DELAY_LEFT_MSB_REG) / - (1E-3 * clkFrequency[SYNC_CLK]); + (NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]); } int64_t getPeriodLeft() { return get64BitReg(PERIOD_LEFT_LSB_REG, PERIOD_LEFT_MSB_REG) / - (1E-3 * clkFrequency[SYNC_CLK]); + (NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]); } int64_t getFramesFromStart() { @@ -1232,13 +1230,14 @@ int64_t getFramesFromStart() { } int64_t getActualTime() { - return get64BitReg(TIME_FROM_START_LSB_REG, TIME_FROM_START_MSB_REG) / - (1E-3 * CLK_FREQ); + // reg in unit of 100ns + return get64BitReg(TIME_FROM_START_LSB_REG, TIME_FROM_START_MSB_REG) * 100; } int64_t getMeasurementTime() { - return get64BitReg(START_FRAME_TIME_LSB_REG, START_FRAME_TIME_MSB_REG) / - (1E-3 * CLK_FREQ); + // reg in unit of 100ns + return get64BitReg(START_FRAME_TIME_LSB_REG, START_FRAME_TIME_MSB_REG) * + 100; } /* parameters - settings */ @@ -2224,9 +2223,8 @@ int getMaxPhase(enum CLKINDEX ind) { MAX_PHASE_SHIFTS_STEPS; char *clock_names[] = {CLK_NAMES}; - LOG(logDEBUG1, - ("Max Phase Shift (%s): %d (Clock: %d MHz, VCO:%d Hz)\n", - clock_names[ind], ret, clkFrequency[ind], PLL_VCO_FREQ_HZ)); + LOG(logDEBUG1, ("Max Phase Shift (%s): %d (Clock: %d MHz, VCO:%d Hz)\n", + clock_names[ind], ret, clkFrequency[ind], PLL_VCO_FREQ_HZ)); return ret; } @@ -2308,16 +2306,17 @@ int getFrequency(enum CLKINDEX ind) { LOG(logERROR, ("Unknown clock index %d to get frequency\n", ind)); return -1; } - #ifndef VIRTUAL - // get the measured frequency from the firmware - int measuredFreqHz = ALTERA_PLL_getFrequency(ind); +#ifndef VIRTUAL + // get the measured frequency from the firmware + int measuredFreqHz = ALTERA_PLL_getFrequency(ind); - // checking against 0 here ensures compatibility with old firmware, TODO: remove this check at some point - if (measuredFreqHz != 0) { - // Round to nearest MHz. (should we round at all ?) - clkFrequency[ind] = measuredFreqHz; - } - #endif VIRTUAL + // checking against 0 here ensures compatibility with old firmware, TODO: + // remove this check at some point + if (measuredFreqHz != 0) { + // Round to nearest MHz. (should we round at all ?) + clkFrequency[ind] = measuredFreqHz; + } +#endif return clkFrequency[ind]; } diff --git a/slsDetectorServers/ctbDetectorServer/slsDetectorServer_defs.h b/slsDetectorServers/ctbDetectorServer/slsDetectorServer_defs.h index 0fa1b534b..94b6fb9b2 100644 --- a/slsDetectorServers/ctbDetectorServer/slsDetectorServer_defs.h +++ b/slsDetectorServers/ctbDetectorServer/slsDetectorServer_defs.h @@ -50,13 +50,16 @@ #define DEFAULT_VLIMIT (0) #define DEFAULT_TIMING_MODE (AUTO_TIMING) #define DEFAULT_TX_UDP_PORT (0x7e9a) -#define DEFAULT_RUN_CLK (80000000) // 80 -#define DEFAULT_ADC_CLK (40000000) // 40 -#define DEFAULT_SYNC_CLK (40000000) // 40 -#define DEFAULT_DBIT_CLK (200000000) -#define NS_TO_CLK_CYCLE (1E-9) // ns to MHz +#define DEFAULT_RUN_CLK (80000000) // 80 MHz +#define DEFAULT_ADC_CLK (40000000) // 40 MHz +#define DEFAULT_SYNC_CLK (40000000) // 40 MHz +#define DEFAULT_DBIT_CLK (200000000) // 200 MHz +#define NS_TO_CLK_CYCLE (1E-9) // ns to MHz #define DEFAULT_TRANSCEIVER_MASK (0x3) +#define MIN_CLK_FREQ (2000000) // 2 MHz +#define MAX_CLK_FREQ (300000000) // 300 MHz + #define MAX_TRANSCEIVER_MASK (0xF) #define MAX_TRANSCEIVER_SAMPLES (0xFFFF) @@ -95,8 +98,8 @@ #define BIT32_MSK (0xFFFFFFFF) #define BIT16_MASK (0xFFFF) -#define MAXIMUM_ADC_CLK (65000000) -#define PLL_VCO_FREQ_HZ (800000000) +#define MAXIMUM_ADC_CLK (65000000) // 65 MHz +#define PLL_VCO_FREQ_HZ (800000000) // 800MHz /* Struct Definitions */ typedef struct udp_header_struct { diff --git a/slsDetectorServers/slsDetectorServer/src/ALTERA_PLL.c b/slsDetectorServers/slsDetectorServer/src/ALTERA_PLL.c index ba5cce501..eed289ae5 100644 --- a/slsDetectorServers/slsDetectorServer/src/ALTERA_PLL.c +++ b/slsDetectorServers/slsDetectorServer/src/ALTERA_PLL.c @@ -328,12 +328,12 @@ int ALTERA_PLL_SetOutputFrequency(int clkIndex, int pllVCOFreqHz, int value) { return (int)temp; */ - #if defined(CHIPTESTBOARDD) && !defined(VIRTUAL) - // wait for firmware to measure the actual frequency - usleep(2 * 1000 * 1000); - value = ALTERA_PLL_getFrequency(clkIndex); - LOG(logDEBUG1, ("Frequency is %d\n", value)); - #endif +#if defined(CHIPTESTBOARDD) && !defined(VIRTUAL) + // wait for firmware to measure the actual frequency + usleep(2 * 1000 * 1000); + value = ALTERA_PLL_getFrequency(clkIndex); + LOG(logDEBUG1, ("Frequency is %d\n", value)); +#endif return value; } diff --git a/slsDetectorServers/slsDetectorServer/src/loadPattern.c b/slsDetectorServers/slsDetectorServer/src/loadPattern.c index 021295476..b119ac674 100644 --- a/slsDetectorServers/slsDetectorServer/src/loadPattern.c +++ b/slsDetectorServers/slsDetectorServer/src/loadPattern.c @@ -307,9 +307,7 @@ uint64_t getPatternWaitInterval(int level) { LOG(logERROR, ("runclk is 0. Cannot divide by 0. Returning -1.\n")); return -1; } - double conv = NS_TO_CLK_CYCLE * runclk; - uint64_t waitNs = (uint64_t)(numClocks / conv + 0.5); - return waitNs; + return (double)numClocks / (NS_TO_CLK_CYCLE * runclk); } int validate_setPatternWaitClocksAndInterval(char *message, int level, diff --git a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c index cfdc933b5..b67c6f37c 100644 --- a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c +++ b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c @@ -5717,15 +5717,34 @@ int set_clock_frequency(int file_des) { if (getFrequency(c) == val) { LOG(logINFO, ("Same %s: %d %s\n", modeName, val, "Hz")); - } else { + } else if (val < MIN_CLK_FREQ || val > MAX_CLK_FREQ) { + ret = FAIL; + sprintf(mess, + "Cannot set frequency to %f MHz. Frequency outside " + "limits (%f - %f MHz)\n", + val / 1e6, MIN_CLK_FREQ / 1e6, MAX_CLK_FREQ / 1e6); + LOG(logERROR, (mess)); + } +#ifdef CHIPTESTBOARDD + else if (ind == ADC_CLOCK && (val > MAXIMUM_ADC_CLK)) { + ret = FAIL; + sprintf(mess, + "Cannot set ADC clock frequency to %f MHz. Frequency " + "outside limits (<= %f MHz)\n", + val / 1e6, MAXIMUM_ADC_CLK / 1e6); + LOG(logERROR, (mess)); + } +#endif + else { int ret = setFrequency(c, val); if (ret == FAIL) { - sprintf(mess, "Could not set %s to %d %s\n", modeName, val,"Hz"); + sprintf(mess, "Could not set %s to %f MHz\n", modeName, + val / 1e6); LOG(logERROR, (mess)); } else { int retval = getFrequency(c); LOG(logDEBUG1, - ("retval %s: %d %s\n", modeName, retval, "Hz")); + ("retval %s: %f MHz\n", modeName, retval / 1e6)); // both CTB's will give the actual frequency, which is not // 100% identical to the set frequency validate(&ret, mess, val, retval, modeName, DEC); @@ -5781,8 +5800,8 @@ int get_clock_frequency(int file_des) { if (ret == OK) { retval = getFrequency(c); char *clock_names[] = {CLK_NAMES}; - LOG(logDEBUG1, - ("retval %s clock (%d) frequency: %d %s\n", clock_names[c], (int)c, retval, "Hz")); + LOG(logDEBUG1, ("retval %s clock (%d) frequency: %d %s\n", + clock_names[c], (int)c, retval, "Hz")); } #endif return Server_SendResult(file_des, INT32, &retval, sizeof(retval)); diff --git a/slsDetectorServers/xilinx_ctbDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/xilinx_ctbDetectorServer/slsDetectorFunctionList.c index 6a218780d..513055e0d 100644 --- a/slsDetectorServers/xilinx_ctbDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/xilinx_ctbDetectorServer/slsDetectorFunctionList.c @@ -768,12 +768,8 @@ int getNumTransceiverSamples() { int setExpTime(int64_t val) { setPatternWaitInterval(0, val); - - // Tolerance: three clock periods in ns. int64_t retval = getExpTime(); - int64_t toleranceNs = 3 * (1000000000 / clkFrequency[RUN_CLK]); - int64_t diff = val - retval; - if (diff < -toleranceNs || diff > toleranceNs) { + if (val != retval) { return FAIL; } return OK; @@ -851,13 +847,14 @@ int64_t getFramesFromStart() { } int64_t getActualTime() { - return getU64BitReg(TIME_FROM_START_OUT_REG_1, TIME_FROM_START_OUT_REG_2) / - (NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]); + // in unit of 100ns + return getU64BitReg(TIME_FROM_START_OUT_REG_1, TIME_FROM_START_OUT_REG_2) * + 100; } int64_t getMeasurementTime() { - return getU64BitReg(FRAME_TIME_OUT_REG_1, FRAME_TIME_OUT_REG_2) / - (NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]); + // in unit of 100ns + return getU64BitReg(FRAME_TIME_OUT_REG_1, FRAME_TIME_OUT_REG_2) * 100; } /* parameters - dac, adc, hv */ diff --git a/slsDetectorServers/xilinx_ctbDetectorServer/slsDetectorServer_defs.h b/slsDetectorServers/xilinx_ctbDetectorServer/slsDetectorServer_defs.h index 6399bc93a..adf4691bc 100644 --- a/slsDetectorServers/xilinx_ctbDetectorServer/slsDetectorServer_defs.h +++ b/slsDetectorServers/xilinx_ctbDetectorServer/slsDetectorServer_defs.h @@ -158,8 +158,11 @@ typedef struct udp_header_struct { enum CLKINDEX { RUN_CLK, ADC_CLK, SYNC_CLK, DBIT_CLK, NUM_CLOCKS }; #define CLK_NAMES "run", "adc", "sync", "dbit" -#define DEFAULT_RUN_CLK (20000) // 20 MHz -#define DEFAULT_ADC_CLK (100000) // 100 MHz -#define DEFAULT_SYNC_CLK (20000) // 20 MHz -#define DEFAULT_DBIT_CLK (100000) // 100 MHz -#define NS_TO_CLK_CYCLE (1E-9) // ns to Hz +#define DEFAULT_RUN_CLK (20000000) // 20 MHz +#define DEFAULT_ADC_CLK (100000000) // 100 MHz +#define DEFAULT_SYNC_CLK (20000000) // 20 MHz +#define DEFAULT_DBIT_CLK (100000000) // 100 MHz +#define NS_TO_CLK_CYCLE (1E-9) // ns to Hz + +#define MIN_CLK_FREQ (10000000) // 10 MHz +#define MAX_CLK_FREQ (300000000) // 300 MHz diff --git a/slsDetectorSoftware/generator/autocomplete/autocomplete.py b/slsDetectorSoftware/generator/autocomplete/autocomplete.py index 356e82eab..f236bcc67 100644 --- a/slsDetectorSoftware/generator/autocomplete/autocomplete.py +++ b/slsDetectorSoftware/generator/autocomplete/autocomplete.py @@ -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 diff --git a/slsDetectorSoftware/generator/autocomplete/bash_autocomplete.sh b/slsDetectorSoftware/generator/autocomplete/bash_autocomplete.sh index ff46a218a..433bd33d4 100644 --- a/slsDetectorSoftware/generator/autocomplete/bash_autocomplete.sh +++ b/slsDetectorSoftware/generator/autocomplete/bash_autocomplete.sh @@ -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 diff --git a/slsDetectorSoftware/generator/autocomplete/zsh_autocomplete.sh b/slsDetectorSoftware/generator/autocomplete/zsh_autocomplete.sh index 92073ccea..953f971d2 100644 --- a/slsDetectorSoftware/generator/autocomplete/zsh_autocomplete.sh +++ b/slsDetectorSoftware/generator/autocomplete/zsh_autocomplete.sh @@ -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 diff --git a/slsDetectorSoftware/generator/commands.yaml b/slsDetectorSoftware/generator/commands.yaml index c133e08e1..9e069f830 100644 --- a/slsDetectorSoftware/generator/commands.yaml +++ b/slsDetectorSoftware/generator/commands.yaml @@ -2,6 +2,56 @@ # detectors: MYTHEN3 ################# TEMPLATES ################# +FREQ_COMMAND: + infer_action: true + help: "" + template: true + actions: + GET: + require_det_id: true + function: '' + args: + - argc: 0 + output: [ OutString(t) ] + - argc: 1 + arg_types: [ special::freq_unit ] + output: [ "OutString(t , args[0])" ] + PUT: + function: '' + require_det_id: true + input: [ converted_freq ] + input_types: [ defs::Hz ] + args: + - argc: 1 + arg_types: [ std::string ] + + separate_freq_units: + input: 'args[0]' + output: [ converted_freq, unit ] + output: [ 'args[0]' ] + - argc: 2 + arg_types: [ int, special::freq_unit ] + + convert_to_freq: + input: [ 'args[0]', 'args[1]' ] + output: converted_freq + output: [ 'args[0]', 'args[1]' ] + +FREQ_GET_COMMAND: + infer_action: true + help: "" + template: true + actions: + GET: + require_det_id: true + function: '' + args: + - argc: 0 + output: [ OutString(t) ] + - argc: 1 + arg_types: [ special::freq_unit ] + output: [ "OutString(t , args[0])" ] + TIME_COMMAND: infer_action: true help: "" @@ -401,6 +451,44 @@ CTB_GET_INDEX: ################# COMMANDS ################################## +################# FREQ_COMMAND ############# +adcclk: + help: "[n_clk] [(optional unit) Hz(default)|kHz|MHz]\n\t[Ctb][Xilinx Ctb] ADC clock frequency." + inherit_actions: FREQ_COMMAND + actions: + GET: + function: getADCClock + PUT: + function: setADCClock + +runclk: + help: "[n_clk] [(optional unit) Hz(default)|kHz|MHz]\n\t[Ctb][Xilinx Ctb] Run clock frequency." + inherit_actions: FREQ_COMMAND + actions: + GET: + function: getRUNClock + PUT: + function: setRUNClock + + +dbitclk: + help: "[n_clk] [(optional unit) Hz(default)|kHz|MHz]\n\t[Ctb][Xilinx Ctb] Clock for latching the digital bits." + inherit_actions: FREQ_COMMAND + actions: + GET: + function: getDBITClock + PUT: + function: setDBITClock + +################# FREQ_GET_COMMAND ############# + +syncclk: + inherit_actions: FREQ_GET_COMMAND + help: "[n_clk] [(optional unit) Hz(default)|kHz|MHz]\n\t[Ctb] Sync clock." + actions: + GET: + function: getSYNCClock + ################# TIME_COMMAND ############# period: @@ -1243,23 +1331,6 @@ asamples: PUT: function: setNumberOfAnalogSamples -adcclk: - help: "[n_clk in MHz]\n\t[Ctb][xilinx Ctb] ADC clock frequency in MHz." - inherit_actions: INTEGER_COMMAND_VEC_ID - actions: - GET: - function: getADCClock - PUT: - function: setADCClock - -runclk: - help: "[n_clk in MHz]\n\t[Ctb][xilinx Ctb] Run clock in MHz." - inherit_actions: INTEGER_COMMAND_VEC_ID - actions: - GET: - function: getRUNClock - PUT: - function: setRUNClock dsamples: help: "[n_value]\n\t[Ctb] Number of digital samples expected." @@ -1289,15 +1360,6 @@ romode: function: setReadoutMode input_types: [ defs::readoutMode ] -dbitclk: - help: "[n_clk in MHz]\n\t[Ctb][xilinx Ctb] Clock for latching the digital bits in MHz." - inherit_actions: INTEGER_COMMAND_VEC_ID - actions: - GET: - function: getDBITClock - PUT: - function: setDBITClock - extsampling: help: "[0, 1]\n\t[Ctb] Enable for external sampling signal for digital data to signal by extsampling src command. For advanced users only." inherit_actions: INTEGER_COMMAND_VEC_ID @@ -1912,19 +1974,12 @@ burstsl: GET: function: getNumberOfBurstsLeft -syncclk: - inherit_actions: GET_COMMAND - help: "[n_clk in MHz]\n\t[Ctb] Sync clock in MHz." - actions: - GET: - function: getSYNCClock - patfname: inherit_actions: GET_COMMAND help: "\n\t[Ctb][Mythen3][Xilinx Ctb] Gets the pattern file name including path of the last pattern uploaded. Returns an empty if nothing was uploaded or via a server default file" actions: GET: - function: getPatterFileName + function: getPatternFileName lastclient: inherit_actions: GET_COMMAND diff --git a/slsDetectorSoftware/generator/commands_parser/commands_parser.py b/slsDetectorSoftware/generator/commands_parser/commands_parser.py index 9a11cd789..576cbfa21 100644 --- a/slsDetectorSoftware/generator/commands_parser/commands_parser.py +++ b/slsDetectorSoftware/generator/commands_parser/commands_parser.py @@ -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') diff --git a/slsDetectorSoftware/generator/cpp_codegen/codegen.py b/slsDetectorSoftware/generator/cpp_codegen/codegen.py index fef9959d0..a9e875b09 100644 --- a/slsDetectorSoftware/generator/cpp_codegen/codegen.py +++ b/slsDetectorSoftware/generator/cpp_codegen/codegen.py @@ -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']: diff --git a/slsDetectorSoftware/generator/extended_commands.yaml b/slsDetectorSoftware/generator/extended_commands.yaml index ac15436f3..c29c13bc5 100644 --- a/slsDetectorSoftware/generator/extended_commands.yaml +++ b/slsDetectorSoftware/generator/extended_commands.yaml @@ -86,27 +86,69 @@ adcclk: - OutString(t) require_det_id: true store_result_in_t: true + - arg_types: + - special::freq_unit + argc: 1 + cast_input: [] + check_det_id: false + convert_det_id: true + function: getADCClock + input: [] + input_types: [] + output: + - OutString(t , args[0]) + require_det_id: true + store_result_in_t: true PUT: args: - arg_types: - - int + - std::string argc: 1 cast_input: - - true + - false check_det_id: false convert_det_id: true function: setADCClock input: - - args[0] + - converted_freq input_types: - - int + - defs::Hz output: - - args.front() + - args[0] + require_det_id: true + separate_freq_units: + input: args[0] + output: + - converted_freq + - unit + store_result_in_t: false + - arg_types: + - int + - special::freq_unit + argc: 2 + cast_input: + - false + check_det_id: false + convert_det_id: true + convert_to_freq: + input: + - args[0] + - args[1] + output: converted_freq + function: setADCClock + input: + - converted_freq + input_types: + - defs::Hz + output: + - args[0] + - args[1] require_det_id: true store_result_in_t: false command_name: adcclk function_alias: adcclk - help: "[n_clk in MHz]\n\t[Ctb][xilinx Ctb] ADC clock frequency in MHz." + help: "[n_clk] [(optional unit) Hz(default)|kHz|MHz]\n\t[Ctb][Xilinx Ctb] ADC clock\ + \ frequency." infer_action: true template: true adcenable: @@ -2059,27 +2101,69 @@ dbitclk: - OutString(t) require_det_id: true store_result_in_t: true + - arg_types: + - special::freq_unit + argc: 1 + cast_input: [] + check_det_id: false + convert_det_id: true + function: getDBITClock + input: [] + input_types: [] + output: + - OutString(t , args[0]) + require_det_id: true + store_result_in_t: true PUT: args: - arg_types: - - int + - std::string argc: 1 cast_input: - - true + - false check_det_id: false convert_det_id: true function: setDBITClock input: - - args[0] + - converted_freq input_types: - - int + - defs::Hz output: - - args.front() + - args[0] + require_det_id: true + separate_freq_units: + input: args[0] + output: + - converted_freq + - unit + store_result_in_t: false + - arg_types: + - int + - special::freq_unit + argc: 2 + cast_input: + - false + check_det_id: false + convert_det_id: true + convert_to_freq: + input: + - args[0] + - args[1] + output: converted_freq + function: setDBITClock + input: + - converted_freq + input_types: + - defs::Hz + output: + - args[0] + - args[1] require_det_id: true store_result_in_t: false command_name: dbitclk function_alias: dbitclk - help: "[n_clk in MHz]\n\t[Ctb][xilinx Ctb] Clock for latching the digital bits in MHz." + help: "[n_clk] [(optional unit) Hz(default)|kHz|MHz]\n\t[Ctb][Xilinx Ctb] Clock\ + \ for latching the digital bits." infer_action: true template: true dbitphase: @@ -5786,7 +5870,7 @@ patfname: cast_input: [] check_det_id: false convert_det_id: true - function: getPatterFileName + function: getPatternFileName input: [] input_types: [] output: @@ -8138,27 +8222,69 @@ runclk: - OutString(t) require_det_id: true store_result_in_t: true + - arg_types: + - special::freq_unit + argc: 1 + cast_input: [] + check_det_id: false + convert_det_id: true + function: getRUNClock + input: [] + input_types: [] + output: + - OutString(t , args[0]) + require_det_id: true + store_result_in_t: true PUT: args: - arg_types: - - int + - std::string argc: 1 cast_input: - - true + - false check_det_id: false convert_det_id: true function: setRUNClock input: - - args[0] + - converted_freq input_types: - - int + - defs::Hz output: - - args.front() + - args[0] + require_det_id: true + separate_freq_units: + input: args[0] + output: + - converted_freq + - unit + store_result_in_t: false + - arg_types: + - int + - special::freq_unit + argc: 2 + cast_input: + - false + check_det_id: false + convert_det_id: true + convert_to_freq: + input: + - args[0] + - args[1] + output: converted_freq + function: setRUNClock + input: + - converted_freq + input_types: + - defs::Hz + output: + - args[0] + - args[1] require_det_id: true store_result_in_t: false command_name: runclk function_alias: runclk - help: "[n_clk in MHz]\n\t[Ctb][xilinx Ctb] Run clock in MHz." + help: "[n_clk] [(optional unit) Hz(default)|kHz|MHz]\n\t[Ctb][Xilinx Ctb] Run clock\ + \ frequency." infer_action: true template: true runtime: @@ -10573,9 +10699,22 @@ syncclk: - OutString(t) require_det_id: true store_result_in_t: true + - arg_types: + - special::freq_unit + argc: 1 + cast_input: [] + check_det_id: false + convert_det_id: true + function: getSYNCClock + input: [] + input_types: [] + output: + - OutString(t , args[0]) + require_det_id: true + store_result_in_t: true command_name: syncclk function_alias: syncclk - help: "[n_clk in MHz]\n\t[Ctb] Sync clock in MHz." + help: "[n_clk] [(optional unit) Hz(default)|kHz|MHz]\n\t[Ctb] Sync clock." infer_action: true template: true temp_10ge: diff --git a/slsDetectorSoftware/generator/gen_commands.py b/slsDetectorSoftware/generator/gen_commands.py index 45dbc878f..4a12ee1af 100644 --- a/slsDetectorSoftware/generator/gen_commands.py +++ b/slsDetectorSoftware/generator/gen_commands.py @@ -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 diff --git a/slsDetectorSoftware/generator/readme.md b/slsDetectorSoftware/generator/readme.md index d480d6c43..2e7054660 100644 --- a/slsDetectorSoftware/generator/readme.md +++ b/slsDetectorSoftware/generator/readme.md @@ -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(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(tmp_freq, $output[1]$); + ``` +- convert_to_time and convert_to_freq: takes three parameters: input[0], input[1], output ```cpp auto output = StringTo(input[0], input[1]); ``` diff --git a/slsDetectorSoftware/include/sls/Detector.h b/slsDetectorSoftware/include/sls/Detector.h index 32310f292..d107370de 100644 --- a/slsDetectorSoftware/include/sls/Detector.h +++ b/slsDetectorSoftware/include/sls/Detector.h @@ -1613,20 +1613,26 @@ class Detector { /** [CTB] */ void setNumberOfAnalogSamples(int value, Positions pos = {}); - /** [CTB] in Hz, [XCTB] in Hz */ - Result getADCClock(Positions pos = {}) const; + /** [CTB][XCTB] */ + Result getADCClock(Positions pos = {}) const; - /** [CTB] in Hz, [XCTB] in Hz */ - void setADCClock(int value_in_Hz, Positions pos = {}); + /** [CTB][XCTB] */ + void setADCClock(defs::Hz val, Positions pos = {}); - /** [CTB] in Hz, [XCTB] in Hz */ - Result getRUNClock(Positions pos = {}) const; + /** [CTB][XCTB] */ + Result getRUNClock(Positions pos = {}) const; - /** [CTB] in Hz, [XCTB] in Hz */ - void setRUNClock(int value_in_Hz, Positions pos = {}); + /** [CTB][XCTB] */ + void setRUNClock(defs::Hz val, Positions pos = {}); - /** [CTB] in MHZ */ - Result getSYNCClock(Positions pos = {}) const; + /** [CTB][XCTB] */ + Result getDBITClock(Positions pos = {}) const; + + /** [CTB][XCTB] */ + void setDBITClock(defs::Hz val, Positions pos = {}); + + /** [CTB][XCTB] */ + Result getSYNCClock(Positions pos = {}) const; /** gets list of power enums */ std::vector getPowerList() const; @@ -1721,12 +1727,6 @@ class Detector { */ void setReadoutMode(defs::readoutMode value, Positions pos = {}); - /** [CTB] in Hz, [XCTB] in Hz */ - Result getDBITClock(Positions pos = {}) const; - - /** [CTB] in Hz, [XCTB] in Hz */ - void setDBITClock(int value_in_Hz, Positions pos = {}); - /** [CTB] */ Result 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 getPatterFileName(Positions pos = {}) const; + Result getPatternFileName(Positions pos = {}) const; /** [CTB][Mythen3][Xilinx CTB] Loads ASCII pattern file directly to server * (instead of executing line by line)*/ diff --git a/slsDetectorSoftware/include/sls/Result.h b/slsDetectorSoftware/include/sls/Result.h index 0cb937408..5554bdaa8 100644 --- a/slsDetectorSoftware/include/sls/Result.h +++ b/slsDetectorSoftware/include/sls/Result.h @@ -38,6 +38,7 @@ template > class Result { template ::value && (std::is_same::value || + std::is_same::value || std::is_same::value)>::type> Result(const Result &from) { vec.reserve(from.size()); @@ -49,6 +50,7 @@ template > class Result { template ::value && (std::is_same::value || + std::is_same::value || std::is_same::value)>::type> Result(Result &from) { vec.reserve(from.size()); @@ -60,6 +62,7 @@ template > class Result { template ::value && (std::is_same::value || + std::is_same::value || std::is_same::value)>::type> Result(Result &&from) { vec.reserve(from.size()); diff --git a/slsDetectorSoftware/src/Caller.cpp b/slsDetectorSoftware/src/Caller.cpp index ef97580a4..1e72aba17 100644 --- a/slsDetectorSoftware/src/Caller.cpp +++ b/slsDetectorSoftware/src/Caller.cpp @@ -72,20 +72,24 @@ std::string Caller::adcclk(int action) { std::ostringstream os; // print help if (action == slsDetectorDefs::HELP_ACTION) { - os << R"V0G0N([ADC clock frequency] [(optional unit) MHz|kHz|Hz])V0G0N" + os << R"V0G0N([n_clk] [(optional unit) Hz(default)|kHz|MHz] + [Ctb][Xilinx Ctb] ADC clock frequency. )V0G0N" << std::endl; return os.str(); } // check if action and arguments are valid if (action == slsDetectorDefs::GET_ACTION) { - if (1 && args.size() != 0) { + if (1 && args.size() != 0 && args.size() != 1) { throw RuntimeError("Wrong number of arguments for action GET"); } if (args.size() == 0) { } + if (args.size() == 1) { + } + } else if (action == slsDetectorDefs::PUT_ACTION) { @@ -97,17 +101,17 @@ std::string Caller::adcclk(int action) { try { std::string tmp_freq(args[0]); std::string unit = RemoveUnit(tmp_freq); - StringToHz(tmp_freq, unit); + auto converted_freq = StringTo(tmp_freq, unit); } catch (...) { - throw RuntimeError("Could not convert argument to frequency"); + throw RuntimeError("Could not convert argument to defs::Hz"); } } if (args.size() == 2) { try { - StringToHz(args[0], args[1]); + StringTo(args[0], args[1]); } catch (...) { - throw RuntimeError("Could not convert arguments to frequency"); + throw RuntimeError("Could not convert arguments to defs::Hz"); } } @@ -125,20 +129,25 @@ std::string Caller::adcclk(int action) { auto t = det->getADCClock(std::vector{det_id}); os << OutString(t) << '\n'; } + + if (args.size() == 1) { + auto t = det->getADCClock(std::vector{det_id}); + os << OutString(t, args[0]) << '\n'; + } } if (action == slsDetectorDefs::PUT_ACTION) { if (args.size() == 1) { std::string tmp_freq(args[0]); std::string unit = RemoveUnit(tmp_freq); - auto converted_freq_hz = StringToHz(tmp_freq, unit); - det->setADCClock(converted_freq_hz, std::vector{det_id}); + auto converted_freq = StringTo(tmp_freq, unit); + det->setADCClock(converted_freq, std::vector{det_id}); os << args[0] << '\n'; } if (args.size() == 2) { - auto converted_freq_hz = StringToHz(args[0], args[1]); - det->setADCClock(converted_freq_hz, std::vector{det_id}); + auto converted_freq = StringTo(args[0], args[1]); + det->setADCClock(converted_freq, std::vector{det_id}); os << args[0] << args[1] << '\n'; } } @@ -2498,20 +2507,24 @@ std::string Caller::dbitclk(int action) { std::ostringstream os; // print help if (action == slsDetectorDefs::HELP_ACTION) { - os << R"V0G0N([dbit clock frequency] [(optional unit) MHz|kHz|Hz])V0G0N" + os << R"V0G0N([n_clk] [(optional unit) Hz(default)|kHz|MHz] + [Ctb][Xilinx Ctb] Clock for latching the digital bits. )V0G0N" << std::endl; return os.str(); } // check if action and arguments are valid if (action == slsDetectorDefs::GET_ACTION) { - if (1 && args.size() != 0) { + if (1 && args.size() != 0 && args.size() != 1) { throw RuntimeError("Wrong number of arguments for action GET"); } if (args.size() == 0) { } + if (args.size() == 1) { + } + } else if (action == slsDetectorDefs::PUT_ACTION) { @@ -2523,17 +2536,17 @@ std::string Caller::dbitclk(int action) { try { std::string tmp_freq(args[0]); std::string unit = RemoveUnit(tmp_freq); - StringToHz(tmp_freq, unit); + auto converted_freq = StringTo(tmp_freq, unit); } catch (...) { - throw RuntimeError("Could not convert argument to frequency"); + throw RuntimeError("Could not convert argument to defs::Hz"); } } if (args.size() == 2) { try { - StringToHz(args[0], args[1]); + StringTo(args[0], args[1]); } catch (...) { - throw RuntimeError("Could not convert arguments to frequency"); + throw RuntimeError("Could not convert arguments to defs::Hz"); } } @@ -2551,20 +2564,25 @@ std::string Caller::dbitclk(int action) { auto t = det->getDBITClock(std::vector{det_id}); os << OutString(t) << '\n'; } + + if (args.size() == 1) { + auto t = det->getDBITClock(std::vector{det_id}); + os << OutString(t, args[0]) << '\n'; + } } if (action == slsDetectorDefs::PUT_ACTION) { if (args.size() == 1) { std::string tmp_freq(args[0]); std::string unit = RemoveUnit(tmp_freq); - auto converted_freq_hz = StringToHz(tmp_freq, unit); - det->setDBITClock(converted_freq_hz, std::vector{det_id}); + auto converted_freq = StringTo(tmp_freq, unit); + det->setDBITClock(converted_freq, std::vector{det_id}); os << args[0] << '\n'; } if (args.size() == 2) { - auto converted_freq_hz = StringToHz(args[0], args[1]); - det->setDBITClock(converted_freq_hz, std::vector{det_id}); + auto converted_freq = StringTo(args[0], args[1]); + det->setDBITClock(converted_freq, std::vector{det_id}); os << args[0] << args[1] << '\n'; } } @@ -7344,7 +7362,7 @@ std::string Caller::patfname(int action) { // generate code for each action if (action == slsDetectorDefs::GET_ACTION) { if (args.size() == 0) { - auto t = det->getPatterFileName(std::vector{det_id}); + auto t = det->getPatternFileName(std::vector{det_id}); os << OutString(t) << '\n'; } } @@ -9941,20 +9959,24 @@ std::string Caller::runclk(int action) { std::ostringstream os; // print help if (action == slsDetectorDefs::HELP_ACTION) { - os << R"V0G0N([Run clock frequency] [(optional unit) MHz|kHz|Hz])V0G0N" + os << R"V0G0N([n_clk] [(optional unit) Hz(default)|kHz|MHz] + [Ctb][Xilinx Ctb] Run clock frequency. )V0G0N" << std::endl; return os.str(); } // check if action and arguments are valid if (action == slsDetectorDefs::GET_ACTION) { - if (1 && args.size() != 0) { + if (1 && args.size() != 0 && args.size() != 1) { throw RuntimeError("Wrong number of arguments for action GET"); } if (args.size() == 0) { } + if (args.size() == 1) { + } + } else if (action == slsDetectorDefs::PUT_ACTION) { @@ -9966,17 +9988,17 @@ std::string Caller::runclk(int action) { try { std::string tmp_freq(args[0]); std::string unit = RemoveUnit(tmp_freq); - StringToHz(tmp_freq, unit); + auto converted_freq = StringTo(tmp_freq, unit); } catch (...) { - throw RuntimeError("Could not convert argument to frequency"); + throw RuntimeError("Could not convert argument to defs::Hz"); } } if (args.size() == 2) { try { - StringToHz(args[0], args[1]); + StringTo(args[0], args[1]); } catch (...) { - throw RuntimeError("Could not convert arguments to frequency"); + throw RuntimeError("Could not convert arguments to defs::Hz"); } } @@ -9994,20 +10016,25 @@ std::string Caller::runclk(int action) { auto t = det->getRUNClock(std::vector{det_id}); os << OutString(t) << '\n'; } + + if (args.size() == 1) { + auto t = det->getRUNClock(std::vector{det_id}); + os << OutString(t, args[0]) << '\n'; + } } if (action == slsDetectorDefs::PUT_ACTION) { if (args.size() == 1) { std::string tmp_freq(args[0]); std::string unit = RemoveUnit(tmp_freq); - auto converted_freq_hz = StringToHz(tmp_freq, unit); - det->setRUNClock(converted_freq_hz, std::vector{det_id}); + auto converted_freq = StringTo(tmp_freq, unit); + det->setRUNClock(converted_freq, std::vector{det_id}); os << args[0] << '\n'; } if (args.size() == 2) { - auto converted_freq_hz = StringToHz(args[0], args[1]); - det->setRUNClock(converted_freq_hz, std::vector{det_id}); + auto converted_freq = StringTo(args[0], args[1]); + det->setRUNClock(converted_freq, std::vector{det_id}); os << args[0] << args[1] << '\n'; } } @@ -13110,21 +13137,24 @@ std::string Caller::syncclk(int action) { std::ostringstream os; // print help if (action == slsDetectorDefs::HELP_ACTION) { - os << R"V0G0N([n_clk in MHz] - [Ctb] Sync clock in MHz. )V0G0N" + os << R"V0G0N([n_clk] [(optional unit) Hz(default)|kHz|MHz] + [Ctb] Sync clock. )V0G0N" << std::endl; return os.str(); } // check if action and arguments are valid if (action == slsDetectorDefs::GET_ACTION) { - if (1 && args.size() != 0) { + if (1 && args.size() != 0 && args.size() != 1) { throw RuntimeError("Wrong number of arguments for action GET"); } if (args.size() == 0) { } + if (args.size() == 1) { + } + } else { @@ -13139,6 +13169,11 @@ std::string Caller::syncclk(int action) { auto t = det->getSYNCClock(std::vector{det_id}); os << OutString(t) << '\n'; } + + if (args.size() == 1) { + auto t = det->getSYNCClock(std::vector{det_id}); + os << OutString(t, args[0]) << '\n'; + } } return os.str(); diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 9d5576bc2..01e9f5a44 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -2144,25 +2144,34 @@ void Detector::setNumberOfAnalogSamples(int value, Positions pos) { pimpl->Parallel(&Module::setNumberOfAnalogSamples, pos, value); } -Result Detector::getADCClock(Positions pos) const { +Result Detector::getADCClock(Positions pos) const { return pimpl->Parallel(&Module::getClockFrequency, pos, defs::ADC_CLOCK); } -void Detector::setADCClock(int value_in_Hz, Positions pos) { +void Detector::setADCClock(defs::Hz val, Positions pos) { pimpl->Parallel(&Module::setClockFrequency, pos, defs::ADC_CLOCK, - value_in_Hz); + val.value); } -Result Detector::getRUNClock(Positions pos) const { +Result Detector::getRUNClock(Positions pos) const { return pimpl->Parallel(&Module::getClockFrequency, pos, defs::RUN_CLOCK); } -void Detector::setRUNClock(int value_in_Hz, Positions pos) { +void Detector::setRUNClock(defs::Hz val, Positions pos) { pimpl->Parallel(&Module::setClockFrequency, pos, defs::RUN_CLOCK, - value_in_Hz); + val.value); } -Result Detector::getSYNCClock(Positions pos) const { +Result 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 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 Detector::getDBITClock(Positions pos) const { - return pimpl->Parallel(&Module::getClockFrequency, pos, defs::DBIT_CLOCK); -} - -void Detector::setDBITClock(int value_in_Hz, Positions pos) { - pimpl->Parallel(&Module::setClockFrequency, pos, defs::DBIT_CLOCK, - value_in_Hz); -} - Result 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 Detector::getPatterFileName(Positions pos) const { - return pimpl->Parallel(&Module::getPatterFileName, pos); +Result Detector::getPatternFileName(Positions pos) const { + return pimpl->Parallel(&Module::getPatternFileName, pos); } void Detector::setPattern(const std::string &fname, Positions pos) { diff --git a/slsDetectorSoftware/src/Module.cpp b/slsDetectorSoftware/src/Module.cpp index 6724f1d9f..e4a384fd3 100644 --- a/slsDetectorSoftware/src/Module.cpp +++ b/slsDetectorSoftware/src/Module.cpp @@ -2669,7 +2669,7 @@ void Module::configureTransceiver() { } // Pattern -std::string Module::getPatterFileName() const { +std::string Module::getPatternFileName() const { char retval[MAX_STR_LENGTH]{}; sendToDetector(F_GET_PATTERN_FILE_NAME, nullptr, retval); return retval; diff --git a/slsDetectorSoftware/src/Module.h b/slsDetectorSoftware/src/Module.h index 1f1f5c2e0..cf4672c93 100644 --- a/slsDetectorSoftware/src/Module.h +++ b/slsDetectorSoftware/src/Module.h @@ -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(); diff --git a/slsDetectorSoftware/src/inferAction.cpp b/slsDetectorSoftware/src/inferAction.cpp index 25467d1d2..af2ff6396 100644 --- a/slsDetectorSoftware/src/inferAction.cpp +++ b/slsDetectorSoftware/src/inferAction.cpp @@ -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"); diff --git a/slsDetectorSoftware/tests/Caller/test-Caller-chiptestboard.cpp b/slsDetectorSoftware/tests/Caller/test-Caller-chiptestboard.cpp index 479ecaff3..81a8a6109 100644 --- a/slsDetectorSoftware/tests/Caller/test-Caller-chiptestboard.cpp +++ b/slsDetectorSoftware/tests/Caller/test-Caller-chiptestboard.cpp @@ -921,22 +921,42 @@ TEST_CASE("adcclk", "[.detectorintegration]") { Caller caller(&det); auto det_type = det.getDetectorType().squash(); - if (det_type == defs::CHIPTESTBOARD) { + if (det_type == defs::CHIPTESTBOARD || + det_type == defs::XILINX_CHIPTESTBOARD) { auto prev_val = det.getADCClock(); + + REQUIRE_NOTHROW(caller.call("adcclk", {"MHZ"}, -1, GET)); + REQUIRE_NOTHROW(caller.call("adcclk", {"mhz"}, -1, GET)); + REQUIRE_NOTHROW(caller.call("adcclk", {"MHz"}, -1, GET)); + REQUIRE_NOTHROW(caller.call("adcclk", {"kHz"}, -1, GET)); + REQUIRE_NOTHROW(caller.call("adcclk", {"Hz"}, -1, GET)); + REQUIRE_NOTHROW(caller.call("adcclk", {}, -1, GET)); + // min + if (det_type == defs::CHIPTESTBOARD) + REQUIRE_THROWS(caller.call("adcclk", {"1", "MHz"}, -1, PUT)); + else + REQUIRE_THROWS(caller.call("adcclk", {"9", "MHz"}, -1, PUT)); + // max + if (det_type == defs::CHIPTESTBOARD) + REQUIRE_THROWS(caller.call("adcclk", {"66", "MHz"}, -1, PUT)); + else + REQUIRE_THROWS(caller.call("adcclk", {"301", "MHz"}, -1, PUT)); + { std::ostringstream oss; - caller.call("adcclk", {"20"}, -1, PUT, oss); - REQUIRE(oss.str() == "adcclk 20\n"); + caller.call("adcclk", {"20MHz"}, -1, PUT, oss); + REQUIRE(oss.str() == "adcclk 20MHz\n"); } { std::ostringstream oss; - caller.call("adcclk", {"10"}, -1, PUT, oss); - REQUIRE(oss.str() == "adcclk 10\n"); + caller.call("adcclk", {"10000000"}, -1, PUT, oss); + REQUIRE(oss.str() == "adcclk 10000000\n"); } + { std::ostringstream oss; caller.call("adcclk", {}, -1, GET, oss); - REQUIRE(oss.str() == "adcclk 10000000\n"); + REQUIRE(oss.str() == "adcclk 10MHz\n"); } { std::ostringstream oss; @@ -946,18 +966,20 @@ TEST_CASE("adcclk", "[.detectorintegration]") { { std::ostringstream oss; caller.call("adcclk", {}, -1, GET, oss); - REQUIRE(oss.str() == "adcclk 15000000\n"); + REQUIRE(oss.str() == "adcclk 15MHz\n"); } { std::ostringstream oss; - caller.call("adcclk", {"5.75", "MHz"}, -1, PUT, oss); - REQUIRE(oss.str() == "adcclk 5.75MHz\n"); + caller.call("adcclk", {"15.75", "MHz"}, -1, PUT, oss); + REQUIRE(oss.str() == "adcclk 15.75MHz\n"); } { std::ostringstream oss; caller.call("adcclk", {}, -1, GET, oss); - REQUIRE(oss.str() == "adcclk 5750000\n"); + REQUIRE(oss.str() == "adcclk 15.75MHz\n"); } + std::cout << "Resetting adc clock to :" << ToString(prev_val) + << std::endl; for (int i = 0; i != det.size(); ++i) { det.setADCClock(prev_val[i], {i}); } @@ -972,22 +994,39 @@ TEST_CASE("runclk", "[.detectorintegration]") { Caller caller(&det); auto det_type = det.getDetectorType().squash(); - if (det_type == defs::CHIPTESTBOARD) { + if (det_type == defs::CHIPTESTBOARD || + det_type == defs::XILINX_CHIPTESTBOARD) { auto prev_val = det.getRUNClock(); + + REQUIRE_NOTHROW(caller.call("runclk", {"MHZ"}, -1, GET)); + REQUIRE_NOTHROW(caller.call("runclk", {"mhz"}, -1, GET)); + REQUIRE_NOTHROW(caller.call("runclk", {"MHz"}, -1, GET)); + REQUIRE_NOTHROW(caller.call("runclk", {"kHz"}, -1, GET)); + REQUIRE_NOTHROW(caller.call("runclk", {"Hz"}, -1, GET)); + REQUIRE_NOTHROW(caller.call("runclk", {}, -1, GET)); + // min + if (det_type == defs::CHIPTESTBOARD) + REQUIRE_THROWS(caller.call("runclk", {"1", "MHz"}, -1, PUT)); + else + REQUIRE_THROWS(caller.call("runclk", {"9", "MHz"}, -1, PUT)); + // max + REQUIRE_THROWS(caller.call("runclk", {"301", "MHz"}, -1, PUT)); + { std::ostringstream oss; - caller.call("runclk", {"20"}, -1, PUT, oss); - REQUIRE(oss.str() == "runclk 20\n"); + caller.call("runclk", {"20MHz"}, -1, PUT, oss); + REQUIRE(oss.str() == "runclk 20MHz\n"); } { std::ostringstream oss; - caller.call("runclk", {"10"}, -1, PUT, oss); - REQUIRE(oss.str() == "runclk 10\n"); + caller.call("runclk", {"10000000"}, -1, PUT, oss); + REQUIRE(oss.str() == "runclk 10000000\n"); } + { std::ostringstream oss; caller.call("runclk", {}, -1, GET, oss); - REQUIRE(oss.str() == "runclk 10000000\n"); + REQUIRE(oss.str() == "runclk 10MHz\n"); } { std::ostringstream oss; @@ -997,17 +1036,17 @@ TEST_CASE("runclk", "[.detectorintegration]") { { std::ostringstream oss; caller.call("runclk", {}, -1, GET, oss); - REQUIRE(oss.str() == "runclk 15000000\n"); + REQUIRE(oss.str() == "runclk 15MHz\n"); } { std::ostringstream oss; - caller.call("runclk", {"5.75", "MHz"}, -1, PUT, oss); - REQUIRE(oss.str() == "runclk 5.75MHz\n"); + caller.call("runclk", {"15.75", "MHz"}, -1, PUT, oss); + REQUIRE(oss.str() == "runclk 15.75MHz\n"); } { std::ostringstream oss; caller.call("runclk", {}, -1, GET, oss); - REQUIRE(oss.str() == "runclk 5750000\n"); + REQUIRE(oss.str() == "runclk 15.75MHz\n"); } for (int i = 0; i != det.size(); ++i) { det.setRUNClock(prev_val[i], {i}); @@ -1023,6 +1062,11 @@ TEST_CASE("syncclk", "[.detectorintegration]") { Caller caller(&det); auto det_type = det.getDetectorType().squash(); if (det_type == defs::CHIPTESTBOARD) { + REQUIRE_NOTHROW(caller.call("syncclk", {"MHZ"}, -1, GET)); + REQUIRE_NOTHROW(caller.call("syncclk", {"mhz"}, -1, GET)); + REQUIRE_NOTHROW(caller.call("syncclk", {"MHz"}, -1, GET)); + REQUIRE_NOTHROW(caller.call("syncclk", {"kHz"}, -1, GET)); + REQUIRE_NOTHROW(caller.call("syncclk", {"Hz"}, -1, GET)); REQUIRE_NOTHROW(caller.call("syncclk", {}, -1, GET)); } else { // clock index might work @@ -1289,22 +1333,39 @@ TEST_CASE("dbitclk", "[.detectorintegration]") { Caller caller(&det); auto det_type = det.getDetectorType().squash(); - if (det_type == defs::CHIPTESTBOARD) { + if (det_type == defs::CHIPTESTBOARD || + det_type == defs::XILINX_CHIPTESTBOARD) { auto prev_val = det.getDBITClock(); + + REQUIRE_NOTHROW(caller.call("dbitclk", {"MHZ"}, -1, GET)); + REQUIRE_NOTHROW(caller.call("dbitclk", {"mhz"}, -1, GET)); + REQUIRE_NOTHROW(caller.call("dbitclk", {"MHz"}, -1, GET)); + REQUIRE_NOTHROW(caller.call("dbitclk", {"kHz"}, -1, GET)); + REQUIRE_NOTHROW(caller.call("dbitclk", {"Hz"}, -1, GET)); + REQUIRE_NOTHROW(caller.call("dbitclk", {}, -1, GET)); + // min + if (det_type == defs::CHIPTESTBOARD) + REQUIRE_THROWS(caller.call("dbitclk", {"1", "MHz"}, -1, PUT)); + else + REQUIRE_THROWS(caller.call("dbitclk", {"9", "MHz"}, -1, PUT)); + // max + REQUIRE_THROWS(caller.call("dbitclk", {"301", "MHz"}, -1, PUT)); + { std::ostringstream oss; - caller.call("dbitclk", {"20"}, -1, PUT, oss); - REQUIRE(oss.str() == "dbitclk 20\n"); + caller.call("dbitclk", {"20MHz"}, -1, PUT, oss); + REQUIRE(oss.str() == "dbitclk 20MHz\n"); } { std::ostringstream oss; - caller.call("dbitclk", {"10"}, -1, PUT, oss); - REQUIRE(oss.str() == "dbitclk 10\n"); + caller.call("dbitclk", {"10000000"}, -1, PUT, oss); + REQUIRE(oss.str() == "dbitclk 10000000\n"); } + { std::ostringstream oss; caller.call("dbitclk", {}, -1, GET, oss); - REQUIRE(oss.str() == "dbitclk 10000000\n"); + REQUIRE(oss.str() == "dbitclk 10MHz\n"); } { std::ostringstream oss; @@ -1314,17 +1375,17 @@ TEST_CASE("dbitclk", "[.detectorintegration]") { { std::ostringstream oss; caller.call("dbitclk", {}, -1, GET, oss); - REQUIRE(oss.str() == "dbitclk 15000000\n"); + REQUIRE(oss.str() == "dbitclk 15MHz\n"); } { std::ostringstream oss; - caller.call("dbitclk", {"5.75", "MHz"}, -1, PUT, oss); - REQUIRE(oss.str() == "dbitclk 5.75MHz\n"); + caller.call("dbitclk", {"15.75", "MHz"}, -1, PUT, oss); + REQUIRE(oss.str() == "dbitclk 15.75MHz\n"); } { std::ostringstream oss; caller.call("dbitclk", {}, -1, GET, oss); - REQUIRE(oss.str() == "dbitclk 5750000\n"); + REQUIRE(oss.str() == "dbitclk 15.75MHz\n"); } for (int i = 0; i != det.size(); ++i) { det.setDBITClock(prev_val[i], {i}); diff --git a/slsSupportLib/include/sls/ToString.h b/slsSupportLib/include/sls/ToString.h index ac2d0791a..95faf53fb 100644 --- a/slsSupportLib/include/sls/ToString.h +++ b/slsSupportLib/include/sls/ToString.h @@ -108,6 +108,44 @@ ToString(From t) { } } +/** Convert frequency with specified output unit */ +template +typename std::enable_if::value, std::string>::type +ToString(T f, const std::string &unit) { + double val = static_cast(f.value); + + auto unitLower = [&] { + std::string result = unit; + std::transform(result.begin(), result.end(), result.begin(), + [](unsigned char c) { return std::tolower(c); }); + return result; + }(); + std::ostringstream os; + if (unitLower == "hz") + os << val << unit; + else if (unitLower == "khz") + os << val / (static_cast(1e3)) << unit; + else if (unitLower == "mhz") + os << val / (static_cast(1e6)) << unit; + else + throw std::runtime_error("Unknown unit: " + unit); + return os.str(); +} + +/** Convert frequency automatically selecting the unit */ +template +typename std::enable_if::value, std::string>::type +ToString(From f) { + int val = f.value; + if (val < 1e3) { + return ToString(f, "Hz"); + } else if (val < 1e6) { + return ToString(f, "kHz"); + } else { + return ToString(f, "MHz"); + } +} + /** Conversion of floating point values, removes trailing zeros*/ template typename std::enable_if::value, std::string>::type @@ -279,7 +317,7 @@ ToString(const T &container, const std::string &unit) { return os.str(); } -template +template ::value, int> = 0> T StringTo(const std::string &t, const std::string &unit) { double tval{0}; try { @@ -304,6 +342,33 @@ T StringTo(const std::string &t, const std::string &unit) { } } +template ::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(fval * 1e6)); + } else if (unitLower == "khz") { + return T(static_cast(fval * 1e3)); + } else if (unitLower.empty() || unitLower == "hz") { + return T(static_cast(fval)); + } else { + throw RuntimeError( + "Invalid unit in conversion from string to frequency"); + } +} + template T StringTo(const std::string &t) { std::string tmp{t}; auto unit = RemoveUnit(tmp); @@ -358,7 +423,4 @@ std::vector StringTo(const std::vector &strings) { return result; } -/** Convert frequency string with unit (MHz, kHz, Hz) to Hz */ -int StringToHz(const std::string &s, const std::string &unit); - } // namespace sls diff --git a/slsSupportLib/include/sls/TypeTraits.h b/slsSupportLib/include/sls/TypeTraits.h index 1a153e67b..926b2227d 100644 --- a/slsSupportLib/include/sls/TypeTraits.h +++ b/slsSupportLib/include/sls/TypeTraits.h @@ -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 #include @@ -120,4 +122,9 @@ struct has_bool_isValid : std::false_type {}; template struct has_bool_isValid().isValid)>> : std::is_same().isValid), bool> {}; + +template struct is_frequency : std::false_type {}; + +template <> struct is_frequency : std::true_type {}; + } // namespace sls \ No newline at end of file diff --git a/slsSupportLib/include/sls/sls_detector_defs.h b/slsSupportLib/include/sls/sls_detector_defs.h index f8b4b7877..79aec83a1 100644 --- a/slsSupportLib/include/sls/sls_detector_defs.h +++ b/slsSupportLib/include/sls/sls_detector_defs.h @@ -211,6 +211,14 @@ class slsDetectorDefs { std::map addJsonHeader; }; + struct Hz { + int value{0}; + explicit Hz(int v) : value(v){}; + constexpr bool operator==(const Hz &other) const { + return (value == other.value); + } + }; + #endif enum frameDiscardPolicy { NO_DISCARD, @@ -837,7 +845,6 @@ typedef struct { #endif #ifdef __cplusplus - // TODO! discuss this #include //hmm... but currently no way around namespace sls { diff --git a/slsSupportLib/src/ToString.cpp b/slsSupportLib/src/ToString.cpp index 6203294cb..f8ac4c684 100644 --- a/slsSupportLib/src/ToString.cpp +++ b/slsSupportLib/src/ToString.cpp @@ -1264,23 +1264,4 @@ template <> int64_t StringTo(const std::string &s) { return std::stol(s, nullptr, base); } -int StringToHz(const std::string &s, const std::string &unit) { - double fval{0}; - try { - fval = std::stod(s); - } catch (const std::invalid_argument &e) { - throw RuntimeError("Could not convert string to frequency"); - } - if (unit.empty() || unit == "MHz") { - return static_cast(fval * 1000000.0); - } else if (unit == "kHz") { - return static_cast(fval * 1000.0); - } else if (unit == "Hz") { - return static_cast(fval); - } else { - throw RuntimeError("Unknown unit: " + unit + - ". Supported units: MHz, kHz, Hz"); - } -} - } // namespace sls \ No newline at end of file diff --git a/slsSupportLib/tests/test-ToString.cpp b/slsSupportLib/tests/test-ToString.cpp index 3d35004e8..a7ef24c7f 100644 --- a/slsSupportLib/tests/test-ToString.cpp +++ b/slsSupportLib/tests/test-ToString.cpp @@ -76,6 +76,15 @@ TEST_CASE("conversion from duration to string", "[support]") { REQUIRE(ToString(us(-100)) == "-100us"); } +TEST_CASE("conversion from frequency to string", "[support]") { + REQUIRE(ToString(defs::Hz(150)) == "150Hz"); + REQUIRE(ToString(defs::Hz(1500)) == "1.5kHz"); + REQUIRE(ToString(defs::Hz(1500000)) == "1.5MHz"); + REQUIRE(ToString(defs::Hz(150), "Hz") == "150Hz"); + REQUIRE(ToString(defs::Hz(150), "kHz") == "0.15kHz"); + REQUIRE(ToString(defs::Hz(150), "MHz") == "0.00015MHz"); +} + TEST_CASE("Convert vector of time", "[support]") { std::vector 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("asvn")); } +TEST_CASE("string to frequency", "[support]") { + REQUIRE(StringTo("150") == defs::Hz(150)); + REQUIRE(StringTo("150Hz") == defs::Hz(150)); + REQUIRE(StringTo("1.5kHz") == defs::Hz(1500)); + REQUIRE(StringTo("1.5MHz") == defs::Hz(1500000)); + REQUIRE_THROWS(StringTo("5xs")); + REQUIRE_THROWS(StringTo("asvn")); +} + TEST_CASE("string to detectorType") { using dt = slsDetectorDefs::detectorType; REQUIRE(StringTo
("Eiger") == dt::EIGER);