mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-06-05 01:20:41 +02:00
Merge pull request #1143 from slsdetectorgroup/9.1.0.rc
Some checks failed
CMake / Configure and build using cmake (push) Failing after 10s
Some checks failed
CMake / Configure and build using cmake (push) Failing after 10s
9.1.0
This commit is contained in:
commit
64aad1e196
2
.github/workflows/cmake.yml
vendored
2
.github/workflows/cmake.yml
vendored
@ -17,7 +17,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: awalsh128/cache-apt-pkgs-action@latest
|
||||
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
|
||||
|
||||
- name: Configure CMake
|
||||
|
@ -1 +0,0 @@
|
||||
# This file is generated by cmake for dependency checking of the CMakeCache.txt file
|
@ -249,8 +249,8 @@ endif()
|
||||
if(SLS_USE_SANITIZER)
|
||||
target_compile_options(slsProjectOptions INTERFACE -fsanitize=address,undefined -fno-omit-frame-pointer)
|
||||
target_link_libraries(slsProjectOptions INTERFACE -fsanitize=address,undefined)
|
||||
# target_compile_options(slsProjectOptions INTERFACE -fsanitize=thread)
|
||||
# target_link_libraries(slsProjectOptions INTERFACE -fsanitize=thread)
|
||||
#target_compile_options(slsProjectOptions INTERFACE -fsanitize=thread -fno-omit-frame-pointer)
|
||||
#target_link_libraries(slsProjectOptions INTERFACE -fsanitize=thread)
|
||||
endif()
|
||||
|
||||
|
||||
|
334
RELEASE.txt
334
RELEASE.txt
@ -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
|
||||
--------
|
||||
1 Compilation Changes
|
||||
2 New or Changed Features
|
||||
2.1 Breaking API
|
||||
2.2 Resolved or Changed Features
|
||||
2.3 New Features
|
||||
3 On-board Detector Server Compatibility
|
||||
4 Firmware Requirements
|
||||
5 Kernel Requirements
|
||||
6 Download, Documentation & Support
|
||||
1 Changes
|
||||
1.1 New or Changed Features
|
||||
1.2 Resolved Features
|
||||
2 On-board Detector Server Compatibility
|
||||
3 Firmware Requirements
|
||||
4 Kernel Requirements
|
||||
5 Download, Documentation & Support
|
||||
|
||||
|
||||
|
||||
|
||||
2 Compilation 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
|
||||
1 Changes
|
||||
==========
|
||||
|
||||
|
||||
|
||||
2 New, Changed or Resolved Features
|
||||
=====================================
|
||||
|
||||
|
||||
|
||||
2.1 Breaking API
|
||||
==================
|
||||
1.1 New or Changed Features
|
||||
============================
|
||||
|
||||
|
||||
Receiver
|
||||
--------
|
||||
|
||||
|
||||
* Receiver callbacks
|
||||
Brought much more metadata to receiver callbacks to construct the image.
|
||||
Update MultiReceiverApp to reflect this change.
|
||||
* Frame Synchronizer (experimental)
|
||||
Added a new binary, similar to slsMultiReceiver, to collect images from
|
||||
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
|
||||
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.
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
|
||||
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
|
||||
Command line: rx_zmqip gives a warning and does nothing
|
||||
Python : rx_zmqip removed
|
||||
C++ API: get/setRxZmqIP removed
|
||||
|
||||
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.
|
||||
* Row and column index (UDP header or callback)
|
||||
Help on how this is determined from the hostname is added to the 'UDP
|
||||
Header' and the 'Quick Start Guide' topics. Also added to the help in '
|
||||
hostname' command line help. Please note that this can be overwritten by
|
||||
corresponding row and column commands.
|
||||
|
||||
|
||||
|
||||
2.2 Resolved or Changed Features
|
||||
================================
|
||||
1.2 Resolved Features
|
||||
======================
|
||||
|
||||
|
||||
Compilation
|
||||
-----------
|
||||
|
||||
|
||||
* 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
|
||||
Firmware
|
||||
---------
|
||||
|
||||
|
||||
* 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
|
||||
---
|
||||
|
||||
|
||||
* Publiser socket constructor
|
||||
|
||||
- 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] Reduced significant print out in zmq processing using energy
|
||||
threshold.
|
||||
|
||||
|
||||
|
||||
2.3 New Features
|
||||
================
|
||||
* [Moench] Zmq dummy packet restreaming command did nothing
|
||||
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
|
||||
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.
|
||||
Simulators
|
||||
-----------
|
||||
|
||||
|
||||
* sls_detector
|
||||
New executable that can be used instead of 'sls_detector_get' and
|
||||
'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
|
||||
* [Jungfrau][Moench] Slightly faster transmistting time by removing sleeping
|
||||
only if there is a transmission delay
|
||||
|
||||
|
||||
|
||||
@ -287,8 +150,8 @@ This document describes the differences between v9.0.0 and v8.0.2
|
||||
|
||||
|
||||
Eiger 9.0.0
|
||||
Jungfrau 9.0.0
|
||||
Mythen3 9.0.0
|
||||
Jungfrau 9.1.0
|
||||
Mythen3 9.1.0
|
||||
Gotthard2 9.0.0
|
||||
Gotthard 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)
|
||||
|
||||
Jungfrau 20.09.2023 (v1.5, HW v1.0) (updated in 8.0.0)
|
||||
21.09.2023 (v2.5, HW v2.0) (updated in 8.0.0)
|
||||
Jungfrau 09.02.2025 (v1.6, HW v1.0) (updated in 9.1.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)
|
||||
|
||||
@ -360,6 +223,7 @@ This document describes the differences between v9.0.0 and v8.0.2
|
||||
4 Kernel Requirements
|
||||
======================
|
||||
|
||||
|
||||
Blackfin
|
||||
--------
|
||||
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
|
||||
the package.
|
||||
|
||||
|
||||
Nios
|
||||
-----
|
||||
Compatible version: Mon May 10 18:00:21 CEST 2021
|
||||
|
||||
|
||||
Kernel Upgrade
|
||||
---------------
|
||||
Eiger via bit files
|
||||
|
@ -11,6 +11,7 @@ cp build/install/lib/* $PREFIX/lib/
|
||||
|
||||
#Binaries
|
||||
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_put $PREFIX/bin/.
|
||||
cp build/install/bin/sls_detector_help $PREFIX/bin/.
|
||||
|
@ -63,4 +63,4 @@ html_static_path = ['static']
|
||||
|
||||
|
||||
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
|
||||
|
@ -4,11 +4,54 @@ Command line interface
|
||||
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
|
||||
--------
|
||||
@ -28,12 +71,15 @@ Help
|
||||
# list of deprecated commands
|
||||
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
|
||||
|
@ -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.
|
||||
|
||||
.. _Cplusplus Api Examples:
|
||||
.. doxygenclass:: sls::Detector
|
||||
:members:
|
||||
:undoc-members:
|
@ -39,7 +39,7 @@ Welcome to slsDetectorPackage's documentation!
|
||||
|
||||
.. toctree::
|
||||
:caption: Command line
|
||||
:maxdepth: 2
|
||||
:maxdepth: 1
|
||||
|
||||
commandline
|
||||
quick_start_guide
|
||||
|
@ -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)
|
||||
are from the developer branch. Please use released tags for stability.
|
||||
|
||||
We have three different packages available:
|
||||
|
||||
* **slsdetlib** shared libraries and command line utilities
|
||||
* **slsdetgui** GUI
|
||||
* **slsdet** Python bindings
|
||||
We have four different packages available:
|
||||
============== =============================================
|
||||
Package Description
|
||||
============== =============================================
|
||||
slsdetlib shared libraries and command line utilities
|
||||
slsdetgui GUI
|
||||
slsdet Python bindings
|
||||
moenchzmq moench
|
||||
============== =============================================
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
@ -43,7 +47,7 @@ We have three different packages available:
|
||||
|
||||
#ready to use
|
||||
sls_detector_get exptime
|
||||
etc ...
|
||||
...
|
||||
|
||||
|
||||
.. code-block:: bash
|
||||
@ -55,6 +59,8 @@ We have three different packages available:
|
||||
conda search slsdet
|
||||
# gui
|
||||
conda search slsdetgui
|
||||
# moench
|
||||
conda search moenchzmq
|
||||
|
||||
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
|
||||
.. _master file attributes:
|
||||
|
||||
Master File Attributes
|
||||
=======================
|
||||
|
||||
|
@ -128,6 +128,10 @@ For Multiple Modules
|
||||
# set file path
|
||||
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
|
||||
----
|
||||
|
||||
|
@ -39,13 +39,13 @@ Arguments
|
||||
|
||||
|
||||
.. _Automatic start servers:
|
||||
|
||||
Automatic start
|
||||
------------------
|
||||
|
||||
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
|
||||
|
||||
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 &
|
||||
|
||||
|
||||
#. Sync, reboot and verify
|
||||
:
|
||||
#. Sync, reboot and verify:
|
||||
.. code-block:: bash
|
||||
|
||||
sync
|
||||
|
@ -73,9 +73,9 @@ Description
|
||||
|
||||
* **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.
|
||||
|
||||
|
@ -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.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/9.0.0_rh8 stable cmake/3.15.5 Qt/5.12.10
|
||||
|
||||
|
||||
|
@ -14,6 +14,8 @@ from pyctbgui.utils.defines import Defines
|
||||
import pyctbgui.utils.pixelmap as pm
|
||||
from pyctbgui.utils.recordOrApplyPedestal import recordOrApplyPedestal
|
||||
|
||||
from slsdet import detectorType
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from pyctbgui.services import AcquisitionTab, PlotTab
|
||||
|
||||
@ -30,6 +32,7 @@ class AdcTab(QtWidgets.QWidget):
|
||||
self.acquisitionTab: AcquisitionTab | None = None
|
||||
self.legend: LegendItem | None = None
|
||||
self.logger = logging.getLogger('AdcTab')
|
||||
self.tengiga = True
|
||||
|
||||
def setup_ui(self):
|
||||
self.plotTab = self.mainWindow.plotTab
|
||||
@ -42,6 +45,12 @@ class AdcTab(QtWidgets.QWidget):
|
||||
self.legend.clear()
|
||||
# subscribe to toggle legend
|
||||
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):
|
||||
self.mainWindow.plotAnalogWaveform = pg.plot()
|
||||
@ -67,7 +76,8 @@ class AdcTab(QtWidgets.QWidget):
|
||||
|
||||
def connect_ui(self):
|
||||
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}Plot").stateChanged.connect(partial(self.setADCEnablePlot, 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.checkBoxADC16_31Plot.stateChanged.connect(
|
||||
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)
|
||||
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):
|
||||
self.updateADCNames()
|
||||
self.updateADCInv()
|
||||
if self.det.type == detectorType.CHIPTESTBOARD:
|
||||
self.updateADCInv()
|
||||
self.updateADCEnable()
|
||||
|
||||
# ADCs Tab functions
|
||||
@ -196,9 +208,11 @@ class AdcTab(QtWidgets.QWidget):
|
||||
return decoder.decode(analog_array, pm.moench04_analog())
|
||||
|
||||
def getADCEnableReg(self):
|
||||
retval = self.det.adcenable
|
||||
if self.det.tengiga:
|
||||
retval = self.det.adcenable10g
|
||||
if self.det.type == detectorType.CHIPTESTBOARD:
|
||||
self.tengiga = self.det.tengiga
|
||||
retval = self.det.adcenable10g
|
||||
if not self.tengiga:
|
||||
retval = self.det.adcenable
|
||||
self.view.lineEditADCEnable.editingFinished.disconnect()
|
||||
self.view.lineEditADCEnable.setText("0x{:08x}".format(retval))
|
||||
self.view.lineEditADCEnable.editingFinished.connect(self.setADCEnableReg)
|
||||
@ -207,8 +221,8 @@ class AdcTab(QtWidgets.QWidget):
|
||||
def setADCEnableReg(self):
|
||||
self.view.lineEditADCEnable.editingFinished.disconnect()
|
||||
try:
|
||||
mask = int(self.mainWindow.lineEditADCEnable.text(), 16)
|
||||
if self.det.tengiga:
|
||||
mask = int(self.view.lineEditADCEnable.text(), 16)
|
||||
if self.tengiga:
|
||||
self.det.adcenable10g = mask
|
||||
else:
|
||||
self.det.adcenable = mask
|
||||
@ -239,7 +253,7 @@ class AdcTab(QtWidgets.QWidget):
|
||||
def setADCEnable(self, i):
|
||||
checkBox = getattr(self.view, f"checkBoxADC{i}En")
|
||||
try:
|
||||
if self.det.tengiga:
|
||||
if self.tengiga:
|
||||
enableMask = manipulate_bit(checkBox.isChecked(), self.det.adcenable10g, i)
|
||||
self.det.adcenable10g = enableMask
|
||||
else:
|
||||
@ -265,7 +279,7 @@ class AdcTab(QtWidgets.QWidget):
|
||||
for i in range(start_nr, end_nr):
|
||||
mask = manipulate_bit(checkBox.isChecked(), mask, i)
|
||||
try:
|
||||
if self.det.tengiga:
|
||||
if self.tengiga:
|
||||
self.det.adcenable10g = mask
|
||||
else:
|
||||
self.det.adcenable = mask
|
||||
@ -344,7 +358,7 @@ class AdcTab(QtWidgets.QWidget):
|
||||
def setADCInvReg(self):
|
||||
self.view.lineEditADCInversion.editingFinished.disconnect()
|
||||
try:
|
||||
self.det.adcinvert = int(self.mainWindow.lineEditADCInversion.text(), 16)
|
||||
self.det.adcinvert = int(self.view.lineEditADCInversion.text(), 16)
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "ADC Inversion Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
pass
|
||||
@ -395,7 +409,12 @@ class AdcTab(QtWidgets.QWidget):
|
||||
self.updateADCInv()
|
||||
|
||||
def saveParameters(self) -> list[str]:
|
||||
return [
|
||||
f"adcenable {self.view.lineEditADCEnable.text()}",
|
||||
f"adcinvert {self.view.lineEditADCInversion.text()}",
|
||||
]
|
||||
if self.det.type == detectorType.CHIPTESTBOARD:
|
||||
return [
|
||||
f"adcenable {self.view.lineEditADCEnable.text()}",
|
||||
f"adcinvert {self.view.lineEditADCInversion.text()}",
|
||||
]
|
||||
else:
|
||||
return [
|
||||
f"adcenable {self.view.lineEditADCEnable.text()}"
|
||||
]
|
||||
|
@ -7,7 +7,7 @@ import zmq
|
||||
from PyQt5 import QtWidgets, uic
|
||||
import logging
|
||||
|
||||
from slsdet import readoutMode, runStatus
|
||||
from slsdet import readoutMode, runStatus, detectorType
|
||||
from pyctbgui.utils.defines import Defines
|
||||
from pyctbgui.utils.numpyWriter.npy_writer import NumpyFileManager
|
||||
from pyctbgui.utils.numpyWriter.npz_writer import NpzFileWriter
|
||||
@ -49,20 +49,37 @@ class AcquisitionTab(QtWidgets.QWidget):
|
||||
self.adcTab = self.mainWindow.adcTab
|
||||
self.plotTab = self.mainWindow.plotTab
|
||||
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):
|
||||
# For Acquistions Tab
|
||||
self.view.comboBoxROMode.currentIndexChanged.connect(self.setReadOut)
|
||||
self.view.spinBoxRunF.editingFinished.connect(self.setRunFrequency)
|
||||
self.view.spinBoxTransceiver.editingFinished.connect(self.setTransceiver)
|
||||
self.view.spinBoxAnalog.editingFinished.connect(self.setAnalog)
|
||||
self.view.spinBoxDigital.editingFinished.connect(self.setDigital)
|
||||
self.view.spinBoxADCF.editingFinished.connect(self.setADCFrequency)
|
||||
self.view.spinBoxADCPhase.editingFinished.connect(self.setADCPhase)
|
||||
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)
|
||||
|
||||
if self.det.type == detectorType.CHIPTESTBOARD:
|
||||
self.view.spinBoxRunF.editingFinished.connect(self.setRunFrequency)
|
||||
self.view.spinBoxADCF.editingFinished.connect(self.setADCFrequency)
|
||||
self.view.spinBoxADCPhase.editingFinished.connect(self.setADCPhase)
|
||||
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.checkBoxFileWriteNumpy.stateChanged.connect(self.setFileWriteNumpy)
|
||||
@ -77,16 +94,19 @@ class AcquisitionTab(QtWidgets.QWidget):
|
||||
|
||||
def refresh(self):
|
||||
self.getReadout()
|
||||
self.getRunFrequency()
|
||||
self.getTransceiver()
|
||||
self.getAnalog()
|
||||
self.getDigital()
|
||||
self.getADCFrequency()
|
||||
self.getADCPhase()
|
||||
self.getADCPipeline()
|
||||
self.getDBITFrequency()
|
||||
self.getDBITPhase()
|
||||
self.getDBITPipeline()
|
||||
|
||||
if self.det.type == detectorType.CHIPTESTBOARD:
|
||||
self.getRunFrequency()
|
||||
self.getADCFrequency()
|
||||
self.getADCPhase()
|
||||
self.getADCPipeline()
|
||||
self.getDBITFrequency()
|
||||
self.getDBITPhase()
|
||||
self.getDBITPipeline()
|
||||
|
||||
self.getFileWrite()
|
||||
self.getFileName()
|
||||
self.getFilePath()
|
||||
@ -697,23 +717,39 @@ class AcquisitionTab(QtWidgets.QWidget):
|
||||
self.socket.subscribe("")
|
||||
|
||||
def saveParameters(self) -> list[str]:
|
||||
return [
|
||||
f'romode {self.view.comboBoxROMode.currentText().lower()}',
|
||||
f'runclk {self.view.spinBoxRunF.value()}',
|
||||
f'adcclk {self.view.spinBoxADCF.value()}',
|
||||
f'adcphase {self.view.spinBoxADCPhase.value()}',
|
||||
f'adcpipeline {self.view.spinBoxADCPipeline.value()}',
|
||||
f'dbitclk {self.view.spinBoxDBITF.value()}',
|
||||
f'dbitphase {self.view.spinBoxDBITPhase.value()}',
|
||||
f'dbitpipeline {self.view.spinBoxDBITPipeline.value()}',
|
||||
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()}',
|
||||
]
|
||||
if self.det.type == detectorType.CHIPTESTBOARD:
|
||||
return [
|
||||
f'romode {self.view.comboBoxROMode.currentText().lower()}',
|
||||
f'runclk {self.view.spinBoxRunF.value()}',
|
||||
f'adcclk {self.view.spinBoxADCF.value()}',
|
||||
f'adcphase {self.view.spinBoxADCPhase.value()}',
|
||||
f'adcpipeline {self.view.spinBoxADCPipeline.value()}',
|
||||
f'dbitclk {self.view.spinBoxDBITF.value()}',
|
||||
f'dbitphase {self.view.spinBoxDBITPhase.value()}',
|
||||
f'dbitpipeline {self.view.spinBoxDBITPipeline.value()}',
|
||||
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()}',
|
||||
]
|
||||
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()}',
|
||||
]
|
||||
|
||||
|
@ -4,7 +4,7 @@ from pathlib import Path
|
||||
from PyQt5 import QtWidgets, uic
|
||||
from pyctbgui.utils.defines import Defines
|
||||
|
||||
from slsdet import dacIndex
|
||||
from slsdet import dacIndex, detectorType
|
||||
|
||||
|
||||
class DacTab(QtWidgets.QWidget):
|
||||
@ -19,7 +19,14 @@ class DacTab(QtWidgets.QWidget):
|
||||
dac = getattr(dacIndex, f"DAC_{i}")
|
||||
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.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}mV").stateChanged.connect(partial(self.getDAC, i))
|
||||
|
||||
self.view.comboBoxADCVpp.currentIndexChanged.connect(self.setADCVpp)
|
||||
self.view.spinBoxHighVoltage.editingFinished.connect(self.setHighVoltage)
|
||||
self.view.checkBoxHighVoltage.stateChanged.connect(self.setHighVoltage)
|
||||
if self.view.comboBoxADCVpp.isEnabled():
|
||||
self.view.comboBoxADCVpp.currentIndexChanged.connect(self.setADCVpp)
|
||||
if self.view.checkBoxHighVoltage.isEnabled():
|
||||
self.view.spinBoxHighVoltage.editingFinished.connect(self.setHighVoltage)
|
||||
self.view.checkBoxHighVoltage.stateChanged.connect(self.setHighVoltage)
|
||||
|
||||
def refresh(self):
|
||||
self.updateDACNames()
|
||||
@ -40,8 +49,10 @@ class DacTab(QtWidgets.QWidget):
|
||||
self.getDACTristate(i)
|
||||
self.getDAC(i)
|
||||
|
||||
self.getADCVpp()
|
||||
self.getHighVoltage()
|
||||
if self.view.comboBoxADCVpp.isEnabled():
|
||||
self.getADCVpp()
|
||||
if self.view.checkBoxHighVoltage.isEnabled():
|
||||
self.getHighVoltage()
|
||||
|
||||
def updateDACNames(self):
|
||||
for i, name in enumerate(self.det.getDacNames()):
|
||||
@ -165,6 +176,8 @@ class DacTab(QtWidgets.QWidget):
|
||||
unit = " mV" if inMV else ""
|
||||
commands.append(f"dac {i} {value}{unit}")
|
||||
|
||||
commands.append(f"adcvpp {self.view.comboBoxADCVpp.currentText()} mV")
|
||||
commands.append(f"highvoltage {self.view.spinBoxHighVoltage.value()}")
|
||||
if self.view.comboBoxADCVpp.isEnabled():
|
||||
commands.append(f"adcvpp {self.view.comboBoxADCVpp.currentText()} mV")
|
||||
if self.view.checkBoxHighVoltage.isEnabled():
|
||||
commands.append(f"highvoltage {self.view.spinBoxHighVoltage.value()}")
|
||||
return commands
|
||||
|
@ -4,7 +4,7 @@ from pathlib import Path
|
||||
from PyQt5 import QtWidgets, uic
|
||||
from pyctbgui.utils.defines import Defines
|
||||
|
||||
from slsdet import dacIndex
|
||||
from slsdet import dacIndex, detectorType
|
||||
|
||||
|
||||
class PowerSuppliesTab(QtWidgets.QWidget):
|
||||
@ -18,7 +18,8 @@ class PowerSuppliesTab(QtWidgets.QWidget):
|
||||
self.updateVoltageNames()
|
||||
for i in Defines.powerSupplies:
|
||||
self.getVoltage(i)
|
||||
self.getCurrent(i)
|
||||
if self.det.type == detectorType.CHIPTESTBOARD:
|
||||
self.getCurrent(i)
|
||||
|
||||
def connect_ui(self):
|
||||
for i in Defines.powerSupplies:
|
||||
@ -38,6 +39,12 @@ class PowerSuppliesTab(QtWidgets.QWidget):
|
||||
if retval == 0:
|
||||
checkBox.setChecked(False)
|
||||
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):
|
||||
retval = self.det.getPowerNames()
|
||||
@ -56,7 +63,10 @@ class PowerSuppliesTab(QtWidgets.QWidget):
|
||||
spinBox.editingFinished.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)
|
||||
if retval > 1:
|
||||
checkBox.setChecked(True)
|
||||
@ -68,8 +78,9 @@ class PowerSuppliesTab(QtWidgets.QWidget):
|
||||
|
||||
spinBox.editingFinished.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)
|
||||
|
||||
@ -91,7 +102,8 @@ class PowerSuppliesTab(QtWidgets.QWidget):
|
||||
# TODO: (properly) disconnecting and connecting to handle multiple events (out of focus and pressing enter).
|
||||
spinBox.editingFinished.connect(partial(self.setVoltage, i))
|
||||
self.getVoltage(i)
|
||||
self.getCurrent(i)
|
||||
if self.det.type == detectorType.CHIPTESTBOARD:
|
||||
self.getCurrent(i)
|
||||
|
||||
def getCurrent(self, i):
|
||||
label = getattr(self.view, f"labelI{i}")
|
||||
|
@ -4,7 +4,7 @@ from pathlib import Path
|
||||
from PyQt5 import uic, QtWidgets
|
||||
|
||||
from pyctbgui.utils.defines import Defines
|
||||
from slsdet import dacIndex
|
||||
from slsdet import dacIndex, detectorType
|
||||
|
||||
|
||||
class SlowAdcTab(QtWidgets.QWidget):
|
||||
@ -17,7 +17,8 @@ class SlowAdcTab(QtWidgets.QWidget):
|
||||
self.det = None
|
||||
|
||||
def setup_ui(self):
|
||||
pass
|
||||
if self.det.type == detectorType.XILINX_CHIPTESTBOARD:
|
||||
self.view.pushButtonTemp.setDisabled(True)
|
||||
|
||||
def connect_ui(self):
|
||||
for i in range(Defines.slowAdc.count):
|
||||
@ -28,7 +29,8 @@ class SlowAdcTab(QtWidgets.QWidget):
|
||||
self.updateSlowAdcNames()
|
||||
for i in range(Defines.slowAdc.count):
|
||||
self.updateSlowAdc(i)
|
||||
self.updateTemperature()
|
||||
if self.det.type == detectorType.CHIPTESTBOARD:
|
||||
self.updateTemperature()
|
||||
|
||||
def updateSlowAdcNames(self):
|
||||
for i, name in enumerate(self.mainWindow.det.getSlowADCNames()):
|
||||
|
@ -817,7 +817,7 @@ Only pressing enter on spinbox will set DAC (with this condition).</string>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="18" column="0">
|
||||
<widget class="QLabel" name="label_125">
|
||||
<widget class="QLabel" name="labelADCVppDacName">
|
||||
<property name="text">
|
||||
<string>ADC_VPP</string>
|
||||
</property>
|
||||
|
@ -118,7 +118,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<widget class="QLabel" name="label_70">
|
||||
<widget class="QLabel" name="labelRunF">
|
||||
<property name="text">
|
||||
<string>Run Clock Frequency (MHz):</string>
|
||||
</property>
|
||||
@ -218,7 +218,7 @@
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<item row="2" column="3">
|
||||
<widget class="QLabel" name="label_74">
|
||||
<widget class="QLabel" name="labelDBITF">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
@ -231,7 +231,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_71">
|
||||
<widget class="QLabel" name="labelADCF">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
@ -278,7 +278,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<widget class="QLabel" name="label_76">
|
||||
<widget class="QLabel" name="labelDBITPipeline">
|
||||
<property name="text">
|
||||
<string>DBIT Pipeline:</string>
|
||||
</property>
|
||||
@ -338,21 +338,21 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_73">
|
||||
<widget class="QLabel" name="labelADCPipeline">
|
||||
<property name="text">
|
||||
<string>ADC Pipeline:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_72">
|
||||
<widget class="QLabel" name="labelADCPhase">
|
||||
<property name="text">
|
||||
<string>ADC Clock Phase (a.u.):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QLabel" name="label_75">
|
||||
<widget class="QLabel" name="labelDBITPhase">
|
||||
<property name="text">
|
||||
<string>DBIT Clock Phase (a.u.):</string>
|
||||
</property>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<widget class="QFrame" name="frame_7">
|
||||
<widget class="QFrame" name="frame_ADC">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
@ -3142,7 +3142,7 @@
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_20">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_67">
|
||||
<widget class="QLabel" name="labelADCInversion">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
@ -3188,7 +3188,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLabel" name="label_68">
|
||||
<widget class="QLabel" name="labelADCEnable">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<widget class="QFrame" name="frame_4">
|
||||
<widget class="QFrame" name="frame_slowadcs">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
19
python/scripts/frameSynchronizerPullSocket.py
Normal file
19
python/scripts/frameSynchronizerPullSocket.py
Normal 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("--------")
|
||||
|
@ -123,6 +123,9 @@ def visit(node):
|
||||
if node.kind == cindex.CursorKind.CLASS_DECL:
|
||||
if node.displayname == "Detector":
|
||||
for child in node.get_children():
|
||||
# Skip assignment operators
|
||||
if child.kind == cindex.CursorKind.CXX_METHOD and child.spelling == "operator=":
|
||||
continue
|
||||
if (
|
||||
child.kind == cindex.CursorKind.CXX_METHOD
|
||||
and child.access_specifier == cindex.AccessSpecifier.PUBLIC
|
||||
|
@ -151,6 +151,10 @@ class Detector(CppDetectorApi):
|
||||
def hostname(self):
|
||||
"""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.
|
||||
|
||||
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
|
||||
-------
|
||||
@ -2566,7 +2570,7 @@ class Detector(CppDetectorApi):
|
||||
|
||||
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.
|
||||
"""
|
||||
return self.getAutoComparatorDisable()
|
||||
@ -2580,10 +2584,6 @@ class Detector(CppDetectorApi):
|
||||
def compdisabletime(self):
|
||||
"""[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
|
||||
|
||||
Example
|
||||
@ -2913,7 +2913,7 @@ class Detector(CppDetectorApi):
|
||||
@property
|
||||
@element
|
||||
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
|
||||
"""
|
||||
return self.getTimingInfoDecoder()
|
||||
|
@ -1 +0,0 @@
|
||||
../slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServerv9.0.0
|
1
serverBin/ctbDetectorServerv9.1.0
Symbolic link
1
serverBin/ctbDetectorServerv9.1.0
Symbolic link
@ -0,0 +1 @@
|
||||
../slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServerv9.1.0
|
@ -1 +0,0 @@
|
||||
../slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServerv9.0.0
|
1
serverBin/jungfrauDetectorServerv9.1.0
Symbolic link
1
serverBin/jungfrauDetectorServerv9.1.0
Symbolic link
@ -0,0 +1 @@
|
||||
../slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServerv9.1.0
|
@ -1 +0,0 @@
|
||||
../slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServerv9.0.0
|
1
serverBin/mythen3DetectorServerv9.1.0
Symbolic link
1
serverBin/mythen3DetectorServerv9.1.0
Symbolic link
@ -0,0 +1 @@
|
||||
../slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServerv9.1.0
|
@ -1 +0,0 @@
|
||||
../slsDetectorServers/xilinx_ctbDetectorServer/bin/xilinx_ctbDetectorServerv9.0.0
|
1
serverBin/xilinx_ctbDetectorServerv9.1.0
Symbolic link
1
serverBin/xilinx_ctbDetectorServerv9.1.0
Symbolic link
@ -0,0 +1 @@
|
||||
../slsDetectorServers/xilinx_ctbDetectorServer/bin/xilinx_ctbDetectorServerv9.1.0
|
@ -503,6 +503,7 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
|
||||
}
|
||||
#endif
|
||||
if (ee == PHOTON && val[iy * nx + ix] == max) {
|
||||
good = 1;
|
||||
ee = PHOTON_MAX;
|
||||
// cout << "**" <<id<< " " << iframe << " " << nDark << " "
|
||||
// << ix << " " << iy << " " << rms << " " << max << " " <<
|
||||
@ -536,7 +537,6 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
|
||||
cout << max << " " << val[iy * nx + ix] << endl;
|
||||
}
|
||||
//else (clusters + nph)->print();
|
||||
good = 1;
|
||||
if (eMin > 0 && tot < eMin)
|
||||
good = 0;
|
||||
if (eMax > 0 && tot > eMax)
|
||||
|
@ -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>
|
||||
static void HandleExceptions(const std::string emsg, const std::string src,
|
||||
S *s, RT (S::*somefunc)(CT...),
|
||||
|
Binary file not shown.
@ -17,7 +17,7 @@
|
||||
#define BUFFERSIZE 16
|
||||
#define I2C_DEVICE_FILE "/dev/i2c-0"
|
||||
#define I2C_DEVICE_ADDRESS 0x4C
|
||||
//#define I2C_DEVICE_ADDRESS 0x48
|
||||
// #define I2C_DEVICE_ADDRESS 0x48
|
||||
#define I2C_REGISTER_ADDRESS 0x40
|
||||
|
||||
int i2c_open(const char *file, unsigned int addr) {
|
||||
|
@ -98,8 +98,8 @@
|
||||
// everything at ~200 kHz (200 kHz MHz ddr readout)
|
||||
#define DAQ_CHIP_CONTROLLER_SUPER_SLOW_SPEED 0x000c0000
|
||||
|
||||
//#define DAQ_FIFO_ENABLE 0x00100000 commented out as it
|
||||
// is not used anywhere
|
||||
// #define DAQ_FIFO_ENABLE 0x00100000 commented out as it
|
||||
// is not used anywhere
|
||||
#define DAQ_REG_CHIP_CMDS_INT_TRIGGER 0x00100000
|
||||
|
||||
// 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_RATE_CORRECTION 0x40000000
|
||||
|
||||
//#define DAQ_MASTER_HALF_MODULE 0x80000000 currently not
|
||||
// used
|
||||
// #define DAQ_MASTER_HALF_MODULE 0x80000000 currently
|
||||
// not
|
||||
// used
|
||||
|
||||
// chips static bits
|
||||
#define DAQ_STATIC_BIT_PROGRAM 0x00000001
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#pragma once
|
||||
|
||||
//#include "types.h"
|
||||
// #include "types.h"
|
||||
#include <stdint.h>
|
||||
/******************************************************************************/
|
||||
/* types */
|
||||
|
@ -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
|
||||
|
||||
/* 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 */
|
||||
#define XPAR_PLB_LL_FIFO_AURORA_DUAL_CTRL_FEB_RIGHT_BASEADDR 0xC4110000
|
||||
|
@ -22,13 +22,13 @@
|
||||
((0x1 << GAIN_CONFGAIN_OFST) & GAIN_CONFGAIN_MSK)
|
||||
|
||||
/** Flow Control register */
|
||||
//#define FLOW_CONTROL_REG (0x11 << MEM_MAP_SHIFT)
|
||||
// #define FLOW_CONTROL_REG (0x11 << MEM_MAP_SHIFT)
|
||||
|
||||
/** Flow Status register */
|
||||
//#define FLOW_STATUS_REG (0x12 << MEM_MAP_SHIFT)
|
||||
// #define FLOW_STATUS_REG (0x12 << MEM_MAP_SHIFT)
|
||||
|
||||
/** Frame register */
|
||||
//#define FRAME_REG (0x13 << MEM_MAP_SHIFT)
|
||||
// #define FRAME_REG (0x13 << MEM_MAP_SHIFT)
|
||||
|
||||
/** Multi Purpose register */
|
||||
#define MULTI_PURPOSE_REG (0x14 << MEM_MAP_SHIFT)
|
||||
@ -79,7 +79,7 @@
|
||||
((0x0007f << DAQ_PCKT_LNGTH_OFST) & DAQ_PCKT_LNGTH_MSK)
|
||||
|
||||
/** 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 */
|
||||
#define SPI_REG (0x17 << MEM_MAP_SHIFT)
|
||||
@ -139,7 +139,7 @@
|
||||
((0x1b << ADC_SYNC_ENET_DELAY_OFST) & ADC_SYNC_ENET_DELAY_MSK)
|
||||
|
||||
/** Time From Start register */
|
||||
//#define MU_TIME_REG (0x1a << MEM_MAP_SHIFT)
|
||||
// #define MU_TIME_REG (0x1a << MEM_MAP_SHIFT)
|
||||
|
||||
/** Temperatre SPI In register */
|
||||
#define TEMP_SPI_IN_REG (0x1b << MEM_MAP_SHIFT)
|
||||
@ -171,7 +171,7 @@
|
||||
#define ENET_CONF_REG (0x1e << MEM_MAP_SHIFT)
|
||||
|
||||
/** 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 */
|
||||
#define HV_REG (0x20 << MEM_MAP_SHIFT)
|
||||
@ -288,10 +288,10 @@
|
||||
((0x4 << EXT_SIGNAL_OFST) & EXT_SIGNAL_MSK)
|
||||
|
||||
/** 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 */
|
||||
//#define FPGA_SVN_REG (0x29 << MEM_MAP_SHIFT)
|
||||
// #define FPGA_SVN_REG (0x29 << MEM_MAP_SHIFT)
|
||||
|
||||
/** Chip of Interest register */
|
||||
#define CHIP_OF_INTRST_REG (0x2a << MEM_MAP_SHIFT)
|
||||
@ -303,7 +303,7 @@
|
||||
(0x0000FFFF << CHIP_OF_INTRST_NUM_CHNNLS_OFST)
|
||||
|
||||
/** Out MUX register */
|
||||
//#define OUT_MUX_REG (0x2b << MEM_MAP_SHIFT)
|
||||
// #define OUT_MUX_REG (0x2b << MEM_MAP_SHIFT)
|
||||
|
||||
/** Board Version register */
|
||||
#define BOARD_REVISION_REG (0x2c << MEM_MAP_SHIFT)
|
||||
@ -312,29 +312,29 @@
|
||||
#define BOARD_REVISION_MSK (0x0000FFFF << BOARD_REVISION_OFST)
|
||||
#define DETECTOR_TYPE_OFST (16)
|
||||
#define DETECTOR_TYPE_MSK (0x0000000F << DETECTOR_TYPE_OFST)
|
||||
//#define DETECTOR_TYPE_GOTTHARD_VAL (??)
|
||||
// #define DETECTOR_TYPE_GOTTHARD_VAL (??)
|
||||
#define DETECTOR_TYPE_MOENCH_VAL (2)
|
||||
|
||||
/** Memory Test register */
|
||||
//#define MEMORY_TEST_REG (0x2d << MEM_MAP_SHIFT)
|
||||
// #define MEMORY_TEST_REG (0x2d << MEM_MAP_SHIFT)
|
||||
|
||||
/** Hit Threshold register */
|
||||
//#define HIT_THRESHOLD_REG (0x2e << MEM_MAP_SHIFT)
|
||||
// #define HIT_THRESHOLD_REG (0x2e << MEM_MAP_SHIFT)
|
||||
|
||||
/** Hit Count register */
|
||||
//#define HIT_COUNT_REG (0x2f << MEM_MAP_SHIFT)
|
||||
// #define HIT_COUNT_REG (0x2f << MEM_MAP_SHIFT)
|
||||
|
||||
/* 16 bit Fifo Data register */
|
||||
#define FIFO_DATA_REG (0x50 << MEM_MAP_SHIFT) // Not used in FW and SW (16bit)
|
||||
|
||||
/** 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 */
|
||||
//#define DACS_SET_2_REG (0x66 << MEM_MAP_SHIFT)
|
||||
// #define DACS_SET_2_REG (0x66 << MEM_MAP_SHIFT)
|
||||
|
||||
/** 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 */
|
||||
#define SET_DELAY_LSB_REG (0x68 << MEM_MAP_SHIFT)
|
||||
@ -377,12 +377,12 @@
|
||||
#define GET_EXPTIME_MSB_REG (0x7b << MEM_MAP_SHIFT)
|
||||
|
||||
/* Set Gates 64 bit register */
|
||||
//#define SET_GATES_LSB_REG (0x7c << MEM_MAP_SHIFT)
|
||||
//#define SET_GATES_MSB_REG (0x7d << MEM_MAP_SHIFT)
|
||||
// #define SET_GATES_LSB_REG (0x7c << MEM_MAP_SHIFT)
|
||||
// #define SET_GATES_MSB_REG (0x7d << MEM_MAP_SHIFT)
|
||||
|
||||
/* Set Gates 64 bit register */
|
||||
//#define GET_GATES_LSB_REG (0x7e << MEM_MAP_SHIFT)
|
||||
//#define GET_GATES_MSB_REG (0x7f << MEM_MAP_SHIFT)
|
||||
// #define GET_GATES_LSB_REG (0x7e << MEM_MAP_SHIFT)
|
||||
// #define GET_GATES_MSB_REG (0x7f << MEM_MAP_SHIFT)
|
||||
|
||||
/* Dark Image starting address */
|
||||
#define DARK_IMAGE_REG (0x81 << MEM_MAP_SHIFT)
|
||||
|
Binary file not shown.
BIN
slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServerv9.1.0
Executable file
BIN
slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServerv9.1.0
Executable file
Binary file not shown.
@ -1974,9 +1974,6 @@ int autoCompDisable(int on) {
|
||||
}
|
||||
|
||||
int setComparatorDisableTime(int64_t val) {
|
||||
if (getChipVersion() != 11) {
|
||||
return FAIL;
|
||||
}
|
||||
if (val < 0) {
|
||||
LOG(logERROR,
|
||||
("Invalid comp disable time: %lld ns\n", (long long int)val));
|
||||
@ -2817,7 +2814,8 @@ void *start_timer(void *arg) {
|
||||
getNextFrameNumber(&frameNr);
|
||||
int iRxEntry = firstDest;
|
||||
for (int iframes = 0; iframes != numFrames; ++iframes) {
|
||||
usleep(transmissionDelayUs);
|
||||
if (transmissionDelayUs)
|
||||
usleep(transmissionDelayUs);
|
||||
|
||||
// check if manual stop
|
||||
if (sharedMemory_getStop() == 1) {
|
||||
|
@ -5,8 +5,8 @@
|
||||
#include "sls/sls_detector_defs.h"
|
||||
|
||||
#define MIN_REQRD_VRSN_T_RD_API 0x171220
|
||||
#define REQRD_FRMWRE_VRSN_BOARD2 0x230920 // 1.0 pcb (version = 010)
|
||||
#define REQRD_FRMWRE_VRSN 0x230921 // 2.0 pcb (version = 011)
|
||||
#define REQRD_FRMWRE_VRSN_BOARD2 0x250209 // 1.0 pcb (version = 010)
|
||||
#define REQRD_FRMWRE_VRSN 0x250208 // 2.0 pcb (version = 011)
|
||||
|
||||
#define NUM_HARDWARE_VERSIONS (2)
|
||||
#define HARDWARE_VERSION_NUMBERS \
|
||||
|
@ -1927,7 +1927,8 @@ void *start_timer(void *arg) {
|
||||
getNextFrameNumber(&frameNr);
|
||||
int iRxEntry = firstDest;
|
||||
for (int iframes = 0; iframes != numFrames; ++iframes) {
|
||||
usleep(transmissionDelayUs);
|
||||
if (transmissionDelayUs)
|
||||
usleep(transmissionDelayUs);
|
||||
|
||||
// check if manual stop
|
||||
if (sharedMemory_getStop() == 1) {
|
||||
|
Binary file not shown.
@ -39,8 +39,8 @@ patternParameters *setChipStatusRegisterPattern(int csr) {
|
||||
patword = clearBit(SIGNAL_resCounter, patword);
|
||||
for (int i = 0; i < 8; i++)
|
||||
pat->word[iaddr++] = patword;
|
||||
//#This version of the serializer pushes in the MSB first (compatible with
|
||||
// the CSR bit numbering)
|
||||
// #This version of the serializer pushes in the MSB first (compatible with
|
||||
// the CSR bit numbering)
|
||||
for (int ib = nbits - 1; ib >= 0; ib--) {
|
||||
if (csr & (1 << ib))
|
||||
patword = setBit(SIGNAL_serialIN, patword);
|
||||
|
@ -38,11 +38,11 @@
|
||||
#define CSR_invpol 4
|
||||
#define CSR_dpulse 5
|
||||
#define CSR_interp 6
|
||||
#define _CSR_C10pre 7 //#default, negative polarity
|
||||
#define _CSR_C10pre 7 // #default, negative polarity
|
||||
#define CSR_pumprobe 8
|
||||
#define CSR_apulse 9
|
||||
#define CSR_C15sh 10
|
||||
#define CSR_C30sh 11 //#default
|
||||
#define CSR_C30sh 11 // #default
|
||||
#define CSR_C50sh 12
|
||||
#define CSR_C225ACsh \
|
||||
13 // Connects 225fF SHAPER AC cap (1: 225 to shaper, 225 to GND. 0: 450 to
|
||||
|
@ -50,7 +50,7 @@
|
||||
#define DEFAULT_NUM_CYCLES (1)
|
||||
#define DEFAULT_GATE_WIDTH (100 * 1000 * 1000) // ns
|
||||
#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_HIGH_VOLTAGE (0)
|
||||
#define DEFAULT_TIMING_MODE (AUTO_TIMING)
|
||||
|
@ -106,9 +106,9 @@
|
||||
(0x0000FFFF << I2C_SDA_HOLD_COUNT_PERIOD_OFST)
|
||||
|
||||
/** Receive Data Fifo Level register */
|
||||
//#define I2C_RX_DATA_FIFO_LVL_OFST (0)
|
||||
//#define I2C_RX_DATA_FIFO_LVL_MSK (0x000000FF <<
|
||||
// I2C_RX_DATA_FIFO_LVL_OFST)
|
||||
// #define I2C_RX_DATA_FIFO_LVL_OFST (0)
|
||||
// #define I2C_RX_DATA_FIFO_LVL_MSK (0x000000FF <<
|
||||
// I2C_RX_DATA_FIFO_LVL_OFST)
|
||||
|
||||
// defines in the fpga
|
||||
uint32_t I2C_Control_Reg = 0x0;
|
||||
|
@ -622,7 +622,7 @@ void getIpAddressinString(char *cip, uint32_t ip) {
|
||||
inet_ntop(AF_INET, &ip, cip, INET_ADDRSTRLEN);
|
||||
#else
|
||||
sprintf(cip, "%d.%d.%d.%d", (ip >> 24) & 0xff, (ip >> 16) & 0xff,
|
||||
(ip >> 8) & 0xff, (ip)&0xff);
|
||||
(ip >> 8) & 0xff, (ip) & 0xff);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -2013,102 +2013,106 @@ int acquire(int blocking, int file_des) {
|
||||
#if defined(JUNGFRAUD)
|
||||
// chipv1.1 has to be configured before acquisition
|
||||
if (getChipVersion() == 11 && !isChipConfigured()) {
|
||||
ret = FAIL;
|
||||
strcpy(mess, "Could not start acquisition. Chip is not configured. "
|
||||
"Power it on to configure it.\n");
|
||||
LOG(logERROR, (mess));
|
||||
} else
|
||||
ret = FAIL;
|
||||
strcpy(mess,
|
||||
"Could not start acquisition. Chip is not configured. "
|
||||
"Power it on to configure it.\n");
|
||||
LOG(logERROR, (mess));
|
||||
} else
|
||||
#endif
|
||||
#if defined(CHIPTESTBOARDD) || defined(XILINX_CHIPTESTBOARDD)
|
||||
if ((getReadoutMode() == ANALOG_AND_DIGITAL ||
|
||||
getReadoutMode() == ANALOG_ONLY) &&
|
||||
(getNumAnalogSamples() <= 0)) {
|
||||
ret = FAIL;
|
||||
sprintf(mess,
|
||||
"Could not start acquisition. Invalid number of analog "
|
||||
"samples: %d.\n",
|
||||
getNumAnalogSamples());
|
||||
LOG(logERROR, (mess));
|
||||
} else if ((getReadoutMode() == ANALOG_AND_DIGITAL ||
|
||||
getReadoutMode() == DIGITAL_ONLY ||
|
||||
getReadoutMode() == DIGITAL_AND_TRANSCEIVER) &&
|
||||
(getNumDigitalSamples() <= 0)) {
|
||||
ret = FAIL;
|
||||
sprintf(mess,
|
||||
if ((getReadoutMode() == ANALOG_AND_DIGITAL ||
|
||||
getReadoutMode() == ANALOG_ONLY) &&
|
||||
(getNumAnalogSamples() <= 0)) {
|
||||
ret = FAIL;
|
||||
sprintf(mess,
|
||||
"Could not start acquisition. Invalid number of analog "
|
||||
"samples: %d.\n",
|
||||
getNumAnalogSamples());
|
||||
LOG(logERROR, (mess));
|
||||
} else if ((getReadoutMode() == ANALOG_AND_DIGITAL ||
|
||||
getReadoutMode() == DIGITAL_ONLY ||
|
||||
getReadoutMode() == DIGITAL_AND_TRANSCEIVER) &&
|
||||
(getNumDigitalSamples() <= 0)) {
|
||||
ret = FAIL;
|
||||
sprintf(
|
||||
mess,
|
||||
"Could not start acquisition. Invalid number of digital "
|
||||
"samples: %d.\n",
|
||||
getNumDigitalSamples());
|
||||
LOG(logERROR, (mess));
|
||||
} else if ((getReadoutMode() == TRANSCEIVER_ONLY ||
|
||||
getReadoutMode() == DIGITAL_AND_TRANSCEIVER) &&
|
||||
(getNumTransceiverSamples() <= 0)) {
|
||||
ret = FAIL;
|
||||
sprintf(mess,
|
||||
"Could not start acquisition. Invalid number of "
|
||||
"transceiver "
|
||||
"samples: %d.\n",
|
||||
getNumTransceiverSamples());
|
||||
LOG(logERROR, (mess));
|
||||
} else
|
||||
LOG(logERROR, (mess));
|
||||
} else if ((getReadoutMode() == TRANSCEIVER_ONLY ||
|
||||
getReadoutMode() == DIGITAL_AND_TRANSCEIVER) &&
|
||||
(getNumTransceiverSamples() <= 0)) {
|
||||
ret = FAIL;
|
||||
sprintf(mess,
|
||||
"Could not start acquisition. Invalid number of "
|
||||
"transceiver "
|
||||
"samples: %d.\n",
|
||||
getNumTransceiverSamples());
|
||||
LOG(logERROR, (mess));
|
||||
} else
|
||||
#endif
|
||||
#ifdef EIGERD
|
||||
// check for hardware mac and hardware ip
|
||||
if (udpDetails[0].srcmac != getDetectorMAC()) {
|
||||
ret = FAIL;
|
||||
uint64_t sourcemac = getDetectorMAC();
|
||||
char src_mac[MAC_ADDRESS_SIZE];
|
||||
getMacAddressinString(src_mac, MAC_ADDRESS_SIZE, sourcemac);
|
||||
sprintf(mess,
|
||||
"Invalid udp source mac address for this detector. "
|
||||
"Must be "
|
||||
"same as hardware detector mac address %s\n",
|
||||
src_mac);
|
||||
LOG(logERROR, (mess));
|
||||
} else if (!enableTenGigabitEthernet(GET_FLAG) &&
|
||||
(udpDetails[0].srcip != getDetectorIP())) {
|
||||
ret = FAIL;
|
||||
uint32_t sourceip = getDetectorIP();
|
||||
char src_ip[INET_ADDRSTRLEN];
|
||||
getIpAddressinString(src_ip, sourceip);
|
||||
sprintf(mess,
|
||||
"Invalid udp source ip address for this detector. Must "
|
||||
"be "
|
||||
"same as hardware detector ip address %s in 1G readout "
|
||||
"mode \n",
|
||||
src_ip);
|
||||
LOG(logERROR, (mess));
|
||||
} else
|
||||
#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);
|
||||
// check for hardware mac and hardware ip
|
||||
if (udpDetails[0].srcmac != getDetectorMAC()) {
|
||||
ret = FAIL;
|
||||
uint64_t sourcemac = getDetectorMAC();
|
||||
char src_mac[MAC_ADDRESS_SIZE];
|
||||
getMacAddressinString(src_mac, MAC_ADDRESS_SIZE, sourcemac);
|
||||
sprintf(mess,
|
||||
"Invalid udp source mac address for this detector. "
|
||||
"Must be "
|
||||
"same as hardware detector mac address %s\n",
|
||||
src_mac);
|
||||
LOG(logERROR, (mess));
|
||||
} else if (!enableTenGigabitEthernet(GET_FLAG) &&
|
||||
(udpDetails[0].srcip != getDetectorIP())) {
|
||||
ret = FAIL;
|
||||
uint32_t sourceip = getDetectorIP();
|
||||
char src_ip[INET_ADDRSTRLEN];
|
||||
getIpAddressinString(src_ip, sourceip);
|
||||
sprintf(
|
||||
mess,
|
||||
"Invalid udp source ip address for this detector. Must "
|
||||
"be "
|
||||
"same as hardware detector ip address %s in 1G readout "
|
||||
"mode \n",
|
||||
src_ip);
|
||||
LOG(logERROR, (mess));
|
||||
} 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);
|
||||
}
|
||||
@ -9086,16 +9090,9 @@ int get_comp_disable_time(int file_des) {
|
||||
functionNotImplemented();
|
||||
#else
|
||||
// get only
|
||||
if (getChipVersion() != 11) {
|
||||
ret = FAIL;
|
||||
strcpy(mess,
|
||||
"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));
|
||||
}
|
||||
retval = getComparatorDisableTime();
|
||||
LOG(logDEBUG1,
|
||||
("retval comp disable time %lld ns\n", (long long int)retval));
|
||||
#endif
|
||||
return Server_SendResult(file_des, INT64, &retval, sizeof(retval));
|
||||
}
|
||||
@ -9113,23 +9110,16 @@ int set_comp_disable_time(int file_des) {
|
||||
#else
|
||||
// only set
|
||||
if (Server_VerifyLock() == OK) {
|
||||
if (getChipVersion() != 11) {
|
||||
ret = FAIL;
|
||||
strcpy(mess, "Cannot get comparator disable time. Only valid for "
|
||||
"chipv1.1\n");
|
||||
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));
|
||||
} 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
|
||||
@ -11100,11 +11090,18 @@ int get_timing_info_decoder(int file_des) {
|
||||
functionNotImplemented();
|
||||
#else
|
||||
// get only
|
||||
ret = getTimingInfoDecoder(&retval);
|
||||
LOG(logDEBUG1, ("retval timing info decoder: %d\n", retval));
|
||||
if (ret == FAIL) {
|
||||
strcpy(mess, "Could not get timing info decoder\n");
|
||||
if (isHardwareVersion_1_0()) {
|
||||
ret = FAIL;
|
||||
sprintf(mess, "Could not get timing info decoder. Not supported "
|
||||
"for hardware version 1.0\n");
|
||||
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
|
||||
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);
|
||||
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) {
|
||||
ret = setTimingInfoDecoder(arg);
|
||||
if (ret == FAIL) {
|
||||
|
@ -7,7 +7,12 @@ support_lib = ../../slsSupportLib/include/
|
||||
det_lib = ../../slsDetectorSoftware/include/sls/
|
||||
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
|
||||
#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
|
||||
|
Binary file not shown.
@ -1056,7 +1056,7 @@ int getPower(enum DACINDEX ind) {
|
||||
|
||||
// dac powered off
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -1505,6 +1505,7 @@ fi
|
||||
if [[ ${IS_GET} -eq 0 ]]; then
|
||||
if [[ "${cword}" == "2" ]]; then
|
||||
FCN_RETURN=""
|
||||
IS_PATH=1
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
@ -1514,6 +1515,7 @@ FCN_RETURN=""
|
||||
if [[ ${IS_GET} -eq 1 ]]; then
|
||||
if [[ "${cword}" == "2" ]]; then
|
||||
FCN_RETURN=""
|
||||
IS_PATH=1
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
|
@ -1429,6 +1429,7 @@ fi
|
||||
if [[ ${IS_GET} -eq 0 ]]; then
|
||||
if [[ "${cword}" == "2" ]]; then
|
||||
FCN_RETURN=""
|
||||
IS_PATH=1
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
@ -1438,6 +1439,7 @@ FCN_RETURN=""
|
||||
if [[ ${IS_GET} -eq 1 ]]; then
|
||||
if [[ "${cword}" == "2" ]]; then
|
||||
FCN_RETURN=""
|
||||
IS_PATH=1
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
|
@ -468,7 +468,7 @@ subdeadtime:
|
||||
function: setSubDeadTime
|
||||
|
||||
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
|
||||
actions:
|
||||
GET:
|
||||
@ -1123,7 +1123,7 @@ temp_control:
|
||||
input_types: [ bool ]
|
||||
|
||||
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
|
||||
actions:
|
||||
GET:
|
||||
@ -1210,7 +1210,7 @@ polarity:
|
||||
input_types: [ defs::polarity ]
|
||||
|
||||
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
|
||||
actions:
|
||||
GET:
|
||||
@ -3429,7 +3429,7 @@ udp_dstlist:
|
||||
output: [ ToString(args) ]
|
||||
|
||||
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:
|
||||
GET:
|
||||
argc: 0
|
||||
@ -3884,8 +3884,8 @@ patternX:
|
||||
require_det_id: true
|
||||
function: setPattern
|
||||
input: [ 'args[0]' ]
|
||||
arg_types: [special::path]
|
||||
input_types: [ std::string ]
|
||||
cast_input: [ false ]
|
||||
output: [ 'args.front()' ]
|
||||
|
||||
patword:
|
||||
|
@ -762,10 +762,9 @@ autocompdisable:
|
||||
function_alias: 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. "
|
||||
\ - 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. "
|
||||
infer_action: true
|
||||
template: true
|
||||
badchannels:
|
||||
@ -1607,7 +1606,7 @@ compdisabletime:
|
||||
command_name: compdisabletime
|
||||
function_alias: 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."
|
||||
\ exposure when comparator is disabled."
|
||||
infer_action: true
|
||||
template: true
|
||||
confadc:
|
||||
@ -6539,7 +6538,7 @@ patternX:
|
||||
PUT:
|
||||
args:
|
||||
- arg_types:
|
||||
- std::string
|
||||
- special::path
|
||||
argc: 1
|
||||
cast_input:
|
||||
- false
|
||||
@ -11488,7 +11487,8 @@ timing_info_decoder:
|
||||
command_name: timing_info_decoder
|
||||
function_alias: 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."
|
||||
\ Shine. Sets the bunch id or timing info decoder. Default is swissfel. Only allowed\
|
||||
\ for pcbv2.0."
|
||||
infer_action: true
|
||||
template: true
|
||||
timinglist:
|
||||
@ -11915,7 +11915,7 @@ 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\
|
||||
\ * 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."
|
||||
infer_action: true
|
||||
|
@ -65,7 +65,12 @@ class Detector {
|
||||
|
||||
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);
|
||||
|
||||
/** connects to n servers at local host starting at specific control port.
|
||||
@ -1304,11 +1309,9 @@ class Detector {
|
||||
* //TODO naming
|
||||
* 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 for chipv1.0. One can set the duration for chipv1.1 using
|
||||
* setComparatorDisableTime\n Default is false or this mode
|
||||
* disabled(comparator enabled throughout). true enables mode. 0 disables
|
||||
* mode.
|
||||
* automatically and the duration is set using setComparatorDisableTime\n
|
||||
* Default is false or this mode disabled(comparator enabled throughout).
|
||||
* true enables mode. 0 disables mode.
|
||||
*/
|
||||
void setAutoComparatorDisable(bool value, Positions pos = {});
|
||||
|
||||
@ -1316,7 +1319,7 @@ class Detector {
|
||||
Result<ns> getComparatorDisableTime(Positions pos = {}) const;
|
||||
|
||||
/** [Jungfrau] Time before end of exposure when comparator is
|
||||
* disabled. It is only possible for chipv1.1.*/
|
||||
* disabled.*/
|
||||
void setComparatorDisableTime(ns t, Positions pos = {});
|
||||
|
||||
/** [Jungfrau] Advanced TODO naming */
|
||||
@ -1382,7 +1385,7 @@ class Detector {
|
||||
Result<defs::timingInfoDecoder>
|
||||
getTimingInfoDecoder(Positions pos = {}) const;
|
||||
|
||||
/** [Jungfrau] Advanced Command! */
|
||||
/** [Jungfrau] Advanced Command! Only for pcb v2.0 */
|
||||
void setTimingInfoDecoder(defs::timingInfoDecoder value,
|
||||
Positions pos = {});
|
||||
|
||||
@ -1749,7 +1752,8 @@ class Detector {
|
||||
Result<std::vector<int>> getRxDbitList(Positions pos = {}) const;
|
||||
|
||||
/** [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 = {});
|
||||
|
||||
/** [CTB] */
|
||||
|
@ -1018,7 +1018,7 @@ std::string Caller::autocompdisable(int action) {
|
||||
// print help
|
||||
if (action == slsDetectorDefs::HELP_ACTION) {
|
||||
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"
|
||||
<< std::endl;
|
||||
return os.str();
|
||||
@ -2108,7 +2108,7 @@ std::string Caller::compdisabletime(int action) {
|
||||
// print help
|
||||
if (action == slsDetectorDefs::HELP_ACTION) {
|
||||
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;
|
||||
return os.str();
|
||||
}
|
||||
@ -14744,7 +14744,7 @@ std::string Caller::timing_info_decoder(int action) {
|
||||
// print help
|
||||
if (action == slsDetectorDefs::HELP_ACTION) {
|
||||
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;
|
||||
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] txdelay_left to (2 * mod_index * n_delay),
|
||||
[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"
|
||||
<< std::endl;
|
||||
return os.str();
|
||||
|
@ -210,7 +210,12 @@ std::string Caller::hostname(int action) {
|
||||
os << "\n\tFrees shared memory and sets hostname (or IP address) of "
|
||||
"all modules concatenated by +.\n\t Virtual servers can already "
|
||||
"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';
|
||||
} else if (action == defs::GET_ACTION) {
|
||||
if (!args.empty()) {
|
||||
@ -1020,10 +1025,16 @@ std::string Caller::slowadc(int action) {
|
||||
std::string Caller::rx_dbitlist(int action) {
|
||||
std::ostringstream os;
|
||||
if (action == defs::HELP_ACTION) {
|
||||
os << "[all] or [i0] [i1] [i2]... \n\t[Ctb] List of digital signal "
|
||||
"bits read out. If all is used instead of a list, all digital "
|
||||
"bits (64) enabled. Each element in list can be 0 - 63 and must "
|
||||
"be non repetitive."
|
||||
os << "[all] or [none] or [i0] [i1] [i2]... \n\t[Ctb] List of digital "
|
||||
"signal bits enabled and rearranged according to the signals "
|
||||
"(all samples of each signal is put together). If 'all' is used "
|
||||
"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';
|
||||
} else if (action == defs::GET_ACTION) {
|
||||
if (!args.empty()) {
|
||||
@ -1041,7 +1052,9 @@ std::string Caller::rx_dbitlist(int action) {
|
||||
for (unsigned int i = 0; i < 64; ++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();
|
||||
t.resize(ntrim);
|
||||
for (unsigned int i = 0; i < ntrim; ++i) {
|
||||
|
@ -99,6 +99,12 @@ void Detector::loadParameters(const std::vector<std::string> ¶meters) {
|
||||
CmdParser parser;
|
||||
for (const auto ¤t_line : parameters) {
|
||||
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(),
|
||||
defs::PUT_ACTION, std::cout, parser.receiver_id());
|
||||
}
|
||||
|
@ -1177,9 +1177,19 @@ int DetectorImpl::acquire() {
|
||||
if (dataReady == nullptr) {
|
||||
setJoinThreadFlag(true);
|
||||
} else if (receiver) {
|
||||
while (numZmqRunning != 0) {
|
||||
Parallel(&Module::restreamStopFromReceiver, {});
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
// wait for postprocessor to process dummies
|
||||
if (dataReady != nullptr) {
|
||||
// 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();
|
||||
|
@ -79,7 +79,9 @@ class DetectorImpl : public virtual slsDetectorDefs {
|
||||
explicit DetectorImpl(int detector_index = 0, bool verify = 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>
|
||||
Result<RT> Parallel(RT (Module::*somefunc)(CT...),
|
||||
std::vector<int> positions,
|
||||
|
@ -905,8 +905,13 @@ void Module::startReceiver() {
|
||||
}
|
||||
|
||||
void Module::stopReceiver() {
|
||||
auto rxStatusPrior = getReceiverStatus();
|
||||
sendToReceiver(F_STOP_RECEIVER, static_cast<int>(shm()->stoppedFlag),
|
||||
nullptr);
|
||||
|
||||
if (rxStatusPrior == IDLE && getReceiverStreaming()) {
|
||||
restreamStopFromReceiver();
|
||||
}
|
||||
}
|
||||
|
||||
void Module::startAcquisition() {
|
||||
@ -920,26 +925,8 @@ void Module::startReadout() {
|
||||
}
|
||||
|
||||
void Module::stopAcquisition() {
|
||||
|
||||
// get det status before stopping acq
|
||||
runStatus detStatus = ERROR;
|
||||
try {
|
||||
detStatus = getRunStatus();
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
sendToDetectorStop(F_STOP_ACQUISITION);
|
||||
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() {
|
||||
|
@ -262,8 +262,7 @@ TEST_CASE("compdisabletime", "[.cmdcall]") {
|
||||
Detector det;
|
||||
Caller caller(&det);
|
||||
auto det_type = det.getDetectorType().squash();
|
||||
if (det_type == defs::JUNGFRAU &&
|
||||
det.getChipVersion().squash() * 10 == 11) {
|
||||
if (det_type == defs::JUNGFRAU) {
|
||||
auto prev_val = det.getComparatorDisableTime();
|
||||
{
|
||||
std::ostringstream oss;
|
||||
@ -670,7 +669,8 @@ TEST_CASE("pedestalmode", "[.cmdcall]") {
|
||||
TEST_CASE("timing_info_decoder", "[.cmdcall]") {
|
||||
Detector 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();
|
||||
/*{
|
||||
std::ostringstream oss;
|
||||
|
@ -3323,7 +3323,7 @@ TEST_CASE("reg", "[.cmdcall]") {
|
||||
addr = 0x80;
|
||||
}
|
||||
if (det_type == defs::GOTTHARD2) {
|
||||
addr = 0x20;
|
||||
addr = 0x298;
|
||||
}
|
||||
std::string saddr = ToStringHex(addr);
|
||||
auto prev_val = det.readRegister(addr);
|
||||
@ -3379,7 +3379,7 @@ TEST_CASE("setbit", "[.cmdcall]") {
|
||||
addr = 0x80;
|
||||
}
|
||||
if (det_type == defs::GOTTHARD2) {
|
||||
addr = 0x20;
|
||||
addr = 0x298;
|
||||
}
|
||||
std::string saddr = ToStringHex(addr);
|
||||
auto prev_val = det.readRegister(addr);
|
||||
@ -3409,7 +3409,7 @@ TEST_CASE("clearbit", "[.cmdcall]") {
|
||||
addr = 0x80;
|
||||
}
|
||||
if (det_type == defs::GOTTHARD2) {
|
||||
addr = 0x20;
|
||||
addr = 0x298;
|
||||
}
|
||||
std::string saddr = ToStringHex(addr);
|
||||
auto prev_val = det.readRegister(addr);
|
||||
@ -3439,7 +3439,7 @@ TEST_CASE("getbit", "[.cmdcall]") {
|
||||
addr = 0x80;
|
||||
}
|
||||
if (det_type == defs::GOTTHARD2) {
|
||||
addr = 0x20;
|
||||
addr = 0x298;
|
||||
}
|
||||
std::string saddr = ToStringHex(addr);
|
||||
auto prev_val = det.readRegister(addr);
|
||||
|
@ -138,13 +138,34 @@ if (SLS_USE_RECEIVER_BINARIES)
|
||||
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}"
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sls
|
||||
)
|
||||
)
|
||||
|
||||
endif(SLS_USE_RECEIVER_BINARIES)
|
||||
|
||||
|
@ -33,6 +33,8 @@ using Interface = ServerInterface;
|
||||
#define gettid() syscall(SYS_gettid)
|
||||
#endif
|
||||
|
||||
std::mutex ClientInterface::callbackMutex;
|
||||
|
||||
ClientInterface::~ClientInterface() {
|
||||
killTcpThread = true;
|
||||
LOG(logINFO) << "Shutting down TCP Socket on port " << portNumber;
|
||||
@ -55,12 +57,14 @@ std::string ClientInterface::getReceiverVersion() { return APIRECEIVER; }
|
||||
/***callback functions***/
|
||||
void ClientInterface::registerCallBackStartAcquisition(
|
||||
int (*func)(const startCallbackHeader, void *), void *arg) {
|
||||
std::lock_guard<std::mutex> lock(callbackMutex);
|
||||
startAcquisitionCallBack = func;
|
||||
pStartAcquisition = arg;
|
||||
}
|
||||
|
||||
void ClientInterface::registerCallBackAcquisitionFinished(
|
||||
void (*func)(const endCallbackHeader, void *), void *arg) {
|
||||
std::lock_guard<std::mutex> lock(callbackMutex);
|
||||
acquisitionFinishedCallBack = func;
|
||||
pAcquisitionFinished = arg;
|
||||
}
|
||||
@ -69,6 +73,7 @@ void ClientInterface::registerCallBackRawDataReady(
|
||||
void (*func)(sls_receiver_header &, dataCallbackHeader, char *, size_t &,
|
||||
void *),
|
||||
void *arg) {
|
||||
std::lock_guard<std::mutex> lock(callbackMutex);
|
||||
rawDataReadyCallBack = func;
|
||||
pRawDataReady = arg;
|
||||
}
|
||||
@ -461,15 +466,18 @@ void ClientInterface::setDetectorType(detectorType arg) {
|
||||
std::string(e.what()) + ']');
|
||||
}
|
||||
// callbacks after (in setdetectortype, the object is reinitialized)
|
||||
if (startAcquisitionCallBack != nullptr)
|
||||
impl()->registerCallBackStartAcquisition(startAcquisitionCallBack,
|
||||
pStartAcquisition);
|
||||
if (acquisitionFinishedCallBack != nullptr)
|
||||
impl()->registerCallBackAcquisitionFinished(acquisitionFinishedCallBack,
|
||||
pAcquisitionFinished);
|
||||
if (rawDataReadyCallBack != nullptr)
|
||||
impl()->registerCallBackRawDataReady(rawDataReadyCallBack,
|
||||
pRawDataReady);
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(callbackMutex);
|
||||
if (startAcquisitionCallBack != nullptr)
|
||||
impl()->registerCallBackStartAcquisition(startAcquisitionCallBack,
|
||||
pStartAcquisition);
|
||||
if (acquisitionFinishedCallBack != nullptr)
|
||||
impl()->registerCallBackAcquisitionFinished(
|
||||
acquisitionFinishedCallBack, pAcquisitionFinished);
|
||||
if (rawDataReadyCallBack != nullptr)
|
||||
impl()->registerCallBackRawDataReady(rawDataReadyCallBack,
|
||||
pRawDataReady);
|
||||
}
|
||||
|
||||
impl()->setThreadIds(parentThreadId, tcpThreadId);
|
||||
}
|
||||
|
@ -194,6 +194,8 @@ class ClientInterface : private virtual slsDetectorDefs {
|
||||
pid_t tcpThreadId{0};
|
||||
std::vector<std::string> udpips =
|
||||
std::vector<std::string>(MAX_NUMBER_OF_LISTENING_THREADS);
|
||||
// necessary if Receiver objects using threads with callbacks
|
||||
static std::mutex callbackMutex;
|
||||
};
|
||||
|
||||
} // namespace sls
|
||||
|
635
slsReceiverSoftware/src/FrameSynchronizerApp.cpp
Normal file
635
slsReceiverSoftware/src/FrameSynchronizerApp.cpp
Normal 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;
|
||||
}
|
@ -149,12 +149,12 @@ void Listener::CreateUDPSocket(int &actualSize) {
|
||||
packetSize = generalData->vetoPacketSize;
|
||||
}
|
||||
|
||||
std::string ip =
|
||||
(eth.length() ? InterfaceNameToIp(eth).str().c_str() : "");
|
||||
|
||||
std::string ip;
|
||||
if (eth.length() > 0)
|
||||
ip = InterfaceNameToIp(eth).str();
|
||||
udpSocket = nullptr;
|
||||
udpSocket = make_unique<UdpRxSocket>(
|
||||
udpPortNumber, packetSize, (ip.length() ? ip.c_str() : nullptr),
|
||||
udpPortNumber, packetSize, (ip.empty() ? nullptr : ip.c_str()),
|
||||
generalData->udpSocketBufferSize);
|
||||
LOG(logINFO) << index << ": UDP port opened at port " << udpPortNumber
|
||||
<< " (" << (ip.length() ? ip : "any") << ')';
|
||||
@ -213,10 +213,13 @@ void Listener::CreateDummySocketForUDPSocketBufferSize(int s, int &actualSize) {
|
||||
try {
|
||||
// to allowe ports to be bound from udpsocket
|
||||
udpSocket.reset();
|
||||
UdpRxSocket g(
|
||||
udpPortNumber, packetSize,
|
||||
(eth.length() ? InterfaceNameToIp(eth).str().c_str() : nullptr),
|
||||
generalData->udpSocketBufferSize);
|
||||
|
||||
std::string ip;
|
||||
if (eth.length() > 0)
|
||||
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
|
||||
// permissions)
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "sls/container_utils.h"
|
||||
#include "sls/logger.h"
|
||||
#include "sls/sls_detector_defs.h"
|
||||
#include "sls/versionAPI.h"
|
||||
|
||||
#include <csignal> //SIGINT
|
||||
#include <cstring>
|
||||
@ -39,7 +40,9 @@ void sigInterruptHandler(int p) { sem_post(&semaphore); }
|
||||
*/
|
||||
std::string getHelpMessage() {
|
||||
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 "
|
||||
"option (optional)]\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[]) {
|
||||
|
||||
// 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 */
|
||||
int numReceivers = 1;
|
||||
uint16_t startTCPPort = DEFAULT_TCP_RX_PORTNO;
|
||||
@ -242,40 +255,43 @@ int main(int argc, char *argv[]) {
|
||||
else if (pid == 0) {
|
||||
cprintf(BLUE, "Child process %d [ Tid: %ld ]\n", i, (long)gettid());
|
||||
|
||||
std::unique_ptr<sls::Receiver> receiver = nullptr;
|
||||
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 (...) {
|
||||
LOG(sls::logINFOBLUE)
|
||||
<< "Exiting Child Process [ Tid: " << gettid() << " ]";
|
||||
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",
|
||||
(long)gettid());
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@ Receiver::Receiver(int argc, char *argv[]) : tcpipInterface(nullptr) {
|
||||
"\t started with privileges. \n\n";
|
||||
|
||||
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.
|
||||
if (c == -1)
|
||||
@ -87,7 +87,7 @@ Receiver::Receiver(int argc, char *argv[]) : tcpipInterface(nullptr) {
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
std::cout << "SLS Receiver Version: " << APIRECEIVER << std::endl;
|
||||
std::cout << "slsReceiver Version: " << APIRECEIVER << std::endl;
|
||||
LOG(logINFOBLUE) << "Exiting [ Tid: " << gettid() << " ]";
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
|
@ -16,6 +16,8 @@ enum TLogLevel {
|
||||
logINFOBLUE,
|
||||
logINFOGREEN,
|
||||
logINFORED,
|
||||
logINFOCYAN,
|
||||
logINFOMAGENTA,
|
||||
logINFO,
|
||||
logDEBUG,
|
||||
logDEBUG1,
|
||||
@ -60,16 +62,25 @@ class Logger {
|
||||
// Danger this buffer need as many elements as TLogLevel
|
||||
static const char *Color(TLogLevel level) noexcept {
|
||||
static const char *const colors[] = {
|
||||
RED BOLD, YELLOW BOLD, BLUE, GREEN, RED, RESET,
|
||||
RESET, RESET, RESET, RESET, RESET, RESET};
|
||||
RED BOLD, YELLOW BOLD, BLUE, GREEN, RED, CYAN, MAGENTA,
|
||||
RESET, RESET, RESET, RESET, RESET, RESET, RESET};
|
||||
// out of bounds
|
||||
if (level < 0 || level >= sizeof(colors) / sizeof(colors[0])) {
|
||||
return RESET;
|
||||
}
|
||||
return colors[level];
|
||||
}
|
||||
|
||||
// Danger this buffer need as many elements as TLogLevel
|
||||
static std::string ToString(TLogLevel level) {
|
||||
static const char *const buffer[] = {
|
||||
"ERROR", "WARNING", "INFO", "INFO", "INFO", "INFO",
|
||||
"DEBUG", "DEBUG1", "DEBUG2", "DEBUG3", "DEBUG4", "DEBUG5"};
|
||||
"ERROR", "WARNING", "INFO", "INFO", "INFO",
|
||||
"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];
|
||||
}
|
||||
|
||||
|
@ -130,7 +130,7 @@ extern "C" {
|
||||
ll = (c)->D; \
|
||||
(void)HOST_l2c(ll, (s)); \
|
||||
} 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)
|
||||
|
||||
#define HOST_c2l(c, l) \
|
||||
|
@ -1,13 +1,13 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
/** API versions */
|
||||
#define APICTB "9.0.0 0x241121"
|
||||
#define APIGOTTHARD "9.0.0 0x241121"
|
||||
#define APIGOTTHARD2 "9.0.0 0x241121"
|
||||
#define APIJUNGFRAU "9.0.0 0x241121"
|
||||
#define APIMOENCH "9.0.0 0x241121"
|
||||
#define APIXILINXCTB "9.0.0 0x241121"
|
||||
#define APIEIGER "9.0.0 0x241121"
|
||||
#define APIMYTHEN3 "9.0.0 0x241121"
|
||||
#define APILIB "9.0.0 0x241126"
|
||||
#define APIRECEIVER "9.0.0 0x241126"
|
||||
#define APICTB "9.1.0 0x250204"
|
||||
#define APIXILINXCTB "9.1.0 0x250204"
|
||||
#define APIMYTHEN3 "9.1.0 0x250304"
|
||||
#define APIJUNGFRAU "9.1.0 0x250318"
|
||||
#define APILIB "9.1.0 0x250325"
|
||||
#define APIRECEIVER "9.1.0 0x250325"
|
||||
|
Loading…
x
Reference in New Issue
Block a user