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);