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 7d3487f29..96d04205e 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 58c972c51..b32b8a659 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
@@ -58,12 +58,6 @@ class AcquisitionTab(QtWidgets.QWidget):
self.view.spinBoxADCPipeline.setDisabled(True)
self.view.spinBoxDBITPhase.setDisabled(True)
self.view.spinBoxDBITPipeline.setDisabled(True)
- self.view.labelRunF.setText("Run Clock Frequency (kHz):")
- self.view.labelDBITF.setText("DBIT Clock Frequency (kHz):")
- self.view.labelADCF.setText("ADC Clock Frequency (kHz):")
- self.view.spinBoxRunF.setMaximum(250000)
- self.view.spinBoxDBITF.setMaximum(250000)
- self.view.spinBoxADCF.setMaximum(250000)
def connect_ui(self):
# For Acquistions Tab
@@ -74,8 +68,11 @@ class AcquisitionTab(QtWidgets.QWidget):
if self.det.type in [detectorType.CHIPTESTBOARD, detectorType.XILINX_CHIPTESTBOARD]:
self.view.spinBoxRunF.editingFinished.connect(self.setRunFrequency)
+ self.view.comboBoxRunF.currentIndexChanged.connect(self.getRunFrequency)
self.view.spinBoxADCF.editingFinished.connect(self.setADCFrequency)
+ self.view.comboBoxADCF.currentIndexChanged.connect(self.getADCFrequency)
self.view.spinBoxDBITF.editingFinished.connect(self.setDBITFrequency)
+ self.view.comboBoxDBITF.currentIndexChanged.connect(self.getDBITFrequency)
if self.det.type == detectorType.CHIPTESTBOARD:
self.view.spinBoxADCPhase.editingFinished.connect(self.setADCPhase)
self.view.spinBoxADCPipeline.editingFinished.connect(self.setADCPipeline)
@@ -195,20 +192,43 @@ class AcquisitionTab(QtWidgets.QWidget):
self.view.comboBoxROMode.currentIndexChanged.connect(self.setReadOut)
self.getReadout()
+
+ def _getFrequency(self, det_attr, spinbox, spinSetter, combobox):
+ spinbox.editingFinished.disconnect()
+ f = getattr(self.det, det_attr).value
+ unit = combobox.currentIndex()
+
+ if unit == 2: #Hz
+ spinbox.setValue(f)
+ elif unit == 1: #kHz
+ spinbox.setValue(f / 1e3)
+ else:
+ spinbox.setValue(f / 1e6)
+
+ spinbox.editingFinished.connect(spinSetter)
+
+ def _setFrequency(self, det_attr, spinbox, combobox, title, getter):
+ value = spinbox.value()
+ idx = combobox.currentIndex()
+
+ if idx == 0:
+ val = MHz(value)
+ elif idx == 1:
+ val = kHz(value)
+ else:
+ val = Hz((int)(value))
+
+ try:
+ setattr(self.det, det_attr, val)
+ except Exception as e:
+ QtWidgets.QMessageBox.warning(self.mainWindow, title + " Fail", str(e), QtWidgets.QMessageBox.Ok)
+ getter()
+
def getRunFrequency(self):
- self.view.spinBoxRunF.editingFinished.disconnect()
- self.view.spinBoxRunF.setValue(self.det.runclk)
- self.view.spinBoxRunF.editingFinished.connect(self.setRunFrequency)
+ self._getFrequency('runclk', self.view.spinBoxRunF, self.setRunFrequency, self.view.comboBoxRunF)
def setRunFrequency(self):
- self.view.spinBoxRunF.editingFinished.disconnect()
- try:
- self.det.runclk = self.view.spinBoxRunF.value()
- except Exception as e:
- QtWidgets.QMessageBox.warning(self.mainWindow, "Run Frequency Fail", str(e), QtWidgets.QMessageBox.Ok)
- # TODO: handling double event exceptions
- self.view.spinBoxRunF.editingFinished.connect(self.setRunFrequency)
- self.getRunFrequency()
+ self._setFrequency('runclk', self.view.spinBoxRunF, self.view.comboBoxRunF, "Run Frequency Fail", self.getRunFrequency)
def getTransceiver(self):
self.view.spinBoxTransceiver.editingFinished.disconnect()
@@ -260,19 +280,10 @@ class AcquisitionTab(QtWidgets.QWidget):
self.getDigital()
def getADCFrequency(self):
- self.view.spinBoxADCF.editingFinished.disconnect()
- self.view.spinBoxADCF.setValue(self.det.adcclk)
- self.view.spinBoxADCF.editingFinished.connect(self.setADCFrequency)
+ self._getFrequency('adcclk', self.view.spinBoxADCF, self.setADCFrequency, self.view.comboBoxADCF)
def setADCFrequency(self):
- self.view.spinBoxADCF.editingFinished.disconnect()
- try:
- self.det.adcclk = self.view.spinBoxADCF.value()
- except Exception as e:
- QtWidgets.QMessageBox.warning(self.mainWindow, "ADC Frequency Fail", str(e), QtWidgets.QMessageBox.Ok)
- # TODO: handling double event exceptions
- self.view.spinBoxADCF.editingFinished.connect(self.setADCFrequency)
- self.getADCFrequency()
+ self._setFrequency('adcclk', self.view.spinBoxADCF, self.view.comboBoxADCF, "ADC Frequency Fail", self.getADCFrequency)
def getADCPhase(self):
self.view.spinBoxADCPhase.editingFinished.disconnect()
@@ -305,19 +316,10 @@ class AcquisitionTab(QtWidgets.QWidget):
self.getADCPipeline()
def getDBITFrequency(self):
- self.view.spinBoxDBITF.editingFinished.disconnect()
- self.view.spinBoxDBITF.setValue(self.det.dbitclk)
- self.view.spinBoxDBITF.editingFinished.connect(self.setDBITFrequency)
+ self._getFrequency('dbitclk', self.view.spinBoxDBITF, self.setDBITFrequency, self.view.comboBoxDBITF)
def setDBITFrequency(self):
- self.view.spinBoxDBITF.editingFinished.disconnect()
- try:
- self.det.dbitclk = self.view.spinBoxDBITF.value()
- except Exception as e:
- QtWidgets.QMessageBox.warning(self.mainWindow, "DBit Frequency Fail", str(e), QtWidgets.QMessageBox.Ok)
- # TODO: handling double event exceptions
- self.view.spinBoxDBITF.editingFinished.connect(self.setDBITFrequency)
- self.getDBITFrequency()
+ self._setFrequency('dbitclk', self.view.spinBoxDBITF, self.view.comboBoxDBITF, "DBit Frequency Fail", self.getDBITFrequency)
def getDBITPhase(self):
self.view.spinBoxDBITPhase.editingFinished.disconnect()
diff --git a/pyctbgui/pyctbgui/ui/acquisition.ui b/pyctbgui/pyctbgui/ui/acquisition.ui
index c2d15dff6..ac36336ed 100644
--- a/pyctbgui/pyctbgui/ui/acquisition.ui
+++ b/pyctbgui/pyctbgui/ui/acquisition.ui
@@ -36,7 +36,7 @@
-
-
+
0
@@ -45,13 +45,13 @@
- 125
+ 120
31
- 125
+ 120
31
@@ -61,18 +61,17 @@
QAbstractSpinBox::UpDownArrows
+
+ 3
+
- 1000
+ 999999999.000000000000000
+
+
+ 1.000000000000000
- 0
-
-
-
- -
-
-
- Read Out Mode:
+ 0.000000000000000
@@ -117,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
+
+
+
+
@@ -152,13 +205,13 @@
- 125
+ 185
32
- 125
+ 185
32
@@ -210,6 +263,12 @@
201
+
+
+ 190
+ 0
+
+
QFrame::StyledPanel
@@ -217,16 +276,128 @@
QFrame::Sunken
- -
-
-
+
-
+
+
+ ADC Pipeline:
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::Expanding
+
+
- 200
- 0
+ 10
+ 20
+
+
+ -
+
- DBIT Clock Frequency (MHz):
+ DBIT Clock Phase (a.u.):
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 120
+ 31
+
+
+
+
+ 120
+ 31
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ 3
+
+
+ 999999999.000000000000000
+
+
+ 1.000000000000000
+
+
+ 0.000000000000000
+
+
+
+ -
+
+
+ ADC Clock Phase (a.u.):
+
+
+
+ -
+
+
+ DBIT Pipeline:
+
+
+
+ -
+
+
+ Digital Samples:
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 120
+ 31
+
+
+
+
+ 120
+ 31
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ 3
+
+
+ 999999999.000000000000000
+
+
+ 1.000000000000000
+
+
+ 0.000000000000000
@@ -245,213 +416,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
-
-
- 1000
-
-
-
- -
-
-
-
- 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
-
-
- 1000
-
-
-
- -
-
-
-
- 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:
@@ -462,7 +427,51 @@
- -
+
-
+
+
+
+ 200
+ 0
+
+
+
+ DBIT Clock Frequency:
+
+
+
+ -
+
+
+
+ 60
+ 31
+
+
+
+
+ 60
+ 16777215
+
+
+
-
+
+ MHz
+
+
+ -
+
+ kHz
+
+
+ -
+
+ Hz
+
+
+
+
+ -
@@ -472,13 +481,13 @@
- 125
+ 185
32
- 125
+ 185
32
@@ -493,14 +502,60 @@
- -
-
-
- Digital Samples:
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 185
+ 31
+
+
+
+
+ 185
+ 31
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ 9999
- -
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 185
+ 31
+
+
+
+
+ 185
+ 31
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
@@ -510,13 +565,13 @@
- 125
+ 185
32
- 125
+ 185
32
@@ -534,6 +589,90 @@
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 185
+ 31
+
+
+
+
+ 185
+ 31
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ 9999
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 185
+ 31
+
+
+
+
+ 185
+ 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 eeed02b79..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,15 +3442,21 @@ class Detector(CppDetectorApi):
@element
def runclk(self):
"""
- [Ctb] Sets Run clock frequency in MHz. \n
- [Xilinx Ctb] Sets Run clock frequency in kHz.
- """
+ [Ctb][Xilinx Ctb] Sets Run clock frequency.
+ Example
+ --------
+ >>> d.runclk
+ >>> 10MHz
+ >>> d.runclk = MHz(5)
+ >>> d.runclk = Hz(5 * 1000 * 1000)
+ >>> d.runclk = kHz(2000)
+ """
return self.getRUNClock()
@runclk.setter
def runclk(self, freq):
- ut.set_using_dict(self.setRUNClock, freq)
+ ut.set_using_dict(self.setRUNClock, freq)
@property
@element
@@ -3526,10 +3533,16 @@ class Detector(CppDetectorApi):
@element
def dbitclk(self):
"""
- [Ctb] Sets clock for latching the digital bits in MHz. \n
- [Xilinx Ctb] clock for latching the digital bits in kHz.
- """
+ [Ctb][Xilinx Ctb] Sets clock for latching the digital bits.
+ Example
+ --------
+ >>> d.dbitclk
+ >>> 10MHz
+ >>> d.dbitclk = MHz(5)
+ >>> d.dbitclk = Hz(5 * 1000 * 1000)
+ >>> d.dbitclk = kHz(2000)
+ """
return self.getDBITClock()
@dbitclk.setter
@@ -3657,10 +3670,16 @@ class Detector(CppDetectorApi):
@element
def adcclk(self):
"""
- [Ctb] Sets ADC clock frequency in MHz. \n
- [Xilinx Ctb] Sets ADC clock frequency in kHz.
- """
+ [Ctb][Xilinx Ctb] Sets ADC clock frequency.
+ Example
+ --------
+ >>> d.adcclk
+ >>> 10MHz
+ >>> d.adcclk = MHz(5)
+ >>> d.adcclk = Hz(5 * 1000 * 1000)
+ >>> d.adcclk = kHz(2000)
+ """
return self.getADCClock()
@adcclk.setter
@@ -3671,7 +3690,7 @@ class Detector(CppDetectorApi):
@element
def syncclk(self):
"""
- [Ctb] Sync clock in MHz.
+ [Ctb] Sync clock.
:setter: Not implemented
"""
@@ -3704,7 +3723,7 @@ class Detector(CppDetectorApi):
[Ctb][Mythen3][Xilinx Ctb] Gets the pattern file name including path of the last pattern uploaded. Returns an empty if nothing was uploaded or via a server default
file
"""
- return self.getPatterFileName()
+ return self.getPatternFileName()
def patternstart(self):
"""[Ctb][Mythen3][Xilinx Ctb] Starts pattern. """
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..7bf942e22 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."""
@@ -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..c4e8b216e
--- /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_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/RegisterDefs.h b/slsDetectorServers/ctbDetectorServer/RegisterDefs.h
index 02a35dd1e..333f367b6 100644
--- a/slsDetectorServers/ctbDetectorServer/RegisterDefs.h
+++ b/slsDetectorServers/ctbDetectorServer/RegisterDefs.h
@@ -628,11 +628,14 @@
#define ADC_SLOW_CTRL_DONE_OFST (1)
#define ADC_SLOW_CTRL_DONE_MSK (0x00000001 << ADC_SLOW_CTRL_DONE_OFST)
+/* Clock Measurement base reg */
+#define PLL_FREQ_MEASURE_REG (0x44 << MEM_MAP_SHIFT)
+
/* SPI */
#define SPI_CTRL_REG (0x48 << MEM_MAP_SHIFT)
- #define SPI_CTRL_RX_EMPTY_BIT 2
- #define SPI_CTRL_CHIPSELECT_BIT 4
- #define SPI_CTRL_NBIT_OFST 16
+#define SPI_CTRL_RX_EMPTY_BIT 2
+#define SPI_CTRL_CHIPSELECT_BIT 4
+#define SPI_CTRL_NBIT_OFST 16
#define SPI_WRITEDATA_REG (0x49 << MEM_MAP_SHIFT)
#define SPI_READDATA_REG (0x4A << MEM_MAP_SHIFT)
diff --git a/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer b/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer
index 0d314ffb4..b717a96dd 100755
Binary files a/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer and b/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer differ
diff --git a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c
index 2cca46fb4..4f8ec83ae 100644
--- a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c
+++ b/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c
@@ -13,6 +13,7 @@
#include "communication_funcs_UDP.h"
#include "loadPattern.h"
+#include
#include
#include
#include
@@ -65,7 +66,7 @@ uint8_t adcEnableMask_10g = 0xFF;
uint32_t transceiverMask = DEFAULT_TRANSCEIVER_MASK;
int32_t clkPhase[NUM_CLOCKS] = {};
-uint32_t clkFrequency[NUM_CLOCKS] = {40, 20, 20, 200};
+uint32_t clkFrequency[NUM_CLOCKS] = {};
int dacValues[NDAC_ONLY] = {};
int powerValues[NPWR] = {}; // powerIndex (A->IO, Chip)
@@ -557,7 +558,7 @@ void setupDetector() {
ALTERA_PLL_SetDefines(PLL_CNTRL_REG, PLL_PARAM_REG,
PLL_CNTRL_RCNFG_PRMTR_RST_MSK, PLL_CNTRL_WR_PRMTR_MSK,
PLL_CNTRL_PLL_RST_MSK, PLL_CNTRL_ADDR_MSK,
- PLL_CNTRL_ADDR_OFST);
+ PLL_CNTRL_ADDR_OFST, PLL_FREQ_MEASURE_REG);
ALTERA_PLL_ResetPLLAndReconfiguration();
resetCore();
@@ -632,10 +633,16 @@ void setupDetector() {
DEFAULT_NUM_SAMPLES); // update databytes and allocate ram
setNumTransceiverSamples(DEFAULT_NUM_SAMPLES);
setNumFrames(DEFAULT_NUM_FRAMES);
- setExpTime(DEFAULT_EXPTIME);
+ initError = setExpTime(DEFAULT_EXPTIME, initErrorMessage);
+ if (initError == FAIL)
+ return;
setNumTriggers(DEFAULT_NUM_CYCLES);
- setPeriod(DEFAULT_PERIOD);
- setDelayAfterTrigger(DEFAULT_DELAY);
+ initError = setPeriod(DEFAULT_PERIOD, initErrorMessage);
+ if (initError == FAIL)
+ return;
+ initError = setDelayAfterTrigger(DEFAULT_DELAY, initErrorMessage);
+ if (initError == FAIL)
+ return;
setTiming(DEFAULT_TIMING_MODE);
setADCEnableMask(BIT32_MSK);
setADCEnableMask_10G(BIT32_MSK);
@@ -1134,64 +1141,132 @@ int setNumTransceiverSamples(int val) {
int getNumTransceiverSamples() { return ntSamples; }
-int setExpTime(int64_t val) {
+int setExpTime(int64_t val, char *mess) {
setPatternWaitInterval(0, val);
- // validate for tolerance
- int64_t retval = getExpTime();
+ // validate
+ uint64_t arg_clocks = ns_to_clocks(val, clkFrequency[RUN_CLK]);
+ uint64_t retval_clocks = getPatternWaitClocks(0);
+ if (arg_clocks != retval_clocks) {
+ sprintf(mess,
+ "Failed to set exposure time. Could not set number of clocks "
+ "to %lld, read %lld\n",
+ (long long int)arg_clocks, (long long int)retval_clocks);
+ LOG(logERROR, (mess));
+ return FAIL;
+ }
+
+ // log rounding if any
+ int64_t retval = getPatternWaitInterval(0);
if (val != retval) {
+ LOG(logWARNING, ("Rounding to %lld ns due to clock frequency\n",
+ (long long int)retval));
+ }
+
+ return OK;
+}
+
+int getExpTime(int64_t *retval, char *mess) {
+ *retval = getPatternWaitInterval(0);
+ if (*retval == -1) {
+ sprintf(mess, "Failed to get exposure time.\n");
+ LOG(logERROR, (mess));
return FAIL;
}
return OK;
}
-int64_t getExpTime() { return getPatternWaitInterval(0); }
-
-int setPeriod(int64_t val) {
+int setPeriod(int64_t val, char *mess) {
if (val < 0) {
- LOG(logERROR, ("Invalid period: %lld ns\n", (long long int)val));
+ sprintf(mess, "Invalid period: %lld ns\n", (long long int)val);
+ LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("Setting period %lld ns\n", (long long int)val));
- val *= (1E-3 * clkFrequency[SYNC_CLK]);
- set64BitReg(val, PERIOD_LSB_REG, PERIOD_MSB_REG);
+ uint64_t arg_clocks = ns_to_clocks(val, clkFrequency[SYNC_CLK]);
+ set64BitReg(arg_clocks, PERIOD_LSB_REG, PERIOD_MSB_REG);
- // validate for tolerance
- int64_t retval = getPeriod();
- val /= (1E-3 * clkFrequency[SYNC_CLK]);
- if (val != retval) {
+ // validate
+ uint64_t retval_clocks = get64BitReg(PERIOD_LSB_REG, PERIOD_MSB_REG);
+ if (arg_clocks != retval_clocks) {
+ sprintf(mess,
+ "Failed to set period. Could not set number of clocks "
+ "to %lld, red %lld\n",
+ (long long int)arg_clocks, (long long int)retval_clocks);
+ LOG(logERROR, (mess));
return FAIL;
}
+
+ // log rounding if any
+ int64_t retval = 0;
+ if (getPeriod(&retval, mess) == FAIL) {
+ return FAIL;
+ }
+ if (val != retval) {
+ LOG(logWARNING, ("Rounding to %lld ns due to clock frequency\n",
+ (long long int)retval));
+ }
+
return OK;
}
-int64_t getPeriod() {
- return get64BitReg(PERIOD_LSB_REG, PERIOD_MSB_REG) /
- (1E-3 * clkFrequency[SYNC_CLK]);
+int getPeriod(int64_t *retval, char *mess) {
+ if (clkFrequency[SYNC_CLK] == 0) {
+ sprintf(mess, "Cannot get period. Sync clock frequency is 0.\n");
+ LOG(logERROR, (mess));
+ return FAIL;
+ }
+ uint64_t numClocks = get64BitReg(PERIOD_LSB_REG, PERIOD_MSB_REG);
+ *retval = clocks_to_ns(numClocks, clkFrequency[SYNC_CLK]);
+ return OK;
}
-int setDelayAfterTrigger(int64_t val) {
+int setDelayAfterTrigger(int64_t val, char *mess) {
if (val < 0) {
- LOG(logERROR,
- ("Invalid delay after trigger: %lld ns\n", (long long int)val));
+ sprintf(mess, "Invalid delay after trigger: %lld ns\n",
+ (long long int)val);
+ LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("Setting delay after trigger %lld ns\n", (long long int)val));
- val *= (1E-3 * clkFrequency[SYNC_CLK]);
- set64BitReg(val, DELAY_LSB_REG, DELAY_MSB_REG);
+ uint64_t arg_clocks = ns_to_clocks(val, clkFrequency[SYNC_CLK]);
+ set64BitReg(arg_clocks, DELAY_LSB_REG, DELAY_MSB_REG);
- // validate for tolerance
- int64_t retval = getDelayAfterTrigger();
- val /= (1E-3 * clkFrequency[SYNC_CLK]);
- if (val != retval) {
+ // validate
+ uint64_t retval_clocks = get64BitReg(DELAY_LSB_REG, DELAY_MSB_REG);
+ if (arg_clocks != retval_clocks) {
+ sprintf(
+ mess,
+ "Failed to set delay after trigger. Could not set number of clocks "
+ "to %lld, read %lld\n",
+ (long long int)arg_clocks, (long long int)retval_clocks);
+ LOG(logERROR, (mess));
return FAIL;
}
+
+ // log rounding if any
+ int64_t retval = 0;
+ if (getDelayAfterTrigger(&retval, mess) == FAIL) {
+ return FAIL;
+ }
+ if (val != retval) {
+ LOG(logWARNING, ("Rounding to %lld ns due to clock frequency\n",
+ (long long int)retval));
+ }
+
return OK;
}
-int64_t getDelayAfterTrigger() {
- return get64BitReg(DELAY_LSB_REG, DELAY_MSB_REG) /
- (1E-3 * clkFrequency[SYNC_CLK]);
+int getDelayAfterTrigger(int64_t *retval, char *mess) {
+ if (clkFrequency[SYNC_CLK] == 0) {
+ sprintf(mess,
+ "Cannot get delay after trigger. Sync clock frequency is 0.\n");
+ LOG(logERROR, (mess));
+ return FAIL;
+ }
+ uint64_t numClocks = get64BitReg(DELAY_LSB_REG, DELAY_MSB_REG);
+ *retval = clocks_to_ns(numClocks, clkFrequency[SYNC_CLK]);
+ return OK;
}
int64_t getNumFramesLeft() {
@@ -1202,14 +1277,27 @@ int64_t getNumTriggersLeft() {
return get64BitReg(CYCLES_LEFT_LSB_REG, CYCLES_LEFT_MSB_REG);
}
-int64_t getDelayAfterTriggerLeft() {
- return get64BitReg(DELAY_LEFT_LSB_REG, DELAY_LEFT_MSB_REG) /
- (1E-3 * clkFrequency[SYNC_CLK]);
+int getDelayAfterTriggerLeft(int64_t *retval, char *mess) {
+ if (clkFrequency[SYNC_CLK] == 0) {
+ sprintf(mess, "Cannot get delay after trigger left. Sync clock "
+ "frequency is 0.\n");
+ LOG(logERROR, (mess));
+ return FAIL;
+ }
+ uint64_t numClocks = get64BitReg(DELAY_LEFT_LSB_REG, DELAY_LEFT_MSB_REG);
+ *retval = clocks_to_ns(numClocks, clkFrequency[SYNC_CLK]);
+ return OK;
}
-int64_t getPeriodLeft() {
- return get64BitReg(PERIOD_LEFT_LSB_REG, PERIOD_LEFT_MSB_REG) /
- (1E-3 * clkFrequency[SYNC_CLK]);
+int getPeriodLeft(int64_t *retval, char *mess) {
+ if (clkFrequency[SYNC_CLK] == 0) {
+ sprintf(mess, "Cannot get period left. Sync clock frequency is 0.\n");
+ LOG(logERROR, (mess));
+ return FAIL;
+ }
+ uint64_t numClocks = get64BitReg(PERIOD_LEFT_LSB_REG, PERIOD_LEFT_MSB_REG);
+ *retval = clocks_to_ns(numClocks, clkFrequency[SYNC_CLK]);
+ return OK;
}
int64_t getFramesFromStart() {
@@ -1218,13 +1306,14 @@ int64_t getFramesFromStart() {
}
int64_t getActualTime() {
- return get64BitReg(TIME_FROM_START_LSB_REG, TIME_FROM_START_MSB_REG) /
- (1E-3 * CLK_FREQ);
+ // reg in unit of 100ns
+ return get64BitReg(TIME_FROM_START_LSB_REG, TIME_FROM_START_MSB_REG) * 100;
}
int64_t getMeasurementTime() {
- return get64BitReg(START_FRAME_TIME_LSB_REG, START_FRAME_TIME_MSB_REG) /
- (1E-3 * CLK_FREQ);
+ // reg in unit of 100ns
+ return get64BitReg(START_FRAME_TIME_LSB_REG, START_FRAME_TIME_MSB_REG) *
+ 100;
}
/* parameters - settings */
@@ -2206,13 +2295,12 @@ int getMaxPhase(enum CLKINDEX ind) {
LOG(logERROR, ("Unknown clock index %d to get max phase\n", ind));
return -1;
}
- int ret = ((double)PLL_VCO_FREQ_MHZ / (double)clkFrequency[ind]) *
+ int ret = ((double)PLL_VCO_FREQ_HZ / (double)clkFrequency[ind]) *
MAX_PHASE_SHIFTS_STEPS;
char *clock_names[] = {CLK_NAMES};
- LOG(logDEBUG1,
- ("Max Phase Shift (%s): %d (Clock: %d MHz, VCO:%d MHz)\n",
- clock_names[ind], ret, clkFrequency[ind], PLL_VCO_FREQ_MHZ));
+ LOG(logDEBUG1, ("Max Phase Shift (%s): %d (Clock: %d Hz, VCO:%d Hz)\n",
+ clock_names[ind], ret, clkFrequency[ind], PLL_VCO_FREQ_HZ));
return ret;
}
@@ -2248,12 +2336,12 @@ int setFrequency(enum CLKINDEX ind, int val) {
return FAIL;
}
char *clock_names[] = {CLK_NAMES};
- LOG(logINFO, ("\tSetting %s clock (%d) frequency to %d MHz\n",
+ LOG(logINFO, ("\tSetting %s clock (%d) frequency to %d Hz\n",
clock_names[ind], ind, val));
// check adc clk too high
if (ind == ADC_CLK && val > MAXIMUM_ADC_CLK) {
- LOG(logERROR, ("Frequency %d MHz too high for ADC\n", val));
+ LOG(logERROR, ("Frequency %d Hz too high for ADC\n", val));
return FAIL;
}
@@ -2265,8 +2353,8 @@ int setFrequency(enum CLKINDEX ind, int val) {
// Calculate and set output frequency
clkFrequency[ind] =
- ALTERA_PLL_SetOuputFrequency(ind, PLL_VCO_FREQ_MHZ, val);
- LOG(logINFO, ("\t%s clock (%d) frequency set to %d MHz\n", clock_names[ind],
+ ALTERA_PLL_SetOutputFrequency(ind, PLL_VCO_FREQ_HZ, val);
+ LOG(logINFO, ("\t%s clock (%d) frequency set to %d Hz\n", clock_names[ind],
ind, clkFrequency[ind]));
// phase reset by pll (when setting output frequency)
@@ -2294,6 +2382,17 @@ int getFrequency(enum CLKINDEX ind) {
LOG(logERROR, ("Unknown clock index %d to get frequency\n", ind));
return -1;
}
+#ifndef VIRTUAL
+ // get the measured frequency from the firmware
+ int measuredFreqHz = ALTERA_PLL_getFrequency(ind);
+
+ // checking against 0 here ensures compatibility with old firmware, TODO:
+ // remove this check at some point
+ if (measuredFreqHz != 0) {
+ // Round to nearest Hz. (should we round at all ?)
+ clkFrequency[ind] = measuredFreqHz;
+ }
+#endif
return clkFrequency[ind];
}
@@ -2507,10 +2606,21 @@ void *start_timer(void *arg) {
return NULL;
}
- int64_t periodNs = getPeriod();
+ int64_t periodNs = 0;
+ int64_t expUs = 0;
+ {
+ char mess[MAX_STR_LENGTH] = {0};
+ if (getPeriod(&periodNs, mess) == FAIL) {
+ LOG(logERROR, ("Failed to get period.\n"));
+ return NULL;
+ }
+ if (getExpTime(&expUs, mess) == FAIL) {
+ LOG(logERROR, ("Failed to get exposure time.\n"));
+ return NULL;
+ }
+ expUs /= 1000;
+ }
int numFrames = (getNumFrames() * getNumTriggers());
- int64_t expUs = getExpTime() / 1000;
-
int imageSize = dataBytes;
int dataSize = UDP_PACKET_DATA_BYTES;
int packetSize = sizeof(sls_detector_header) + dataSize;
diff --git a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.h b/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.h
index 3dccdf8c1..e5db4281f 100644
--- a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.h
+++ b/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.h
@@ -98,10 +98,10 @@ void setNumFrames(int64_t val);
int64_t getNumFrames();
void setNumTriggers(int64_t val);
int64_t getNumTriggers();
-int setExpTime(int64_t val);
-int64_t getExpTime();
-int setPeriod(int64_t val);
-int64_t getPeriod();
+int setExpTime(int64_t val, char *mess);
+int getExpTime(int64_t *retval, char *mess);
+int setPeriod(int64_t val, char *mess);
+int getPeriod(int64_t *retval, char *mess);
int setNumAnalogSamples(int val);
int getNumAnalogSamples();
int setNumDigitalSamples(int val);
@@ -111,10 +111,10 @@ int getNumTransceiverSamples();
int64_t getNumFramesLeft();
int64_t getNumTriggersLeft();
-int setDelayAfterTrigger(int64_t val);
-int64_t getDelayAfterTrigger();
-int64_t getDelayAfterTriggerLeft();
-int64_t getPeriodLeft();
+int setDelayAfterTrigger(int64_t val, char *mess);
+int getDelayAfterTrigger(int64_t *retval, char *mess);
+int getDelayAfterTriggerLeft(int64_t *retval, char *mess);
+int getPeriodLeft(int64_t *retval, char *mess);
int64_t getFramesFromStart();
int64_t getActualTime();
int64_t getMeasurementTime();
diff --git a/slsDetectorServers/ctbDetectorServer/slsDetectorServer_defs.h b/slsDetectorServers/ctbDetectorServer/slsDetectorServer_defs.h
index aeb66b82c..61b59b66a 100644
--- a/slsDetectorServers/ctbDetectorServer/slsDetectorServer_defs.h
+++ b/slsDetectorServers/ctbDetectorServer/slsDetectorServer_defs.h
@@ -44,13 +44,16 @@
#define DEFAULT_VLIMIT (0)
#define DEFAULT_TIMING_MODE (AUTO_TIMING)
#define DEFAULT_TX_UDP_PORT (0x7e9a)
-#define DEFAULT_RUN_CLK (200) // 40
-#define DEFAULT_ADC_CLK (40) // 20
-#define DEFAULT_SYNC_CLK (40) // 20
-#define DEFAULT_DBIT_CLK (200)
-#define NS_TO_CLK_CYCLE (1E-3) // ns to MHz
+#define DEFAULT_RUN_CLK (80000000) // 80 MHz
+#define DEFAULT_ADC_CLK (40000000) // 40 MHz
+#define DEFAULT_SYNC_CLK (40000000) // 40 MHz
+#define DEFAULT_DBIT_CLK (200000000) // 200 MHz
+#define NS_TO_CLK_CYCLE (1E-9) // ns to MHz
#define DEFAULT_TRANSCEIVER_MASK (0x3)
+#define MIN_CLK_FREQ (2000000) // 2 MHz
+#define MAX_CLK_FREQ (300000000) // 300 MHz
+
#define MAX_TRANSCEIVER_MASK (0xF)
#define MAX_TRANSCEIVER_SAMPLES (0xFFFF)
@@ -89,8 +92,8 @@
#define BIT32_MSK (0xFFFFFFFF)
#define BIT16_MASK (0xFFFF)
-#define MAXIMUM_ADC_CLK (65)
-#define PLL_VCO_FREQ_MHZ (800)
+#define MAXIMUM_ADC_CLK (65000000) // 65 MHz
+#define PLL_VCO_FREQ_HZ (800000000) // 800MHz
/* Struct Definitions */
typedef struct udp_header_struct {
diff --git a/slsDetectorServers/gotthard2DetectorServer/slsDetectorFunctionList.h b/slsDetectorServers/gotthard2DetectorServer/slsDetectorFunctionList.h
index 7c442f7b1..124a058f8 100644
--- a/slsDetectorServers/gotthard2DetectorServer/slsDetectorFunctionList.h
+++ b/slsDetectorServers/gotthard2DetectorServer/slsDetectorFunctionList.h
@@ -163,7 +163,6 @@ int setPhase(enum CLKINDEX ind, int val, int degrees);
int getPhase(enum CLKINDEX ind, int degrees);
int getMaxPhase(enum CLKINDEX ind);
int validatePhaseinDegrees(enum CLKINDEX ind, int val, int retval);
-// void setFrequency(enum CLKINDEX ind, int val);
int getFrequency(enum CLKINDEX ind);
int getVCOFrequency(enum CLKINDEX ind);
int setReadoutSpeed(int val);
diff --git a/slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServer_developer b/slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServer_developer
index 490129740..28608b061 100755
Binary files a/slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServer_developer and b/slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServer_developer differ
diff --git a/slsDetectorServers/mythen3DetectorServer/slsDetectorFunctionList.h b/slsDetectorServers/mythen3DetectorServer/slsDetectorFunctionList.h
index 09f49d589..47bb0e1c4 100644
--- a/slsDetectorServers/mythen3DetectorServer/slsDetectorFunctionList.h
+++ b/slsDetectorServers/mythen3DetectorServer/slsDetectorFunctionList.h
@@ -195,7 +195,6 @@ int setPhase(enum CLKINDEX ind, int val, int degrees);
int getPhase(enum CLKINDEX ind, int degrees);
int getMaxPhase(enum CLKINDEX ind);
int validatePhaseinDegrees(enum CLKINDEX ind, int val, int retval);
-// void setFrequency(enum CLKINDEX ind, int val);
int getFrequency(enum CLKINDEX ind);
int getVCOFrequency(enum CLKINDEX ind);
int getMaxClockDivider();
diff --git a/slsDetectorServers/slsDetectorServer/include/ALTERA_PLL.h b/slsDetectorServers/slsDetectorServer/include/ALTERA_PLL.h
index d531db5b0..9c8b88677 100644
--- a/slsDetectorServers/slsDetectorServer/include/ALTERA_PLL.h
+++ b/slsDetectorServers/slsDetectorServer/include/ALTERA_PLL.h
@@ -20,6 +20,10 @@
void ALTERA_PLL_SetDefines(uint32_t creg, uint32_t preg, uint32_t rprmsk,
uint32_t wpmsk, uint32_t prmsk, uint32_t amsk,
int aofst, uint32_t wd2msk, int clk2Index);
+#elif defined(CHIPTESTBOARDD)
+void ALTERA_PLL_SetDefines(uint32_t creg, uint32_t preg, uint32_t rprmsk,
+ uint32_t wpmsk, uint32_t prmsk, uint32_t amsk,
+ int aofst, uint32_t freqreg);
#else
/**
* Set Defines
@@ -71,8 +75,15 @@ void ALTERA_PLL_SetModePolling();
/**
* Calculate and write output frequency
* @param clkIndex clock index
- * @param pllVCOFreqMhz PLL VCO Frequency in Mhz
+ * @param pllVCOFreqHz PLL VCO Frequency in Hz
* @param value frequency to set to
* @param frequency set
*/
-int ALTERA_PLL_SetOuputFrequency(int clkIndex, int pllVCOFreqMhz, int value);
+int ALTERA_PLL_SetOutputFrequency(int clkIndex, int pllVCOFreqHz, int value);
+
+/**
+ * get measured clock frequency
+ */
+#if defined(CHIPTESTBOARDD)
+uint32_t ALTERA_PLL_getFrequency(uint32_t clkIDX);
+#endif
diff --git a/slsDetectorServers/slsDetectorServer/include/common.h b/slsDetectorServers/slsDetectorServer/include/common.h
index 7c6139f16..6dbbaae4e 100644
--- a/slsDetectorServers/slsDetectorServer/include/common.h
+++ b/slsDetectorServers/slsDetectorServer/include/common.h
@@ -2,6 +2,7 @@
// Copyright (C) 2021 Contributors to the SLS Detector Package
#pragma once
+#include "clogger.h"
#include "sls/md5.h"
#include // int64_t
#include
@@ -21,6 +22,19 @@
enum numberMode { DEC, HEX };
enum PROGRAM_INDEX { PROGRAM_FPGA, PROGRAM_KERNEL, PROGRAM_SERVER };
+#define NS_PER_SEC 1000000000ULL
+#define HALF_NS_PER_SEC (NS_PER_SEC / 2)
+static inline uint64_t ns_to_clocks(uint64_t t, uint32_t freq_hz) {
+ return (t * (uint64_t)freq_hz + HALF_NS_PER_SEC) / NS_PER_SEC;
+}
+static inline uint64_t clocks_to_ns(uint64_t clocks, uint32_t freq_hz) {
+ if (freq_hz == 0) {
+ LOG(logERROR, ("Frequency is 0, cannot convert clocks to ns\n"));
+ return (uint64_t)-1;
+ }
+ return (clocks * (uint64_t)NS_PER_SEC + freq_hz / 2) / freq_hz;
+}
+
/**
* Convert a value from a range to a different range (eg voltage to dac or vice
* versa)
diff --git a/slsDetectorServers/slsDetectorServer/src/ALTERA_PLL.c b/slsDetectorServers/slsDetectorServer/src/ALTERA_PLL.c
index 0bf12e61f..eed289ae5 100644
--- a/slsDetectorServers/slsDetectorServer/src/ALTERA_PLL.c
+++ b/slsDetectorServers/slsDetectorServer/src/ALTERA_PLL.c
@@ -130,7 +130,8 @@ uint32_t ALTERA_PLL_Cntrl_WrPrmtrMask = 0x0;
#if defined(JUNGFRAUD)
uint32_t ALTERA_PLL_Cntrl_DBIT_PLL_WrPrmtrMask = 0x0;
int ALTERA_PLL_Cntrl_DBIT_ClkIndex = 0;
-
+#elif defined(CHIPTESTBOARDD)
+uint32_t ALTERA_PLL_FREQ_MEASURE_BASE = 0x0;
#endif
uint32_t ALTERA_PLL_Cntrl_PLLRstMask = 0x0;
uint32_t ALTERA_PLL_Cntrl_AddrMask = 0x0;
@@ -150,6 +151,19 @@ void ALTERA_PLL_SetDefines(uint32_t creg, uint32_t preg, uint32_t rprmsk,
ALTERA_PLL_Cntrl_DBIT_PLL_WrPrmtrMask = wd2msk;
ALTERA_PLL_Cntrl_DBIT_ClkIndex = clk2Index;
}
+#elif defined(CHIPTESTBOARDD)
+void ALTERA_PLL_SetDefines(uint32_t creg, uint32_t preg, uint32_t rprmsk,
+ uint32_t wpmsk, uint32_t prmsk, uint32_t amsk,
+ int aofst, uint32_t freqreg) {
+ ALTERA_PLL_Cntrl_Reg = creg;
+ ALTERA_PLL_Param_Reg = preg;
+ ALTERA_PLL_Cntrl_RcnfgPrmtrRstMask = rprmsk;
+ ALTERA_PLL_Cntrl_WrPrmtrMask = wpmsk;
+ ALTERA_PLL_Cntrl_PLLRstMask = prmsk;
+ ALTERA_PLL_Cntrl_AddrMask = amsk;
+ ALTERA_PLL_Cntrl_AddrOfst = aofst;
+ ALTERA_PLL_FREQ_MEASURE_BASE = freqreg;
+}
#else
void ALTERA_PLL_SetDefines(uint32_t creg, uint32_t preg, uint32_t rprmsk,
uint32_t wpmsk, uint32_t prmsk, uint32_t amsk,
@@ -269,12 +283,12 @@ void ALTERA_PLL_SetModePolling() {
ALTERA_PLL_MODE_PLLNG_MD_VAL, 0);
}
-int ALTERA_PLL_SetOuputFrequency(int clkIndex, int pllVCOFreqMhz, int value) {
- LOG(logDEBUG1, ("C%d: Setting output frequency to %d (pllvcofreq: %dMhz)\n",
- clkIndex, value, pllVCOFreqMhz));
+int ALTERA_PLL_SetOutputFrequency(int clkIndex, int pllVCOFreqHz, int value) {
+ LOG(logDEBUG1, ("C%d: Setting output frequency to %d (pllvcofreq: %dHz)\n",
+ clkIndex, value, pllVCOFreqHz));
- // calculate output frequency
- uint32_t total_div = (float)pllVCOFreqMhz / (float)value;
+ // calculate output frequency, round to next closest integer division
+ uint32_t total_div = (pllVCOFreqHz + value / 2) / value;
// assume 50% duty cycle
uint32_t low_count = total_div / 2;
@@ -307,11 +321,24 @@ int ALTERA_PLL_SetOuputFrequency(int clkIndex, int pllVCOFreqMhz, int value) {
// as adc clock is stopped temporarily when resetting pll)
ALTERA_PLL_ResetPLL();
- /*double temp = ((double)pllVCOFreqMhz / (double)(low_count + high_count));
+ /*double temp = ((double)pllVCOFreqHz / (double)(low_count + high_count));
if ((temp - (int)temp) > 0.0001) {
temp += 0.5;
}
return (int)temp;
*/
+
+#if defined(CHIPTESTBOARDD) && !defined(VIRTUAL)
+ // wait for firmware to measure the actual frequency
+ usleep(2 * 1000 * 1000);
+ value = ALTERA_PLL_getFrequency(clkIndex);
+ LOG(logDEBUG1, ("Frequency is %d\n", value));
+#endif
return value;
}
+
+#if defined(CHIPTESTBOARDD)
+uint32_t ALTERA_PLL_getFrequency(uint32_t clk_index) {
+ return bus_r(ALTERA_PLL_FREQ_MEASURE_BASE + clk_index * 2);
+}
+#endif
\ No newline at end of file
diff --git a/slsDetectorServers/slsDetectorServer/src/XILINX_PLL.c b/slsDetectorServers/slsDetectorServer/src/XILINX_PLL.c
index 8adec26be..09f31df52 100644
--- a/slsDetectorServers/slsDetectorServer/src/XILINX_PLL.c
+++ b/slsDetectorServers/slsDetectorServer/src/XILINX_PLL.c
@@ -11,9 +11,9 @@
// leave some things away)
// clang-format off
-#define XILINX_PLL_INPUT_FREQ (100000) // 100 MHz
-#define XILINX_PLL_MIN_FREQ (10000)
-#define XILINX_PLL_MAX_FREQ (250000)
+#define XILINX_PLL_INPUT_FREQ (100000000) // 100 MHz
+#define XILINX_PLL_MIN_FREQ (10000000)
+#define XILINX_PLL_MAX_FREQ (250000000)
#define XILINX_PLL_MAX_CLK_DIV (256)
#define XILINX_PLL_NUM_CLKS (7)
#define XILINX_PLL_MAX_NUM_CLKS_FOR_GET (3)
@@ -71,14 +71,14 @@
// clang-format on
-// freq in kHz !!
+// freq in Hz !!
int XILINX_PLL_setFrequency(uint32_t clk_index, uint32_t freq) {
if (clk_index >= XILINX_PLL_NUM_CLKS) {
LOG(logERROR, ("XILINX_PLL: Invalid clock index %d\n", clk_index));
return 1;
}
if (freq < XILINX_PLL_MIN_FREQ || freq > XILINX_PLL_MAX_FREQ) {
- LOG(logERROR, ("XILINX_PLL: Frequency %d kHz is out of range\n", freq));
+ LOG(logERROR, ("XILINX_PLL: Frequency %d Hz is out of range\n", freq));
return 1;
}
@@ -160,11 +160,7 @@ uint32_t XILINX_PLL_getFrequency(uint32_t clk_index) {
clk_index -= XILINX_PLL_MEASURE_BASE_ADDR0_MAX_CLKS;
base_addr = XILINX_PLL_MEASURE_BASE_ADDR1;
}
- uint32_t addr = base_addr + clk_index * XILINX_PLL_MEASURE_WIDTH;
- uint32_t counter_val = bus_r_csp2(addr);
- // Hz => round to nearest kHz
- uint32_t freq_kHz = (counter_val + 500) / 1000; // round to nearest kHz
- return freq_kHz;
+ return bus_r_csp2(base_addr + clk_index * XILINX_PLL_MEASURE_WIDTH);
}
bool XILINX_PLL_isLocked() {
diff --git a/slsDetectorServers/slsDetectorServer/src/loadPattern.c b/slsDetectorServers/slsDetectorServer/src/loadPattern.c
index 929460897..154094b87 100644
--- a/slsDetectorServers/slsDetectorServer/src/loadPattern.c
+++ b/slsDetectorServers/slsDetectorServer/src/loadPattern.c
@@ -11,7 +11,7 @@
#ifdef MYTHEN3D
extern enum TLogLevel trimmingPrint;
-extern uint32_t clkDivider[];
+extern int getFrequency(enum CLKINDEX ind);
#endif
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
extern uint32_t clkFrequency[];
@@ -277,6 +277,14 @@ int validate_getPatternWaitClocksAndInterval(char *message, int level,
*waittime = getPatternWaitClocks(level);
} else {
*waittime = getPatternWaitInterval(level);
+ if (*waittime == (uint64_t)-1) {
+ sprintf(
+ message,
+ "Cannot get pattern wait interval for level %d. runclk is 0.\n",
+ level);
+ LOG(logERROR, (message));
+ return FAIL;
+ }
}
return OK;
}
@@ -297,17 +305,17 @@ uint64_t getPatternWaitClocks(int level) {
uint64_t getPatternWaitInterval(int level) {
uint64_t numClocks = getPatternWaitClocks(level);
- int runclk = 0;
+ uint32_t runclk = 0;
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
runclk = clkFrequency[RUN_CLK];
#elif MYTHEN3D
- runclk = clkDivider[SYSTEM_C0];
+ runclk = getFrequency(SYSTEM_C0);
#endif
if (runclk == 0) {
LOG(logERROR, ("runclk is 0. Cannot divide by 0. Returning -1.\n"));
return -1;
}
- return numClocks / (NS_TO_CLK_CYCLE * runclk);
+ return clocks_to_ns(numClocks, runclk);
}
int validate_setPatternWaitClocksAndInterval(char *message, int level,
@@ -321,27 +329,50 @@ int validate_setPatternWaitClocksAndInterval(char *message, int level,
return FAIL;
}
- uint64_t retval = 0;
if (clocks) {
setPatternWaitClocks(level, waittime);
// validate result
- retval = getPatternWaitClocks(level);
+ uint64_t retval = getPatternWaitClocks(level);
LOG(logDEBUG1, ("Pattern wait time in clocks (level:%d) retval: %d\n",
level, (long long int)retval));
- } else {
- setPatternWaitInterval(level, waittime);
- // validate result
- retval = getPatternWaitInterval(level);
- LOG(logDEBUG1, ("Pattern wait time (level:%d) retval: %d\n", level,
- (long long int)retval));
+
+ int ret = OK;
+ char mode[128];
+ memset(mode, 0, sizeof(mode));
+ sprintf(mode, "set pattern Loop %d wait time (clocks)", level);
+ validate64(&ret, message, waittime, retval, mode, DEC);
+ return ret;
}
- int ret = OK;
- char mode[128];
- memset(mode, 0, sizeof(mode));
- sprintf(mode, "set pattern Loop %d wait time", level);
- validate64(&ret, message, waittime, retval, mode, DEC);
- return ret;
+ // interval
+ setPatternWaitInterval(level, waittime);
+
+ // validate
+ uint32_t runclk = 0;
+#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
+ runclk = clkFrequency[RUN_CLK];
+#elif MYTHEN3D
+ runclk = getFrequency(SYSTEM_C0);
+#endif
+ uint64_t arg_clocks = ns_to_clocks(waittime, runclk);
+ uint64_t retval_clocks = getPatternWaitClocks(level);
+ if (arg_clocks != retval_clocks) {
+ sprintf(message,
+ "Failed to set pattern loop %d wait interval. Could not set "
+ "number of clocks to %lld, read %lld\n",
+ level, (long long int)arg_clocks, (long long int)retval_clocks);
+ LOG(logERROR, (message));
+ return FAIL;
+ }
+
+ // log rounding if any
+ uint64_t retval = getPatternWaitInterval(level);
+ if (waittime != retval) {
+ LOG(logWARNING, ("Rounding to %lld ns due to clock frequency\n",
+ (long long int)retval));
+ }
+
+ return OK;
}
void setPatternWaitClocks(int level, uint64_t t) {
@@ -375,13 +406,13 @@ void setPatternWaitInterval(int level, uint64_t t) {
#endif
("Setting Pattern Wait Time (level:%d) :%lld ns\n", level,
(long long int)t));
- int runclk = 0;
+ uint32_t runclk = 0;
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
runclk = clkFrequency[RUN_CLK];
#elif MYTHEN3D
- runclk = clkDivider[SYSTEM_C0];
+ runclk = getFrequency(SYSTEM_C0);
#endif
- uint64_t numClocks = t * (NS_TO_CLK_CYCLE * runclk);
+ uint64_t numClocks = ns_to_clocks(t, runclk);
setPatternWaitClocks(level, numClocks);
}
diff --git a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c
index 755f78104..f4d9d930f 100644
--- a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c
+++ b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c
@@ -2402,7 +2402,11 @@ int get_exptime(int file_des) {
"for this detector\n");
LOG(logERROR, (mess));
} else {
+#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
+ ret = getExpTime(&retval, mess);
+#else
retval = getExpTime();
+#endif
LOG(logDEBUG1, ("retval exptime %lld ns\n", (long long int)retval));
}
#endif
@@ -2472,6 +2476,9 @@ int set_exptime(int file_des) {
"for this detector\n");
LOG(logERROR, (mess));
} else {
+#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
+ ret = setExpTime(val, mess);
+#else
ret = setExpTime(val);
int64_t retval = getExpTime();
LOG(logDEBUG1, ("retval exptime %lld ns\n", (long long int)retval));
@@ -2482,6 +2489,7 @@ int set_exptime(int file_des) {
(long long int)val, (long long int)retval);
LOG(logERROR, (mess));
}
+#endif
}
#endif
}
@@ -2494,7 +2502,11 @@ int get_period(int file_des) {
int64_t retval = -1;
// get only
+#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
+ ret = getPeriod(&retval, mess);
+#else
retval = getPeriod();
+#endif
LOG(logDEBUG1, ("retval period %lld ns\n", (long long int)retval));
return Server_SendResult(file_des, INT64, &retval, sizeof(retval));
}
@@ -2510,6 +2522,9 @@ int set_period(int file_des) {
// only set
if (Server_VerifyLock() == OK) {
+#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
+ ret = setPeriod(arg, mess);
+#else
ret = setPeriod(arg);
int64_t retval = getPeriod();
LOG(logDEBUG1, ("retval period %lld ns\n", (long long int)retval));
@@ -2518,6 +2533,7 @@ int set_period(int file_des) {
(long long int)arg, (long long int)retval);
LOG(logERROR, (mess));
}
+#endif
}
return Server_SendResult(file_des, INT64, NULL, 0);
}
@@ -2533,7 +2549,11 @@ int get_delay_after_trigger(int file_des) {
functionNotImplemented();
#else
// get only
+#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
+ ret = getDelayAfterTrigger(&retval, mess);
+#else
retval = getDelayAfterTrigger();
+#endif
LOG(logDEBUG1,
("retval delay after trigger %lld ns\n", (long long int)retval));
#endif
@@ -2557,6 +2577,9 @@ int set_delay_after_trigger(int file_des) {
#else
// only set
if (Server_VerifyLock() == OK) {
+#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
+ ret = setDelayAfterTrigger(arg, mess);
+#else
ret = setDelayAfterTrigger(arg);
int64_t retval = getDelayAfterTrigger();
LOG(logDEBUG1,
@@ -2568,6 +2591,7 @@ int set_delay_after_trigger(int file_des) {
(long long int)arg, (long long int)retval);
LOG(logERROR, (mess));
}
+#endif
}
#endif
return Server_SendResult(file_des, INT64, NULL, 0);
@@ -2802,7 +2826,11 @@ int get_period_left(int file_des) {
functionNotImplemented();
#else
// get only
+#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
+ ret = getPeriodLeft(&retval, mess);
+#else
retval = getPeriodLeft();
+#endif
LOG(logDEBUG1, ("retval period left %lld ns\n", (long long int)retval));
#endif
return Server_SendResult(file_des, INT64, &retval, sizeof(retval));
@@ -2819,7 +2847,11 @@ int get_delay_after_trigger_left(int file_des) {
functionNotImplemented();
#else
// get only
+#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
+ ret = getDelayAfterTriggerLeft(&retval, mess);
+#else
retval = getDelayAfterTriggerLeft();
+#endif
LOG(logDEBUG1,
("retval delay after trigger left %lld ns\n", (long long int)retval));
#endif
@@ -3306,10 +3338,6 @@ int set_pattern_wait_clocks(int file_des) {
if (ret == OK) {
ret = validate_getPatternWaitClocksAndInterval(mess, loopLevel,
&retval, 1);
- if ((int64_t)timeval != GET_FLAG) {
- validate64(&ret, mess, (int64_t)timeval, retval,
- "set pattern wait clocks", DEC);
- }
}
}
#endif
@@ -5693,11 +5721,9 @@ int set_clock_frequency(int file_des) {
case ADC_CLOCK:
c = ADC_CLK;
break;
-#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
case DBIT_CLOCK:
c = DBIT_CLK;
break;
-#endif
case RUN_CLOCK:
c = RUN_CLK;
break;
@@ -5718,26 +5744,38 @@ int set_clock_frequency(int file_des) {
(int)c);
if (getFrequency(c) == val) {
- LOG(logINFO, ("Same %s: %d %s\n", modeName, val,
- myDetectorType == GOTTHARD2 ? "Hz" : "MHz"));
- } else {
+ LOG(logINFO, ("Same %s: %d %s\n", modeName, val, "Hz"));
+ } else if (val < MIN_CLK_FREQ || val > MAX_CLK_FREQ) {
+ ret = FAIL;
+ sprintf(mess,
+ "Cannot set frequency to %f MHz. Frequency outside "
+ "limits (%f - %f MHz)\n",
+ val / 1e6, MIN_CLK_FREQ / 1e6, MAX_CLK_FREQ / 1e6);
+ LOG(logERROR, (mess));
+ }
+#ifdef CHIPTESTBOARDD
+ else if (ind == ADC_CLOCK && (val > MAXIMUM_ADC_CLK)) {
+ ret = FAIL;
+ sprintf(mess,
+ "Cannot set ADC clock frequency to %f MHz. Frequency "
+ "outside limits (<= %f MHz)\n",
+ val / 1e6, MAXIMUM_ADC_CLK / 1e6);
+ LOG(logERROR, (mess));
+ }
+#endif
+ else {
int ret = setFrequency(c, val);
if (ret == FAIL) {
- sprintf(mess, "Could not set %s to %d %s\n", modeName, val,
- myDetectorType == XILINX_CHIPTESTBOARD ? "kHz"
- : "MHz");
+ sprintf(mess, "Could not set %s to %f MHz\n", modeName,
+ val / 1e6);
LOG(logERROR, (mess));
} else {
int retval = getFrequency(c);
LOG(logDEBUG1,
- ("retval %s: %d %s\n", modeName, retval,
- myDetectorType == XILINX_CHIPTESTBOARD ? "kHz"
- : "MHz"));
-#if !defined(XILINX_CHIPTESTBOARDD)
- // XCTB will give the actual frequency, which is not
+ ("retval %s: %f MHz\n", modeName, retval / 1e6));
+ // both CTB's will give the actual frequency, which is not
// 100% identical to the set frequency
validate(&ret, mess, val, retval, modeName, DEC);
-#endif
}
}
}
@@ -5790,14 +5828,8 @@ int get_clock_frequency(int file_des) {
if (ret == OK) {
retval = getFrequency(c);
char *clock_names[] = {CLK_NAMES};
- LOG(logDEBUG1,
- ("retval %s clock (%d) frequency: %d %s\n", clock_names[c], (int)c,
- retval,
- myDetectorType == XILINX_CHIPTESTBOARD
- ? "kHz"
- : (myDetectorType == GOTTHARD2 || myDetectorType == MYTHEN3
- ? "Hz"
- : "MHz")));
+ LOG(logDEBUG1, ("retval %s clock (%d) frequency: %d %s\n",
+ clock_names[c], (int)c, retval, "Hz"));
}
#endif
return Server_SendResult(file_des, INT32, &retval, sizeof(retval));
@@ -7029,6 +7061,11 @@ int get_receiver_parameters(int file_des) {
// exptime
#ifdef MYTHEN3D
i64 = 0;
+#elif defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
+ if (getExpTime(&i64, mess) == FAIL) {
+ sprintf(mess, "Could not get exposure time.\n");
+ return sendError(file_des);
+ }
#else
i64 = getExpTime();
#endif
@@ -7037,7 +7074,15 @@ int get_receiver_parameters(int file_des) {
return printSocketReadError();
// period
+ i64 = 0;
+#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
+ if (getPeriod(&i64, mess) == FAIL) {
+ sprintf(mess, "Could not get period.\n");
+ return sendError(file_des);
+ }
+#else
i64 = getPeriod();
+#endif
n += sendData(file_des, &i64, sizeof(i64), INT64);
if (n < 0)
return printSocketReadError();
@@ -10894,13 +10939,6 @@ int set_pattern_wait_interval(int file_des) {
if (Server_VerifyLock() == OK) {
ret = validate_setPatternWaitClocksAndInterval(mess, loopLevel, timeval,
0);
- if (ret == OK) {
- uint64_t retval = 0;
- ret = validate_getPatternWaitClocksAndInterval(mess, loopLevel,
- &retval, 0);
- validate64(&ret, mess, (int64_t)timeval, retval,
- "set pattern wait interval", DEC);
- }
}
#endif
diff --git a/slsDetectorServers/xilinx_ctbDetectorServer/bin/xilinx_ctbDetectorServer_developer b/slsDetectorServers/xilinx_ctbDetectorServer/bin/xilinx_ctbDetectorServer_developer
index 28c2a4532..175991ee8 100755
Binary files a/slsDetectorServers/xilinx_ctbDetectorServer/bin/xilinx_ctbDetectorServer_developer and b/slsDetectorServers/xilinx_ctbDetectorServer/bin/xilinx_ctbDetectorServer_developer differ
diff --git a/slsDetectorServers/xilinx_ctbDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/xilinx_ctbDetectorServer/slsDetectorFunctionList.c
index 625dbabd0..6d4e13a1a 100644
--- a/slsDetectorServers/xilinx_ctbDetectorServer/slsDetectorFunctionList.c
+++ b/slsDetectorServers/xilinx_ctbDetectorServer/slsDetectorFunctionList.c
@@ -363,7 +363,7 @@ void initStopServer() {
return;
}
#ifdef VIRTUAL
- sharedMemory_setStop(0);
+ setupDetector();
#endif
}
initCheckDone = 1;
@@ -389,9 +389,13 @@ void setupDetector() {
vLimit = DEFAULT_VLIMIT;
#ifdef VIRTUAL
- sharedMemory_setStatus(IDLE);
- setupUDPCommParameters();
- initializePatternWord();
+ if (isControlServer) {
+ sharedMemory_setStatus(IDLE);
+ setupUDPCommParameters();
+ initializePatternWord();
+ } else {
+ sharedMemory_setStop(0);
+ }
#endif
// initialization only at start up (restart fpga)
initError = waitTransceiverReset(initErrorMessage);
@@ -444,9 +448,15 @@ void setupDetector() {
setNumFrames(DEFAULT_NUM_FRAMES);
setNumTriggers(DEFAULT_NUM_CYCLES);
setTiming(DEFAULT_TIMING_MODE);
- setExpTime(DEFAULT_EXPTIME);
- setPeriod(DEFAULT_PERIOD);
- setDelayAfterTrigger(DEFAULT_DELAY);
+ initError = setExpTime(DEFAULT_EXPTIME, initErrorMessage);
+ if (initError == FAIL)
+ return;
+ initError = setPeriod(DEFAULT_PERIOD, initErrorMessage);
+ if (initError == FAIL)
+ return;
+ initError = setDelayAfterTrigger(DEFAULT_DELAY, initErrorMessage);
+ if (initError == FAIL)
+ return;
setNextFrameNumber(DEFAULT_STARTING_FRAME_NUMBER);
}
@@ -766,63 +776,132 @@ int getNumTransceiverSamples() {
return ((bus_r(NO_SAMPLES_X_REG) & NO_SAMPLES_X_MSK) >> NO_SAMPLES_X_OFST);
}
-int setExpTime(int64_t val) {
+int setExpTime(int64_t val, char *mess) {
setPatternWaitInterval(0, val);
- // validate for tolerance
- int64_t retval = getExpTime();
+ // validate
+ uint64_t arg_clocks = ns_to_clocks(val, clkFrequency[RUN_CLK]);
+ uint64_t retval_clocks = getPatternWaitClocks(0);
+ if (arg_clocks != retval_clocks) {
+ sprintf(mess,
+ "Failed to set exposure time. Could not set number of clocks "
+ "to %lld, read %lld\n",
+ (long long int)arg_clocks, (long long int)retval_clocks);
+ LOG(logERROR, (mess));
+ return FAIL;
+ }
+
+ // log rounding if any
+ int64_t retval = getPatternWaitInterval(0);
if (val != retval) {
+ LOG(logWARNING, ("Rounding to %lld ns due to clock frequency\n",
+ (long long int)retval));
+ }
+
+ return OK;
+}
+
+int getExpTime(int64_t *retval, char *mess) {
+ *retval = getPatternWaitInterval(0);
+ if (*retval == -1) {
+ sprintf(mess, "Failed to get exposure time.\n");
+ LOG(logERROR, (mess));
return FAIL;
}
return OK;
}
-int64_t getExpTime() { return getPatternWaitInterval(0); }
-
-int setPeriod(int64_t val) {
+int setPeriod(int64_t val, char *mess) {
if (val < 0) {
- LOG(logERROR, ("Invalid period: %lld ns\n", (long long int)val));
+ sprintf(mess, "Invalid period: %lld ns\n", (long long int)val);
+ LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("Setting period %lld ns\n", (long long int)val));
- val *= (NS_TO_CLK_CYCLE * clkFrequency[RUN_CLK]);
- setU64BitReg(val, PERIOD_IN_REG_1, PERIOD_IN_REG_2);
+ uint64_t arg_clocks = ns_to_clocks(val, clkFrequency[RUN_CLK]);
+ setU64BitReg(arg_clocks, PERIOD_IN_REG_1, PERIOD_IN_REG_2);
- // validate for tolerance
- int64_t retval = getPeriod();
- val /= (NS_TO_CLK_CYCLE * clkFrequency[RUN_CLK]);
- if (val != retval) {
+ // validate
+ uint64_t retval_clocks = getU64BitReg(PERIOD_IN_REG_1, PERIOD_IN_REG_2);
+ if (arg_clocks != retval_clocks) {
+ sprintf(mess,
+ "Failed to set period. Could not set number of clocks "
+ "to %lld, red %lld\n",
+ (long long int)arg_clocks, (long long int)retval_clocks);
+ LOG(logERROR, (mess));
return FAIL;
}
+
+ // log rounding if any
+ int64_t retval = 0;
+ if (getPeriod(&retval, mess) == FAIL) {
+ return FAIL;
+ }
+ if (val != retval) {
+ LOG(logWARNING, ("Rounding to %lld ns due to clock frequency\n",
+ (long long int)retval));
+ }
+
return OK;
}
-int64_t getPeriod() {
- return getU64BitReg(PERIOD_IN_REG_1, PERIOD_IN_REG_2) /
- (NS_TO_CLK_CYCLE * clkFrequency[RUN_CLK]);
+int getPeriod(int64_t *retval, char *mess) {
+ if (clkFrequency[RUN_CLK] == 0) {
+ sprintf(mess, "Cannot get period. Run clock frequency is 0.\n");
+ LOG(logERROR, (mess));
+ return FAIL;
+ }
+ uint64_t numClocks = getU64BitReg(PERIOD_IN_REG_1, PERIOD_IN_REG_2);
+ *retval = clocks_to_ns(numClocks, clkFrequency[RUN_CLK]);
+ return OK;
}
-int setDelayAfterTrigger(int64_t val) {
+int setDelayAfterTrigger(int64_t val, char *mess) {
if (val < 0) {
- LOG(logERROR, ("Invalid delay after trigger: %ld ns\n", val));
+ sprintf(mess, "Invalid delay after trigger: %lld ns\n",
+ (long long int)val);
+ LOG(logERROR, (mess));
return FAIL;
}
- LOG(logINFO, ("Setting delay after trigger %ld ns\n", val));
- val *= (NS_TO_CLK_CYCLE * clkFrequency[RUN_CLK]);
- setU64BitReg(val, DELAY_IN_REG_1, DELAY_IN_REG_2);
+ LOG(logINFO, ("Setting delay after trigger %lld ns\n", (long long int)val));
+ uint64_t arg_clocks = ns_to_clocks(val, clkFrequency[RUN_CLK]);
+ setU64BitReg(arg_clocks, DELAY_IN_REG_1, DELAY_IN_REG_2);
- // validate for tolerance
- int64_t retval = getDelayAfterTrigger();
- val /= (NS_TO_CLK_CYCLE * clkFrequency[RUN_CLK]);
- if (val != retval) {
+ // validate
+ uint64_t retval_clocks = getU64BitReg(DELAY_IN_REG_1, DELAY_IN_REG_2);
+ if (arg_clocks != retval_clocks) {
+ sprintf(
+ mess,
+ "Failed to set delay after trigger. Could not set number of clocks "
+ "to %lld, read %lld\n",
+ (long long int)arg_clocks, (long long int)retval_clocks);
+ LOG(logERROR, (mess));
return FAIL;
}
+
+ // log rounding if any
+ int64_t retval = 0;
+ if (getDelayAfterTrigger(&retval, mess) == FAIL) {
+ return FAIL;
+ }
+ if (val != retval) {
+ LOG(logWARNING, ("Rounding to %lld ns due to clock frequency\n",
+ (long long int)retval));
+ }
+
return OK;
}
-int64_t getDelayAfterTrigger() {
- return getU64BitReg(DELAY_IN_REG_1, DELAY_IN_REG_2) /
- (NS_TO_CLK_CYCLE * clkFrequency[RUN_CLK]);
+int getDelayAfterTrigger(int64_t *retval, char *mess) {
+ if (clkFrequency[RUN_CLK] == 0) {
+ sprintf(mess,
+ "Cannot get delay after trigger. Run clock frequency is 0.\n");
+ LOG(logERROR, (mess));
+ return FAIL;
+ }
+ uint64_t numClocks = getU64BitReg(DELAY_IN_REG_1, DELAY_IN_REG_2);
+ *retval = clocks_to_ns(numClocks, clkFrequency[RUN_CLK]);
+ return OK;
}
int64_t getNumFramesLeft() {
@@ -833,14 +912,27 @@ int64_t getNumTriggersLeft() {
return getU64BitReg(CYCLES_OUT_REG_1, CYCLES_OUT_REG_2);
}
-int64_t getDelayAfterTriggerLeft() {
- return getU64BitReg(DELAY_OUT_REG_1, DELAY_OUT_REG_2) /
- (NS_TO_CLK_CYCLE * clkFrequency[RUN_CLK]);
+int getDelayAfterTriggerLeft(int64_t *retval, char *mess) {
+ if (clkFrequency[RUN_CLK] == 0) {
+ sprintf(mess, "Cannot get delay after trigger left. Run clock "
+ "frequency is 0.\n");
+ LOG(logERROR, (mess));
+ return FAIL;
+ }
+ uint64_t numClocks = getU64BitReg(DELAY_OUT_REG_1, DELAY_OUT_REG_2);
+ *retval = clocks_to_ns(numClocks, clkFrequency[RUN_CLK]);
+ return OK;
}
-int64_t getPeriodLeft() {
- return getU64BitReg(PERIOD_OUT_REG_1, PERIOD_OUT_REG_2) /
- (NS_TO_CLK_CYCLE * clkFrequency[RUN_CLK]);
+int getPeriodLeft(int64_t *retval, char *mess) {
+ if (clkFrequency[RUN_CLK] == 0) {
+ sprintf(mess, "Cannot get period left. Run clock frequency is 0.\n");
+ LOG(logERROR, (mess));
+ return FAIL;
+ }
+ uint64_t numClocks = getU64BitReg(PERIOD_OUT_REG_1, PERIOD_OUT_REG_2);
+ *retval = clocks_to_ns(numClocks, clkFrequency[RUN_CLK]);
+ return OK;
}
int64_t getFramesFromStart() {
@@ -849,13 +941,14 @@ int64_t getFramesFromStart() {
}
int64_t getActualTime() {
- return getU64BitReg(TIME_FROM_START_OUT_REG_1, TIME_FROM_START_OUT_REG_2) /
- (NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]);
+ // in unit of 100ns
+ return getU64BitReg(TIME_FROM_START_OUT_REG_1, TIME_FROM_START_OUT_REG_2) *
+ 100;
}
int64_t getMeasurementTime() {
- return getU64BitReg(FRAME_TIME_OUT_REG_1, FRAME_TIME_OUT_REG_2) /
- (NS_TO_CLK_CYCLE * clkFrequency[SYNC_CLK]);
+ // in unit of 100ns
+ return getU64BitReg(FRAME_TIME_OUT_REG_1, FRAME_TIME_OUT_REG_2) * 100;
}
/* parameters - dac, adc, hv */
@@ -1447,11 +1540,22 @@ void *start_timer(void *arg) {
if (!isControlServer) {
return NULL;
}
+ int64_t periodNs = 0;
+ int64_t expUs = 0;
+ {
+ char mess[MAX_STR_LENGTH] = {0};
+ if (getPeriod(&periodNs, mess) == FAIL) {
+ LOG(logERROR, ("Failed to get period.\n"));
+ return NULL;
+ }
+ if (getExpTime(&expUs, mess) == FAIL) {
+ LOG(logERROR, ("Failed to get exposure time.\n"));
+ return NULL;
+ }
+ expUs /= 1000;
+ }
- int64_t periodNs = getPeriod();
int numFrames = (getNumFrames() * getNumTriggers());
- int64_t expUs = getExpTime() / 1000;
-
int imageSize = calculateDataBytes();
int maxDataSize = MAX_DATA_SIZE_IN_PACKET;
int packetSize = sizeof(sls_detector_header) + maxDataSize;
@@ -1716,11 +1820,11 @@ int setFrequency(enum CLKINDEX ind, int val) {
}
char *clock_names[] = {CLK_NAMES};
- LOG(logINFO, ("\tSetting %s clock (%d) frequency to %d kHz\n",
+ LOG(logINFO, ("\tSetting %s clock (%d) frequency to %d Hz\n",
clock_names[ind], ind, val));
if (XILINX_PLL_setFrequency(ind, val) == FAIL) {
- LOG(logERROR, ("\tCould not set %s clock (%d) frequency to %d kHz\n",
+ LOG(logERROR, ("\tCould not set %s clock (%d) frequency to %d Hz\n",
clock_names[ind], ind, val));
return FAIL;
}
diff --git a/slsDetectorServers/xilinx_ctbDetectorServer/slsDetectorFunctionList.h b/slsDetectorServers/xilinx_ctbDetectorServer/slsDetectorFunctionList.h
index 4d1ce9889..14de21741 100644
--- a/slsDetectorServers/xilinx_ctbDetectorServer/slsDetectorFunctionList.h
+++ b/slsDetectorServers/xilinx_ctbDetectorServer/slsDetectorFunctionList.h
@@ -84,10 +84,10 @@ void setNumFrames(int64_t val);
int64_t getNumFrames();
void setNumTriggers(int64_t val);
int64_t getNumTriggers();
-int setExpTime(int64_t val);
-int64_t getExpTime();
-int setPeriod(int64_t val);
-int64_t getPeriod();
+int setExpTime(int64_t val, char *mess);
+int getExpTime(int64_t *retval, char *mess);
+int setPeriod(int64_t val, char *mess);
+int getPeriod(int64_t *retval, char *mess);
int setNumAnalogSamples(int val);
int getNumAnalogSamples();
int setNumDigitalSamples(int val);
@@ -97,10 +97,10 @@ int getNumTransceiverSamples();
int64_t getNumFramesLeft();
int64_t getNumTriggersLeft();
-int setDelayAfterTrigger(int64_t val);
-int64_t getDelayAfterTrigger();
-int64_t getDelayAfterTriggerLeft();
-int64_t getPeriodLeft();
+int setDelayAfterTrigger(int64_t val, char *mess);
+int getDelayAfterTrigger(int64_t *retval, char *mess);
+int getDelayAfterTriggerLeft(int64_t *retval, char *mess);
+int getPeriodLeft(int64_t *retval, char *mess);
int64_t getFramesFromStart();
int64_t getActualTime();
int64_t getMeasurementTime();
diff --git a/slsDetectorServers/xilinx_ctbDetectorServer/slsDetectorServer_defs.h b/slsDetectorServers/xilinx_ctbDetectorServer/slsDetectorServer_defs.h
index 757df2e0c..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-6) // ns to kHz
+#define DEFAULT_RUN_CLK (20000000) // 20 MHz
+#define DEFAULT_ADC_CLK (100000000) // 100 MHz
+#define DEFAULT_SYNC_CLK (20000000) // 20 MHz
+#define DEFAULT_DBIT_CLK (100000000) // 100 MHz
+#define NS_TO_CLK_CYCLE (1E-9) // ns to Hz
+
+#define MIN_CLK_FREQ (10000000) // 10 MHz
+#define MAX_CLK_FREQ (300000000) // 300 MHz
diff --git a/slsDetectorSoftware/generator/Caller.in.h b/slsDetectorSoftware/generator/Caller.in.h
index f7128620e..e18dec02c 100644
--- a/slsDetectorSoftware/generator/Caller.in.h
+++ b/slsDetectorSoftware/generator/Caller.in.h
@@ -54,6 +54,9 @@ class Caller {
return ToString(value, unit);
}
+ std::string OutString(const Result &value,
+ const std::string &unit);
+
std::vector getAllCommands();
std::map GetDeprecatedCommands();
std::string list(int action);
@@ -96,6 +99,7 @@ class Caller {
defs::dacIndex parseDacIndex(int argIndex, bool isCtb);
bool parseMV(int argIndex);
defs::powerIndex parsePowerIndex(int argIndex);
+ defs::FrequencyUnit parseFrequencyUnit(const std::string &s);
FunctionMap functions{
{"list", &Caller::list},
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 20f94b12a..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] ADC clock frequency in MHz.\n\t[xilinx Ctb] ADC clock frequency in kHz."
- inherit_actions: INTEGER_COMMAND_VEC_ID
- actions:
- GET:
- function: getADCClock
- PUT:
- function: setADCClock
-
-runclk:
- help: "[n_clk in MHz]\n\t[Ctb] Run clock in MHz.\n\t[xilinx Ctb] Run clock in kHz."
- inherit_actions: INTEGER_COMMAND_VEC_ID
- actions:
- GET:
- function: getRUNClock
- PUT:
- function: setRUNClock
dsamples:
help: "[n_value]\n\t[Ctb] Number of digital samples expected."
@@ -1289,15 +1360,6 @@ romode:
function: setReadoutMode
input_types: [ defs::readoutMode ]
-dbitclk:
- help: "[n_clk in MHz]\n\t[Ctb] Clock for latching the digital bits in MHz.\n\t[xilinx Ctb] Clock for latching the digital bits in kHz."
- inherit_actions: INTEGER_COMMAND_VEC_ID
- actions:
- GET:
- function: getDBITClock
- PUT:
- function: setDBITClock
-
extsampling:
help: "[0, 1]\n\t[Ctb] Enable for external sampling signal for digital data to signal by extsampling src command. For advanced users only."
inherit_actions: INTEGER_COMMAND_VEC_ID
@@ -1912,19 +1974,12 @@ burstsl:
GET:
function: getNumberOfBurstsLeft
-syncclk:
- inherit_actions: GET_COMMAND
- help: "[n_clk in MHz]\n\t[Ctb] Sync clock in MHz."
- actions:
- GET:
- function: getSYNCClock
-
patfname:
inherit_actions: GET_COMMAND
help: "\n\t[Ctb][Mythen3][Xilinx Ctb] Gets the pattern file name including path of the last pattern uploaded. Returns an empty if nothing was uploaded or via a server default file"
actions:
GET:
- function: getPatterFileName
+ function: getPatternFileName
lastclient:
inherit_actions: GET_COMMAND
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 9dd24bb5d..c29c13bc5 100644
--- a/slsDetectorSoftware/generator/extended_commands.yaml
+++ b/slsDetectorSoftware/generator/extended_commands.yaml
@@ -86,28 +86,69 @@ adcclk:
- OutString(t)
require_det_id: true
store_result_in_t: true
+ - arg_types:
+ - special::freq_unit
+ argc: 1
+ cast_input: []
+ check_det_id: false
+ convert_det_id: true
+ function: getADCClock
+ input: []
+ input_types: []
+ output:
+ - OutString(t , args[0])
+ require_det_id: true
+ store_result_in_t: true
PUT:
args:
- arg_types:
- - int
+ - std::string
argc: 1
cast_input:
- - true
+ - false
check_det_id: false
convert_det_id: true
function: setADCClock
input:
- - args[0]
+ - converted_freq
input_types:
- - int
+ - defs::Hz
output:
- - args.front()
+ - args[0]
+ require_det_id: true
+ separate_freq_units:
+ input: args[0]
+ output:
+ - converted_freq
+ - unit
+ store_result_in_t: false
+ - arg_types:
+ - int
+ - special::freq_unit
+ argc: 2
+ cast_input:
+ - false
+ check_det_id: false
+ convert_det_id: true
+ convert_to_freq:
+ input:
+ - args[0]
+ - args[1]
+ output: converted_freq
+ function: setADCClock
+ input:
+ - converted_freq
+ input_types:
+ - defs::Hz
+ output:
+ - args[0]
+ - args[1]
require_det_id: true
store_result_in_t: false
command_name: adcclk
function_alias: adcclk
- help: "[n_clk in MHz]\n\t[Ctb] ADC clock frequency in MHz.\n\t[xilinx Ctb] ADC clock\
- \ frequency in kHz."
+ help: "[n_clk] [(optional unit) Hz(default)|kHz|MHz]\n\t[Ctb][Xilinx Ctb] ADC clock\
+ \ frequency."
infer_action: true
template: true
adcenable:
@@ -2060,28 +2101,69 @@ dbitclk:
- OutString(t)
require_det_id: true
store_result_in_t: true
+ - arg_types:
+ - special::freq_unit
+ argc: 1
+ cast_input: []
+ check_det_id: false
+ convert_det_id: true
+ function: getDBITClock
+ input: []
+ input_types: []
+ output:
+ - OutString(t , args[0])
+ require_det_id: true
+ store_result_in_t: true
PUT:
args:
- arg_types:
- - int
+ - std::string
argc: 1
cast_input:
- - true
+ - false
check_det_id: false
convert_det_id: true
function: setDBITClock
input:
- - args[0]
+ - converted_freq
input_types:
- - int
+ - defs::Hz
output:
- - args.front()
+ - args[0]
+ require_det_id: true
+ separate_freq_units:
+ input: args[0]
+ output:
+ - converted_freq
+ - unit
+ store_result_in_t: false
+ - arg_types:
+ - int
+ - special::freq_unit
+ argc: 2
+ cast_input:
+ - false
+ check_det_id: false
+ convert_det_id: true
+ convert_to_freq:
+ input:
+ - args[0]
+ - args[1]
+ output: converted_freq
+ function: setDBITClock
+ input:
+ - converted_freq
+ input_types:
+ - defs::Hz
+ output:
+ - args[0]
+ - args[1]
require_det_id: true
store_result_in_t: false
command_name: dbitclk
function_alias: dbitclk
- help: "[n_clk in MHz]\n\t[Ctb] Clock for latching the digital bits in MHz.\n\t[xilinx\
- \ Ctb] Clock for latching the digital bits in kHz."
+ help: "[n_clk] [(optional unit) Hz(default)|kHz|MHz]\n\t[Ctb][Xilinx Ctb] Clock\
+ \ for latching the digital bits."
infer_action: true
template: true
dbitphase:
@@ -5788,7 +5870,7 @@ patfname:
cast_input: []
check_det_id: false
convert_det_id: true
- function: getPatterFileName
+ function: getPatternFileName
input: []
input_types: []
output:
@@ -8140,27 +8222,69 @@ runclk:
- OutString(t)
require_det_id: true
store_result_in_t: true
+ - arg_types:
+ - special::freq_unit
+ argc: 1
+ cast_input: []
+ check_det_id: false
+ convert_det_id: true
+ function: getRUNClock
+ input: []
+ input_types: []
+ output:
+ - OutString(t , args[0])
+ require_det_id: true
+ store_result_in_t: true
PUT:
args:
- arg_types:
- - int
+ - std::string
argc: 1
cast_input:
- - true
+ - false
check_det_id: false
convert_det_id: true
function: setRUNClock
input:
- - args[0]
+ - converted_freq
input_types:
- - int
+ - defs::Hz
output:
- - args.front()
+ - args[0]
+ require_det_id: true
+ separate_freq_units:
+ input: args[0]
+ output:
+ - converted_freq
+ - unit
+ store_result_in_t: false
+ - arg_types:
+ - int
+ - special::freq_unit
+ argc: 2
+ cast_input:
+ - false
+ check_det_id: false
+ convert_det_id: true
+ convert_to_freq:
+ input:
+ - args[0]
+ - args[1]
+ output: converted_freq
+ function: setRUNClock
+ input:
+ - converted_freq
+ input_types:
+ - defs::Hz
+ output:
+ - args[0]
+ - args[1]
require_det_id: true
store_result_in_t: false
command_name: runclk
function_alias: runclk
- help: "[n_clk in MHz]\n\t[Ctb] Run clock in MHz.\n\t[xilinx Ctb] Run clock in kHz."
+ help: "[n_clk] [(optional unit) Hz(default)|kHz|MHz]\n\t[Ctb][Xilinx Ctb] Run clock\
+ \ frequency."
infer_action: true
template: true
runtime:
@@ -10575,9 +10699,22 @@ syncclk:
- OutString(t)
require_det_id: true
store_result_in_t: true
+ - arg_types:
+ - special::freq_unit
+ argc: 1
+ cast_input: []
+ check_det_id: false
+ convert_det_id: true
+ function: getSYNCClock
+ input: []
+ input_types: []
+ output:
+ - OutString(t , args[0])
+ require_det_id: true
+ store_result_in_t: true
command_name: syncclk
function_alias: syncclk
- help: "[n_clk in MHz]\n\t[Ctb] Sync clock in MHz."
+ help: "[n_clk] [(optional unit) Hz(default)|kHz|MHz]\n\t[Ctb] Sync clock."
infer_action: true
template: true
temp_10ge:
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 a44a46e5f..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 MHz, [XCTB] in kHz */
- Result getADCClock(Positions pos = {}) const;
+ /** [CTB][XCTB] */
+ Result getADCClock(Positions pos = {}) const;
- /** [CTB] in MHz, [XCTB] in kHz */
- void setADCClock(int value_in_MHz, Positions pos = {});
+ /** [CTB][XCTB] */
+ void setADCClock(defs::Hz val, Positions pos = {});
- /** [CTB] in MHz, [XCTB] in kHz */
- Result getRUNClock(Positions pos = {}) const;
+ /** [CTB][XCTB] */
+ Result getRUNClock(Positions pos = {}) const;
- /** [CTB] in MHz, [XCTB] in kHz */
- void setRUNClock(int value_in_MHz, Positions pos = {});
+ /** [CTB][XCTB] */
+ void setRUNClock(defs::Hz val, Positions pos = {});
- /** [CTB] in MHZ */
- Result 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 MHz, [XCTB] in kHz */
- Result getDBITClock(Positions pos = {}) const;
-
- /** [CTB] in MHz, [XCTB] in kHz */
- void setDBITClock(int value_in_MHz, 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 17405241e..1e72aba17 100644
--- a/slsDetectorSoftware/src/Caller.cpp
+++ b/slsDetectorSoftware/src/Caller.cpp
@@ -72,34 +72,46 @@ std::string Caller::adcclk(int action) {
std::ostringstream os;
// print help
if (action == slsDetectorDefs::HELP_ACTION) {
- os << R"V0G0N([n_clk in MHz]
- [Ctb] ADC clock frequency in MHz.
- [xilinx Ctb] ADC clock frequency in kHz. )V0G0N"
+ os << R"V0G0N([n_clk] [(optional unit) Hz(default)|kHz|MHz]
+ [Ctb][Xilinx Ctb] ADC clock frequency. )V0G0N"
<< std::endl;
return os.str();
}
// check if action and arguments are valid
if (action == slsDetectorDefs::GET_ACTION) {
- if (1 && args.size() != 0) {
+ if (1 && args.size() != 0 && args.size() != 1) {
throw RuntimeError("Wrong number of arguments for action GET");
}
if (args.size() == 0) {
}
+ if (args.size() == 1) {
+ }
+
}
else if (action == slsDetectorDefs::PUT_ACTION) {
- if (1 && args.size() != 1) {
+ if (1 && args.size() != 1 && args.size() != 2) {
throw RuntimeError("Wrong number of arguments for action PUT");
}
if (args.size() == 1) {
try {
- StringTo(args[0]);
+ std::string tmp_freq(args[0]);
+ std::string unit = RemoveUnit(tmp_freq);
+ auto converted_freq = StringTo(tmp_freq, unit);
} catch (...) {
- throw RuntimeError("Could not convert argument 0 to int");
+ throw RuntimeError("Could not convert argument to defs::Hz");
+ }
+ }
+
+ if (args.size() == 2) {
+ try {
+ StringTo(args[0], args[1]);
+ } catch (...) {
+ throw RuntimeError("Could not convert arguments to defs::Hz");
}
}
@@ -117,13 +129,26 @@ std::string Caller::adcclk(int action) {
auto t = det->getADCClock(std::vector{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) {
- auto arg0 = StringTo(args[0]);
- det->setADCClock(arg0, std::vector{det_id});
- os << args.front() << '\n';
+ std::string tmp_freq(args[0]);
+ std::string unit = RemoveUnit(tmp_freq);
+ 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 = StringTo(args[0], args[1]);
+ det->setADCClock(converted_freq, std::vector{det_id});
+ os << args[0] << args[1] << '\n';
}
}
@@ -2482,34 +2507,46 @@ std::string Caller::dbitclk(int action) {
std::ostringstream os;
// print help
if (action == slsDetectorDefs::HELP_ACTION) {
- os << R"V0G0N([n_clk in MHz]
- [Ctb] Clock for latching the digital bits in MHz.
- [xilinx Ctb] Clock for latching the digital bits in kHz. )V0G0N"
+ os << R"V0G0N([n_clk] [(optional unit) Hz(default)|kHz|MHz]
+ [Ctb][Xilinx Ctb] Clock for latching the digital bits. )V0G0N"
<< std::endl;
return os.str();
}
// check if action and arguments are valid
if (action == slsDetectorDefs::GET_ACTION) {
- if (1 && args.size() != 0) {
+ if (1 && args.size() != 0 && args.size() != 1) {
throw RuntimeError("Wrong number of arguments for action GET");
}
if (args.size() == 0) {
}
+ if (args.size() == 1) {
+ }
+
}
else if (action == slsDetectorDefs::PUT_ACTION) {
- if (1 && args.size() != 1) {
+ if (1 && args.size() != 1 && args.size() != 2) {
throw RuntimeError("Wrong number of arguments for action PUT");
}
if (args.size() == 1) {
try {
- StringTo(args[0]);
+ std::string tmp_freq(args[0]);
+ std::string unit = RemoveUnit(tmp_freq);
+ auto converted_freq = StringTo(tmp_freq, unit);
} catch (...) {
- throw RuntimeError("Could not convert argument 0 to int");
+ throw RuntimeError("Could not convert argument to defs::Hz");
+ }
+ }
+
+ if (args.size() == 2) {
+ try {
+ StringTo(args[0], args[1]);
+ } catch (...) {
+ throw RuntimeError("Could not convert arguments to defs::Hz");
}
}
@@ -2527,13 +2564,26 @@ std::string Caller::dbitclk(int action) {
auto t = det->getDBITClock(std::vector{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) {
- auto arg0 = StringTo(args[0]);
- det->setDBITClock(arg0, std::vector{det_id});
- os << args.front() << '\n';
+ std::string tmp_freq(args[0]);
+ std::string unit = RemoveUnit(tmp_freq);
+ 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 = StringTo(args[0], args[1]);
+ det->setDBITClock(converted_freq, std::vector{det_id});
+ os << args[0] << args[1] << '\n';
}
}
@@ -7312,7 +7362,7 @@ std::string Caller::patfname(int action) {
// generate code for each action
if (action == slsDetectorDefs::GET_ACTION) {
if (args.size() == 0) {
- auto t = det->getPatterFileName(std::vector{det_id});
+ auto t = det->getPatternFileName(std::vector{det_id});
os << OutString(t) << '\n';
}
}
@@ -9909,34 +9959,46 @@ std::string Caller::runclk(int action) {
std::ostringstream os;
// print help
if (action == slsDetectorDefs::HELP_ACTION) {
- os << R"V0G0N([n_clk in MHz]
- [Ctb] Run clock in MHz.
- [xilinx Ctb] Run clock in kHz. )V0G0N"
+ os << R"V0G0N([n_clk] [(optional unit) Hz(default)|kHz|MHz]
+ [Ctb][Xilinx Ctb] Run clock frequency. )V0G0N"
<< std::endl;
return os.str();
}
// check if action and arguments are valid
if (action == slsDetectorDefs::GET_ACTION) {
- if (1 && args.size() != 0) {
+ if (1 && args.size() != 0 && args.size() != 1) {
throw RuntimeError("Wrong number of arguments for action GET");
}
if (args.size() == 0) {
}
+ if (args.size() == 1) {
+ }
+
}
else if (action == slsDetectorDefs::PUT_ACTION) {
- if (1 && args.size() != 1) {
+ if (1 && args.size() != 1 && args.size() != 2) {
throw RuntimeError("Wrong number of arguments for action PUT");
}
if (args.size() == 1) {
try {
- StringTo(args[0]);
+ std::string tmp_freq(args[0]);
+ std::string unit = RemoveUnit(tmp_freq);
+ auto converted_freq = StringTo(tmp_freq, unit);
} catch (...) {
- throw RuntimeError("Could not convert argument 0 to int");
+ throw RuntimeError("Could not convert argument to defs::Hz");
+ }
+ }
+
+ if (args.size() == 2) {
+ try {
+ StringTo(args[0], args[1]);
+ } catch (...) {
+ throw RuntimeError("Could not convert arguments to defs::Hz");
}
}
@@ -9954,13 +10016,26 @@ std::string Caller::runclk(int action) {
auto t = det->getRUNClock(std::vector{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) {
- auto arg0 = StringTo(args[0]);
- det->setRUNClock(arg0, std::vector{det_id});
- os << args.front() << '\n';
+ std::string tmp_freq(args[0]);
+ std::string unit = RemoveUnit(tmp_freq);
+ 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 = StringTo(args[0], args[1]);
+ det->setRUNClock(converted_freq, std::vector{det_id});
+ os << args[0] << args[1] << '\n';
}
}
@@ -13062,21 +13137,24 @@ std::string Caller::syncclk(int action) {
std::ostringstream os;
// print help
if (action == slsDetectorDefs::HELP_ACTION) {
- os << R"V0G0N([n_clk in MHz]
- [Ctb] Sync clock in MHz. )V0G0N"
+ os << R"V0G0N([n_clk] [(optional unit) Hz(default)|kHz|MHz]
+ [Ctb] Sync clock. )V0G0N"
<< std::endl;
return os.str();
}
// check if action and arguments are valid
if (action == slsDetectorDefs::GET_ACTION) {
- if (1 && args.size() != 0) {
+ if (1 && args.size() != 0 && args.size() != 1) {
throw RuntimeError("Wrong number of arguments for action GET");
}
if (args.size() == 0) {
}
+ if (args.size() == 1) {
+ }
+
}
else {
@@ -13091,6 +13169,11 @@ std::string Caller::syncclk(int action) {
auto t = det->getSYNCClock(std::vector{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/Caller.h b/slsDetectorSoftware/src/Caller.h
index ce9e7cc93..d35ffe569 100644
--- a/slsDetectorSoftware/src/Caller.h
+++ b/slsDetectorSoftware/src/Caller.h
@@ -54,6 +54,9 @@ class Caller {
return ToString(value, unit);
}
+ std::string OutString(const Result &value,
+ const std::string &unit);
+
std::vector getAllCommands();
std::map GetDeprecatedCommands();
std::string list(int action);
@@ -421,6 +424,7 @@ class Caller {
defs::dacIndex parseDacIndex(int argIndex, bool isCtb);
bool parseMV(int argIndex);
defs::powerIndex parsePowerIndex(int argIndex);
+ defs::FrequencyUnit parseFrequencyUnit(const std::string &s);
FunctionMap functions{
{"list", &Caller::list},
diff --git a/slsDetectorSoftware/src/CallerSpecial.cpp b/slsDetectorSoftware/src/CallerSpecial.cpp
index cf339ee5d..50cd1e72d 100644
--- a/slsDetectorSoftware/src/CallerSpecial.cpp
+++ b/slsDetectorSoftware/src/CallerSpecial.cpp
@@ -11,6 +11,14 @@
namespace sls {
// some helper functions to print
+std::string Caller::OutString(const Result &value,
+ const std::string &unit) {
+ auto u = parseFrequencyUnit(unit);
+ if (value.equal())
+ return ToString(value.front(), u);
+ return ToString(value, u);
+}
+
std::vector Caller::getAllCommands() {
std::vector ret;
for (auto it : functions)
@@ -2105,4 +2113,21 @@ std::string Caller::powervalues(int action) {
return os.str();
}
+defs::FrequencyUnit Caller::parseFrequencyUnit(const std::string &unit) {
+ auto unitLower = [&] {
+ std::string result = unit;
+ std::transform(result.begin(), result.end(), result.begin(),
+ [](unsigned char c) { return std::tolower(c); });
+ return result;
+ }();
+ if (unitLower == "hz")
+ return defs::FrequencyUnit::Hz;
+ if (unitLower == "khz")
+ return defs::FrequencyUnit::kHz;
+ if (unitLower == "mhz")
+ return defs::FrequencyUnit::MHz;
+
+ throw std::runtime_error("Unknown frequency unit: " + unit);
+}
+
} // namespace sls
\ No newline at end of file
diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp
index a6bd47a2f..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_MHz, Positions pos) {
+void Detector::setADCClock(defs::Hz val, Positions pos) {
pimpl->Parallel(&Module::setClockFrequency, pos, defs::ADC_CLOCK,
- value_in_MHz);
+ val.value);
}
-Result 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_MHz, Positions pos) {
+void Detector::setRUNClock(defs::Hz val, Positions pos) {
pimpl->Parallel(&Module::setClockFrequency, pos, defs::RUN_CLOCK,
- value_in_MHz);
+ val.value);
}
-Result 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_MHz, Positions pos) {
- pimpl->Parallel(&Module::setClockFrequency, pos, defs::DBIT_CLOCK,
- value_in_MHz);
-}
-
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 5cfa39875..17fe8841b 100644
--- a/slsDetectorSoftware/src/Module.cpp
+++ b/slsDetectorSoftware/src/Module.cpp
@@ -2668,7 +2668,7 @@ void Module::configureTransceiver() {
}
// Pattern
-std::string Module::getPatterFileName() const {
+std::string Module::getPatternFileName() const {
char retval[MAX_STR_LENGTH]{};
sendToDetector(F_GET_PATTERN_FILE_NAME, nullptr, retval);
return retval;
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 71c64048f..214c2ffa8 100644
--- a/slsDetectorSoftware/tests/Caller/test-Caller-chiptestboard.cpp
+++ b/slsDetectorSoftware/tests/Caller/test-Caller-chiptestboard.cpp
@@ -921,23 +921,65 @@ TEST_CASE("adcclk", "[.detectorintegration]") {
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
- if (det_type == defs::CHIPTESTBOARD) {
+ if (det_type == defs::CHIPTESTBOARD ||
+ det_type == defs::XILINX_CHIPTESTBOARD) {
auto prev_val = det.getADCClock();
+
+ REQUIRE_NOTHROW(caller.call("adcclk", {"MHZ"}, -1, GET));
+ REQUIRE_NOTHROW(caller.call("adcclk", {"mhz"}, -1, GET));
+ REQUIRE_NOTHROW(caller.call("adcclk", {"MHz"}, -1, GET));
+ REQUIRE_NOTHROW(caller.call("adcclk", {"kHz"}, -1, GET));
+ REQUIRE_NOTHROW(caller.call("adcclk", {"Hz"}, -1, GET));
+ REQUIRE_NOTHROW(caller.call("adcclk", {}, -1, GET));
+ // min
+ if (det_type == defs::CHIPTESTBOARD)
+ REQUIRE_THROWS(caller.call("adcclk", {"1", "MHz"}, -1, PUT));
+ else
+ REQUIRE_THROWS(caller.call("adcclk", {"9", "MHz"}, -1, PUT));
+ // max
+ if (det_type == defs::CHIPTESTBOARD)
+ REQUIRE_THROWS(caller.call("adcclk", {"66", "MHz"}, -1, PUT));
+ else
+ REQUIRE_THROWS(caller.call("adcclk", {"301", "MHz"}, -1, PUT));
+
{
std::ostringstream oss;
- caller.call("adcclk", {"20"}, -1, PUT, oss);
- REQUIRE(oss.str() == "adcclk 20\n");
+ caller.call("adcclk", {"20MHz"}, -1, PUT, oss);
+ REQUIRE(oss.str() == "adcclk 20MHz\n");
}
{
std::ostringstream oss;
- caller.call("adcclk", {"10"}, -1, PUT, oss);
- REQUIRE(oss.str() == "adcclk 10\n");
+ caller.call("adcclk", {"10000000"}, -1, PUT, oss);
+ REQUIRE(oss.str() == "adcclk 10000000\n");
+ }
+
+ {
+ std::ostringstream oss;
+ caller.call("adcclk", {}, -1, GET, oss);
+ REQUIRE(oss.str() == "adcclk 10MHz\n");
+ }
+ {
+ std::ostringstream oss;
+ caller.call("adcclk", {"15000", "kHz"}, -1, PUT, oss);
+ REQUIRE(oss.str() == "adcclk 15000kHz\n");
}
{
std::ostringstream oss;
caller.call("adcclk", {}, -1, GET, oss);
- REQUIRE(oss.str() == "adcclk 10\n");
+ REQUIRE(oss.str() == "adcclk 15MHz\n");
}
+ {
+ std::ostringstream oss;
+ caller.call("adcclk", {"15.75", "MHz"}, -1, PUT, oss);
+ REQUIRE(oss.str() == "adcclk 15.75MHz\n");
+ }
+ {
+ std::ostringstream oss;
+ caller.call("adcclk", {}, -1, GET, oss);
+ REQUIRE(oss.str() == "adcclk 15.75MHz\n");
+ }
+ std::cout << "Resetting adc clock to :" << ToString(prev_val)
+ << std::endl;
for (int i = 0; i != det.size(); ++i) {
det.setADCClock(prev_val[i], {i});
}
@@ -952,25 +994,119 @@ TEST_CASE("runclk", "[.detectorintegration]") {
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
- if (det_type == defs::CHIPTESTBOARD) {
+ if (det_type == defs::CHIPTESTBOARD ||
+ det_type == defs::XILINX_CHIPTESTBOARD) {
auto prev_val = det.getRUNClock();
+
+ REQUIRE_NOTHROW(caller.call("runclk", {"MHZ"}, -1, GET));
+ REQUIRE_NOTHROW(caller.call("runclk", {"mhz"}, -1, GET));
+ REQUIRE_NOTHROW(caller.call("runclk", {"MHz"}, -1, GET));
+ REQUIRE_NOTHROW(caller.call("runclk", {"kHz"}, -1, GET));
+ REQUIRE_NOTHROW(caller.call("runclk", {"Hz"}, -1, GET));
+ REQUIRE_NOTHROW(caller.call("runclk", {}, -1, GET));
+ // min
+ if (det_type == defs::CHIPTESTBOARD)
+ REQUIRE_THROWS(caller.call("runclk", {"1", "MHz"}, -1, PUT));
+ else
+ REQUIRE_THROWS(caller.call("runclk", {"9", "MHz"}, -1, PUT));
+ // max
+ REQUIRE_THROWS(caller.call("runclk", {"301", "MHz"}, -1, PUT));
+
{
std::ostringstream oss;
- caller.call("runclk", {"20"}, -1, PUT, oss);
- REQUIRE(oss.str() == "runclk 20\n");
+ caller.call("runclk", {"20MHz"}, -1, PUT, oss);
+ REQUIRE(oss.str() == "runclk 20MHz\n");
}
{
std::ostringstream oss;
- caller.call("runclk", {"10"}, -1, PUT, oss);
- REQUIRE(oss.str() == "runclk 10\n");
+ caller.call("runclk", {"10000000"}, -1, PUT, oss);
+ REQUIRE(oss.str() == "runclk 10000000\n");
+ }
+
+ {
+ std::ostringstream oss;
+ caller.call("runclk", {}, -1, GET, oss);
+ REQUIRE(oss.str() == "runclk 10MHz\n");
+ }
+ {
+ std::ostringstream oss;
+ caller.call("runclk", {"15000", "kHz"}, -1, PUT, oss);
+ REQUIRE(oss.str() == "runclk 15000kHz\n");
}
{
std::ostringstream oss;
caller.call("runclk", {}, -1, GET, oss);
- REQUIRE(oss.str() == "runclk 10\n");
+ REQUIRE(oss.str() == "runclk 15MHz\n");
+ }
+ {
+ std::ostringstream oss;
+ caller.call("runclk", {"15.75", "MHz"}, -1, PUT, oss);
+ REQUIRE(oss.str() == "runclk 15.75MHz\n");
+ }
+ {
+ std::ostringstream oss;
+ caller.call("runclk", {}, -1, GET, oss);
+ REQUIRE(oss.str() == "runclk 15.75MHz\n");
+ }
+ // tolerance
+ auto prev_exptime = det.getExptime();
+ auto prev_period = det.getPeriod();
+ auto prev_delay = det.getDelayAfterTrigger();
+ {
+ caller.call("runclk", {"80", "MHz"}, -1, PUT);
+ {
+ std::ostringstream oss;
+ REQUIRE_NOTHROW(
+ caller.call("exptime", {"10012", "ns"}, -1, PUT));
+ REQUIRE_NOTHROW(caller.call("exptime", {"ns"}, -1, GET, oss));
+ REQUIRE(oss.str() == "exptime 10013ns\n");
+ }
+ {
+ std::ostringstream oss;
+ REQUIRE_NOTHROW(
+ caller.call("exptime", {"10013", "ns"}, -1, PUT));
+ REQUIRE_NOTHROW(caller.call("exptime", {"ns"}, -1, GET, oss));
+ REQUIRE(oss.str() == "exptime 10013ns\n");
+ }
+ {
+ std::ostringstream oss;
+ REQUIRE_NOTHROW(
+ caller.call("exptime", {"10019", "ns"}, -1, PUT));
+ REQUIRE_NOTHROW(caller.call("exptime", {"ns"}, -1, GET, oss));
+ REQUIRE(oss.str() == "exptime 10025ns\n");
+ }
+ {
+ std::ostringstream oss;
+ REQUIRE_NOTHROW(
+ caller.call("period", {"10125", "ns"}, -1, PUT));
+ REQUIRE_NOTHROW(caller.call("period", {"ns"}, -1, GET, oss));
+ REQUIRE(oss.str() == "period 10125ns\n");
+ }
+ {
+ std::ostringstream oss;
+ REQUIRE_NOTHROW(
+ caller.call("period", {"10124", "ns"}, -1, PUT));
+ REQUIRE_NOTHROW(caller.call("period", {"ns"}, -1, GET, oss));
+ REQUIRE(oss.str() == "period 10125ns\n");
+ }
+ {
+ std::ostringstream oss;
+ REQUIRE_NOTHROW(caller.call("delay", {"10125", "ns"}, -1, PUT));
+ REQUIRE_NOTHROW(caller.call("delay", {"ns"}, -1, GET, oss));
+ REQUIRE(oss.str() == "delay 10125ns\n");
+ }
+ {
+ std::ostringstream oss;
+ REQUIRE_NOTHROW(caller.call("delay", {"10124", "ns"}, -1, PUT));
+ REQUIRE_NOTHROW(caller.call("delay", {"ns"}, -1, GET, oss));
+ REQUIRE(oss.str() == "delay 10125ns\n");
+ }
}
for (int i = 0; i != det.size(); ++i) {
det.setRUNClock(prev_val[i], {i});
+ det.setExptime(prev_exptime[i], {i});
+ det.setPeriod(prev_period[i], {i});
+ det.setDelayAfterTrigger(prev_delay[i], {i});
}
} else {
// clock index might work
@@ -983,6 +1119,11 @@ TEST_CASE("syncclk", "[.detectorintegration]") {
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::CHIPTESTBOARD) {
+ REQUIRE_NOTHROW(caller.call("syncclk", {"MHZ"}, -1, GET));
+ REQUIRE_NOTHROW(caller.call("syncclk", {"mhz"}, -1, GET));
+ REQUIRE_NOTHROW(caller.call("syncclk", {"MHz"}, -1, GET));
+ REQUIRE_NOTHROW(caller.call("syncclk", {"kHz"}, -1, GET));
+ REQUIRE_NOTHROW(caller.call("syncclk", {"Hz"}, -1, GET));
REQUIRE_NOTHROW(caller.call("syncclk", {}, -1, GET));
} else {
// clock index might work
@@ -1249,22 +1390,59 @@ TEST_CASE("dbitclk", "[.detectorintegration]") {
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
- if (det_type == defs::CHIPTESTBOARD) {
+ if (det_type == defs::CHIPTESTBOARD ||
+ det_type == defs::XILINX_CHIPTESTBOARD) {
auto prev_val = det.getDBITClock();
+
+ REQUIRE_NOTHROW(caller.call("dbitclk", {"MHZ"}, -1, GET));
+ REQUIRE_NOTHROW(caller.call("dbitclk", {"mhz"}, -1, GET));
+ REQUIRE_NOTHROW(caller.call("dbitclk", {"MHz"}, -1, GET));
+ REQUIRE_NOTHROW(caller.call("dbitclk", {"kHz"}, -1, GET));
+ REQUIRE_NOTHROW(caller.call("dbitclk", {"Hz"}, -1, GET));
+ REQUIRE_NOTHROW(caller.call("dbitclk", {}, -1, GET));
+ // min
+ if (det_type == defs::CHIPTESTBOARD)
+ REQUIRE_THROWS(caller.call("dbitclk", {"1", "MHz"}, -1, PUT));
+ else
+ REQUIRE_THROWS(caller.call("dbitclk", {"9", "MHz"}, -1, PUT));
+ // max
+ REQUIRE_THROWS(caller.call("dbitclk", {"301", "MHz"}, -1, PUT));
+
{
std::ostringstream oss;
- caller.call("dbitclk", {"20"}, -1, PUT, oss);
- REQUIRE(oss.str() == "dbitclk 20\n");
+ caller.call("dbitclk", {"20MHz"}, -1, PUT, oss);
+ REQUIRE(oss.str() == "dbitclk 20MHz\n");
}
{
std::ostringstream oss;
- caller.call("dbitclk", {"10"}, -1, PUT, oss);
- REQUIRE(oss.str() == "dbitclk 10\n");
+ caller.call("dbitclk", {"10000000"}, -1, PUT, oss);
+ REQUIRE(oss.str() == "dbitclk 10000000\n");
+ }
+
+ {
+ std::ostringstream oss;
+ caller.call("dbitclk", {}, -1, GET, oss);
+ REQUIRE(oss.str() == "dbitclk 10MHz\n");
+ }
+ {
+ std::ostringstream oss;
+ caller.call("dbitclk", {"15000", "kHz"}, -1, PUT, oss);
+ REQUIRE(oss.str() == "dbitclk 15000kHz\n");
}
{
std::ostringstream oss;
caller.call("dbitclk", {}, -1, GET, oss);
- REQUIRE(oss.str() == "dbitclk 10\n");
+ REQUIRE(oss.str() == "dbitclk 15MHz\n");
+ }
+ {
+ std::ostringstream oss;
+ caller.call("dbitclk", {"15.75", "MHz"}, -1, PUT, oss);
+ REQUIRE(oss.str() == "dbitclk 15.75MHz\n");
+ }
+ {
+ std::ostringstream oss;
+ caller.call("dbitclk", {}, -1, GET, oss);
+ REQUIRE(oss.str() == "dbitclk 15.75MHz\n");
}
for (int i = 0; i != det.size(); ++i) {
det.setDBITClock(prev_val[i], {i});
diff --git a/slsSupportLib/include/sls/ToString.h b/slsSupportLib/include/sls/ToString.h
index 777a98207..7035f9c38 100644
--- a/slsSupportLib/include/sls/ToString.h
+++ b/slsSupportLib/include/sls/ToString.h
@@ -108,6 +108,12 @@ ToString(From t) {
}
}
+/** Convert frequency with specified output unit */
+std::string ToString(defs::Hz f, defs::FrequencyUnit unit);
+
+/** Convert frequency automatically selecting the unit */
+std::string ToString(defs::Hz f);
+
/** Conversion of floating point values, removes trailing zeros*/
template
typename std::enable_if::value, std::string>::type
@@ -279,7 +285,23 @@ ToString(const T &container, const std::string &unit) {
return os.str();
}
+/** Container and specified unit, call ToString(value, FrequencyUnit) */
template
+typename std::enable_if::value, std::string>::type
+ToString(const T &container, defs::FrequencyUnit unit) {
+ std::ostringstream os;
+ os << '[';
+ if (!container.empty()) {
+ auto it = container.cbegin();
+ os << ToString(*it++, unit);
+ while (it != container.cend())
+ os << ", " << ToString(*it++, unit);
+ }
+ os << ']';
+ return os.str();
+}
+
+template ::value, int> = 0>
T StringTo(const std::string &t, const std::string &unit) {
double tval{0};
try {
@@ -304,6 +326,33 @@ T StringTo(const std::string &t, const std::string &unit) {
}
}
+template ::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);
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 54285ba17..283eb2f5e 100644
--- a/slsSupportLib/include/sls/sls_detector_defs.h
+++ b/slsSupportLib/include/sls/sls_detector_defs.h
@@ -221,6 +221,16 @@ 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);
+ }
+ };
+
+ enum class FrequencyUnit { Hz, kHz, MHz };
+
#endif
enum frameDiscardPolicy {
NO_DISCARD,
@@ -854,7 +864,6 @@ typedef struct {
#endif
#ifdef __cplusplus
-
// TODO! discuss this
#include //hmm... but currently no way around
namespace sls {
diff --git a/slsSupportLib/include/sls/versionAPI.h b/slsSupportLib/include/sls/versionAPI.h
index 1b1f5ce66..32fba195b 100644
--- a/slsSupportLib/include/sls/versionAPI.h
+++ b/slsSupportLib/include/sls/versionAPI.h
@@ -3,11 +3,11 @@
/** API versions */
#define APILIB "0.0.0 0x250909"
#define APIRECEIVER "0.0.0 0x250822"
-#define APICTB "0.0.0 0x260427"
+#define APICTB "0.0.0 0x260506"
#define APIGOTTHARD2 "0.0.0 0x260427"
#define APIMOENCH "0.0.0 0x260424"
#define APIEIGER "0.0.0 0x260424"
-#define APIXILINXCTB "0.0.0 0x260427"
+#define APIXILINXCTB "0.0.0 0x260506"
#define APIJUNGFRAU "0.0.0 0x260424"
-#define APIMYTHEN3 "0.0.0 0x260427"
-#define APIMATTERHORN "0.0.0 0x260212"
\ No newline at end of file
+#define APIMYTHEN3 "0.0.0 0x260506"
+#define APIMATTERHORN "0.0.0 0x260212"
diff --git a/slsSupportLib/src/ToString.cpp b/slsSupportLib/src/ToString.cpp
index dedb2f165..505b4517f 100644
--- a/slsSupportLib/src/ToString.cpp
+++ b/slsSupportLib/src/ToString.cpp
@@ -741,6 +741,36 @@ std::string ToString(const defs::collectionMode s) {
const std::string &ToString(const std::string &s) { return s; }
+std::string ToString(defs::Hz f, defs::FrequencyUnit unit) {
+ double val = static_cast(f.value);
+ std::ostringstream os;
+ switch (unit) {
+ case defs::FrequencyUnit::Hz:
+ os << val << "Hz";
+ break;
+ case defs::FrequencyUnit::kHz:
+ os << val / (static_cast(1e3)) << "kHz";
+ break;
+ case defs::FrequencyUnit::MHz:
+ os << val / (static_cast(1e6)) << "MHz";
+ break;
+ default:
+ throw std::runtime_error("Unknown frequency unit");
+ }
+ return os.str();
+}
+
+std::string ToString(defs::Hz f) {
+ int val = f.value;
+ if (val < 1e3) {
+ return ToString(f, defs::FrequencyUnit::Hz);
+ } else if (val < 1e6) {
+ return ToString(f, defs::FrequencyUnit::kHz);
+ } else {
+ return ToString(f, defs::FrequencyUnit::MHz);
+ }
+}
+
template <> defs::detectorType StringTo(const std::string &s) {
if (s == "Eiger")
return defs::EIGER;
diff --git a/slsSupportLib/tests/test-ToString.cpp b/slsSupportLib/tests/test-ToString.cpp
index 3d35004e8..0c35bdfc0 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), defs::FrequencyUnit::Hz) == "150Hz");
+ REQUIRE(ToString(defs::Hz(150), defs::FrequencyUnit::kHz) == "0.15kHz");
+ REQUIRE(ToString(defs::Hz(150), defs::FrequencyUnit::MHz) == "0.00015MHz");
+}
+
TEST_CASE("Convert vector of time", "[support]") {
std::vector 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);