Merge pull request #1143 from slsdetectorgroup/9.1.0.rc
Some checks failed
CMake / Configure and build using cmake (push) Failing after 10s

9.1.0
This commit is contained in:
maliakal_d 2025-03-26 08:38:23 +01:00 committed by GitHub
commit 64aad1e196
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
82 changed files with 1397 additions and 638 deletions

View File

@ -17,7 +17,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: awalsh128/cache-apt-pkgs-action@latest - uses: awalsh128/cache-apt-pkgs-action@latest
with: with:
packages: libhdf5-dev qtbase5-dev qt5-qmake libqt5svg5-dev packages: libhdf5-dev qtbase5-dev qt5-qmake libqt5svg5-dev libpng-dev libtiff-dev
version: 1.0 version: 1.0
- name: Configure CMake - name: Configure CMake

View File

@ -1 +0,0 @@
# This file is generated by cmake for dependency checking of the CMakeCache.txt file

View File

@ -249,8 +249,8 @@ endif()
if(SLS_USE_SANITIZER) if(SLS_USE_SANITIZER)
target_compile_options(slsProjectOptions INTERFACE -fsanitize=address,undefined -fno-omit-frame-pointer) target_compile_options(slsProjectOptions INTERFACE -fsanitize=address,undefined -fno-omit-frame-pointer)
target_link_libraries(slsProjectOptions INTERFACE -fsanitize=address,undefined) target_link_libraries(slsProjectOptions INTERFACE -fsanitize=address,undefined)
# target_compile_options(slsProjectOptions INTERFACE -fsanitize=thread) #target_compile_options(slsProjectOptions INTERFACE -fsanitize=thread -fno-omit-frame-pointer)
# target_link_libraries(slsProjectOptions INTERFACE -fsanitize=thread) #target_link_libraries(slsProjectOptions INTERFACE -fsanitize=thread)
endif() endif()

View File

@ -1,284 +1,147 @@
SLS Detector Package Major Release 9.0.0 released on 26.11.2024 SLS Detector Package Minor Release 9.1.0 released on 26.03.2025
=============================================================== ===============================================================
This document describes the differences between v9.0.0 and v8.0.2 This document describes the differences between v9.1.0 and v9.0.0
CONTENTS CONTENTS
-------- --------
1 Compilation Changes 1 Changes
2 New or Changed Features 1.1 New or Changed Features
2.1 Breaking API 1.2 Resolved Features
2.2 Resolved or Changed Features 2 On-board Detector Server Compatibility
2.3 New Features 3 Firmware Requirements
3 On-board Detector Server Compatibility 4 Kernel Requirements
4 Firmware Requirements 5 Download, Documentation & Support
5 Kernel Requirements
6 Download, Documentation & Support
2 Compilation Changes 1 Changes
===================== ==========
* Python version
Minimum python version is changed from 3.6 to 3.8
* Pybind11 version
In-built version and the one picked up from github
updated from v2.11.0 to v2.13.6
* Python lib versioning
slsdet.__version__ now returns the package release version.
* Python version in conda build
Added python 3.13 also to conda build
2 New, Changed or Resolved Features 1.1 New or Changed Features
===================================== ============================
2.1 Breaking API
==================
Receiver Receiver
-------- --------
* Receiver callbacks * Frame Synchronizer (experimental)
Brought much more metadata to receiver callbacks to construct the image. Added a new binary, similar to slsMultiReceiver, to collect images from
Update MultiReceiverApp to reflect this change. several receivers and stream them out as a ZMQ multipart message
(one part for each UDP port). No reconstuction of the image. Includeds start
and end ZMQ messages as well for the start and end callback parameters.
* File path Documentation
At start of acquisition or at rx_start command, the file path is only -------------
then verified if it exists and created if it does not.
Client * Command line - multi module and multi detector indices
------ Help on this topic has been added to the 'Command line' topic.
* Removed receiver/publisher ZMQ IP * Row and column index (UDP header or callback)
Command line: rx_zmqip gives a warning and does nothing Help on how this is determined from the hostname is added to the 'UDP
Python : rx_zmqip removed Header' and the 'Quick Start Guide' topics. Also added to the help in '
C++ API: get/setRxZmqIP removed hostname' command line help. Please note that this can be overwritten by
corresponding row and column commands.
Publisher zmq IP set to '0.0.0.0' or to listen on all interfaces.
The publisher will determine which interface to stream out from based on
the network route to the subscriber IP. Hence, receiver zmq IP is not
required.
* Write register, Set or Clear bit
Validation for this advanced feature has been removed by default.
One can force validation by using --validate in the command line or by
setting the validate option in the API.
ZMQ
---
* Publisher socket constructor does not take an IP anymore.
The details are above under 'Removed receiver/publisher ZMQ IP'.
GUI/ Client Callback
--------------------
* completeImage member in detectorData attribute now returns false only
if any the sub images (from different udp ports) have completeImage
set to false in the JSON header. This is set if therea are any missing
packets for that udp port on slsReceiver/slsMultiReceiver.
The different subimages are anyway not synchronized. This errs when
there are different missing images across multiple UDP ports.
The Gui does not show "complete image" in the status bar anymore.
If any of the udp ports have missing packets for that current disaplayed
image, then the "missing packets" will show in red in the status bar.
Detector Server
---------------
* [Mythen3] Only run clock can be set
Clock 0 is now the run clock and the only one that can be set.
The others are be read only.
This affects the following commands:
Command line or python API: clkdiv, clkfreq, clkphase, maxclkphaseshift
C++ API: get/setClockDivider, getClockFrequency, get/setClockPhase,
getMaxClockPhaseShift
* [Jungfrau] Temperature Control
Temperature control is enabled by default at on-board detector server
startup.
As before, the default temperature threshold is 65°C and crossing this
value will set a temperature event.
2.2 Resolved or Changed Features 1.2 Resolved Features
================================ ======================
Compilation Firmware
-----------
* cmake_source_dir
Fixed compilation error when using python and adding the slsDetectorPackage
as a subfolder due to cmake source directory changing.
Client
------
* Command line Code Generation
The command line parsing code is now generated from a yaml file. This is
transparent to the user.
* Clearer error message about freeing shared memory.
Detector Server
---------------
* [Gotthard2] Chip reconfiguration
- Powering off/on the chip will now switch off chip configuration
property/ configure the chip every time.
- Switching off high voltage from a non zero value will now wait
10s to return for safety reasons.
- Powering off the chip requires high voltage to have been
switched off prior.
- Acquisition requires chip to have been configured prior.
* [Gotthard2] Burst mode options restricted
Burst mode external and continuous mode internal are not allowed to be set
anymore as they are anyway not implemented.
Receiver
--------
* [Gotthard I] fixed header stripping fixing segfault.
* Error or help message for invalid arguments to slsMultiReceiver.
Simulator
--------- ---------
* Refactored stop server to have better start up. * [Jungfrau] Column select and filter resistor
Configuration fix for chip v1.1 for these parameters
* Fixed possible memory leak when taking non blocking acquisitions. Firmware &/ On-board Detector Server
------------------------------------
* [Jungfrau] Valid gain values in data sent out. Previously, 2 was also sent out. * [Jungfrau] Timing Info Decoder
Only allowed for hardware v2.0 now.
* [Jungfrau] Auto Comparator Disable - chip v1.0
Previously, this mode for chip v1.0 automatically disabled the on-chip
gain switching compatator after a fixed portion of the exposure time.
Now, one must set also the comparator disable time using 'compdisabletime'
just as in chip v1.1.
* [Mythen3] Default period on server start up is 0 now.
Client
-------
* Command line - Multi detector index inside file
Multi detector index '[index]-' was ignored silently in the config/parameter
file since 5.0.0. Now, it will throw an exception. Please use the multi
detector index on the 'config' or 'parameter' command instead.
* [Mythen3] patternX command autocompletes the argument to a path now.
Receiver
--------
* Multiple Receiver objects in multiple threads
slsMultiReceiver uses child processes, but if user rewrote to use multiple
receiver objects in multiple threads instead, a callback mutex is now
implemented to handle the locking mechanism between threads for the callbacks.
* Removed potentially unsafe str().c_str() calls.
* slsMultiReceiver Ctrl + C
Now cleans up properly upon Ctrl + C, including exiting the Arping thread.
* slsMultiReceiver version
--version or -v now gives the version of slsMultiReceiver.
ZMQ ZMQ
--- ---
* Publiser socket constructor * [Moench] Reduced significant print out in zmq processing using energy
threshold.
- enables keep alive socket options to send heartbeat messages to prevent
discarded TCP flows if there is no packet for a longer period.
- enables IPv6 interfaces
* Prints specific error for ENOENT (endpoint does not exist)
* [Moench] Zmq dummy packet restreaming command did nothing
2.3 New Features Temporary solution was to move from 'stop' to 'rx_stop' as 'stop' did not
================ go further if module is idle.
Client * [Moench] Too many Zmq dummy packets- unclear end in acquire
------ Give time to process dummy packet before restreaming it and wait more
before restreaming to reduce amoutn of zmq dummy packets to process.
* Auto completion Simulators
bash_autocomplete.sh or zsh_autocomplete.sh must be sourced from the -----------
main package folder to enable auto completion of commands and arguments
for the command line on that shell.
* sls_detector * [Jungfrau][Moench] Slightly faster transmistting time by removing sleeping
New executable that can be used instead of 'sls_detector_get' and only if there is a transmission delay
'sls_detector_put' for most commands. It will infer from the number of
arguments, which executable (sls_detector_put or sls_detector_get) to use.
For the rare commands that cannot be inferred from the number of arguments,
it will complain accordingly.
* [Jungfrau] Timing Info Decoder (Advanced configuration)
Command line or python API: timing_info_decoder
C++ API: get/setTimingInfoDecoder. Options: SWISSFEL (Default), SHINE
* [Jungfrau] Collection Mode (Advanced configuration)
Command line or python API: collectionmode
C++ API: get/setCollectionMode. Options: ELECTRON, HOLE (Default)
If chip v1.1, also configures the chip afterwards.
* [Gotthard2] Next frame number
'Stop' in G2 25um is not synchronous and hence might trigger an extra set
of frames in the slave module, resulting in the next acquiistion starting
with inconsistent frame numbers between master and slave. Solved by
setting next frame number to the larger value (max + 1) after a stop command.
Requires a firmware update.
Command line or python API: nextframenumber
C++ API: get/setNextFrameNumber
Can set/get the starting frame number for the next acquistion.
* [Mythen3] Readout speed
Command line, python API: readoutspeed. Options: full_speed (10MHz),
half_speed (20MHz, default), quarter_speed (40MHz)
C++ API: get/setReadoutSpeed
Also affect:
Command line, python API: readoutspeedlist
C++ API: getReadoutSpeedList
* Sleep
Command line, python/ C++ API: sleep
Client sleeps for required time. Advanced command mainly for firmware
developers to use in config files.
* Xilinx Chip Test Board added
@ -287,8 +150,8 @@ This document describes the differences between v9.0.0 and v8.0.2
Eiger 9.0.0 Eiger 9.0.0
Jungfrau 9.0.0 Jungfrau 9.1.0
Mythen3 9.0.0 Mythen3 9.1.0
Gotthard2 9.0.0 Gotthard2 9.0.0
Gotthard 9.0.0 Gotthard 9.0.0
Moench 9.0.0 Moench 9.0.0
@ -317,8 +180,8 @@ This document describes the differences between v9.0.0 and v8.0.2
Eiger 02.10.2023 (v32) (updated in 7.0.3) Eiger 02.10.2023 (v32) (updated in 7.0.3)
Jungfrau 20.09.2023 (v1.5, HW v1.0) (updated in 8.0.0) Jungfrau 09.02.2025 (v1.6, HW v1.0) (updated in 9.1.0)
21.09.2023 (v2.5, HW v2.0) (updated in 8.0.0) 08.02.2025 (v2.6, HW v2.0) (updated in 9.1.0)
Mythen3 13.11.2024 (v2.0) (updated in 9.0.0) Mythen3 13.11.2024 (v2.0) (updated in 9.0.0)
@ -360,6 +223,7 @@ This document describes the differences between v9.0.0 and v8.0.2
4 Kernel Requirements 4 Kernel Requirements
====================== ======================
Blackfin Blackfin
-------- --------
Latest version: Fri Oct 29 00:00:00 2021 Latest version: Fri Oct 29 00:00:00 2021
@ -367,10 +231,12 @@ This document describes the differences between v9.0.0 and v8.0.2
Older ones will work, but might have issues with programming firmware via Older ones will work, but might have issues with programming firmware via
the package. the package.
Nios Nios
----- -----
Compatible version: Mon May 10 18:00:21 CEST 2021 Compatible version: Mon May 10 18:00:21 CEST 2021
Kernel Upgrade Kernel Upgrade
--------------- ---------------
Eiger via bit files Eiger via bit files

View File

@ -1 +1 @@
9.0.0 9.1.0

View File

@ -11,6 +11,7 @@ cp build/install/lib/* $PREFIX/lib/
#Binaries #Binaries
cp build/install/bin/sls_detector_acquire $PREFIX/bin/. cp build/install/bin/sls_detector_acquire $PREFIX/bin/.
cp build/install/bin/sls_detector_acquire_zmq $PREFIX/bin/.
cp build/install/bin/sls_detector_get $PREFIX/bin/. cp build/install/bin/sls_detector_get $PREFIX/bin/.
cp build/install/bin/sls_detector_put $PREFIX/bin/. cp build/install/bin/sls_detector_put $PREFIX/bin/.
cp build/install/bin/sls_detector_help $PREFIX/bin/. cp build/install/bin/sls_detector_help $PREFIX/bin/.

View File

@ -63,4 +63,4 @@ html_static_path = ['static']
def setup(app): def setup(app):
app.add_stylesheet('css/extra.css') # may also be an URL app.add_css_file('css/extra.css') # may also be an URL

View File

@ -4,11 +4,54 @@ Command line interface
Usage Usage
------------- -------------
Commands can be used either with sls_detector_get or sls_detector_put The syntax is *'[detector index]-[module index]:[command]'*, where the indices are by default '0', when not specified.
Module index
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Modules are indexed based on their order in the hostname command. They are used to configure a specific module within a detector and are followed by a ':' in syntax.
.. code-block::
# Applies to all modules of detector 0
sls_detector_put exptime 5s
# Applies to only the 4th module
sls_detector_put 3:exptime 5s
Detector index
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This index is useful when configuring multiple detectors from a single host. Each detector uses a unique shared memory identified by a detector index, derived again from the hostname command. It is followed by a '-'.
.. code-block::
# For detector with index 2 in shared memory
sls_detector_put 2-hostname bchip133+bchip123+bchip456
# Without '-', the detector index defaults to 0
sls_detector_put hostname bchip133+bchip123+bchip456
# Accessing all modules with detector index 2
sls_detector_put 2-exptime
# Starting acquisition only for detector with index 2
sls_detector_put 2-start
# Applies only to the 2nd detector, 4th module
sls_detector_put 1-3:exptime 5s
Command Execution
^^^^^^^^^^^^^^^^^^^^^^^
Commands can be executed using:
* **sls_detector_put**: setting values
* **sls_detector_get**: getting values
* **sls_detector**: automatically infers based on the number of arguments.
* **sls_detector_help**: gets help on the specific command
* **sls_detector_acquire**: initiates acquisition with the detector. This command blocks until the entire acquisition process is completed.
.. code-block::
sls_detector_get exptime
Help Help
-------- --------
@ -28,12 +71,15 @@ Help
# list of deprecated commands # list of deprecated commands
list deprecated list deprecated
# autocompletion
# bash_autocomplete.sh or zsh_autocomplete.sh must be sourced from the
# main package folder to enable auto completion of commands and arguments
# for the command line on that shell.
source bash_autocomplete.sh
Autocompletion
---------------
bash_autocomplete.sh or zsh_autocomplete.sh must be sourced from the main package folder to enable auto completion of commands and arguments for the command line on that shell.
.. code-block::
source bash_autocomplete.sh
Commands Commands

View File

@ -13,7 +13,6 @@ containing results from all modules. (:ref:`Result class<Result Class>`)
Here are some :ref:`examples <Cplusplus Api Examples>` on how to use the API. Here are some :ref:`examples <Cplusplus Api Examples>` on how to use the API.
.. _Cplusplus Api Examples:
.. doxygenclass:: sls::Detector .. doxygenclass:: sls::Detector
:members: :members:
:undoc-members: :undoc-members:

View File

@ -39,7 +39,7 @@ Welcome to slsDetectorPackage's documentation!
.. toctree:: .. toctree::
:caption: Command line :caption: Command line
:maxdepth: 2 :maxdepth: 1
commandline commandline
quick_start_guide quick_start_guide

View File

@ -23,11 +23,15 @@ Conda is not only useful to manage python environments but can also
be used as a user space package manager. Dates in the tag (for eg. 2020.07.23.dev0) be used as a user space package manager. Dates in the tag (for eg. 2020.07.23.dev0)
are from the developer branch. Please use released tags for stability. are from the developer branch. Please use released tags for stability.
We have three different packages available: We have four different packages available:
============== =============================================
* **slsdetlib** shared libraries and command line utilities Package Description
* **slsdetgui** GUI ============== =============================================
* **slsdet** Python bindings slsdetlib shared libraries and command line utilities
slsdetgui GUI
slsdet Python bindings
moenchzmq moench
============== =============================================
.. code-block:: bash .. code-block:: bash
@ -43,7 +47,7 @@ We have three different packages available:
#ready to use #ready to use
sls_detector_get exptime sls_detector_get exptime
etc ... ...
.. code-block:: bash .. code-block:: bash
@ -55,6 +59,8 @@ We have three different packages available:
conda search slsdet conda search slsdet
# gui # gui
conda search slsdetgui conda search slsdetgui
# moench
conda search moenchzmq

View File

@ -1,5 +1,6 @@
.. _master file attributes: .. _master file attributes:
Master File Attributes Master File Attributes
======================= =======================

View File

@ -128,6 +128,10 @@ For Multiple Modules
# set file path # set file path
fpath /tmp fpath /tmp
.. note ::
The **hostname** and **detsize** command in a multi module system can affect the row and column values in the udp/zmq header. The modules are stacked row by row until they reach the y-axis limit set by detsize (if specified). Then, stacking continues in the next column and so on.
Gui Gui
---- ----

View File

@ -39,13 +39,13 @@ Arguments
.. _Automatic start servers: .. _Automatic start servers:
Automatic start Automatic start
------------------ ------------------
One can start the on-board detector server automatically upon powering on the board. One can start the on-board detector server automatically upon powering on the board.
#. Create a soft link to the binary on board #. Create a soft link to the binary on board:
:
.. code-block:: bash .. code-block:: bash
ln -sf someDetectorServervx.x.x someDetectorServer ln -sf someDetectorServervx.x.x someDetectorServer
@ -87,8 +87,7 @@ One can start the on-board detector server automatically upon powering on the bo
/root/xxxDetectorServer >> /dev/null & /root/xxxDetectorServer >> /dev/null &
#. Sync, reboot and verify #. Sync, reboot and verify:
:
.. code-block:: bash .. code-block:: bash
sync sync

View File

@ -73,9 +73,9 @@ Description
* **modId**: module ID picked up from det_id_[detector type].txt on the detector cpu. * **modId**: module ID picked up from det_id_[detector type].txt on the detector cpu.
* **row**: row position of the module in the detector system. It is calculated by the order of the module in hostname command, as well as the detsize command. * **row**: row position of the module in the detector system. It is calculated by the order of the module in hostname command, as well as the detsize command. The modules are stacked row by row until they reach the y-axis limit set by detsize (if specified). Then, stacking continues in the next column and so on.
* **column**: column position of the module in the detector system. It is calculated by the order of the module in hostname command, as well as the detsize command. * **column**: column position of the module in the detector system. It is calculated by the order of the module in hostname command, as well as the detsize command. The modules are stacked row by row until they reach the y-axis limit set by detsize (if specified). Then, stacking continues in the next column and so on.
* **detType**: detector type from enum of detectorType in the package. * **detType**: detector type from enum of detectorType in the package.

View File

@ -11,4 +11,6 @@ slsDetectorPackage/8.0.1_rh7 stable cmake/3.15.5 Qt/5.12.10
slsDetectorPackage/8.0.1_rh8 stable cmake/3.15.5 Qt/5.12.10 slsDetectorPackage/8.0.1_rh8 stable cmake/3.15.5 Qt/5.12.10
slsDetectorPackage/8.0.2_rh7 stable cmake/3.15.5 Qt/5.12.10 slsDetectorPackage/8.0.2_rh7 stable cmake/3.15.5 Qt/5.12.10
slsDetectorPackage/8.0.2_rh8 stable cmake/3.15.5 Qt/5.12.10 slsDetectorPackage/8.0.2_rh8 stable cmake/3.15.5 Qt/5.12.10
slsDetectorPackage/9.0.0_rh8 stable cmake/3.15.5 Qt/5.12.10

View File

@ -14,6 +14,8 @@ from pyctbgui.utils.defines import Defines
import pyctbgui.utils.pixelmap as pm import pyctbgui.utils.pixelmap as pm
from pyctbgui.utils.recordOrApplyPedestal import recordOrApplyPedestal from pyctbgui.utils.recordOrApplyPedestal import recordOrApplyPedestal
from slsdet import detectorType
if typing.TYPE_CHECKING: if typing.TYPE_CHECKING:
from pyctbgui.services import AcquisitionTab, PlotTab from pyctbgui.services import AcquisitionTab, PlotTab
@ -30,6 +32,7 @@ class AdcTab(QtWidgets.QWidget):
self.acquisitionTab: AcquisitionTab | None = None self.acquisitionTab: AcquisitionTab | None = None
self.legend: LegendItem | None = None self.legend: LegendItem | None = None
self.logger = logging.getLogger('AdcTab') self.logger = logging.getLogger('AdcTab')
self.tengiga = True
def setup_ui(self): def setup_ui(self):
self.plotTab = self.mainWindow.plotTab self.plotTab = self.mainWindow.plotTab
@ -42,6 +45,12 @@ class AdcTab(QtWidgets.QWidget):
self.legend.clear() self.legend.clear()
# subscribe to toggle legend # subscribe to toggle legend
self.plotTab.subscribeToggleLegend(self.updateLegend) self.plotTab.subscribeToggleLegend(self.updateLegend)
if self.det.type == detectorType.XILINX_CHIPTESTBOARD:
self.view.checkBoxADC0_15Inv.setDisabled(True)
self.view.checkBoxADC16_31Inv.setDisabled(True)
self.view.lineEditADCInversion.setDisabled(True)
self.view.labelADCInversion.setDisabled(True)
def initializeAllAnalogPlots(self): def initializeAllAnalogPlots(self):
self.mainWindow.plotAnalogWaveform = pg.plot() self.mainWindow.plotAnalogWaveform = pg.plot()
@ -67,7 +76,8 @@ class AdcTab(QtWidgets.QWidget):
def connect_ui(self): def connect_ui(self):
for i in range(Defines.adc.count): for i in range(Defines.adc.count):
getattr(self.view, f"checkBoxADC{i}Inv").stateChanged.connect(partial(self.setADCInv, i)) if self.det.type == detectorType.CHIPTESTBOARD:
getattr(self.view, f"checkBoxADC{i}Inv").stateChanged.connect(partial(self.setADCInv, i))
getattr(self.view, f"checkBoxADC{i}En").stateChanged.connect(partial(self.setADCEnable, i)) getattr(self.view, f"checkBoxADC{i}En").stateChanged.connect(partial(self.setADCEnable, i))
getattr(self.view, f"checkBoxADC{i}Plot").stateChanged.connect(partial(self.setADCEnablePlot, i)) getattr(self.view, f"checkBoxADC{i}Plot").stateChanged.connect(partial(self.setADCEnablePlot, i))
getattr(self.view, f"pushButtonADC{i}").clicked.connect(partial(self.selectADCColor, i)) getattr(self.view, f"pushButtonADC{i}").clicked.connect(partial(self.selectADCColor, i))
@ -77,15 +87,17 @@ class AdcTab(QtWidgets.QWidget):
self.view.checkBoxADC0_15Plot.stateChanged.connect(partial(self.setADCEnablePlotRange, 0, Defines.adc.half)) self.view.checkBoxADC0_15Plot.stateChanged.connect(partial(self.setADCEnablePlotRange, 0, Defines.adc.half))
self.view.checkBoxADC16_31Plot.stateChanged.connect( self.view.checkBoxADC16_31Plot.stateChanged.connect(
partial(self.setADCEnablePlotRange, Defines.adc.half, Defines.adc.count)) partial(self.setADCEnablePlotRange, Defines.adc.half, Defines.adc.count))
self.view.checkBoxADC0_15Inv.stateChanged.connect(partial(self.setADCInvRange, 0, Defines.adc.half))
self.view.checkBoxADC16_31Inv.stateChanged.connect(
partial(self.setADCInvRange, Defines.adc.half, Defines.adc.count))
self.view.lineEditADCInversion.editingFinished.connect(self.setADCInvReg)
self.view.lineEditADCEnable.editingFinished.connect(self.setADCEnableReg) self.view.lineEditADCEnable.editingFinished.connect(self.setADCEnableReg)
if self.det.type == detectorType.CHIPTESTBOARD:
self.view.checkBoxADC0_15Inv.stateChanged.connect(partial(self.setADCInvRange, 0, Defines.adc.half))
self.view.checkBoxADC16_31Inv.stateChanged.connect(
partial(self.setADCInvRange, Defines.adc.half, Defines.adc.count))
self.view.lineEditADCInversion.editingFinished.connect(self.setADCInvReg)
def refresh(self): def refresh(self):
self.updateADCNames() self.updateADCNames()
self.updateADCInv() if self.det.type == detectorType.CHIPTESTBOARD:
self.updateADCInv()
self.updateADCEnable() self.updateADCEnable()
# ADCs Tab functions # ADCs Tab functions
@ -196,9 +208,11 @@ class AdcTab(QtWidgets.QWidget):
return decoder.decode(analog_array, pm.moench04_analog()) return decoder.decode(analog_array, pm.moench04_analog())
def getADCEnableReg(self): def getADCEnableReg(self):
retval = self.det.adcenable if self.det.type == detectorType.CHIPTESTBOARD:
if self.det.tengiga: self.tengiga = self.det.tengiga
retval = self.det.adcenable10g retval = self.det.adcenable10g
if not self.tengiga:
retval = self.det.adcenable
self.view.lineEditADCEnable.editingFinished.disconnect() self.view.lineEditADCEnable.editingFinished.disconnect()
self.view.lineEditADCEnable.setText("0x{:08x}".format(retval)) self.view.lineEditADCEnable.setText("0x{:08x}".format(retval))
self.view.lineEditADCEnable.editingFinished.connect(self.setADCEnableReg) self.view.lineEditADCEnable.editingFinished.connect(self.setADCEnableReg)
@ -207,8 +221,8 @@ class AdcTab(QtWidgets.QWidget):
def setADCEnableReg(self): def setADCEnableReg(self):
self.view.lineEditADCEnable.editingFinished.disconnect() self.view.lineEditADCEnable.editingFinished.disconnect()
try: try:
mask = int(self.mainWindow.lineEditADCEnable.text(), 16) mask = int(self.view.lineEditADCEnable.text(), 16)
if self.det.tengiga: if self.tengiga:
self.det.adcenable10g = mask self.det.adcenable10g = mask
else: else:
self.det.adcenable = mask self.det.adcenable = mask
@ -239,7 +253,7 @@ class AdcTab(QtWidgets.QWidget):
def setADCEnable(self, i): def setADCEnable(self, i):
checkBox = getattr(self.view, f"checkBoxADC{i}En") checkBox = getattr(self.view, f"checkBoxADC{i}En")
try: try:
if self.det.tengiga: if self.tengiga:
enableMask = manipulate_bit(checkBox.isChecked(), self.det.adcenable10g, i) enableMask = manipulate_bit(checkBox.isChecked(), self.det.adcenable10g, i)
self.det.adcenable10g = enableMask self.det.adcenable10g = enableMask
else: else:
@ -265,7 +279,7 @@ class AdcTab(QtWidgets.QWidget):
for i in range(start_nr, end_nr): for i in range(start_nr, end_nr):
mask = manipulate_bit(checkBox.isChecked(), mask, i) mask = manipulate_bit(checkBox.isChecked(), mask, i)
try: try:
if self.det.tengiga: if self.tengiga:
self.det.adcenable10g = mask self.det.adcenable10g = mask
else: else:
self.det.adcenable = mask self.det.adcenable = mask
@ -344,7 +358,7 @@ class AdcTab(QtWidgets.QWidget):
def setADCInvReg(self): def setADCInvReg(self):
self.view.lineEditADCInversion.editingFinished.disconnect() self.view.lineEditADCInversion.editingFinished.disconnect()
try: try:
self.det.adcinvert = int(self.mainWindow.lineEditADCInversion.text(), 16) self.det.adcinvert = int(self.view.lineEditADCInversion.text(), 16)
except Exception as e: except Exception as e:
QtWidgets.QMessageBox.warning(self.mainWindow, "ADC Inversion Fail", str(e), QtWidgets.QMessageBox.Ok) QtWidgets.QMessageBox.warning(self.mainWindow, "ADC Inversion Fail", str(e), QtWidgets.QMessageBox.Ok)
pass pass
@ -395,7 +409,12 @@ class AdcTab(QtWidgets.QWidget):
self.updateADCInv() self.updateADCInv()
def saveParameters(self) -> list[str]: def saveParameters(self) -> list[str]:
return [ if self.det.type == detectorType.CHIPTESTBOARD:
f"adcenable {self.view.lineEditADCEnable.text()}", return [
f"adcinvert {self.view.lineEditADCInversion.text()}", f"adcenable {self.view.lineEditADCEnable.text()}",
] f"adcinvert {self.view.lineEditADCInversion.text()}",
]
else:
return [
f"adcenable {self.view.lineEditADCEnable.text()}"
]

View File

@ -7,7 +7,7 @@ import zmq
from PyQt5 import QtWidgets, uic from PyQt5 import QtWidgets, uic
import logging import logging
from slsdet import readoutMode, runStatus from slsdet import readoutMode, runStatus, detectorType
from pyctbgui.utils.defines import Defines from pyctbgui.utils.defines import Defines
from pyctbgui.utils.numpyWriter.npy_writer import NumpyFileManager from pyctbgui.utils.numpyWriter.npy_writer import NumpyFileManager
from pyctbgui.utils.numpyWriter.npz_writer import NpzFileWriter from pyctbgui.utils.numpyWriter.npz_writer import NpzFileWriter
@ -49,20 +49,37 @@ class AcquisitionTab(QtWidgets.QWidget):
self.adcTab = self.mainWindow.adcTab self.adcTab = self.mainWindow.adcTab
self.plotTab = self.mainWindow.plotTab self.plotTab = self.mainWindow.plotTab
self.toggleStartButton(False) self.toggleStartButton(False)
if self.det.type == detectorType.XILINX_CHIPTESTBOARD:
self.view.labelRunF.setDisabled(True)
self.view.labelADCF.setDisabled(True)
self.view.labelADCPhase.setDisabled(True)
self.view.labelADCPipeline.setDisabled(True)
self.view.labelDBITF.setDisabled(True)
self.view.labelDBITPhase.setDisabled(True)
self.view.labelDBITPipeline.setDisabled(True)
self.view.spinBoxRunF.setDisabled(True)
self.view.spinBoxADCF.setDisabled(True)
self.view.spinBoxADCPhase.setDisabled(True)
self.view.spinBoxADCPipeline.setDisabled(True)
self.view.spinBoxDBITF.setDisabled(True)
self.view.spinBoxDBITPhase.setDisabled(True)
self.view.spinBoxDBITPipeline.setDisabled(True)
def connect_ui(self): def connect_ui(self):
# For Acquistions Tab # For Acquistions Tab
self.view.comboBoxROMode.currentIndexChanged.connect(self.setReadOut) self.view.comboBoxROMode.currentIndexChanged.connect(self.setReadOut)
self.view.spinBoxRunF.editingFinished.connect(self.setRunFrequency)
self.view.spinBoxTransceiver.editingFinished.connect(self.setTransceiver) self.view.spinBoxTransceiver.editingFinished.connect(self.setTransceiver)
self.view.spinBoxAnalog.editingFinished.connect(self.setAnalog) self.view.spinBoxAnalog.editingFinished.connect(self.setAnalog)
self.view.spinBoxDigital.editingFinished.connect(self.setDigital) self.view.spinBoxDigital.editingFinished.connect(self.setDigital)
self.view.spinBoxADCF.editingFinished.connect(self.setADCFrequency)
self.view.spinBoxADCPhase.editingFinished.connect(self.setADCPhase) if self.det.type == detectorType.CHIPTESTBOARD:
self.view.spinBoxADCPipeline.editingFinished.connect(self.setADCPipeline) self.view.spinBoxRunF.editingFinished.connect(self.setRunFrequency)
self.view.spinBoxDBITF.editingFinished.connect(self.setDBITFrequency) self.view.spinBoxADCF.editingFinished.connect(self.setADCFrequency)
self.view.spinBoxDBITPhase.editingFinished.connect(self.setDBITPhase) self.view.spinBoxADCPhase.editingFinished.connect(self.setADCPhase)
self.view.spinBoxDBITPipeline.editingFinished.connect(self.setDBITPipeline) self.view.spinBoxADCPipeline.editingFinished.connect(self.setADCPipeline)
self.view.spinBoxDBITF.editingFinished.connect(self.setDBITFrequency)
self.view.spinBoxDBITPhase.editingFinished.connect(self.setDBITPhase)
self.view.spinBoxDBITPipeline.editingFinished.connect(self.setDBITPipeline)
self.view.checkBoxFileWriteRaw.stateChanged.connect(self.setFileWrite) self.view.checkBoxFileWriteRaw.stateChanged.connect(self.setFileWrite)
self.view.checkBoxFileWriteNumpy.stateChanged.connect(self.setFileWriteNumpy) self.view.checkBoxFileWriteNumpy.stateChanged.connect(self.setFileWriteNumpy)
@ -77,16 +94,19 @@ class AcquisitionTab(QtWidgets.QWidget):
def refresh(self): def refresh(self):
self.getReadout() self.getReadout()
self.getRunFrequency()
self.getTransceiver() self.getTransceiver()
self.getAnalog() self.getAnalog()
self.getDigital() self.getDigital()
self.getADCFrequency()
self.getADCPhase() if self.det.type == detectorType.CHIPTESTBOARD:
self.getADCPipeline() self.getRunFrequency()
self.getDBITFrequency() self.getADCFrequency()
self.getDBITPhase() self.getADCPhase()
self.getDBITPipeline() self.getADCPipeline()
self.getDBITFrequency()
self.getDBITPhase()
self.getDBITPipeline()
self.getFileWrite() self.getFileWrite()
self.getFileName() self.getFileName()
self.getFilePath() self.getFilePath()
@ -697,23 +717,39 @@ class AcquisitionTab(QtWidgets.QWidget):
self.socket.subscribe("") self.socket.subscribe("")
def saveParameters(self) -> list[str]: def saveParameters(self) -> list[str]:
return [ if self.det.type == detectorType.CHIPTESTBOARD:
f'romode {self.view.comboBoxROMode.currentText().lower()}', return [
f'runclk {self.view.spinBoxRunF.value()}', f'romode {self.view.comboBoxROMode.currentText().lower()}',
f'adcclk {self.view.spinBoxADCF.value()}', f'runclk {self.view.spinBoxRunF.value()}',
f'adcphase {self.view.spinBoxADCPhase.value()}', f'adcclk {self.view.spinBoxADCF.value()}',
f'adcpipeline {self.view.spinBoxADCPipeline.value()}', f'adcphase {self.view.spinBoxADCPhase.value()}',
f'dbitclk {self.view.spinBoxDBITF.value()}', f'adcpipeline {self.view.spinBoxADCPipeline.value()}',
f'dbitphase {self.view.spinBoxDBITPhase.value()}', f'dbitclk {self.view.spinBoxDBITF.value()}',
f'dbitpipeline {self.view.spinBoxDBITPipeline.value()}', f'dbitphase {self.view.spinBoxDBITPhase.value()}',
f'fwrite {int(self.view.checkBoxFileWriteRaw.isChecked())}', f'dbitpipeline {self.view.spinBoxDBITPipeline.value()}',
f'fname {self.view.lineEditFileName.text()}', f'fwrite {int(self.view.checkBoxFileWriteRaw.isChecked())}',
f'fpath {self.view.lineEditFilePath.text()}', f'fname {self.view.lineEditFileName.text()}',
f'findex {self.view.spinBoxAcquisitionIndex.value()}', f'fpath {self.view.lineEditFilePath.text()}',
f'frames {self.view.spinBoxFrames.value()}', f'findex {self.view.spinBoxAcquisitionIndex.value()}',
f'triggers {self.view.spinBoxTriggers.value()}', f'frames {self.view.spinBoxFrames.value()}',
f'period {self.view.spinBoxPeriod.value()} {self.view.comboBoxPeriod.currentText().lower()}', f'triggers {self.view.spinBoxTriggers.value()}',
f'asamples {self.view.spinBoxAnalog.value()}', f'period {self.view.spinBoxPeriod.value()} {self.view.comboBoxPeriod.currentText().lower()}',
f'dsamples {self.view.spinBoxDigital.value()}', f'asamples {self.view.spinBoxAnalog.value()}',
f'tsamples {self.view.spinBoxTransceiver.value()}', f'dsamples {self.view.spinBoxDigital.value()}',
] f'tsamples {self.view.spinBoxTransceiver.value()}',
]
else:
return [
f'romode {self.view.comboBoxROMode.currentText().lower()}',
f'fwrite {int(self.view.checkBoxFileWriteRaw.isChecked())}',
f'fname {self.view.lineEditFileName.text()}',
f'fpath {self.view.lineEditFilePath.text()}',
f'findex {self.view.spinBoxAcquisitionIndex.value()}',
f'frames {self.view.spinBoxFrames.value()}',
f'triggers {self.view.spinBoxTriggers.value()}',
f'period {self.view.spinBoxPeriod.value()} {self.view.comboBoxPeriod.currentText().lower()}',
f'asamples {self.view.spinBoxAnalog.value()}',
f'dsamples {self.view.spinBoxDigital.value()}',
f'tsamples {self.view.spinBoxTransceiver.value()}',
]

View File

@ -4,7 +4,7 @@ from pathlib import Path
from PyQt5 import QtWidgets, uic from PyQt5 import QtWidgets, uic
from pyctbgui.utils.defines import Defines from pyctbgui.utils.defines import Defines
from slsdet import dacIndex from slsdet import dacIndex, detectorType
class DacTab(QtWidgets.QWidget): class DacTab(QtWidgets.QWidget):
@ -19,7 +19,14 @@ class DacTab(QtWidgets.QWidget):
dac = getattr(dacIndex, f"DAC_{i}") dac = getattr(dacIndex, f"DAC_{i}")
getattr(self.view, f"spinBoxDAC{i}").setValue(self.det.getDAC(dac)[0]) getattr(self.view, f"spinBoxDAC{i}").setValue(self.det.getDAC(dac)[0])
if self.det.highvoltage == 0: if self.det.type == detectorType.XILINX_CHIPTESTBOARD:
self.view.checkBoxHighVoltage.setDisabled(True)
self.view.spinBoxHighVoltage.setDisabled(True)
self.view.labelHighVoltage.setDisabled(True)
self.view.labelADCVppDacName.setDisabled(True)
self.view.labelADCVpp.setDisabled(True)
self.view.comboBoxADCVpp.setDisabled(True)
elif self.det.highvoltage == 0:
self.view.spinBoxHighVoltage.setDisabled(True) self.view.spinBoxHighVoltage.setDisabled(True)
self.view.checkBoxHighVoltage.setChecked(False) self.view.checkBoxHighVoltage.setChecked(False)
@ -30,9 +37,11 @@ class DacTab(QtWidgets.QWidget):
getattr(self.view, f"checkBoxDAC{i}").stateChanged.connect(partial(self.setDACTristate, i)) getattr(self.view, f"checkBoxDAC{i}").stateChanged.connect(partial(self.setDACTristate, i))
getattr(self.view, f"checkBoxDAC{i}mV").stateChanged.connect(partial(self.getDAC, i)) getattr(self.view, f"checkBoxDAC{i}mV").stateChanged.connect(partial(self.getDAC, i))
self.view.comboBoxADCVpp.currentIndexChanged.connect(self.setADCVpp) if self.view.comboBoxADCVpp.isEnabled():
self.view.spinBoxHighVoltage.editingFinished.connect(self.setHighVoltage) self.view.comboBoxADCVpp.currentIndexChanged.connect(self.setADCVpp)
self.view.checkBoxHighVoltage.stateChanged.connect(self.setHighVoltage) if self.view.checkBoxHighVoltage.isEnabled():
self.view.spinBoxHighVoltage.editingFinished.connect(self.setHighVoltage)
self.view.checkBoxHighVoltage.stateChanged.connect(self.setHighVoltage)
def refresh(self): def refresh(self):
self.updateDACNames() self.updateDACNames()
@ -40,8 +49,10 @@ class DacTab(QtWidgets.QWidget):
self.getDACTristate(i) self.getDACTristate(i)
self.getDAC(i) self.getDAC(i)
self.getADCVpp() if self.view.comboBoxADCVpp.isEnabled():
self.getHighVoltage() self.getADCVpp()
if self.view.checkBoxHighVoltage.isEnabled():
self.getHighVoltage()
def updateDACNames(self): def updateDACNames(self):
for i, name in enumerate(self.det.getDacNames()): for i, name in enumerate(self.det.getDacNames()):
@ -165,6 +176,8 @@ class DacTab(QtWidgets.QWidget):
unit = " mV" if inMV else "" unit = " mV" if inMV else ""
commands.append(f"dac {i} {value}{unit}") commands.append(f"dac {i} {value}{unit}")
commands.append(f"adcvpp {self.view.comboBoxADCVpp.currentText()} mV") if self.view.comboBoxADCVpp.isEnabled():
commands.append(f"highvoltage {self.view.spinBoxHighVoltage.value()}") commands.append(f"adcvpp {self.view.comboBoxADCVpp.currentText()} mV")
if self.view.checkBoxHighVoltage.isEnabled():
commands.append(f"highvoltage {self.view.spinBoxHighVoltage.value()}")
return commands return commands

View File

@ -4,7 +4,7 @@ from pathlib import Path
from PyQt5 import QtWidgets, uic from PyQt5 import QtWidgets, uic
from pyctbgui.utils.defines import Defines from pyctbgui.utils.defines import Defines
from slsdet import dacIndex from slsdet import dacIndex, detectorType
class PowerSuppliesTab(QtWidgets.QWidget): class PowerSuppliesTab(QtWidgets.QWidget):
@ -18,7 +18,8 @@ class PowerSuppliesTab(QtWidgets.QWidget):
self.updateVoltageNames() self.updateVoltageNames()
for i in Defines.powerSupplies: for i in Defines.powerSupplies:
self.getVoltage(i) self.getVoltage(i)
self.getCurrent(i) if self.det.type == detectorType.CHIPTESTBOARD:
self.getCurrent(i)
def connect_ui(self): def connect_ui(self):
for i in Defines.powerSupplies: for i in Defines.powerSupplies:
@ -38,6 +39,12 @@ class PowerSuppliesTab(QtWidgets.QWidget):
if retval == 0: if retval == 0:
checkBox.setChecked(False) checkBox.setChecked(False)
spinBox.setDisabled(True) spinBox.setDisabled(True)
if self.det.type == detectorType.XILINX_CHIPTESTBOARD:
label = getattr(self.view, f"labelI{i}")
label.setDisabled(True)
if self.det.type == detectorType.XILINX_CHIPTESTBOARD:
self.view.spinBoxVChip.setDisabled(True)
def updateVoltageNames(self): def updateVoltageNames(self):
retval = self.det.getPowerNames() retval = self.det.getPowerNames()
@ -56,7 +63,10 @@ class PowerSuppliesTab(QtWidgets.QWidget):
spinBox.editingFinished.disconnect() spinBox.editingFinished.disconnect()
checkBox.stateChanged.disconnect() checkBox.stateChanged.disconnect()
retval = self.det.getMeasuredPower(voltageIndex)[0] if self.det.type == detectorType.XILINX_CHIPTESTBOARD:
retval = self.det.getPower(voltageIndex)[0]
else:
retval = self.det.getMeasuredPower(voltageIndex)[0]
# spinBox.setValue(retval) # spinBox.setValue(retval)
if retval > 1: if retval > 1:
checkBox.setChecked(True) checkBox.setChecked(True)
@ -68,8 +78,9 @@ class PowerSuppliesTab(QtWidgets.QWidget):
spinBox.editingFinished.connect(partial(self.setVoltage, i)) spinBox.editingFinished.connect(partial(self.setVoltage, i))
checkBox.stateChanged.connect(partial(self.setVoltage, i)) checkBox.stateChanged.connect(partial(self.setVoltage, i))
self.getVChip() if self.det.type == detectorType.CHIPTESTBOARD:
self.getVChip()
# TODO: handle multiple events when pressing enter (twice) # TODO: handle multiple events when pressing enter (twice)
@ -91,7 +102,8 @@ class PowerSuppliesTab(QtWidgets.QWidget):
# TODO: (properly) disconnecting and connecting to handle multiple events (out of focus and pressing enter). # TODO: (properly) disconnecting and connecting to handle multiple events (out of focus and pressing enter).
spinBox.editingFinished.connect(partial(self.setVoltage, i)) spinBox.editingFinished.connect(partial(self.setVoltage, i))
self.getVoltage(i) self.getVoltage(i)
self.getCurrent(i) if self.det.type == detectorType.CHIPTESTBOARD:
self.getCurrent(i)
def getCurrent(self, i): def getCurrent(self, i):
label = getattr(self.view, f"labelI{i}") label = getattr(self.view, f"labelI{i}")

View File

@ -4,7 +4,7 @@ from pathlib import Path
from PyQt5 import uic, QtWidgets from PyQt5 import uic, QtWidgets
from pyctbgui.utils.defines import Defines from pyctbgui.utils.defines import Defines
from slsdet import dacIndex from slsdet import dacIndex, detectorType
class SlowAdcTab(QtWidgets.QWidget): class SlowAdcTab(QtWidgets.QWidget):
@ -17,7 +17,8 @@ class SlowAdcTab(QtWidgets.QWidget):
self.det = None self.det = None
def setup_ui(self): def setup_ui(self):
pass if self.det.type == detectorType.XILINX_CHIPTESTBOARD:
self.view.pushButtonTemp.setDisabled(True)
def connect_ui(self): def connect_ui(self):
for i in range(Defines.slowAdc.count): for i in range(Defines.slowAdc.count):
@ -28,7 +29,8 @@ class SlowAdcTab(QtWidgets.QWidget):
self.updateSlowAdcNames() self.updateSlowAdcNames()
for i in range(Defines.slowAdc.count): for i in range(Defines.slowAdc.count):
self.updateSlowAdc(i) self.updateSlowAdc(i)
self.updateTemperature() if self.det.type == detectorType.CHIPTESTBOARD:
self.updateTemperature()
def updateSlowAdcNames(self): def updateSlowAdcNames(self):
for i, name in enumerate(self.mainWindow.det.getSlowADCNames()): for i, name in enumerate(self.mainWindow.det.getSlowADCNames()):

View File

@ -817,7 +817,7 @@ Only pressing enter on spinbox will set DAC (with this condition).</string>
</widget> </widget>
</item> </item>
<item row="18" column="0"> <item row="18" column="0">
<widget class="QLabel" name="label_125"> <widget class="QLabel" name="labelADCVppDacName">
<property name="text"> <property name="text">
<string>ADC_VPP</string> <string>ADC_VPP</string>
</property> </property>

View File

@ -118,7 +118,7 @@
</widget> </widget>
</item> </item>
<item row="1" column="4"> <item row="1" column="4">
<widget class="QLabel" name="label_70"> <widget class="QLabel" name="labelRunF">
<property name="text"> <property name="text">
<string>Run Clock Frequency (MHz):</string> <string>Run Clock Frequency (MHz):</string>
</property> </property>
@ -218,7 +218,7 @@
</property> </property>
<layout class="QGridLayout" name="gridLayout_6"> <layout class="QGridLayout" name="gridLayout_6">
<item row="2" column="3"> <item row="2" column="3">
<widget class="QLabel" name="label_74"> <widget class="QLabel" name="labelDBITF">
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>200</width> <width>200</width>
@ -231,7 +231,7 @@
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="2" column="0">
<widget class="QLabel" name="label_71"> <widget class="QLabel" name="labelADCF">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred"> <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch> <horstretch>0</horstretch>
@ -278,7 +278,7 @@
</widget> </widget>
</item> </item>
<item row="4" column="3"> <item row="4" column="3">
<widget class="QLabel" name="label_76"> <widget class="QLabel" name="labelDBITPipeline">
<property name="text"> <property name="text">
<string>DBIT Pipeline:</string> <string>DBIT Pipeline:</string>
</property> </property>
@ -338,21 +338,21 @@
</widget> </widget>
</item> </item>
<item row="4" column="0"> <item row="4" column="0">
<widget class="QLabel" name="label_73"> <widget class="QLabel" name="labelADCPipeline">
<property name="text"> <property name="text">
<string>ADC Pipeline:</string> <string>ADC Pipeline:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0"> <item row="3" column="0">
<widget class="QLabel" name="label_72"> <widget class="QLabel" name="labelADCPhase">
<property name="text"> <property name="text">
<string>ADC Clock Phase (a.u.):</string> <string>ADC Clock Phase (a.u.):</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="3"> <item row="3" column="3">
<widget class="QLabel" name="label_75"> <widget class="QLabel" name="labelDBITPhase">
<property name="text"> <property name="text">
<string>DBIT Clock Phase (a.u.):</string> <string>DBIT Clock Phase (a.u.):</string>
</property> </property>

View File

@ -19,7 +19,7 @@
<property name="windowTitle"> <property name="windowTitle">
<string>Form</string> <string>Form</string>
</property> </property>
<widget class="QFrame" name="frame_7"> <widget class="QFrame" name="frame_ADC">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@ -3142,7 +3142,7 @@
</property> </property>
<layout class="QGridLayout" name="gridLayout_20"> <layout class="QGridLayout" name="gridLayout_20">
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label_67"> <widget class="QLabel" name="labelADCInversion">
<property name="font"> <property name="font">
<font> <font>
<pointsize>10</pointsize> <pointsize>10</pointsize>
@ -3188,7 +3188,7 @@
</widget> </widget>
</item> </item>
<item row="0" column="3"> <item row="0" column="3">
<widget class="QLabel" name="label_68"> <widget class="QLabel" name="labelADCEnable">
<property name="font"> <property name="font">
<font> <font>
<pointsize>10</pointsize> <pointsize>10</pointsize>

View File

@ -19,7 +19,7 @@
<property name="windowTitle"> <property name="windowTitle">
<string>Form</string> <string>Form</string>
</property> </property>
<widget class="QFrame" name="frame_4"> <widget class="QFrame" name="frame_slowadcs">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>

View File

@ -0,0 +1,19 @@
# SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package
# Script to get combined zmq packets from frame synchronizer using pull zmq sockets
import json
import zmq
c = zmq.Context()
s = c.socket(zmq.PULL)
s.connect("tcp://127.0.0.1:5555")
while True:
m = s.recv_multipart()
for p in m:
if p.startswith(b"{"):
print(p.decode().strip())
else:
print("binary")
print("--------")

View File

@ -123,6 +123,9 @@ def visit(node):
if node.kind == cindex.CursorKind.CLASS_DECL: if node.kind == cindex.CursorKind.CLASS_DECL:
if node.displayname == "Detector": if node.displayname == "Detector":
for child in node.get_children(): for child in node.get_children():
# Skip assignment operators
if child.kind == cindex.CursorKind.CXX_METHOD and child.spelling == "operator=":
continue
if ( if (
child.kind == cindex.CursorKind.CXX_METHOD child.kind == cindex.CursorKind.CXX_METHOD
and child.access_specifier == cindex.AccessSpecifier.PUBLIC and child.access_specifier == cindex.AccessSpecifier.PUBLIC

View File

@ -151,6 +151,10 @@ class Detector(CppDetectorApi):
def hostname(self): def hostname(self):
"""Frees shared memory and sets hostname (or IP address) of all modules concatenated by + """Frees shared memory and sets hostname (or IP address) of all modules concatenated by +
Virtual servers can already use the port in hostname separated by ':' and ports incremented by 2 to accomodate the stop server as well. Virtual servers can already use the port in hostname separated by ':' and ports incremented by 2 to accomodate the stop server as well.
Note
-----
The row and column values in the udp/zmq header are affected by the order in this command and the detsize command. The modules are stacked row by row until they reach the y-axis limit set by detsize (if specified). Then, stacking continues in the next column and so on. This only affects row and column in udp/zmq header.
Example Example
------- -------
@ -2566,7 +2570,7 @@ class Detector(CppDetectorApi):
Note Note
----- -----
By default, the on-chip gain switching is active during the entire exposure. This mode disables the on-chip gain switching comparator automatically after 93.75% of exposure time (only for longer than 100us). The % is only for chipv1.0, the duration can be set for chipv1.1.\n By default, the on-chip gain switching is active during the entire exposure. This mode disables the on-chip gain switching comparator automatically and the duration is set using compdisabletime.\n
Default is 0 or this mode disabled (comparator enabled throughout). 1 enables mode. 0 disables mode. Default is 0 or this mode disabled (comparator enabled throughout). 1 enables mode. 0 disables mode.
""" """
return self.getAutoComparatorDisable() return self.getAutoComparatorDisable()
@ -2580,10 +2584,6 @@ class Detector(CppDetectorApi):
def compdisabletime(self): def compdisabletime(self):
"""[Jungfrau] Time before end of exposure when comparator is disabled. """[Jungfrau] Time before end of exposure when comparator is disabled.
Note
-----
It is only possible for chipv1.1.
:getter: always returns in seconds. To get in DurationWrapper, use getComparatorDisableTime :getter: always returns in seconds. To get in DurationWrapper, use getComparatorDisableTime
Example Example
@ -2913,7 +2913,7 @@ class Detector(CppDetectorApi):
@property @property
@element @element
def timing_info_decoder(self): def timing_info_decoder(self):
"""[Jungfrau] [Jungfrau] Advanced Command and only for SWISSFEL and SHINE. Sets the bunch id or timing info decoder. Default is SWISSFEL. """[Jungfrau] [Jungfrau] Advanced Command and only for SWISSFEL and SHINE. Sets the bunch id or timing info decoder. Default is SWISSFEL. Only allowed for pcbv2.0.
Enum: timingInfoDecoder Enum: timingInfoDecoder
""" """
return self.getTimingInfoDecoder() return self.getTimingInfoDecoder()

View File

@ -1 +0,0 @@
../slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServerv9.0.0

View File

@ -0,0 +1 @@
../slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServerv9.1.0

View File

@ -1 +0,0 @@
../slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServerv9.0.0

View File

@ -0,0 +1 @@
../slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServerv9.1.0

View File

@ -1 +0,0 @@
../slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServerv9.0.0

View File

@ -0,0 +1 @@
../slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServerv9.1.0

View File

@ -1 +0,0 @@
../slsDetectorServers/xilinx_ctbDetectorServer/bin/xilinx_ctbDetectorServerv9.0.0

View File

@ -0,0 +1 @@
../slsDetectorServers/xilinx_ctbDetectorServer/bin/xilinx_ctbDetectorServerv9.1.0

View File

@ -503,6 +503,7 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
} }
#endif #endif
if (ee == PHOTON && val[iy * nx + ix] == max) { if (ee == PHOTON && val[iy * nx + ix] == max) {
good = 1;
ee = PHOTON_MAX; ee = PHOTON_MAX;
// cout << "**" <<id<< " " << iframe << " " << nDark << " " // cout << "**" <<id<< " " << iframe << " " << nDark << " "
// << ix << " " << iy << " " << rms << " " << max << " " << // << ix << " " << iy << " " << rms << " " << max << " " <<
@ -536,7 +537,6 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
cout << max << " " << val[iy * nx + ix] << endl; cout << max << " " << val[iy * nx + ix] << endl;
} }
//else (clusters + nph)->print(); //else (clusters + nph)->print();
good = 1;
if (eMin > 0 && tot < eMin) if (eMin > 0 && tot < eMin)
good = 0; good = 0;
if (eMax > 0 && tot > eMax) if (eMax > 0 && tot > eMax)

View File

@ -61,7 +61,9 @@ class qDefs : public QWidget {
} }
} }
template <class CT> struct NonDeduced { using type = CT; }; template <class CT> struct NonDeduced {
using type = CT;
};
template <class S, typename RT, typename... CT> template <class S, typename RT, typename... CT>
static void HandleExceptions(const std::string emsg, const std::string src, static void HandleExceptions(const std::string emsg, const std::string src,
S *s, RT (S::*somefunc)(CT...), S *s, RT (S::*somefunc)(CT...),

View File

@ -17,7 +17,7 @@
#define BUFFERSIZE 16 #define BUFFERSIZE 16
#define I2C_DEVICE_FILE "/dev/i2c-0" #define I2C_DEVICE_FILE "/dev/i2c-0"
#define I2C_DEVICE_ADDRESS 0x4C #define I2C_DEVICE_ADDRESS 0x4C
//#define I2C_DEVICE_ADDRESS 0x48 // #define I2C_DEVICE_ADDRESS 0x48
#define I2C_REGISTER_ADDRESS 0x40 #define I2C_REGISTER_ADDRESS 0x40
int i2c_open(const char *file, unsigned int addr) { int i2c_open(const char *file, unsigned int addr) {

View File

@ -98,8 +98,8 @@
// everything at ~200 kHz (200 kHz MHz ddr readout) // everything at ~200 kHz (200 kHz MHz ddr readout)
#define DAQ_CHIP_CONTROLLER_SUPER_SLOW_SPEED 0x000c0000 #define DAQ_CHIP_CONTROLLER_SUPER_SLOW_SPEED 0x000c0000
//#define DAQ_FIFO_ENABLE 0x00100000 commented out as it // #define DAQ_FIFO_ENABLE 0x00100000 commented out as it
// is not used anywhere // is not used anywhere
#define DAQ_REG_CHIP_CMDS_INT_TRIGGER 0x00100000 #define DAQ_REG_CHIP_CMDS_INT_TRIGGER 0x00100000
// direct chip commands to the DAQ_REG_CHIP_CMDS register // direct chip commands to the DAQ_REG_CHIP_CMDS register
@ -131,8 +131,9 @@
#define DAQ_NEXPOSURERS_ACTIVATE_AUTO_SUBIMAGING 0x20000000 #define DAQ_NEXPOSURERS_ACTIVATE_AUTO_SUBIMAGING 0x20000000
#define DAQ_NEXPOSURERS_ACTIVATE_RATE_CORRECTION 0x40000000 #define DAQ_NEXPOSURERS_ACTIVATE_RATE_CORRECTION 0x40000000
//#define DAQ_MASTER_HALF_MODULE 0x80000000 currently not // #define DAQ_MASTER_HALF_MODULE 0x80000000 currently
// used // not
// used
// chips static bits // chips static bits
#define DAQ_STATIC_BIT_PROGRAM 0x00000001 #define DAQ_STATIC_BIT_PROGRAM 0x00000001

View File

@ -2,7 +2,7 @@
// Copyright (C) 2021 Contributors to the SLS Detector Package // Copyright (C) 2021 Contributors to the SLS Detector Package
#pragma once #pragma once
//#include "types.h" // #include "types.h"
#include <stdint.h> #include <stdint.h>
/******************************************************************************/ /******************************************************************************/
/* types */ /* types */

View File

@ -92,7 +92,7 @@ XPAR_PLB_LL_FIFO_AURORA_DUAL_CTRL_FEB_LEFT_BASEADDR
#define XPAR_PLB_LL_FIFO_AURORA_DUAL_CTRL_FEB_LEFT_HIGHADDR 0xC410FFFF #define XPAR_PLB_LL_FIFO_AURORA_DUAL_CTRL_FEB_LEFT_HIGHADDR 0xC410FFFF
/* Definitions for a new memory */ /* Definitions for a new memory */
//#define XPAR_PLB_LL_NEW_MEMORY 0xD1000000//0xD1000084//0xC4200000 // #define XPAR_PLB_LL_NEW_MEMORY 0xD1000000//0xD1000084//0xC4200000
/* Definitions for peripheral PLB_LL_FIFO_AURORA_DUAL_CTRL_FEB_RIGHT */ /* Definitions for peripheral PLB_LL_FIFO_AURORA_DUAL_CTRL_FEB_RIGHT */
#define XPAR_PLB_LL_FIFO_AURORA_DUAL_CTRL_FEB_RIGHT_BASEADDR 0xC4110000 #define XPAR_PLB_LL_FIFO_AURORA_DUAL_CTRL_FEB_RIGHT_BASEADDR 0xC4110000

View File

@ -22,13 +22,13 @@
((0x1 << GAIN_CONFGAIN_OFST) & GAIN_CONFGAIN_MSK) ((0x1 << GAIN_CONFGAIN_OFST) & GAIN_CONFGAIN_MSK)
/** Flow Control register */ /** Flow Control register */
//#define FLOW_CONTROL_REG (0x11 << MEM_MAP_SHIFT) // #define FLOW_CONTROL_REG (0x11 << MEM_MAP_SHIFT)
/** Flow Status register */ /** Flow Status register */
//#define FLOW_STATUS_REG (0x12 << MEM_MAP_SHIFT) // #define FLOW_STATUS_REG (0x12 << MEM_MAP_SHIFT)
/** Frame register */ /** Frame register */
//#define FRAME_REG (0x13 << MEM_MAP_SHIFT) // #define FRAME_REG (0x13 << MEM_MAP_SHIFT)
/** Multi Purpose register */ /** Multi Purpose register */
#define MULTI_PURPOSE_REG (0x14 << MEM_MAP_SHIFT) #define MULTI_PURPOSE_REG (0x14 << MEM_MAP_SHIFT)
@ -79,7 +79,7 @@
((0x0007f << DAQ_PCKT_LNGTH_OFST) & DAQ_PCKT_LNGTH_MSK) ((0x0007f << DAQ_PCKT_LNGTH_OFST) & DAQ_PCKT_LNGTH_MSK)
/** Time From Start register */ /** Time From Start register */
//#define TIME_FROM_START_REG (0x16 << MEM_MAP_SHIFT) // #define TIME_FROM_START_REG (0x16 << MEM_MAP_SHIFT)
/** DAC Control register */ /** DAC Control register */
#define SPI_REG (0x17 << MEM_MAP_SHIFT) #define SPI_REG (0x17 << MEM_MAP_SHIFT)
@ -139,7 +139,7 @@
((0x1b << ADC_SYNC_ENET_DELAY_OFST) & ADC_SYNC_ENET_DELAY_MSK) ((0x1b << ADC_SYNC_ENET_DELAY_OFST) & ADC_SYNC_ENET_DELAY_MSK)
/** Time From Start register */ /** Time From Start register */
//#define MU_TIME_REG (0x1a << MEM_MAP_SHIFT) // #define MU_TIME_REG (0x1a << MEM_MAP_SHIFT)
/** Temperatre SPI In register */ /** Temperatre SPI In register */
#define TEMP_SPI_IN_REG (0x1b << MEM_MAP_SHIFT) #define TEMP_SPI_IN_REG (0x1b << MEM_MAP_SHIFT)
@ -171,7 +171,7 @@
#define ENET_CONF_REG (0x1e << MEM_MAP_SHIFT) #define ENET_CONF_REG (0x1e << MEM_MAP_SHIFT)
/** Write TSE Shadow register */ /** Write TSE Shadow register */
//#define WRITE_TSE_SHADOW_REG (0x1f << MEM_MAP_SHIFT) // #define WRITE_TSE_SHADOW_REG (0x1f << MEM_MAP_SHIFT)
/** High Voltage register */ /** High Voltage register */
#define HV_REG (0x20 << MEM_MAP_SHIFT) #define HV_REG (0x20 << MEM_MAP_SHIFT)
@ -288,10 +288,10 @@
((0x4 << EXT_SIGNAL_OFST) & EXT_SIGNAL_MSK) ((0x4 << EXT_SIGNAL_OFST) & EXT_SIGNAL_MSK)
/** Look at me register */ /** Look at me register */
//#define LOOK_AT_ME_REG (0x28 << MEM_MAP_SHIFT) // #define LOOK_AT_ME_REG (0x28 << MEM_MAP_SHIFT)
/** FPGA SVN register */ /** FPGA SVN register */
//#define FPGA_SVN_REG (0x29 << MEM_MAP_SHIFT) // #define FPGA_SVN_REG (0x29 << MEM_MAP_SHIFT)
/** Chip of Interest register */ /** Chip of Interest register */
#define CHIP_OF_INTRST_REG (0x2a << MEM_MAP_SHIFT) #define CHIP_OF_INTRST_REG (0x2a << MEM_MAP_SHIFT)
@ -303,7 +303,7 @@
(0x0000FFFF << CHIP_OF_INTRST_NUM_CHNNLS_OFST) (0x0000FFFF << CHIP_OF_INTRST_NUM_CHNNLS_OFST)
/** Out MUX register */ /** Out MUX register */
//#define OUT_MUX_REG (0x2b << MEM_MAP_SHIFT) // #define OUT_MUX_REG (0x2b << MEM_MAP_SHIFT)
/** Board Version register */ /** Board Version register */
#define BOARD_REVISION_REG (0x2c << MEM_MAP_SHIFT) #define BOARD_REVISION_REG (0x2c << MEM_MAP_SHIFT)
@ -312,29 +312,29 @@
#define BOARD_REVISION_MSK (0x0000FFFF << BOARD_REVISION_OFST) #define BOARD_REVISION_MSK (0x0000FFFF << BOARD_REVISION_OFST)
#define DETECTOR_TYPE_OFST (16) #define DETECTOR_TYPE_OFST (16)
#define DETECTOR_TYPE_MSK (0x0000000F << DETECTOR_TYPE_OFST) #define DETECTOR_TYPE_MSK (0x0000000F << DETECTOR_TYPE_OFST)
//#define DETECTOR_TYPE_GOTTHARD_VAL (??) // #define DETECTOR_TYPE_GOTTHARD_VAL (??)
#define DETECTOR_TYPE_MOENCH_VAL (2) #define DETECTOR_TYPE_MOENCH_VAL (2)
/** Memory Test register */ /** Memory Test register */
//#define MEMORY_TEST_REG (0x2d << MEM_MAP_SHIFT) // #define MEMORY_TEST_REG (0x2d << MEM_MAP_SHIFT)
/** Hit Threshold register */ /** Hit Threshold register */
//#define HIT_THRESHOLD_REG (0x2e << MEM_MAP_SHIFT) // #define HIT_THRESHOLD_REG (0x2e << MEM_MAP_SHIFT)
/** Hit Count register */ /** Hit Count register */
//#define HIT_COUNT_REG (0x2f << MEM_MAP_SHIFT) // #define HIT_COUNT_REG (0x2f << MEM_MAP_SHIFT)
/* 16 bit Fifo Data register */ /* 16 bit Fifo Data register */
#define FIFO_DATA_REG (0x50 << MEM_MAP_SHIFT) // Not used in FW and SW (16bit) #define FIFO_DATA_REG (0x50 << MEM_MAP_SHIFT) // Not used in FW and SW (16bit)
/** Dacs Set 1 register */ /** Dacs Set 1 register */
//#define DACS_SET_1_REG (0x65 << MEM_MAP_SHIFT) // #define DACS_SET_1_REG (0x65 << MEM_MAP_SHIFT)
/** Dacs Set 2 register */ /** Dacs Set 2 register */
//#define DACS_SET_2_REG (0x66 << MEM_MAP_SHIFT) // #define DACS_SET_2_REG (0x66 << MEM_MAP_SHIFT)
/** Dacs Set 3 register */ /** Dacs Set 3 register */
//#define DACS_SET_3_REG (0x67 << MEM_MAP_SHIFT) // #define DACS_SET_3_REG (0x67 << MEM_MAP_SHIFT)
/* Set Delay 64 bit register */ /* Set Delay 64 bit register */
#define SET_DELAY_LSB_REG (0x68 << MEM_MAP_SHIFT) #define SET_DELAY_LSB_REG (0x68 << MEM_MAP_SHIFT)
@ -377,12 +377,12 @@
#define GET_EXPTIME_MSB_REG (0x7b << MEM_MAP_SHIFT) #define GET_EXPTIME_MSB_REG (0x7b << MEM_MAP_SHIFT)
/* Set Gates 64 bit register */ /* Set Gates 64 bit register */
//#define SET_GATES_LSB_REG (0x7c << MEM_MAP_SHIFT) // #define SET_GATES_LSB_REG (0x7c << MEM_MAP_SHIFT)
//#define SET_GATES_MSB_REG (0x7d << MEM_MAP_SHIFT) // #define SET_GATES_MSB_REG (0x7d << MEM_MAP_SHIFT)
/* Set Gates 64 bit register */ /* Set Gates 64 bit register */
//#define GET_GATES_LSB_REG (0x7e << MEM_MAP_SHIFT) // #define GET_GATES_LSB_REG (0x7e << MEM_MAP_SHIFT)
//#define GET_GATES_MSB_REG (0x7f << MEM_MAP_SHIFT) // #define GET_GATES_MSB_REG (0x7f << MEM_MAP_SHIFT)
/* Dark Image starting address */ /* Dark Image starting address */
#define DARK_IMAGE_REG (0x81 << MEM_MAP_SHIFT) #define DARK_IMAGE_REG (0x81 << MEM_MAP_SHIFT)

View File

@ -1974,9 +1974,6 @@ int autoCompDisable(int on) {
} }
int setComparatorDisableTime(int64_t val) { int setComparatorDisableTime(int64_t val) {
if (getChipVersion() != 11) {
return FAIL;
}
if (val < 0) { if (val < 0) {
LOG(logERROR, LOG(logERROR,
("Invalid comp disable time: %lld ns\n", (long long int)val)); ("Invalid comp disable time: %lld ns\n", (long long int)val));
@ -2817,7 +2814,8 @@ void *start_timer(void *arg) {
getNextFrameNumber(&frameNr); getNextFrameNumber(&frameNr);
int iRxEntry = firstDest; int iRxEntry = firstDest;
for (int iframes = 0; iframes != numFrames; ++iframes) { for (int iframes = 0; iframes != numFrames; ++iframes) {
usleep(transmissionDelayUs); if (transmissionDelayUs)
usleep(transmissionDelayUs);
// check if manual stop // check if manual stop
if (sharedMemory_getStop() == 1) { if (sharedMemory_getStop() == 1) {

View File

@ -5,8 +5,8 @@
#include "sls/sls_detector_defs.h" #include "sls/sls_detector_defs.h"
#define MIN_REQRD_VRSN_T_RD_API 0x171220 #define MIN_REQRD_VRSN_T_RD_API 0x171220
#define REQRD_FRMWRE_VRSN_BOARD2 0x230920 // 1.0 pcb (version = 010) #define REQRD_FRMWRE_VRSN_BOARD2 0x250209 // 1.0 pcb (version = 010)
#define REQRD_FRMWRE_VRSN 0x230921 // 2.0 pcb (version = 011) #define REQRD_FRMWRE_VRSN 0x250208 // 2.0 pcb (version = 011)
#define NUM_HARDWARE_VERSIONS (2) #define NUM_HARDWARE_VERSIONS (2)
#define HARDWARE_VERSION_NUMBERS \ #define HARDWARE_VERSION_NUMBERS \

View File

@ -1927,7 +1927,8 @@ void *start_timer(void *arg) {
getNextFrameNumber(&frameNr); getNextFrameNumber(&frameNr);
int iRxEntry = firstDest; int iRxEntry = firstDest;
for (int iframes = 0; iframes != numFrames; ++iframes) { for (int iframes = 0; iframes != numFrames; ++iframes) {
usleep(transmissionDelayUs); if (transmissionDelayUs)
usleep(transmissionDelayUs);
// check if manual stop // check if manual stop
if (sharedMemory_getStop() == 1) { if (sharedMemory_getStop() == 1) {

View File

@ -39,8 +39,8 @@ patternParameters *setChipStatusRegisterPattern(int csr) {
patword = clearBit(SIGNAL_resCounter, patword); patword = clearBit(SIGNAL_resCounter, patword);
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
pat->word[iaddr++] = patword; pat->word[iaddr++] = patword;
//#This version of the serializer pushes in the MSB first (compatible with // #This version of the serializer pushes in the MSB first (compatible with
// the CSR bit numbering) // the CSR bit numbering)
for (int ib = nbits - 1; ib >= 0; ib--) { for (int ib = nbits - 1; ib >= 0; ib--) {
if (csr & (1 << ib)) if (csr & (1 << ib))
patword = setBit(SIGNAL_serialIN, patword); patword = setBit(SIGNAL_serialIN, patword);

View File

@ -38,11 +38,11 @@
#define CSR_invpol 4 #define CSR_invpol 4
#define CSR_dpulse 5 #define CSR_dpulse 5
#define CSR_interp 6 #define CSR_interp 6
#define _CSR_C10pre 7 //#default, negative polarity #define _CSR_C10pre 7 // #default, negative polarity
#define CSR_pumprobe 8 #define CSR_pumprobe 8
#define CSR_apulse 9 #define CSR_apulse 9
#define CSR_C15sh 10 #define CSR_C15sh 10
#define CSR_C30sh 11 //#default #define CSR_C30sh 11 // #default
#define CSR_C50sh 12 #define CSR_C50sh 12
#define CSR_C225ACsh \ #define CSR_C225ACsh \
13 // Connects 225fF SHAPER AC cap (1: 225 to shaper, 225 to GND. 0: 450 to 13 // Connects 225fF SHAPER AC cap (1: 225 to shaper, 225 to GND. 0: 450 to

View File

@ -50,7 +50,7 @@
#define DEFAULT_NUM_CYCLES (1) #define DEFAULT_NUM_CYCLES (1)
#define DEFAULT_GATE_WIDTH (100 * 1000 * 1000) // ns #define DEFAULT_GATE_WIDTH (100 * 1000 * 1000) // ns
#define DEFAULT_GATE_DELAY (0) #define DEFAULT_GATE_DELAY (0)
#define DEFAULT_PERIOD (2 * 1000 * 1000) // ns #define DEFAULT_PERIOD (0) // ns
#define DEFAULT_DELAY_AFTER_TRIGGER (0) #define DEFAULT_DELAY_AFTER_TRIGGER (0)
#define DEFAULT_HIGH_VOLTAGE (0) #define DEFAULT_HIGH_VOLTAGE (0)
#define DEFAULT_TIMING_MODE (AUTO_TIMING) #define DEFAULT_TIMING_MODE (AUTO_TIMING)

View File

@ -106,9 +106,9 @@
(0x0000FFFF << I2C_SDA_HOLD_COUNT_PERIOD_OFST) (0x0000FFFF << I2C_SDA_HOLD_COUNT_PERIOD_OFST)
/** Receive Data Fifo Level register */ /** Receive Data Fifo Level register */
//#define I2C_RX_DATA_FIFO_LVL_OFST (0) // #define I2C_RX_DATA_FIFO_LVL_OFST (0)
//#define I2C_RX_DATA_FIFO_LVL_MSK (0x000000FF << // #define I2C_RX_DATA_FIFO_LVL_MSK (0x000000FF <<
// I2C_RX_DATA_FIFO_LVL_OFST) // I2C_RX_DATA_FIFO_LVL_OFST)
// defines in the fpga // defines in the fpga
uint32_t I2C_Control_Reg = 0x0; uint32_t I2C_Control_Reg = 0x0;

View File

@ -622,7 +622,7 @@ void getIpAddressinString(char *cip, uint32_t ip) {
inet_ntop(AF_INET, &ip, cip, INET_ADDRSTRLEN); inet_ntop(AF_INET, &ip, cip, INET_ADDRSTRLEN);
#else #else
sprintf(cip, "%d.%d.%d.%d", (ip >> 24) & 0xff, (ip >> 16) & 0xff, sprintf(cip, "%d.%d.%d.%d", (ip >> 24) & 0xff, (ip >> 16) & 0xff,
(ip >> 8) & 0xff, (ip)&0xff); (ip >> 8) & 0xff, (ip) & 0xff);
#endif #endif
} }

View File

@ -2013,102 +2013,106 @@ int acquire(int blocking, int file_des) {
#if defined(JUNGFRAUD) #if defined(JUNGFRAUD)
// chipv1.1 has to be configured before acquisition // chipv1.1 has to be configured before acquisition
if (getChipVersion() == 11 && !isChipConfigured()) { if (getChipVersion() == 11 && !isChipConfigured()) {
ret = FAIL; ret = FAIL;
strcpy(mess, "Could not start acquisition. Chip is not configured. " strcpy(mess,
"Power it on to configure it.\n"); "Could not start acquisition. Chip is not configured. "
LOG(logERROR, (mess)); "Power it on to configure it.\n");
} else LOG(logERROR, (mess));
} else
#endif #endif
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD) #if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
if ((getReadoutMode() == ANALOG_AND_DIGITAL || if ((getReadoutMode() == ANALOG_AND_DIGITAL ||
getReadoutMode() == ANALOG_ONLY) && getReadoutMode() == ANALOG_ONLY) &&
(getNumAnalogSamples() <= 0)) { (getNumAnalogSamples() <= 0)) {
ret = FAIL; ret = FAIL;
sprintf(mess, sprintf(mess,
"Could not start acquisition. Invalid number of analog " "Could not start acquisition. Invalid number of analog "
"samples: %d.\n", "samples: %d.\n",
getNumAnalogSamples()); getNumAnalogSamples());
LOG(logERROR, (mess)); LOG(logERROR, (mess));
} else if ((getReadoutMode() == ANALOG_AND_DIGITAL || } else if ((getReadoutMode() == ANALOG_AND_DIGITAL ||
getReadoutMode() == DIGITAL_ONLY || getReadoutMode() == DIGITAL_ONLY ||
getReadoutMode() == DIGITAL_AND_TRANSCEIVER) && getReadoutMode() == DIGITAL_AND_TRANSCEIVER) &&
(getNumDigitalSamples() <= 0)) { (getNumDigitalSamples() <= 0)) {
ret = FAIL; ret = FAIL;
sprintf(mess, sprintf(
mess,
"Could not start acquisition. Invalid number of digital " "Could not start acquisition. Invalid number of digital "
"samples: %d.\n", "samples: %d.\n",
getNumDigitalSamples()); getNumDigitalSamples());
LOG(logERROR, (mess)); LOG(logERROR, (mess));
} else if ((getReadoutMode() == TRANSCEIVER_ONLY || } else if ((getReadoutMode() == TRANSCEIVER_ONLY ||
getReadoutMode() == DIGITAL_AND_TRANSCEIVER) && getReadoutMode() == DIGITAL_AND_TRANSCEIVER) &&
(getNumTransceiverSamples() <= 0)) { (getNumTransceiverSamples() <= 0)) {
ret = FAIL; ret = FAIL;
sprintf(mess, sprintf(mess,
"Could not start acquisition. Invalid number of " "Could not start acquisition. Invalid number of "
"transceiver " "transceiver "
"samples: %d.\n", "samples: %d.\n",
getNumTransceiverSamples()); getNumTransceiverSamples());
LOG(logERROR, (mess)); LOG(logERROR, (mess));
} else } else
#endif #endif
#ifdef EIGERD #ifdef EIGERD
// check for hardware mac and hardware ip // check for hardware mac and hardware ip
if (udpDetails[0].srcmac != getDetectorMAC()) { if (udpDetails[0].srcmac != getDetectorMAC()) {
ret = FAIL; ret = FAIL;
uint64_t sourcemac = getDetectorMAC(); uint64_t sourcemac = getDetectorMAC();
char src_mac[MAC_ADDRESS_SIZE]; char src_mac[MAC_ADDRESS_SIZE];
getMacAddressinString(src_mac, MAC_ADDRESS_SIZE, sourcemac); getMacAddressinString(src_mac, MAC_ADDRESS_SIZE, sourcemac);
sprintf(mess, sprintf(mess,
"Invalid udp source mac address for this detector. " "Invalid udp source mac address for this detector. "
"Must be " "Must be "
"same as hardware detector mac address %s\n", "same as hardware detector mac address %s\n",
src_mac); src_mac);
LOG(logERROR, (mess)); LOG(logERROR, (mess));
} else if (!enableTenGigabitEthernet(GET_FLAG) && } else if (!enableTenGigabitEthernet(GET_FLAG) &&
(udpDetails[0].srcip != getDetectorIP())) { (udpDetails[0].srcip != getDetectorIP())) {
ret = FAIL; ret = FAIL;
uint32_t sourceip = getDetectorIP(); uint32_t sourceip = getDetectorIP();
char src_ip[INET_ADDRSTRLEN]; char src_ip[INET_ADDRSTRLEN];
getIpAddressinString(src_ip, sourceip); getIpAddressinString(src_ip, sourceip);
sprintf(mess, sprintf(
"Invalid udp source ip address for this detector. Must " mess,
"be " "Invalid udp source ip address for this detector. Must "
"same as hardware detector ip address %s in 1G readout " "be "
"mode \n", "same as hardware detector ip address %s in 1G readout "
src_ip); "mode \n",
LOG(logERROR, (mess)); src_ip);
} else LOG(logERROR, (mess));
#endif
if (configured == FAIL) {
ret = FAIL;
strcpy(mess, "Could not start acquisition because ");
strcat(mess, configureMessage);
LOG(logERROR, (mess));
} else if (sharedMemory_getScanStatus() == RUNNING) {
ret = FAIL;
strcpy(mess, "Could not start acquisition because a scan is "
"already running!\n");
LOG(logERROR, (mess));
} else {
memset(scanErrMessage, 0, MAX_STR_LENGTH);
sharedMemory_setScanStop(0);
sharedMemory_setScanStatus(IDLE); // if it was error
if (pthread_create(&pthread_tid, NULL, &start_state_machine,
&blocking)) {
ret = FAIL;
strcpy(mess, "Could not start acquisition thread!\n");
LOG(logERROR, (mess));
} else {
// wait for blocking always (scan or not)
// non blocking-no scan also wait (for error message)
// non blcoking-scan dont wait (there is
// scanErrorMessage)
if (blocking || !scan) {
pthread_join(pthread_tid, NULL);
} else } else
pthread_detach(pthread_tid); #endif
} if (configured == FAIL) {
} ret = FAIL;
strcpy(mess, "Could not start acquisition because ");
strcat(mess, configureMessage);
LOG(logERROR, (mess));
} else if (sharedMemory_getScanStatus() == RUNNING) {
ret = FAIL;
strcpy(mess,
"Could not start acquisition because a scan is "
"already running!\n");
LOG(logERROR, (mess));
} else {
memset(scanErrMessage, 0, MAX_STR_LENGTH);
sharedMemory_setScanStop(0);
sharedMemory_setScanStatus(IDLE); // if it was error
if (pthread_create(&pthread_tid, NULL, &start_state_machine,
&blocking)) {
ret = FAIL;
strcpy(mess, "Could not start acquisition thread!\n");
LOG(logERROR, (mess));
} else {
// wait for blocking always (scan or not)
// non blocking-no scan also wait (for error message)
// non blcoking-scan dont wait (there is
// scanErrorMessage)
if (blocking || !scan) {
pthread_join(pthread_tid, NULL);
} else
pthread_detach(pthread_tid);
}
}
} }
return Server_SendResult(file_des, INT32, NULL, 0); return Server_SendResult(file_des, INT32, NULL, 0);
} }
@ -9086,16 +9090,9 @@ int get_comp_disable_time(int file_des) {
functionNotImplemented(); functionNotImplemented();
#else #else
// get only // get only
if (getChipVersion() != 11) { retval = getComparatorDisableTime();
ret = FAIL; LOG(logDEBUG1,
strcpy(mess, ("retval comp disable time %lld ns\n", (long long int)retval));
"Cannot get comparator disable time. Only valid for chipv1.1\n");
LOG(logERROR, (mess));
} else {
retval = getComparatorDisableTime();
LOG(logDEBUG1,
("retval comp disable time %lld ns\n", (long long int)retval));
}
#endif #endif
return Server_SendResult(file_des, INT64, &retval, sizeof(retval)); return Server_SendResult(file_des, INT64, &retval, sizeof(retval));
} }
@ -9113,23 +9110,16 @@ int set_comp_disable_time(int file_des) {
#else #else
// only set // only set
if (Server_VerifyLock() == OK) { if (Server_VerifyLock() == OK) {
if (getChipVersion() != 11) { ret = setComparatorDisableTime(arg);
ret = FAIL; int64_t retval = getComparatorDisableTime();
strcpy(mess, "Cannot get comparator disable time. Only valid for " LOG(logDEBUG1,
"chipv1.1\n"); ("retval get comp disable time %lld ns\n", (long long int)retval));
if (ret == FAIL) {
sprintf(mess,
"Could not set comp disable time. Set %lld ns, read "
"%lld ns.\n",
(long long int)arg, (long long int)retval);
LOG(logERROR, (mess)); LOG(logERROR, (mess));
} else {
ret = setComparatorDisableTime(arg);
int64_t retval = getComparatorDisableTime();
LOG(logDEBUG1, ("retval get comp disable time %lld ns\n",
(long long int)retval));
if (ret == FAIL) {
sprintf(mess,
"Could not set comp disable time. Set %lld ns, read "
"%lld ns.\n",
(long long int)arg, (long long int)retval);
LOG(logERROR, (mess));
}
} }
} }
#endif #endif
@ -11100,11 +11090,18 @@ int get_timing_info_decoder(int file_des) {
functionNotImplemented(); functionNotImplemented();
#else #else
// get only // get only
ret = getTimingInfoDecoder(&retval); if (isHardwareVersion_1_0()) {
LOG(logDEBUG1, ("retval timing info decoder: %d\n", retval)); ret = FAIL;
if (ret == FAIL) { sprintf(mess, "Could not get timing info decoder. Not supported "
strcpy(mess, "Could not get timing info decoder\n"); "for hardware version 1.0\n");
LOG(logERROR, (mess)); LOG(logERROR, (mess));
} else {
ret = getTimingInfoDecoder(&retval);
LOG(logDEBUG1, ("retval timing info decoder: %d\n", retval));
if (ret == FAIL) {
strcpy(mess, "Could not get timing info decoder\n");
LOG(logERROR, (mess));
}
} }
#endif #endif
return Server_SendResult(file_des, INT32, &retval, sizeof(retval)); return Server_SendResult(file_des, INT32, &retval, sizeof(retval));
@ -11132,6 +11129,12 @@ int set_timing_info_decoder(int file_des) {
modeNotImplemented("Timing info decoder index", (int)arg); modeNotImplemented("Timing info decoder index", (int)arg);
break; break;
} }
if (ret == OK && isHardwareVersion_1_0()) {
ret = FAIL;
sprintf(mess, "Could not set timing info decoder. Not supported "
"for hardware version 1.0\n");
LOG(logERROR, (mess));
}
if (ret == OK) { if (ret == OK) {
ret = setTimingInfoDecoder(arg); ret = setTimingInfoDecoder(arg);
if (ret == FAIL) { if (ret == FAIL) {

View File

@ -7,7 +7,12 @@ support_lib = ../../slsSupportLib/include/
det_lib = ../../slsDetectorSoftware/include/sls/ det_lib = ../../slsDetectorSoftware/include/sls/
md5_dir = ../../slsSupportLib/src/ md5_dir = ../../slsSupportLib/src/
CROSS = aarch64-none-linux-gnu- ifeq ($(shell uname -m),aarch64)
# no cross compilation needed when on aarch64
CROSS =
else
CROSS = aarch64-none-linux-gnu-
endif
CC = $(CROSS)gcc CC = $(CROSS)gcc
#TODO: allow these warnings and fix code #TODO: allow these warnings and fix code
CFLAGS += -Wall -std=gnu99 -Wno-format-overflow -Wno-format-truncation -DXILINX_CHIPTESTBOARDD -DARMPROCESSOR -DSTOP_SERVER -I$(main_inc) -I$(support_lib) -I$(det_lib) -I$(current_dir) #-DDEBUG1 #-DVERBOSEI #-DVERBOSE CFLAGS += -Wall -std=gnu99 -Wno-format-overflow -Wno-format-truncation -DXILINX_CHIPTESTBOARDD -DARMPROCESSOR -DSTOP_SERVER -I$(main_inc) -I$(support_lib) -I$(det_lib) -I$(current_dir) #-DDEBUG1 #-DVERBOSEI #-DVERBOSE

View File

@ -1056,7 +1056,7 @@ int getPower(enum DACINDEX ind) {
// dac powered off // dac powered off
if (dacValues[ind] == LTC2620_D_GetPowerDownValue()) { if (dacValues[ind] == LTC2620_D_GetPowerDownValue()) {
LOG(logWARNING, ("Power V%s powered down\n", powerNames[pwrIndex])); LOG(logWARNING, ("Power V%s is powered down\n", powerNames[pwrIndex]));
return LTC2620_D_GetPowerDownValue(); return LTC2620_D_GetPowerDownValue();
} }

View File

@ -1505,6 +1505,7 @@ fi
if [[ ${IS_GET} -eq 0 ]]; then if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then if [[ "${cword}" == "2" ]]; then
FCN_RETURN="" FCN_RETURN=""
IS_PATH=1
fi fi
fi fi
return 0 return 0
@ -1514,6 +1515,7 @@ FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then if [[ "${cword}" == "2" ]]; then
FCN_RETURN="" FCN_RETURN=""
IS_PATH=1
fi fi
fi fi
return 0 return 0

View File

@ -1429,6 +1429,7 @@ fi
if [[ ${IS_GET} -eq 0 ]]; then if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then if [[ "${cword}" == "2" ]]; then
FCN_RETURN="" FCN_RETURN=""
IS_PATH=1
fi fi
fi fi
return 0 return 0
@ -1438,6 +1439,7 @@ FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then if [[ "${cword}" == "2" ]]; then
FCN_RETURN="" FCN_RETURN=""
IS_PATH=1
fi fi
fi fi
return 0 return 0

View File

@ -468,7 +468,7 @@ subdeadtime:
function: setSubDeadTime function: setSubDeadTime
compdisabletime: compdisabletime:
help: "[duration] [(optional unit) ns|us|ms|s]\n\t[Jungfrau] Time before end of exposure when comparator is disabled. It is only possible for chipv1.1." help: "[duration] [(optional unit) ns|us|ms|s]\n\t[Jungfrau] Time before end of exposure when comparator is disabled."
inherit_actions: TIME_COMMAND inherit_actions: TIME_COMMAND
actions: actions:
GET: GET:
@ -1123,7 +1123,7 @@ temp_control:
input_types: [ bool ] input_types: [ bool ]
autocompdisable: autocompdisable:
help: "[0, 1]\n\t[Jungfrau] Auto comparator disable mode. By default, the on-chip gain switching is active during the entire exposure.This mode disables the on - chip gain switching comparator automatically after 93.75% (only for chipv1.0) of exposure time (only for longer than 100us). It is possible to set the duration for chipv1.1 using compdisabletime command.\n\tDefault is 0 or this mode disabled(comparator enabled throughout). 1 enables mode. 0 disables mode. " help: "[0, 1]\n\t[Jungfrau] Auto comparator disable mode. By default, the on-chip gain switching is active during the entire exposure.This mode disables the on - chip gain switching comparator automatically and the duration is set using compdisabletime command.\n\tDefault is 0 or this mode disabled(comparator enabled throughout). 1 enables mode. 0 disables mode. "
inherit_actions: INTEGER_COMMAND_VEC_ID inherit_actions: INTEGER_COMMAND_VEC_ID
actions: actions:
GET: GET:
@ -1210,7 +1210,7 @@ polarity:
input_types: [ defs::polarity ] input_types: [ defs::polarity ]
timing_info_decoder: timing_info_decoder:
help: "[swissfel|shine]\n\t[Jungfrau] Advanced Command and only for Swissfel and Shine. Sets the bunch id or timing info decoder. Default is swissfel." help: "[swissfel|shine]\n\t[Jungfrau] Advanced Command and only for Swissfel and Shine. Sets the bunch id or timing info decoder. Default is swissfel. Only allowed for pcbv2.0."
inherit_actions: INTEGER_COMMAND_VEC_ID inherit_actions: INTEGER_COMMAND_VEC_ID
actions: actions:
GET: GET:
@ -3429,7 +3429,7 @@ udp_dstlist:
output: [ ToString(args) ] output: [ ToString(args) ]
txdelay: txdelay:
help: "[n_delay]\n\t[Eiger][Jungfrau][Moench][Mythen3] Set transmission delay for all modules in the detector using the step size provided.Sets up \n\t[Eiger] txdelay_left to (2 * mod_index * n_delay), \n\t[Eiger] txdelay_right to ((2 * mod_index + 1) * n_delay) and \n\t[Eiger] txdelay_frame to (2 *num_modules * n_delay)\n\t[Jungfrau][Moench][Mythen3] txdelay_frame to (num_modules * n_delay) for every module." help: "[n_delay]\n\t[Eiger][Jungfrau][Moench][Mythen3] Set transmission delay for all modules in the detector using the step size provided.Sets up \n\t[Eiger] txdelay_left to (2 * mod_index * n_delay), \n\t[Eiger] txdelay_right to ((2 * mod_index + 1) * n_delay) and \n\t[Eiger] txdelay_frame to (2 * num_modules * n_delay)\n\t[Jungfrau][Moench][Mythen3] txdelay_frame to (num_modules * n_delay) for every module."
actions: actions:
GET: GET:
argc: 0 argc: 0
@ -3884,8 +3884,8 @@ patternX:
require_det_id: true require_det_id: true
function: setPattern function: setPattern
input: [ 'args[0]' ] input: [ 'args[0]' ]
arg_types: [special::path]
input_types: [ std::string ] input_types: [ std::string ]
cast_input: [ false ]
output: [ 'args.front()' ] output: [ 'args.front()' ]
patword: patword:

View File

@ -762,10 +762,9 @@ autocompdisable:
function_alias: autocompdisable function_alias: autocompdisable
help: "[0, 1]\n\t[Jungfrau] Auto comparator disable mode. By default, the on-chip\ help: "[0, 1]\n\t[Jungfrau] Auto comparator disable mode. By default, the on-chip\
\ gain switching is active during the entire exposure.This mode disables the on\ \ gain switching is active during the entire exposure.This mode disables the on\
\ - chip gain switching comparator automatically after 93.75% (only for chipv1.0)\ \ - chip gain switching comparator automatically and the duration is set using\
\ of exposure time (only for longer than 100us). It is possible to set the duration\ \ compdisabletime command.\n\tDefault is 0 or this mode disabled(comparator enabled\
\ for chipv1.1 using compdisabletime command.\n\tDefault is 0 or this mode disabled(comparator\ \ throughout). 1 enables mode. 0 disables mode. "
\ enabled throughout). 1 enables mode. 0 disables mode. "
infer_action: true infer_action: true
template: true template: true
badchannels: badchannels:
@ -1607,7 +1606,7 @@ compdisabletime:
command_name: compdisabletime command_name: compdisabletime
function_alias: compdisabletime function_alias: compdisabletime
help: "[duration] [(optional unit) ns|us|ms|s]\n\t[Jungfrau] Time before end of\ help: "[duration] [(optional unit) ns|us|ms|s]\n\t[Jungfrau] Time before end of\
\ exposure when comparator is disabled. It is only possible for chipv1.1." \ exposure when comparator is disabled."
infer_action: true infer_action: true
template: true template: true
confadc: confadc:
@ -6539,7 +6538,7 @@ patternX:
PUT: PUT:
args: args:
- arg_types: - arg_types:
- std::string - special::path
argc: 1 argc: 1
cast_input: cast_input:
- false - false
@ -11488,7 +11487,8 @@ timing_info_decoder:
command_name: timing_info_decoder command_name: timing_info_decoder
function_alias: timing_info_decoder function_alias: timing_info_decoder
help: "[swissfel|shine]\n\t[Jungfrau] Advanced Command and only for Swissfel and\ help: "[swissfel|shine]\n\t[Jungfrau] Advanced Command and only for Swissfel and\
\ Shine. Sets the bunch id or timing info decoder. Default is swissfel." \ Shine. Sets the bunch id or timing info decoder. Default is swissfel. Only allowed\
\ for pcbv2.0."
infer_action: true infer_action: true
template: true template: true
timinglist: timinglist:
@ -11915,7 +11915,7 @@ txdelay:
help: "[n_delay]\n\t[Eiger][Jungfrau][Moench][Mythen3] Set transmission delay for\ help: "[n_delay]\n\t[Eiger][Jungfrau][Moench][Mythen3] Set transmission delay for\
\ all modules in the detector using the step size provided.Sets up \n\t[Eiger]\ \ all modules in the detector using the step size provided.Sets up \n\t[Eiger]\
\ txdelay_left to (2 * mod_index * n_delay), \n\t[Eiger] txdelay_right to ((2\ \ txdelay_left to (2 * mod_index * n_delay), \n\t[Eiger] txdelay_right to ((2\
\ * mod_index + 1) * n_delay) and \n\t[Eiger] txdelay_frame to (2 *num_modules\ \ * mod_index + 1) * n_delay) and \n\t[Eiger] txdelay_frame to (2 * num_modules\
\ * n_delay)\n\t[Jungfrau][Moench][Mythen3] txdelay_frame to (num_modules * n_delay)\ \ * n_delay)\n\t[Jungfrau][Moench][Mythen3] txdelay_frame to (num_modules * n_delay)\
\ for every module." \ for every module."
infer_action: true infer_action: true

View File

@ -65,7 +65,12 @@ class Detector {
Result<std::string> getHostname(Positions pos = {}) const; Result<std::string> getHostname(Positions pos = {}) const;
/**Frees shared memory, adds detectors to the list. */ /**Frees shared memory, adds detectors to the list. The row and column
* values in the udp/zmq header are affected by the order in this command
* and the setDetectorSize function. The modules are stacked row by row
* until they reach the y-axis limit set by detsize (if specified). Then,
* stacking continues in the next column and so on. This only affects row
* and column in udp/zmq header.*/
void setHostname(const std::vector<std::string> &hostname); void setHostname(const std::vector<std::string> &hostname);
/** connects to n servers at local host starting at specific control port. /** connects to n servers at local host starting at specific control port.
@ -1304,11 +1309,9 @@ class Detector {
* //TODO naming * //TODO naming
* By default, the on-chip gain switching is active during the * By default, the on-chip gain switching is active during the
* entire exposure. This mode disables the on-chip gain switching comparator * entire exposure. This mode disables the on-chip gain switching comparator
* automatically after 93.75% of exposure time (only for longer than 100us). * automatically and the duration is set using setComparatorDisableTime\n
* The % is for chipv1.0. One can set the duration for chipv1.1 using * Default is false or this mode disabled(comparator enabled throughout).
* setComparatorDisableTime\n Default is false or this mode * true enables mode. 0 disables mode.
* disabled(comparator enabled throughout). true enables mode. 0 disables
* mode.
*/ */
void setAutoComparatorDisable(bool value, Positions pos = {}); void setAutoComparatorDisable(bool value, Positions pos = {});
@ -1316,7 +1319,7 @@ class Detector {
Result<ns> getComparatorDisableTime(Positions pos = {}) const; Result<ns> getComparatorDisableTime(Positions pos = {}) const;
/** [Jungfrau] Time before end of exposure when comparator is /** [Jungfrau] Time before end of exposure when comparator is
* disabled. It is only possible for chipv1.1.*/ * disabled.*/
void setComparatorDisableTime(ns t, Positions pos = {}); void setComparatorDisableTime(ns t, Positions pos = {});
/** [Jungfrau] Advanced TODO naming */ /** [Jungfrau] Advanced TODO naming */
@ -1382,7 +1385,7 @@ class Detector {
Result<defs::timingInfoDecoder> Result<defs::timingInfoDecoder>
getTimingInfoDecoder(Positions pos = {}) const; getTimingInfoDecoder(Positions pos = {}) const;
/** [Jungfrau] Advanced Command! */ /** [Jungfrau] Advanced Command! Only for pcb v2.0 */
void setTimingInfoDecoder(defs::timingInfoDecoder value, void setTimingInfoDecoder(defs::timingInfoDecoder value,
Positions pos = {}); Positions pos = {});
@ -1749,7 +1752,8 @@ class Detector {
Result<std::vector<int>> getRxDbitList(Positions pos = {}) const; Result<std::vector<int>> getRxDbitList(Positions pos = {}) const;
/** [CTB] list contains the set of digital signal bits (0-63) to save, must /** [CTB] list contains the set of digital signal bits (0-63) to save, must
* be non repetitive */ * be non repetitive. Note: data will be rearranged according to signal bits
*/
void setRxDbitList(const std::vector<int> &list, Positions pos = {}); void setRxDbitList(const std::vector<int> &list, Positions pos = {});
/** [CTB] */ /** [CTB] */

View File

@ -1018,7 +1018,7 @@ std::string Caller::autocompdisable(int action) {
// print help // print help
if (action == slsDetectorDefs::HELP_ACTION) { if (action == slsDetectorDefs::HELP_ACTION) {
os << R"V0G0N([0, 1] os << R"V0G0N([0, 1]
[Jungfrau] Auto comparator disable mode. By default, the on-chip gain switching is active during the entire exposure.This mode disables the on - chip gain switching comparator automatically after 93.75% (only for chipv1.0) of exposure time (only for longer than 100us). It is possible to set the duration for chipv1.1 using compdisabletime command. [Jungfrau] Auto comparator disable mode. By default, the on-chip gain switching is active during the entire exposure.This mode disables the on - chip gain switching comparator automatically and the duration is set using compdisabletime command.
Default is 0 or this mode disabled(comparator enabled throughout). 1 enables mode. 0 disables mode. )V0G0N" Default is 0 or this mode disabled(comparator enabled throughout). 1 enables mode. 0 disables mode. )V0G0N"
<< std::endl; << std::endl;
return os.str(); return os.str();
@ -2108,7 +2108,7 @@ std::string Caller::compdisabletime(int action) {
// print help // print help
if (action == slsDetectorDefs::HELP_ACTION) { if (action == slsDetectorDefs::HELP_ACTION) {
os << R"V0G0N([duration] [(optional unit) ns|us|ms|s] os << R"V0G0N([duration] [(optional unit) ns|us|ms|s]
[Jungfrau] Time before end of exposure when comparator is disabled. It is only possible for chipv1.1. )V0G0N" [Jungfrau] Time before end of exposure when comparator is disabled. )V0G0N"
<< std::endl; << std::endl;
return os.str(); return os.str();
} }
@ -14744,7 +14744,7 @@ std::string Caller::timing_info_decoder(int action) {
// print help // print help
if (action == slsDetectorDefs::HELP_ACTION) { if (action == slsDetectorDefs::HELP_ACTION) {
os << R"V0G0N([swissfel|shine] os << R"V0G0N([swissfel|shine]
[Jungfrau] Advanced Command and only for Swissfel and Shine. Sets the bunch id or timing info decoder. Default is swissfel. )V0G0N" [Jungfrau] Advanced Command and only for Swissfel and Shine. Sets the bunch id or timing info decoder. Default is swissfel. Only allowed for pcbv2.0. )V0G0N"
<< std::endl; << std::endl;
return os.str(); return os.str();
} }
@ -15365,7 +15365,7 @@ std::string Caller::txdelay(int action) {
[Eiger][Jungfrau][Moench][Mythen3] Set transmission delay for all modules in the detector using the step size provided.Sets up [Eiger][Jungfrau][Moench][Mythen3] Set transmission delay for all modules in the detector using the step size provided.Sets up
[Eiger] txdelay_left to (2 * mod_index * n_delay), [Eiger] txdelay_left to (2 * mod_index * n_delay),
[Eiger] txdelay_right to ((2 * mod_index + 1) * n_delay) and [Eiger] txdelay_right to ((2 * mod_index + 1) * n_delay) and
[Eiger] txdelay_frame to (2 *num_modules * n_delay) [Eiger] txdelay_frame to (2 * num_modules * n_delay)
[Jungfrau][Moench][Mythen3] txdelay_frame to (num_modules * n_delay) for every module. )V0G0N" [Jungfrau][Moench][Mythen3] txdelay_frame to (num_modules * n_delay) for every module. )V0G0N"
<< std::endl; << std::endl;
return os.str(); return os.str();

View File

@ -210,7 +210,12 @@ std::string Caller::hostname(int action) {
os << "\n\tFrees shared memory and sets hostname (or IP address) of " os << "\n\tFrees shared memory and sets hostname (or IP address) of "
"all modules concatenated by +.\n\t Virtual servers can already " "all modules concatenated by +.\n\t Virtual servers can already "
"use the port in hostname separated by ':' and ports incremented " "use the port in hostname separated by ':' and ports incremented "
"by 2 to accomodate the stop server as well." "by 2 to accomodate the stop server as well. The row and column "
"values in the udp/zmq header are affected by the order in this "
"command and the detsize command. The modules are stacked row by "
"row until they reach the y-axis limit set by detsize (if "
"specified). Then, stacking continues in the next column and so "
"on. This only affects row and column in udp/zmq header."
<< '\n'; << '\n';
} else if (action == defs::GET_ACTION) { } else if (action == defs::GET_ACTION) {
if (!args.empty()) { if (!args.empty()) {
@ -1020,10 +1025,16 @@ std::string Caller::slowadc(int action) {
std::string Caller::rx_dbitlist(int action) { std::string Caller::rx_dbitlist(int action) {
std::ostringstream os; std::ostringstream os;
if (action == defs::HELP_ACTION) { if (action == defs::HELP_ACTION) {
os << "[all] or [i0] [i1] [i2]... \n\t[Ctb] List of digital signal " os << "[all] or [none] or [i0] [i1] [i2]... \n\t[Ctb] List of digital "
"bits read out. If all is used instead of a list, all digital " "signal bits enabled and rearranged according to the signals "
"bits (64) enabled. Each element in list can be 0 - 63 and must " "(all samples of each signal is put together). If 'all' is used "
"be non repetitive." "instead of a list, all digital bits (64) enabled. Each element "
"in list can be 0 - 63 and must be non repetitive. The option "
"'none' will still spit out all data as is from the detector, "
"but without rearranging it. Please note that when using the "
"receiver list, the data size will be bigger if the number of "
"samples is not divisible by 8 as every signal bit is padded to "
"the next byte when combining all the samples in the receiver."
<< '\n'; << '\n';
} else if (action == defs::GET_ACTION) { } else if (action == defs::GET_ACTION) {
if (!args.empty()) { if (!args.empty()) {
@ -1041,7 +1052,9 @@ std::string Caller::rx_dbitlist(int action) {
for (unsigned int i = 0; i < 64; ++i) { for (unsigned int i = 0; i < 64; ++i) {
t[i] = i; t[i] = i;
} }
} else { }
// 'none' option already covered as t is empty by default
else if (args[0] != "none") {
unsigned int ntrim = args.size(); unsigned int ntrim = args.size();
t.resize(ntrim); t.resize(ntrim);
for (unsigned int i = 0; i < ntrim; ++i) { for (unsigned int i = 0; i < ntrim; ++i) {

View File

@ -99,6 +99,12 @@ void Detector::loadParameters(const std::vector<std::string> &parameters) {
CmdParser parser; CmdParser parser;
for (const auto &current_line : parameters) { for (const auto &current_line : parameters) {
parser.Parse(current_line); parser.Parse(current_line);
if (parser.multi_id() != 0) {
throw RuntimeError(
"Multi-detector indices [" + std::to_string(parser.multi_id()) +
"] are not allowed in the file. Instead, use the index for "
"'config' or 'parameters' command?");
}
caller.call(parser.command(), parser.arguments(), parser.detector_id(), caller.call(parser.command(), parser.arguments(), parser.detector_id(),
defs::PUT_ACTION, std::cout, parser.receiver_id()); defs::PUT_ACTION, std::cout, parser.receiver_id());
} }

View File

@ -1177,9 +1177,19 @@ int DetectorImpl::acquire() {
if (dataReady == nullptr) { if (dataReady == nullptr) {
setJoinThreadFlag(true); setJoinThreadFlag(true);
} else if (receiver) { } else if (receiver) {
while (numZmqRunning != 0) { // wait for postprocessor to process dummies
Parallel(&Module::restreamStopFromReceiver, {}); if (dataReady != nullptr) {
std::this_thread::sleep_for(std::chrono::milliseconds(200)); // process dummy from stop receier
if (numZmqRunning != 0)
std::this_thread::sleep_for(std::chrono::milliseconds(200));
while (numZmqRunning != 0) {
Parallel(&Module::restreamStopFromReceiver, {});
// time to process restream dummy
std::this_thread::sleep_for(std::chrono::milliseconds(200));
// increase time for fewer dummies and to catch up
if (numZmqRunning != 0)
std::this_thread::sleep_for(std::chrono::seconds(2));
}
} }
} }
dataProcessingThread.join(); dataProcessingThread.join();

View File

@ -79,7 +79,9 @@ class DetectorImpl : public virtual slsDetectorDefs {
explicit DetectorImpl(int detector_index = 0, bool verify = true, explicit DetectorImpl(int detector_index = 0, bool verify = true,
bool update = true); bool update = true);
template <class CT> struct NonDeduced { using type = CT; }; template <class CT> struct NonDeduced {
using type = CT;
};
template <typename RT, typename... CT> template <typename RT, typename... CT>
Result<RT> Parallel(RT (Module::*somefunc)(CT...), Result<RT> Parallel(RT (Module::*somefunc)(CT...),
std::vector<int> positions, std::vector<int> positions,

View File

@ -905,8 +905,13 @@ void Module::startReceiver() {
} }
void Module::stopReceiver() { void Module::stopReceiver() {
auto rxStatusPrior = getReceiverStatus();
sendToReceiver(F_STOP_RECEIVER, static_cast<int>(shm()->stoppedFlag), sendToReceiver(F_STOP_RECEIVER, static_cast<int>(shm()->stoppedFlag),
nullptr); nullptr);
if (rxStatusPrior == IDLE && getReceiverStreaming()) {
restreamStopFromReceiver();
}
} }
void Module::startAcquisition() { void Module::startAcquisition() {
@ -920,26 +925,8 @@ void Module::startReadout() {
} }
void Module::stopAcquisition() { void Module::stopAcquisition() {
// get det status before stopping acq
runStatus detStatus = ERROR;
try {
detStatus = getRunStatus();
} catch (...) {
}
sendToDetectorStop(F_STOP_ACQUISITION); sendToDetectorStop(F_STOP_ACQUISITION);
shm()->stoppedFlag = true; shm()->stoppedFlag = true;
// restream dummy header, if rxr streaming and det idle before stop
try {
if (shm()->useReceiverFlag && getReceiverStreaming()) {
if (detStatus == IDLE && getReceiverStatus() == IDLE) {
restreamStopFromReceiver();
}
}
} catch (...) {
}
} }
void Module::restreamStopFromReceiver() { void Module::restreamStopFromReceiver() {

View File

@ -262,8 +262,7 @@ TEST_CASE("compdisabletime", "[.cmdcall]") {
Detector det; Detector det;
Caller caller(&det); Caller caller(&det);
auto det_type = det.getDetectorType().squash(); auto det_type = det.getDetectorType().squash();
if (det_type == defs::JUNGFRAU && if (det_type == defs::JUNGFRAU) {
det.getChipVersion().squash() * 10 == 11) {
auto prev_val = det.getComparatorDisableTime(); auto prev_val = det.getComparatorDisableTime();
{ {
std::ostringstream oss; std::ostringstream oss;
@ -670,7 +669,8 @@ TEST_CASE("pedestalmode", "[.cmdcall]") {
TEST_CASE("timing_info_decoder", "[.cmdcall]") { TEST_CASE("timing_info_decoder", "[.cmdcall]") {
Detector det; Detector det;
Caller caller(&det); Caller caller(&det);
if (det.getDetectorType().squash() == defs::JUNGFRAU) { if (det.getDetectorType().squash() == defs::JUNGFRAU &&
det.getHardwareVersion().squash() == "2.0") {
auto prev_val = det.getTimingInfoDecoder(); auto prev_val = det.getTimingInfoDecoder();
/*{ /*{
std::ostringstream oss; std::ostringstream oss;

View File

@ -3323,7 +3323,7 @@ TEST_CASE("reg", "[.cmdcall]") {
addr = 0x80; addr = 0x80;
} }
if (det_type == defs::GOTTHARD2) { if (det_type == defs::GOTTHARD2) {
addr = 0x20; addr = 0x298;
} }
std::string saddr = ToStringHex(addr); std::string saddr = ToStringHex(addr);
auto prev_val = det.readRegister(addr); auto prev_val = det.readRegister(addr);
@ -3379,7 +3379,7 @@ TEST_CASE("setbit", "[.cmdcall]") {
addr = 0x80; addr = 0x80;
} }
if (det_type == defs::GOTTHARD2) { if (det_type == defs::GOTTHARD2) {
addr = 0x20; addr = 0x298;
} }
std::string saddr = ToStringHex(addr); std::string saddr = ToStringHex(addr);
auto prev_val = det.readRegister(addr); auto prev_val = det.readRegister(addr);
@ -3409,7 +3409,7 @@ TEST_CASE("clearbit", "[.cmdcall]") {
addr = 0x80; addr = 0x80;
} }
if (det_type == defs::GOTTHARD2) { if (det_type == defs::GOTTHARD2) {
addr = 0x20; addr = 0x298;
} }
std::string saddr = ToStringHex(addr); std::string saddr = ToStringHex(addr);
auto prev_val = det.readRegister(addr); auto prev_val = det.readRegister(addr);
@ -3439,7 +3439,7 @@ TEST_CASE("getbit", "[.cmdcall]") {
addr = 0x80; addr = 0x80;
} }
if (det_type == defs::GOTTHARD2) { if (det_type == defs::GOTTHARD2) {
addr = 0x20; addr = 0x298;
} }
std::string saddr = ToStringHex(addr); std::string saddr = ToStringHex(addr);
auto prev_val = det.readRegister(addr); auto prev_val = det.readRegister(addr);

View File

@ -138,13 +138,34 @@ if (SLS_USE_RECEIVER_BINARIES)
slsProjectWarnings slsProjectWarnings
) )
install(TARGETS slsReceiver slsMultiReceiver add_executable(slsFrameSynchronizer
src/FrameSynchronizerApp.cpp
)
set_target_properties(slsFrameSynchronizer PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
)
if((CMAKE_BUILD_TYPE STREQUAL "Release") AND SLS_LTO_AVAILABLE)
set_property(TARGET slsFrameSynchronizer PROPERTY INTERPROCEDURAL_OPTIMIZATION True)
endif()
target_link_libraries(slsFrameSynchronizer
PUBLIC
slsReceiverStatic
pthread
rt
PRIVATE
slsProjectWarnings
"$<BUILD_INTERFACE:libzmq-static>"
)
install(TARGETS slsReceiver slsMultiReceiver slsFrameSynchronizer
EXPORT "${TARGETS_EXPORT_NAME}" EXPORT "${TARGETS_EXPORT_NAME}"
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sls PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sls
) )
endif(SLS_USE_RECEIVER_BINARIES) endif(SLS_USE_RECEIVER_BINARIES)

View File

@ -33,6 +33,8 @@ using Interface = ServerInterface;
#define gettid() syscall(SYS_gettid) #define gettid() syscall(SYS_gettid)
#endif #endif
std::mutex ClientInterface::callbackMutex;
ClientInterface::~ClientInterface() { ClientInterface::~ClientInterface() {
killTcpThread = true; killTcpThread = true;
LOG(logINFO) << "Shutting down TCP Socket on port " << portNumber; LOG(logINFO) << "Shutting down TCP Socket on port " << portNumber;
@ -55,12 +57,14 @@ std::string ClientInterface::getReceiverVersion() { return APIRECEIVER; }
/***callback functions***/ /***callback functions***/
void ClientInterface::registerCallBackStartAcquisition( void ClientInterface::registerCallBackStartAcquisition(
int (*func)(const startCallbackHeader, void *), void *arg) { int (*func)(const startCallbackHeader, void *), void *arg) {
std::lock_guard<std::mutex> lock(callbackMutex);
startAcquisitionCallBack = func; startAcquisitionCallBack = func;
pStartAcquisition = arg; pStartAcquisition = arg;
} }
void ClientInterface::registerCallBackAcquisitionFinished( void ClientInterface::registerCallBackAcquisitionFinished(
void (*func)(const endCallbackHeader, void *), void *arg) { void (*func)(const endCallbackHeader, void *), void *arg) {
std::lock_guard<std::mutex> lock(callbackMutex);
acquisitionFinishedCallBack = func; acquisitionFinishedCallBack = func;
pAcquisitionFinished = arg; pAcquisitionFinished = arg;
} }
@ -69,6 +73,7 @@ void ClientInterface::registerCallBackRawDataReady(
void (*func)(sls_receiver_header &, dataCallbackHeader, char *, size_t &, void (*func)(sls_receiver_header &, dataCallbackHeader, char *, size_t &,
void *), void *),
void *arg) { void *arg) {
std::lock_guard<std::mutex> lock(callbackMutex);
rawDataReadyCallBack = func; rawDataReadyCallBack = func;
pRawDataReady = arg; pRawDataReady = arg;
} }
@ -461,15 +466,18 @@ void ClientInterface::setDetectorType(detectorType arg) {
std::string(e.what()) + ']'); std::string(e.what()) + ']');
} }
// callbacks after (in setdetectortype, the object is reinitialized) // callbacks after (in setdetectortype, the object is reinitialized)
if (startAcquisitionCallBack != nullptr) {
impl()->registerCallBackStartAcquisition(startAcquisitionCallBack, std::lock_guard<std::mutex> lock(callbackMutex);
pStartAcquisition); if (startAcquisitionCallBack != nullptr)
if (acquisitionFinishedCallBack != nullptr) impl()->registerCallBackStartAcquisition(startAcquisitionCallBack,
impl()->registerCallBackAcquisitionFinished(acquisitionFinishedCallBack, pStartAcquisition);
pAcquisitionFinished); if (acquisitionFinishedCallBack != nullptr)
if (rawDataReadyCallBack != nullptr) impl()->registerCallBackAcquisitionFinished(
impl()->registerCallBackRawDataReady(rawDataReadyCallBack, acquisitionFinishedCallBack, pAcquisitionFinished);
pRawDataReady); if (rawDataReadyCallBack != nullptr)
impl()->registerCallBackRawDataReady(rawDataReadyCallBack,
pRawDataReady);
}
impl()->setThreadIds(parentThreadId, tcpThreadId); impl()->setThreadIds(parentThreadId, tcpThreadId);
} }

View File

@ -194,6 +194,8 @@ class ClientInterface : private virtual slsDetectorDefs {
pid_t tcpThreadId{0}; pid_t tcpThreadId{0};
std::vector<std::string> udpips = std::vector<std::string> udpips =
std::vector<std::string>(MAX_NUMBER_OF_LISTENING_THREADS); std::vector<std::string>(MAX_NUMBER_OF_LISTENING_THREADS);
// necessary if Receiver objects using threads with callbacks
static std::mutex callbackMutex;
}; };
} // namespace sls } // namespace sls

View File

@ -0,0 +1,635 @@
// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
/* Creates the slsFrameSynchronizer for running multiple receivers in different
* threads form a single binary that will spit out zmq streams without
* reconstructing image. Sample python script for pull socket for this combiner
* in python/scripts folder. TODO: Not handling empty frames from one socket
*/
#include "sls/Receiver.h"
#include "sls/ToString.h"
#include "sls/container_utils.h"
#include "sls/logger.h"
#include "sls/sls_detector_defs.h"
#include "sls/versionAPI.h"
#include <csignal> //SIGINT
#include <cstdio>
#include <cstring>
#include <iostream>
#include <mutex>
#include <ostream>
#include <semaphore.h>
#include <sys/socket.h>
#include <sys/wait.h> //wait
#include <thread>
#include <unistd.h>
#include <set>
#include <vector>
#include <zmq.h>
std::vector<std::thread> threads;
std::vector<sem_t *> semaphores;
sls::TLogLevel printHeadersLevel = sls::logDEBUG;
/** Define Colors to print data call back in different colors for different
* recievers */
#define PRINT_IN_COLOR(c, f, ...) \
printf("\033[%dm" f RESET, 30 + c + 1, ##__VA_ARGS__)
/** Structure handling different threads */
using ZmqMsgList = std::vector<zmq_msg_t *>;
using FrameMap = std::map<uint64_t, ZmqMsgList>;
using PortFrameMap = std::map<uint16_t, FrameMap>;
struct FrameStatus {
bool starting = true;
bool terminate = false;
int num_receivers;
sem_t available;
std::mutex mtx;
ZmqMsgList headers;
PortFrameMap frames;
ZmqMsgList ends;
FrameStatus(bool start, bool term, int num_recv)
: starting(start), terminate(term), num_receivers(num_recv) {
sem_init(&available, 0, 0);
}
};
FrameStatus *global_frame_status = nullptr;
/**
* Control+C Interrupt Handler
* to let all the processes know to exit properly
*/
void sigInterruptHandler(int p) {
for (size_t i = 0; i != semaphores.size(); ++i) {
sem_post(semaphores[i]);
}
}
void cleanup() {
if (global_frame_status) {
std::lock_guard<std::mutex> lock(global_frame_status->mtx);
for (auto &outer_pair : global_frame_status->frames) {
for (auto &inner_pair : outer_pair.second) {
for (zmq_msg_t *msg : inner_pair.second) {
if (msg) {
zmq_msg_close(msg);
delete msg;
}
}
inner_pair.second.clear();
}
outer_pair.second.clear();
}
global_frame_status->frames.clear();
}
}
/**
* prints usage of this example program
*/
std::string getHelpMessage() {
std::ostringstream os;
os << "\nUsage:\n"
<< "./slsFrameSynchronizer --version or -v\n"
<< "\t - Gets the slsFrameSynchronizer version\n\n"
<< "./slsFrameSynchronizer [start tcp port] [num recevers] [print "
"callback headers (optional)]\n"
<< "\t - tcp port has to be non-zero and 16 bit\n"
<< "\t - print callback headers option is 0 (disabled) by default\n";
return os.str();
}
void zmq_free(void *data, void *hint) { delete[] static_cast<char *>(data); }
void print_frames(const PortFrameMap &frame_port_map) {
LOG(sls::logDEBUG) << "Printing frames";
for (const auto &it : frame_port_map) {
uint16_t udpPort = it.first;
const auto &frame_map = it.second;
LOG(sls::logDEBUG) << "UDP port: " << udpPort;
for (const auto &frame : frame_map) {
uint64_t fnum = frame.first;
const auto &msg_list = frame.second;
LOG(sls::logDEBUG)
<< " acq index: " << fnum << '[' << msg_list.size() << ']';
}
}
}
/** Valid frame numbers mean they exist across all ports or
* has at least a larger fnum in the port with the missing fnum **/
std::set<uint64_t> get_valid_fnums(const PortFrameMap &port_frame_map) {
// empty list
std::set<uint64_t> valid_fnums;
if (port_frame_map.empty()) {
return valid_fnums;
}
// collect all unique frame numbers from all ports
std::set<uint64_t> unique_fnums;
for (auto it = port_frame_map.begin(); it != port_frame_map.begin(); ++it) {
const FrameMap &frame_map = it->second;
for (auto frame = frame_map.begin(); frame != frame_map.end();
++frame) {
unique_fnums.insert(frame->first);
}
}
// collect valid frame numbers
for (auto &fnum : unique_fnums) {
bool is_valid = true;
for (auto it = port_frame_map.begin(); it != port_frame_map.end();
++it) {
uint16_t port = it->first;
const FrameMap &frame_map = it->second;
auto frame = frame_map.find(fnum);
// invalid: fnum missing in one port
if (frame == frame_map.end()) {
LOG(sls::logDEBUG)
<< "Fnum " << fnum << " is missing in port " << port;
// invalid: fnum greater than all in that port
auto last_frame = std::prev(frame_map.end());
auto last_fnum = last_frame->first;
if (fnum > last_fnum) {
LOG(sls::logDEBUG) << "And no larger fnum found. Fnum "
<< fnum << " is invalid.\n";
is_valid = false;
break;
}
}
}
if (is_valid) {
valid_fnums.insert(fnum);
}
}
return valid_fnums;
}
int zmq_send_multipart(void *socket, const ZmqMsgList &messages) {
size_t num_messages = messages.size();
for (size_t i = 0; i != num_messages; ++i) {
zmq_msg_t *msg = messages[i];
// determine flags: ZMQ_SNDMORE for all messages except the last
int flags = (i == num_messages - 1) ? 0 : ZMQ_SNDMORE;
if (zmq_msg_send(msg, socket, flags) == -1) {
LOG(sls::logERROR)
<< "Error sending message: " << zmq_strerror(zmq_errno());
return slsDetectorDefs::FAIL;
}
}
return slsDetectorDefs::OK;
}
void Correlate(FrameStatus *stat) {
void *context = zmq_ctx_new();
void *socket = zmq_socket(context, ZMQ_PUSH);
int rc = zmq_bind(socket, "tcp://*:5555");
if (rc != 0) {
LOG(sls::logERROR) << "failed to bind";
}
while (true) {
sem_wait(&(stat->available));
{
std::lock_guard<std::mutex> lock(stat->mtx);
if (stat->terminate) {
break;
}
if (stat->starting) {
// sending all start packets
if (static_cast<int>(stat->headers.size()) ==
stat->num_receivers) {
stat->starting = false;
// clean up
zmq_send_multipart(socket, stat->headers);
for (zmq_msg_t *msg : stat->headers) {
if (msg) {
zmq_msg_close(msg);
delete msg;
}
}
stat->headers.clear();
}
} else {
// print_frames(stat->frames);
auto valid_fnums = get_valid_fnums(stat->frames);
// sending all valid fnum data packets
for (const auto &fnum : valid_fnums) {
ZmqMsgList msg_list;
PortFrameMap &port_frame_map = stat->frames;
for (auto it = port_frame_map.begin();
it != port_frame_map.end(); ++it) {
uint16_t port = it->first;
const FrameMap &frame_map = it->second;
auto frame = frame_map.find(fnum);
if (frame != frame_map.end()) {
msg_list.insert(msg_list.end(),
stat->frames[port][fnum].begin(),
stat->frames[port][fnum].end());
// clean up
for (zmq_msg_t *msg : stat->frames[port][fnum]) {
if (msg) {
zmq_msg_close(msg);
delete msg;
}
}
stat->frames[port].erase(fnum);
}
}
LOG(printHeadersLevel)
<< "Sending data packets for fnum " << fnum;
zmq_send_multipart(socket, msg_list);
}
}
// sending all end packets
if (static_cast<int>(stat->ends.size()) == stat->num_receivers) {
zmq_send_multipart(socket, stat->ends);
// clean up
for (zmq_msg_t *msg : stat->ends) {
if (msg) {
zmq_msg_close(msg);
delete msg;
}
}
stat->ends.clear();
}
}
}
zmq_close(socket);
zmq_ctx_destroy(context);
}
int StartAcquisitionCallback(
const slsDetectorDefs::startCallbackHeader callbackHeader,
void *objectPointer) {
LOG(printHeadersLevel)
<< "Start Acquisition:"
<< "\n\t["
<< "\n\tUDP Port : " << sls::ToString(callbackHeader.udpPort)
<< "\n\tDynamic Range : " << callbackHeader.dynamicRange
<< "\n\tDetector Shape : "
<< sls::ToString(callbackHeader.detectorShape)
<< "\n\tImage Size : " << callbackHeader.imageSize
<< "\n\tFile Path : " << callbackHeader.filePath
<< "\n\tFile Name : " << callbackHeader.fileName
<< "\n\tFile Index : " << callbackHeader.fileIndex
<< "\n\tQuad Enable : " << callbackHeader.quad
<< "\n\tAdditional Json Header : "
<< sls::ToString(callbackHeader.addJsonHeader).c_str() << "\n\t]";
std::ostringstream oss;
oss << "{\"htype\":\"header\""
<< ", \"udpPorts\":" << sls::ToString(callbackHeader.udpPort)
<< ", \"bitmode\":" << callbackHeader.dynamicRange
<< ", \"filePath\":\"" << callbackHeader.filePath
<< "\", \"fileName\":\"" << callbackHeader.fileName
<< "\", \"fileIndex\":" << callbackHeader.fileIndex
<< ", \"detshape\":" << sls::ToString(callbackHeader.detectorShape)
<< ", \"size\":" << callbackHeader.imageSize
<< ", \"quad\":" << (callbackHeader.quad ? 1 : 0);
if (!callbackHeader.addJsonHeader.empty()) {
oss << ", \"addJsonHeader\": {";
for (auto it = callbackHeader.addJsonHeader.begin();
it != callbackHeader.addJsonHeader.end(); ++it) {
if (it != callbackHeader.addJsonHeader.begin()) {
oss << ", ";
}
oss << "\"" << it->first.c_str() << "\":\"" << it->second.c_str()
<< "\"";
}
oss << " } ";
}
oss << "}\n";
std::string message = oss.str();
LOG(sls::logDEBUG) << "Start Acquisition message:" << std::endl << message;
int length = message.length();
char *hdata = new char[length];
memcpy(hdata, message.c_str(), length);
zmq_msg_t *hmsg = new zmq_msg_t;
zmq_msg_init_data(hmsg, hdata, length, zmq_free, NULL);
// push zmq msg into stat to be processed
FrameStatus *stat = static_cast<FrameStatus *>(objectPointer);
{
std::lock_guard<std::mutex> lock(stat->mtx);
stat->headers.push_back(hmsg);
stat->starting = true;
// clean up old frames
for (int port : callbackHeader.udpPort) {
for (auto &frame_map : stat->frames[port]) {
for (zmq_msg_t *msg : frame_map.second) {
if (msg) {
zmq_msg_close(msg);
delete msg;
}
}
frame_map.second.clear();
}
stat->frames[port].clear();
}
}
sem_post(&stat->available);
return slsDetectorDefs::OK; // TODO: change return to void
}
void AcquisitionFinishedCallback(
const slsDetectorDefs::endCallbackHeader callbackHeader,
void *objectPointer) {
LOG(printHeadersLevel) << "Acquisition Finished:"
<< "\n\t["
<< "\n\tUDP Port : "
<< sls::ToString(callbackHeader.udpPort)
<< "\n\tComplete Frames : "
<< sls::ToString(callbackHeader.completeFrames)
<< "\n\tLast Frame Index : "
<< sls::ToString(callbackHeader.lastFrameIndex)
<< "\n\t]";
std::ostringstream oss;
oss << "{\"htype\":\"series_end\""
<< ", \"udpPorts\":" << sls::ToString(callbackHeader.udpPort)
<< ", \"comleteFrames\":"
<< sls::ToString(callbackHeader.completeFrames)
<< ", \"lastFrameIndex\":"
<< sls::ToString(callbackHeader.lastFrameIndex) << "}\n";
std::string message = oss.str();
int length = message.length();
LOG(sls::logDEBUG) << "Acquisition Finished message:" << std::endl
<< message;
char *hdata = new char[length];
memcpy(hdata, message.c_str(), length);
zmq_msg_t *hmsg = new zmq_msg_t;
zmq_msg_init_data(hmsg, hdata, length, zmq_free, NULL);
// push zmq msg into stat to be processed
FrameStatus *stat = static_cast<FrameStatus *>(objectPointer);
{
std::lock_guard<std::mutex> lock(stat->mtx);
stat->ends.push_back(hmsg);
}
sem_post(&stat->available);
}
void GetDataCallback(slsDetectorDefs::sls_receiver_header &header,
slsDetectorDefs::dataCallbackHeader callbackHeader,
char *dataPointer, size_t &imageSize,
void *objectPointer) {
slsDetectorDefs::sls_detector_header detectorHeader = header.detHeader;
if (printHeadersLevel < sls::logDEBUG) {
// print in different color for each udp port
PRINT_IN_COLOR((callbackHeader.udpPort % 10),
"Data: "
"\n\tCallback Header: "
"\n\t["
"\n\tUDP Port: %u"
"\n\tShape: [%u, %u]"
"\n\tAcq Index : %lu"
"\n\tFrame Index :%lu"
"\n\tProgress : %.2f%%"
"\n\tComplete Image :%s"
"\n\tFlip Rows :%s"
"\n\tAdditional Json Header : %s"
"\n\t]"
"\n\ttReceiver Header: "
"\n\t["
"\n\tFrame Number : %lu"
"\n\tExposure Length :%u"
"\n\tPackets Caught :%u"
"\n\tDetector Specific 1: %lu"
"\n\tTimestamp : %lu"
"\n\tModule Id :%u"
"\n\tRow : %u"
"\n\tColumn :%u"
"\n\tDetector Specific 2 : %u"
"\n\tDetector Specific 3 : %u"
"\n\tDetector Specific 4 : %u"
"\n\tDetector Type : %s"
"\n\tVersion: %u"
"\n\t]"
"\n\tFirst Byte Data: 0x%x"
"\n\tImage Size: %zu\n\n",
callbackHeader.udpPort, callbackHeader.shape.x,
callbackHeader.shape.y, callbackHeader.acqIndex,
callbackHeader.frameIndex, callbackHeader.progress,
sls::ToString(callbackHeader.completeImage).c_str(),
sls::ToString(callbackHeader.flipRows).c_str(),
sls::ToString(callbackHeader.addJsonHeader).c_str(),
detectorHeader.frameNumber, detectorHeader.expLength,
detectorHeader.packetNumber, detectorHeader.detSpec1,
detectorHeader.timestamp, detectorHeader.modId,
detectorHeader.row, detectorHeader.column,
detectorHeader.detSpec2, detectorHeader.detSpec3,
detectorHeader.detSpec4,
sls::ToString(detectorHeader.detType).c_str(),
detectorHeader.version,
// header->packetsMask.to_string().c_str(),
((uint8_t)(*((uint8_t *)(dataPointer)))), imageSize);
}
std::ostringstream oss;
oss << "{\"htype\":\"module\""
<< ", \"port\":" << callbackHeader.udpPort
<< ", \"shape\":" << sls::ToString(callbackHeader.shape)
<< ", \"acqIndex\":" << callbackHeader.acqIndex
<< ", \"frameIndex\":" << callbackHeader.frameIndex
<< ", \"flipRows\":" << (callbackHeader.flipRows ? 1 : 0)
<< ", \"progress\":" << callbackHeader.progress
<< ", \"completeImage\":" << (callbackHeader.completeImage ? 1 : 0)
<< ", \"imageSize\":" << imageSize
<< ", \"frameNumber\":" << detectorHeader.frameNumber
<< ", \"expLength\":" << detectorHeader.expLength
<< ", \"packetNumber\":" << detectorHeader.packetNumber
<< ", \"detSpec1\":" << detectorHeader.detSpec1
<< ", \"timestamp\":" << detectorHeader.timestamp
<< ", \"modId\":" << detectorHeader.modId
<< ", \"row\":" << detectorHeader.row
<< ", \"column\":" << detectorHeader.column
<< ", \"detSpec2\":" << detectorHeader.detSpec2
<< ", \"detSpec3\":" << detectorHeader.detSpec3
<< ", \"detSpec4\":" << detectorHeader.detSpec4
<< ", \"detType\":" << static_cast<int>(detectorHeader.detType)
<< ", \"version\":" << static_cast<int>(detectorHeader.version);
if (!callbackHeader.addJsonHeader.empty()) {
oss << ", \"addJsonHeader\": {";
for (auto it = callbackHeader.addJsonHeader.begin();
it != callbackHeader.addJsonHeader.end(); ++it) {
if (it != callbackHeader.addJsonHeader.begin()) {
oss << ", ";
}
oss << "\"" << it->first.c_str() << "\":\"" << it->second.c_str()
<< "\"";
}
oss << " } ";
}
oss << "}\n";
std::string message = oss.str();
LOG(sls::logDEBUG) << "Data message:" << std::endl << message;
// creating header part of data packet
int length = message.length();
char *hdata = new char[length];
memcpy(hdata, message.c_str(), length);
zmq_msg_t *hmsg = new zmq_msg_t;
zmq_msg_init_data(hmsg, hdata, length, zmq_free, NULL);
// created data part of data packet
char *data = new char[imageSize];
zmq_msg_t *msg = new zmq_msg_t;
zmq_msg_init_data(msg, data, imageSize, zmq_free, NULL);
// push both parts into stat to be processed
FrameStatus *stat = static_cast<FrameStatus *>(objectPointer);
{
std::lock_guard<std::mutex> lock(stat->mtx);
stat->frames[callbackHeader.udpPort][header.detHeader.frameNumber]
.push_back(hmsg);
stat->frames[callbackHeader.udpPort][header.detHeader.frameNumber]
.push_back(msg);
}
sem_post(&stat->available);
}
/**
* Example of main program using the Receiver class
*
* - Defines in file for:
* - Default Number of receivers is 1
* - Default Start TCP port is 1954
*/
int main(int argc, char *argv[]) {
// version
if (argc == 2) {
std::string sargv1 = std::string(argv[1]);
if (sargv1 == "--version" || sargv1 == "-v") {
std::cout << "slsFrameSynchronizer Version: " << APIRECEIVER
<< std::endl;
exit(EXIT_SUCCESS);
}
}
/** - set default values */
int numReceivers = 1;
uint16_t startTCPPort = DEFAULT_TCP_RX_PORTNO;
bool printHeaders = false;
/** - get number of receivers and start tcp port from command line
* arguments */
if (argc > 1) {
try {
if (argc == 3 || argc == 4) {
startTCPPort = sls::StringTo<uint16_t>(argv[1]);
if (startTCPPort == 0) {
throw std::runtime_error("Invalid start tcp port");
}
numReceivers = std::stoi(argv[2]);
if (numReceivers > 1024) {
cprintf(RED,
"Did you mix up the order of the arguments?\n%s\n",
getHelpMessage().c_str());
return EXIT_FAILURE;
}
if (numReceivers == 0) {
cprintf(RED, "Invalid number of receivers.\n%s\n",
getHelpMessage().c_str());
return EXIT_FAILURE;
}
if (argc == 4) {
printHeaders = sls::StringTo<bool>(argv[3]);
if (printHeaders) {
printHeadersLevel = sls::logINFOBLUE;
}
}
} else
throw std::runtime_error("Invalid number of arguments");
} catch (const std::exception &e) {
cprintf(RED, "Error: %s\n%s\n", e.what(), getHelpMessage().c_str());
return EXIT_FAILURE;
}
}
cprintf(RESET, "Number of Receivers: %d\n", numReceivers);
cprintf(RESET, "Start TCP Port: %hu\n", startTCPPort);
cprintf(RESET, "Print Callback Headers: %s\n\n",
(printHeaders ? "Enabled" : "Disabled"));
/** - Catch signal SIGINT to close files and call destructors properly */
struct sigaction sa;
sa.sa_flags = 0; // no flags
sa.sa_handler = sigInterruptHandler; // handler function
sigemptyset(&sa.sa_mask); // dont block additional signals during invocation
// of handler
if (sigaction(SIGINT, &sa, nullptr) == -1) {
cprintf(RED, "Could not set handler function for SIGINT\n");
}
/** - Ignore SIG_PIPE, prevents global signal handler, handle locally,
instead of a server crashing due to client crash when writing, it just
gives error */
struct sigaction asa;
asa.sa_flags = 0; // no flags
asa.sa_handler = SIG_IGN; // handler function
sigemptyset(&asa.sa_mask); // dont block additional signals during
// invocation of handler
if (sigaction(SIGPIPE, &asa, nullptr) == -1) {
cprintf(RED, "Could not set handler function for SIGPIPE\n");
}
FrameStatus stat{true, false, numReceivers};
// store pointer for signal handler
global_frame_status = &stat;
// thread synchronizing all packets
void *user_data = static_cast<void *>(&stat);
std::thread combinerThread(Correlate, &stat);
for (int i = 0; i != numReceivers; ++i) {
sem_t *semaphore = new sem_t;
sem_init(semaphore, 1, 0);
semaphores.push_back(semaphore);
uint16_t port = startTCPPort + i;
threads.emplace_back([i, semaphore, port, user_data]() {
sls::Receiver receiver(port);
receiver.registerCallBackStartAcquisition(StartAcquisitionCallback,
user_data);
receiver.registerCallBackAcquisitionFinished(
AcquisitionFinishedCallback, user_data);
receiver.registerCallBackRawDataReady(GetDataCallback, user_data);
/** - as long as no Ctrl+C */
sem_wait(semaphore);
sem_destroy(semaphore);
delete semaphore;
// clean up frames
if (i == 0)
cleanup();
});
}
for (auto &thread : threads) {
thread.join();
}
{
std::lock_guard<std::mutex> lock(stat.mtx);
stat.terminate = true;
sem_post(&stat.available);
}
combinerThread.join();
sem_destroy(&stat.available);
LOG(sls::logINFOBLUE) << "Goodbye!";
return EXIT_SUCCESS;
}

View File

@ -149,12 +149,12 @@ void Listener::CreateUDPSocket(int &actualSize) {
packetSize = generalData->vetoPacketSize; packetSize = generalData->vetoPacketSize;
} }
std::string ip = std::string ip;
(eth.length() ? InterfaceNameToIp(eth).str().c_str() : ""); if (eth.length() > 0)
ip = InterfaceNameToIp(eth).str();
udpSocket = nullptr; udpSocket = nullptr;
udpSocket = make_unique<UdpRxSocket>( udpSocket = make_unique<UdpRxSocket>(
udpPortNumber, packetSize, (ip.length() ? ip.c_str() : nullptr), udpPortNumber, packetSize, (ip.empty() ? nullptr : ip.c_str()),
generalData->udpSocketBufferSize); generalData->udpSocketBufferSize);
LOG(logINFO) << index << ": UDP port opened at port " << udpPortNumber LOG(logINFO) << index << ": UDP port opened at port " << udpPortNumber
<< " (" << (ip.length() ? ip : "any") << ')'; << " (" << (ip.length() ? ip : "any") << ')';
@ -213,10 +213,13 @@ void Listener::CreateDummySocketForUDPSocketBufferSize(int s, int &actualSize) {
try { try {
// to allowe ports to be bound from udpsocket // to allowe ports to be bound from udpsocket
udpSocket.reset(); udpSocket.reset();
UdpRxSocket g(
udpPortNumber, packetSize, std::string ip;
(eth.length() ? InterfaceNameToIp(eth).str().c_str() : nullptr), if (eth.length() > 0)
generalData->udpSocketBufferSize); ip = InterfaceNameToIp(eth).str();
UdpRxSocket g(udpPortNumber, packetSize,
(ip.empty() ? nullptr : ip.c_str()),
generalData->udpSocketBufferSize);
// doubled due to kernel bookkeeping (could also be less due to // doubled due to kernel bookkeeping (could also be less due to
// permissions) // permissions)

View File

@ -7,6 +7,7 @@
#include "sls/container_utils.h" #include "sls/container_utils.h"
#include "sls/logger.h" #include "sls/logger.h"
#include "sls/sls_detector_defs.h" #include "sls/sls_detector_defs.h"
#include "sls/versionAPI.h"
#include <csignal> //SIGINT #include <csignal> //SIGINT
#include <cstring> #include <cstring>
@ -39,7 +40,9 @@ void sigInterruptHandler(int p) { sem_post(&semaphore); }
*/ */
std::string getHelpMessage() { std::string getHelpMessage() {
std::ostringstream os; std::ostringstream os;
os << "\nUsage:\n" os << "\nUsage:\n\n"
<< "./slsMultiReceiver --version or -v\n"
<< "\t - Gets the slsMultiReceiver version\n\n"
<< "./slsMultiReceiver [start tcp port] [num recevers] [call back " << "./slsMultiReceiver [start tcp port] [num recevers] [call back "
"option (optional)]\n" "option (optional)]\n"
<< "\t - tcp port has to be non-zero and 16 bit\n" << "\t - tcp port has to be non-zero and 16 bit\n"
@ -160,6 +163,16 @@ void GetData(slsDetectorDefs::sls_receiver_header &header,
*/ */
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
// version
if (argc == 2) {
std::string sargv1 = std::string(argv[1]);
if (sargv1 == "--version" || sargv1 == "-v") {
std::cout << "slsMultiReceiver Version: " << APIRECEIVER
<< std::endl;
exit(EXIT_SUCCESS);
}
}
/** - set default values */ /** - set default values */
int numReceivers = 1; int numReceivers = 1;
uint16_t startTCPPort = DEFAULT_TCP_RX_PORTNO; uint16_t startTCPPort = DEFAULT_TCP_RX_PORTNO;
@ -242,40 +255,43 @@ int main(int argc, char *argv[]) {
else if (pid == 0) { else if (pid == 0) {
cprintf(BLUE, "Child process %d [ Tid: %ld ]\n", i, (long)gettid()); cprintf(BLUE, "Child process %d [ Tid: %ld ]\n", i, (long)gettid());
std::unique_ptr<sls::Receiver> receiver = nullptr;
try { try {
receiver = sls::make_unique<sls::Receiver>(startTCPPort + i); uint16_t port = startTCPPort + i;
sls::Receiver receiver(port);
/** - register callbacks. remember to set file write enable
* to 0 (using the client) if we should not write files and you
* will write data using the callbacks */
if (withCallback) {
/** - Call back for start acquisition */
cprintf(BLUE, "Registering StartAcq()\n");
receiver.registerCallBackStartAcquisition(StartAcq,
nullptr);
/** - Call back for acquisition finished */
cprintf(BLUE, "Registering AcquisitionFinished()\n");
receiver.registerCallBackAcquisitionFinished(
AcquisitionFinished, nullptr);
/* - Call back for raw data */
cprintf(BLUE, "Registering GetData() \n");
receiver.registerCallBackRawDataReady(GetData, nullptr);
}
/** - as long as no Ctrl+C */
sem_wait(&semaphore);
sem_destroy(&semaphore);
} catch (...) { } catch (...) {
LOG(sls::logINFOBLUE) LOG(sls::logINFOBLUE)
<< "Exiting Child Process [ Tid: " << gettid() << " ]"; << "Exiting Child Process [ Tid: " << gettid() << " ]";
throw; throw;
} }
/** - register callbacks. remember to set file write enable to 0
* (using the client) if we should not write files and you will
* write data using the callbacks */
if (withCallback) {
/** - Call back for start acquisition */
cprintf(BLUE, "Registering StartAcq()\n");
receiver->registerCallBackStartAcquisition(StartAcq, nullptr);
/** - Call back for acquisition finished */
cprintf(BLUE, "Registering AcquisitionFinished()\n");
receiver->registerCallBackAcquisitionFinished(
AcquisitionFinished, nullptr);
/* - Call back for raw data */
cprintf(BLUE, "Registering GetData() \n");
receiver->registerCallBackRawDataReady(GetData, nullptr);
}
/** - as long as no Ctrl+C */
sem_wait(&semaphore);
sem_destroy(&semaphore);
cprintf(BLUE, "Exiting Child Process [ Tid: %ld ]\n", cprintf(BLUE, "Exiting Child Process [ Tid: %ld ]\n",
(long)gettid()); (long)gettid());
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
break;
} }
} }

View File

@ -62,7 +62,7 @@ Receiver::Receiver(int argc, char *argv[]) : tcpipInterface(nullptr) {
"\t started with privileges. \n\n"; "\t started with privileges. \n\n";
while (c != -1) { while (c != -1) {
c = getopt_long(argc, argv, "hvf:t:u:", long_options, &option_index); c = getopt_long(argc, argv, "hvt:u:", long_options, &option_index);
// Detect the end of the options. // Detect the end of the options.
if (c == -1) if (c == -1)
@ -87,7 +87,7 @@ Receiver::Receiver(int argc, char *argv[]) : tcpipInterface(nullptr) {
break; break;
case 'v': case 'v':
std::cout << "SLS Receiver Version: " << APIRECEIVER << std::endl; std::cout << "slsReceiver Version: " << APIRECEIVER << std::endl;
LOG(logINFOBLUE) << "Exiting [ Tid: " << gettid() << " ]"; LOG(logINFOBLUE) << "Exiting [ Tid: " << gettid() << " ]";
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);

View File

@ -16,6 +16,8 @@ enum TLogLevel {
logINFOBLUE, logINFOBLUE,
logINFOGREEN, logINFOGREEN,
logINFORED, logINFORED,
logINFOCYAN,
logINFOMAGENTA,
logINFO, logINFO,
logDEBUG, logDEBUG,
logDEBUG1, logDEBUG1,
@ -60,16 +62,25 @@ class Logger {
// Danger this buffer need as many elements as TLogLevel // Danger this buffer need as many elements as TLogLevel
static const char *Color(TLogLevel level) noexcept { static const char *Color(TLogLevel level) noexcept {
static const char *const colors[] = { static const char *const colors[] = {
RED BOLD, YELLOW BOLD, BLUE, GREEN, RED, RESET, RED BOLD, YELLOW BOLD, BLUE, GREEN, RED, CYAN, MAGENTA,
RESET, RESET, RESET, RESET, RESET, RESET}; RESET, RESET, RESET, RESET, RESET, RESET, RESET};
// out of bounds
if (level < 0 || level >= sizeof(colors) / sizeof(colors[0])) {
return RESET;
}
return colors[level]; return colors[level];
} }
// Danger this buffer need as many elements as TLogLevel // Danger this buffer need as many elements as TLogLevel
static std::string ToString(TLogLevel level) { static std::string ToString(TLogLevel level) {
static const char *const buffer[] = { static const char *const buffer[] = {
"ERROR", "WARNING", "INFO", "INFO", "INFO", "INFO", "ERROR", "WARNING", "INFO", "INFO", "INFO",
"DEBUG", "DEBUG1", "DEBUG2", "DEBUG3", "DEBUG4", "DEBUG5"}; "INFO", "INFO", "INFO", "DEBUG", "DEBUG1",
"DEBUG2", "DEBUG3", "DEBUG4", "DEBUG5"};
// out of bounds
if (level < 0 || level >= sizeof(buffer) / sizeof(buffer[0])) {
return "UNKNOWN";
}
return buffer[level]; return buffer[level];
} }

View File

@ -130,7 +130,7 @@ extern "C" {
ll = (c)->D; \ ll = (c)->D; \
(void)HOST_l2c(ll, (s)); \ (void)HOST_l2c(ll, (s)); \
} while (0) } while (0)
#define ROTATE(a, n) (((a) << (n)) | (((a)&0xffffffff) >> (32 - (n)))) #define ROTATE(a, n) (((a) << (n)) | (((a) & 0xffffffff) >> (32 - (n))))
#if defined(DATA_ORDER_IS_BIG_ENDIAN) #if defined(DATA_ORDER_IS_BIG_ENDIAN)
#define HOST_c2l(c, l) \ #define HOST_c2l(c, l) \

View File

@ -1,13 +1,13 @@
// SPDX-License-Identifier: LGPL-3.0-or-other // SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package // Copyright (C) 2021 Contributors to the SLS Detector Package
/** API versions */ /** API versions */
#define APICTB "9.0.0 0x241121"
#define APIGOTTHARD "9.0.0 0x241121" #define APIGOTTHARD "9.0.0 0x241121"
#define APIGOTTHARD2 "9.0.0 0x241121" #define APIGOTTHARD2 "9.0.0 0x241121"
#define APIJUNGFRAU "9.0.0 0x241121"
#define APIMOENCH "9.0.0 0x241121" #define APIMOENCH "9.0.0 0x241121"
#define APIXILINXCTB "9.0.0 0x241121"
#define APIEIGER "9.0.0 0x241121" #define APIEIGER "9.0.0 0x241121"
#define APIMYTHEN3 "9.0.0 0x241121" #define APICTB "9.1.0 0x250204"
#define APILIB "9.0.0 0x241126" #define APIXILINXCTB "9.1.0 0x250204"
#define APIRECEIVER "9.0.0 0x241126" #define APIMYTHEN3 "9.1.0 0x250304"
#define APIJUNGFRAU "9.1.0 0x250318"
#define APILIB "9.1.0 0x250325"
#define APIRECEIVER "9.1.0 0x250325"