mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-07-13 19:31:49 +02:00
merge fix from developer
This commit is contained in:
29
.gitea/workflows/rh8-native.yml
Normal file
29
.gitea/workflows/rh8-native.yml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
name: Build on RHEL8
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: "ubuntu-latest"
|
||||||
|
container:
|
||||||
|
image: gitea.psi.ch/detectors/rhel8-detectors-dev
|
||||||
|
steps:
|
||||||
|
- name: Clone repository
|
||||||
|
run: |
|
||||||
|
echo Cloning ${{ github.ref_name }}
|
||||||
|
git clone https://${{secrets.GITHUB_TOKEN}}@gitea.psi.ch/${{ github.repository }}.git --branch=${{ github.ref_name }} .
|
||||||
|
|
||||||
|
- name: Build library
|
||||||
|
run: |
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake .. -DSLS_USE_PYTHON=ON -DSLS_USE_TESTS=ON
|
||||||
|
make -j 2
|
||||||
|
|
||||||
|
- name: C++ unit tests
|
||||||
|
working-directory: ${{gitea.workspace}}/build
|
||||||
|
run: ctest
|
27
.gitea/workflows/rh9-native.yml
Normal file
27
.gitea/workflows/rh9-native.yml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
name: Build on RHEL9
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: "ubuntu-latest"
|
||||||
|
container:
|
||||||
|
image: gitea.psi.ch/detectors/rhel9-detectors-dev
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
|
||||||
|
- name: Build library
|
||||||
|
run: |
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake .. -DSLS_USE_PYTHON=ON -DSLS_USE_TESTS=ON
|
||||||
|
make -j 2
|
||||||
|
|
||||||
|
- name: C++ unit tests
|
||||||
|
working-directory: ${{gitea.workspace}}/build
|
||||||
|
run: ctest
|
64
.github/workflows/build_wheel.yml
vendored
Normal file
64
.github/workflows/build_wheel.yml
vendored
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
name: Build wheel
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build_wheels:
|
||||||
|
name: Build wheels on ${{ matrix.os }}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest,]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Build wheels
|
||||||
|
run: pipx run cibuildwheel==2.23.0
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
|
||||||
|
path: ./wheelhouse/*.whl
|
||||||
|
|
||||||
|
build_sdist:
|
||||||
|
name: Build source distribution
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Build sdist
|
||||||
|
run: pipx run build --sdist
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: cibw-sdist
|
||||||
|
path: dist/*.tar.gz
|
||||||
|
|
||||||
|
upload_pypi:
|
||||||
|
needs: [build_wheels, build_sdist]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
environment: pypi
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
if: github.event_name == 'release' && github.event.action == 'published'
|
||||||
|
# or, alternatively, upload to PyPI on every tag starting with 'v' (remove on: release above to use this)
|
||||||
|
# if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
||||||
|
steps:
|
||||||
|
- uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
# unpacks all CIBW artifacts into dist/
|
||||||
|
pattern: cibw-*
|
||||||
|
path: dist
|
||||||
|
merge-multiple: true
|
||||||
|
|
||||||
|
- uses: pypa/gh-action-pypi-publish@release/v1
|
@ -21,6 +21,7 @@ if (${CMAKE_VERSION} VERSION_GREATER "3.24")
|
|||||||
endif()
|
endif()
|
||||||
include(cmake/project_version.cmake)
|
include(cmake/project_version.cmake)
|
||||||
include(cmake/SlsAddFlag.cmake)
|
include(cmake/SlsAddFlag.cmake)
|
||||||
|
include(cmake/helpers.cmake)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -44,6 +45,10 @@ endif()
|
|||||||
# Patch is applied in the FetchContent_Declare
|
# Patch is applied in the FetchContent_Declare
|
||||||
set(SLS_LIBZMQ_VERSION "4.3.4")
|
set(SLS_LIBZMQ_VERSION "4.3.4")
|
||||||
|
|
||||||
|
find_program(PATCH_EXECUTABLE patch)
|
||||||
|
if(NOT PATCH_EXECUTABLE)
|
||||||
|
message(FATAL_ERROR "The 'patch' tool is required for patching lib zeromq. Please install it.")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(SLS_FETCH_ZMQ_FROM_GITHUB)
|
if(SLS_FETCH_ZMQ_FROM_GITHUB)
|
||||||
# Opt in to pull down a zmq version from github instead of
|
# Opt in to pull down a zmq version from github instead of
|
||||||
@ -189,11 +194,9 @@ find_package(ClangFormat)
|
|||||||
|
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
default_build_type("Release")
|
||||||
message(STATUS "No build type selected, default to Release")
|
set_std_fs_lib()
|
||||||
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type (default Release)" FORCE)
|
message(STATUS "Extra linking to fs lib:${STD_FS_LIB}")
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
#Enable LTO if available
|
#Enable LTO if available
|
||||||
include(CheckIPOSupported)
|
include(CheckIPOSupported)
|
||||||
@ -216,7 +219,7 @@ endif()
|
|||||||
# to control options for the libraries
|
# to control options for the libraries
|
||||||
if(NOT TARGET slsProjectOptions)
|
if(NOT TARGET slsProjectOptions)
|
||||||
add_library(slsProjectOptions INTERFACE)
|
add_library(slsProjectOptions INTERFACE)
|
||||||
target_compile_features(slsProjectOptions INTERFACE cxx_std_11)
|
target_compile_features(slsProjectOptions INTERFACE cxx_std_17)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT TARGET slsProjectWarnings)
|
if (NOT TARGET slsProjectWarnings)
|
||||||
@ -329,7 +332,8 @@ if (SLS_USE_INTEGRATION_TESTS)
|
|||||||
endif (SLS_USE_INTEGRATION_TESTS)
|
endif (SLS_USE_INTEGRATION_TESTS)
|
||||||
|
|
||||||
if (SLS_USE_PYTHON)
|
if (SLS_USE_PYTHON)
|
||||||
find_package (Python 3.8 COMPONENTS Interpreter Development)
|
find_package (Python 3.8 COMPONENTS Interpreter Development.Module REQUIRED)
|
||||||
|
set(PYBIND11_FINDPYTHON ON) # Needed for RH8
|
||||||
if(SLS_FETCH_PYBIND11_FROM_GITHUB)
|
if(SLS_FETCH_PYBIND11_FROM_GITHUB)
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
pybind11
|
pybind11
|
||||||
|
@ -25,7 +25,9 @@ mark_as_advanced(
|
|||||||
ClangFormat_BIN)
|
ClangFormat_BIN)
|
||||||
|
|
||||||
if(ClangFormat_FOUND)
|
if(ClangFormat_FOUND)
|
||||||
exec_program(${ClangFormat_BIN} ${CMAKE_CURRENT_SOURCE_DIR} ARGS --version OUTPUT_VARIABLE CLANG_VERSION_TEXT)
|
execute_process(COMMAND ${ClangFormat_BIN} --version
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
OUTPUT_VARIABLE CLANG_VERSION_TEXT)
|
||||||
string(REGEX MATCH "([0-9]+)\\.[0-9]+\\.[0-9]+" CLANG_VERSION ${CLANG_VERSION_TEXT})
|
string(REGEX MATCH "([0-9]+)\\.[0-9]+\\.[0-9]+" CLANG_VERSION ${CLANG_VERSION_TEXT})
|
||||||
if((${CLANG_VERSION} GREATER "9") OR (${CLANG_VERSION} EQUAL "9"))
|
if((${CLANG_VERSION} GREATER "9") OR (${CLANG_VERSION} EQUAL "9"))
|
||||||
# A CMake script to find all source files and setup clang-format targets for them
|
# A CMake script to find all source files and setup clang-format targets for them
|
||||||
|
46
cmake/helpers.cmake
Normal file
46
cmake/helpers.cmake
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
function(default_build_type val)
|
||||||
|
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||||
|
message(STATUS "No build type selected, default to Release")
|
||||||
|
set(CMAKE_BUILD_TYPE ${val} CACHE STRING "Build type (default ${val})" FORCE)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(set_std_fs_lib)
|
||||||
|
# from pybind11
|
||||||
|
# Check if we need to add -lstdc++fs or -lc++fs or nothing
|
||||||
|
if(DEFINED CMAKE_CXX_STANDARD AND CMAKE_CXX_STANDARD LESS 17)
|
||||||
|
set(STD_FS_NO_LIB_NEEDED TRUE)
|
||||||
|
elseif(MSVC)
|
||||||
|
set(STD_FS_NO_LIB_NEEDED TRUE)
|
||||||
|
else()
|
||||||
|
file(
|
||||||
|
WRITE ${CMAKE_CURRENT_BINARY_DIR}/main.cpp
|
||||||
|
"#include <filesystem>\nint main(int argc, char ** argv) {\n std::filesystem::path p(argv[0]);\n return p.string().length();\n}"
|
||||||
|
)
|
||||||
|
try_compile(
|
||||||
|
STD_FS_NO_LIB_NEEDED ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/main.cpp
|
||||||
|
COMPILE_DEFINITIONS -std=c++17)
|
||||||
|
try_compile(
|
||||||
|
STD_FS_NEEDS_STDCXXFS ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/main.cpp
|
||||||
|
COMPILE_DEFINITIONS -std=c++17
|
||||||
|
LINK_LIBRARIES stdc++fs)
|
||||||
|
try_compile(
|
||||||
|
STD_FS_NEEDS_CXXFS ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/main.cpp
|
||||||
|
COMPILE_DEFINITIONS -std=c++17
|
||||||
|
LINK_LIBRARIES c++fs)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(${STD_FS_NEEDS_STDCXXFS})
|
||||||
|
set(STD_FS_LIB stdc++fs PARENT_SCOPE)
|
||||||
|
elseif(${STD_FS_NEEDS_CXXFS})
|
||||||
|
set(STD_FS_LIB c++fs PARENT_SCOPE)
|
||||||
|
elseif(${STD_FS_NO_LIB_NEEDED})
|
||||||
|
set(STD_FS_LIB "" PARENT_SCOPE)
|
||||||
|
else()
|
||||||
|
message(WARNING "Unknown C++17 compiler - not passing -lstdc++fs")
|
||||||
|
set(STD_FS_LIB "")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
@ -1,11 +1,11 @@
|
|||||||
package:
|
|
||||||
name: sls_detector_software
|
|
||||||
version: 2025.3.19
|
|
||||||
|
|
||||||
|
|
||||||
source:
|
source:
|
||||||
path: ../..
|
path: ../..
|
||||||
|
|
||||||
|
{% set version = load_file_regex(load_file = 'VERSION', regex_pattern = '(\d+(?:\.\d+)*(?:[\+\w\.]+))').group(1) %}
|
||||||
|
package:
|
||||||
|
name: sls_detector_software
|
||||||
|
version: {{ version }}
|
||||||
|
|
||||||
build:
|
build:
|
||||||
number: 0
|
number: 0
|
||||||
binary_relocation: True
|
binary_relocation: True
|
||||||
@ -28,6 +28,7 @@ requirements:
|
|||||||
- libgl-devel # [linux]
|
- libgl-devel # [linux]
|
||||||
- libtiff
|
- libtiff
|
||||||
- zlib
|
- zlib
|
||||||
|
- expat
|
||||||
|
|
||||||
run:
|
run:
|
||||||
- libstdcxx-ng
|
- libstdcxx-ng
|
||||||
@ -49,8 +50,6 @@ outputs:
|
|||||||
- libgcc-ng
|
- libgcc-ng
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- name: slsdetgui
|
- name: slsdetgui
|
||||||
script: copy_gui.sh
|
script: copy_gui.sh
|
||||||
requirements:
|
requirements:
|
||||||
@ -60,6 +59,7 @@ outputs:
|
|||||||
- {{compiler('cxx')}}
|
- {{compiler('cxx')}}
|
||||||
- {{ pin_subpackage('slsdetlib', exact=True) }}
|
- {{ pin_subpackage('slsdetlib', exact=True) }}
|
||||||
|
|
||||||
|
|
||||||
run:
|
run:
|
||||||
- {{ pin_subpackage('slsdetlib', exact=True) }}
|
- {{ pin_subpackage('slsdetlib', exact=True) }}
|
||||||
- qt 5.*
|
- qt 5.*
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
package:
|
|
||||||
name: slsdet
|
|
||||||
version: 2025.3.19 #TODO! how to not duplicate this?
|
|
||||||
|
|
||||||
source:
|
source:
|
||||||
path: ../..
|
path: ../..
|
||||||
|
|
||||||
|
{% set version = load_file_regex(load_file = 'VERSION', regex_pattern = '(\d+(?:\.\d+)*(?:[\+\w\.]+))').group(1) %}
|
||||||
|
package:
|
||||||
|
name: slsdet
|
||||||
|
version: {{ version }}
|
||||||
|
|
||||||
build:
|
build:
|
||||||
number: 0
|
number: 0
|
||||||
script:
|
script:
|
||||||
@ -17,7 +18,6 @@ requirements:
|
|||||||
- {{ stdlib("c") }}
|
- {{ stdlib("c") }}
|
||||||
- {{ compiler('cxx') }}
|
- {{ compiler('cxx') }}
|
||||||
|
|
||||||
|
|
||||||
host:
|
host:
|
||||||
- cmake
|
- cmake
|
||||||
- ninja
|
- ninja
|
||||||
|
@ -42,6 +42,7 @@ set(SPHINX_SOURCE_FILES
|
|||||||
src/pyexamples.rst
|
src/pyexamples.rst
|
||||||
src/pyPatternGenerator.rst
|
src/pyPatternGenerator.rst
|
||||||
src/servers.rst
|
src/servers.rst
|
||||||
|
src/multidet.rst
|
||||||
src/receiver_api.rst
|
src/receiver_api.rst
|
||||||
src/result.rst
|
src/result.rst
|
||||||
src/type_traits.rst
|
src/type_traits.rst
|
||||||
|
@ -359,6 +359,7 @@ Chip Test Board
|
|||||||
"Digital Flag": 0,
|
"Digital Flag": 0,
|
||||||
"Digital Samples": 1000,
|
"Digital Samples": 1000,
|
||||||
"Dbit Offset": 0,
|
"Dbit Offset": 0,
|
||||||
|
"Dbit Reorder": 1,
|
||||||
"Dbit Bitset": 0,
|
"Dbit Bitset": 0,
|
||||||
"Transceiver Mask": "0x3",
|
"Transceiver Mask": "0x3",
|
||||||
"Transceiver Flag": 0,
|
"Transceiver Flag": 0,
|
||||||
|
@ -6,6 +6,8 @@ Usage
|
|||||||
|
|
||||||
The syntax is *'[detector index]-[module index]:[command]'*, where the indices are by default '0', when not specified.
|
The syntax is *'[detector index]-[module index]:[command]'*, where the indices are by default '0', when not specified.
|
||||||
|
|
||||||
|
.. _cl-module-index-label:
|
||||||
|
|
||||||
Module index
|
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.
|
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.
|
||||||
|
@ -28,6 +28,12 @@ Welcome to slsDetectorPackage's documentation!
|
|||||||
receiver_api
|
receiver_api
|
||||||
examples
|
examples
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:caption: how to
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
multidet
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:caption: Python API
|
:caption: Python API
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
@ -81,8 +87,9 @@ Welcome to slsDetectorPackage's documentation!
|
|||||||
:caption: Receiver
|
:caption: Receiver
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
receivers
|
|
||||||
slsreceiver
|
slsreceiver
|
||||||
|
receivers
|
||||||
|
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:caption: Receiver Files
|
:caption: Receiver Files
|
||||||
|
@ -6,18 +6,33 @@
|
|||||||
Installation
|
Installation
|
||||||
===============
|
===============
|
||||||
|
|
||||||
One can either install pre-built binaries using conda or build from source.
|
.. contents::
|
||||||
|
:local:
|
||||||
|
:depth: 2
|
||||||
|
:backlinks: top
|
||||||
|
|
||||||
.. warning ::
|
|
||||||
|
|
||||||
Before building from source make sure that you have the
|
Overview
|
||||||
:doc:`dependencies <../dependencies>` installed. If installing using conda, conda will
|
--------------
|
||||||
manage the dependencies. Avoid also installing packages with pip.
|
|
||||||
|
The ``slsDetectorPackage`` provides core detector software implemented in C++, along with Python bindings packaged as the ``slsdet`` Python extension module. Choose the option that best fits your environment and use case.
|
||||||
|
|
||||||
|
:ref:`conda pre-built binaries`:
|
||||||
|
Install pre-built binaries for the C++ client, receiver, GUI and the Python API (``slsdet``), simplifying setup across platforms.
|
||||||
|
|
||||||
|
:ref:`pip`:
|
||||||
|
Install only the Python extension module, either by downloading the pre-built library from PyPI or by building the extension locally from source. Available only from v9.2.0 onwards.
|
||||||
|
|
||||||
|
:ref:`build from source`:
|
||||||
|
Compile the entire package yourself, including both the C++ core and the Python bindings, for maximum control and customization. However, make sure that you have the :doc:`dependencies <../dependencies>` installed. If installing using conda, conda will manage the dependencies. Avoid installing packages with pip and conda simultaneously.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Install binaries using conda
|
|
||||||
----------------------------------
|
.. _conda pre-built binaries:
|
||||||
|
|
||||||
|
1. Install pre-built binaries using conda (Recommended)
|
||||||
|
--------------------------------------------------------
|
||||||
|
|
||||||
Conda is not only useful to manage python environments but can also
|
Conda is not only useful to manage python environments but can also
|
||||||
be used as a user space package manager. Dates in the tag (for eg. 2020.07.23.dev0)
|
be used as a user space package manager. Dates in the tag (for eg. 2020.07.23.dev0)
|
||||||
@ -63,12 +78,29 @@ We have four different packages available:
|
|||||||
conda search moenchzmq
|
conda search moenchzmq
|
||||||
|
|
||||||
|
|
||||||
|
.. _pip:
|
||||||
|
|
||||||
|
2. Pip
|
||||||
|
-------
|
||||||
|
The Python extension module ``slsdet`` can be installed using pip. This is available from v9.2.0 onwards.
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
#Install the Python extension module from PyPI
|
||||||
|
pip install slsdet
|
||||||
|
|
||||||
|
# or install the python extension locally from source
|
||||||
|
git clone https://github.com/slsdetectorgroup/slsDetectorPackage.git --branch 9.2.0
|
||||||
|
cd slsDetectorPackage
|
||||||
|
pip install .
|
||||||
|
|
||||||
|
|
||||||
Build from source
|
.. _build from source:
|
||||||
----------------------
|
|
||||||
|
|
||||||
1. Download Source Code from github
|
3. Build from source
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
3.1. Download Source Code from github
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
@ -83,12 +115,12 @@ Build from source
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
2. Build from Source
|
3.2. Build from Source
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
One can either build using cmake or use the in-built cmk.sh script.
|
One can either build using cmake or use the in-built cmk.sh script.
|
||||||
|
|
||||||
Build using CMake
|
3.2.1. Build using CMake
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
@ -135,7 +167,7 @@ Example cmake options Comment
|
|||||||
For v7.x.x of slsDetectorPackage and older, refer :ref:`zeromq notes for cmake option to hint library location. <zeromq for different slsDetectorPackage versions>`
|
For v7.x.x of slsDetectorPackage and older, refer :ref:`zeromq notes for cmake option to hint library location. <zeromq for different slsDetectorPackage versions>`
|
||||||
|
|
||||||
|
|
||||||
Build using in-built cmk.sh script
|
3.2.2. Build using in-built cmk.sh script
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
|
||||||
@ -185,8 +217,8 @@ Build using in-built cmk.sh script
|
|||||||
For v7.x.x of slsDetectorPackage and older, refer :ref:`zeromq notes for cmk script option to hint library location. <zeromq for different slsDetectorPackage versions>`
|
For v7.x.x of slsDetectorPackage and older, refer :ref:`zeromq notes for cmk script option to hint library location. <zeromq for different slsDetectorPackage versions>`
|
||||||
|
|
||||||
|
|
||||||
Build on old distributions
|
3.3. Build on old distributions using conda
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
If your linux distribution doesn't come with a C++11 compiler (gcc>4.8) then
|
If your linux distribution doesn't come with a C++11 compiler (gcc>4.8) then
|
||||||
it's possible to install a newer gcc using conda and build the slsDetectorPackage
|
it's possible to install a newer gcc using conda and build the slsDetectorPackage
|
||||||
@ -210,7 +242,7 @@ using this compiler
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Build slsDetectorGui (Qt5)
|
3.4. Build slsDetectorGui (Qt5)
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
1. Using pre-built binary on conda
|
1. Using pre-built binary on conda
|
||||||
@ -271,7 +303,7 @@ Build slsDetectorGui (Qt5)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Build this documentation
|
3.5. Build this documentation
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
The documentation for the slsDetectorPackage is build using a combination
|
The documentation for the slsDetectorPackage is build using a combination
|
||||||
@ -294,8 +326,8 @@ is to use conda
|
|||||||
make rst # rst only, saves time in case the API did not change
|
make rst # rst only, saves time in case the API did not change
|
||||||
|
|
||||||
|
|
||||||
Pybind and Zeromq
|
4. Pybind and Zeromq
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
-------------------------
|
||||||
|
|
||||||
.. _pybind for different slsDetectorPackage versions:
|
.. _pybind for different slsDetectorPackage versions:
|
||||||
|
|
||||||
|
@ -345,6 +345,9 @@ Chip Test Board
|
|||||||
+-----------------------+-------------------------------------------------+
|
+-----------------------+-------------------------------------------------+
|
||||||
| Dbit Offset | Digital offset of valid data in bytes |
|
| Dbit Offset | Digital offset of valid data in bytes |
|
||||||
+-----------------------+-------------------------------------------------+
|
+-----------------------+-------------------------------------------------+
|
||||||
|
| Dbit Reorder | Reorder such that it groups each signal (0-63) |
|
||||||
|
| | from all the different samples together |
|
||||||
|
+-----------------------+-------------------------------------------------+
|
||||||
| Dbit Bitset | Digital 64 bit mask of bits enabled in receiver |
|
| Dbit Bitset | Digital 64 bit mask of bits enabled in receiver |
|
||||||
+-----------------------+-------------------------------------------------+
|
+-----------------------+-------------------------------------------------+
|
||||||
| Transceiver Mask | Mask of channels enabled in Transceiver |
|
| Transceiver Mask | Mask of channels enabled in Transceiver |
|
||||||
|
228
docs/src/multidet.rst
Normal file
228
docs/src/multidet.rst
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
Using multiple detectors
|
||||||
|
==========================
|
||||||
|
|
||||||
|
The slsDetectorPackage supports using several detectors on the same computer.
|
||||||
|
This can either be two users, that need to use the same computer without interfering
|
||||||
|
with each other, or the same user that wants to use multiple detectors at the same time.
|
||||||
|
The detectors in turn can consist of multiple modules. For example, a 9M Jungfrau detector
|
||||||
|
consists of 18 modules which typically are addressed at once as a single detector.
|
||||||
|
|
||||||
|
.. note ::
|
||||||
|
|
||||||
|
To address a single module of a multi-module detector you can use the module index.
|
||||||
|
|
||||||
|
- Command line: :ref:`cl-module-index-label`
|
||||||
|
- Python: :ref:`py-module-index-label`
|
||||||
|
|
||||||
|
|
||||||
|
Coming back to multiple detectors we have two tools to our disposal:
|
||||||
|
|
||||||
|
#. Detector index
|
||||||
|
#. The SLSDETNAME environment variable
|
||||||
|
|
||||||
|
They can be used together or separately depending on the use case.
|
||||||
|
|
||||||
|
Detector index
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
When configuring a detector you can specify a detector index. The default is 0.
|
||||||
|
|
||||||
|
**Command line**
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
# Given that we have two detectors (my-det and my-det2) that we want to use,
|
||||||
|
# we can configure them with different indices.
|
||||||
|
|
||||||
|
# Configure the first detector with index 0
|
||||||
|
$ sls_detector_put hostname my-det
|
||||||
|
|
||||||
|
# Set number of frames for detector 0 to 10
|
||||||
|
$ sls_detector_put frames 10
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
#Configure the second detector with index 1 (notice the 1- before hostname)
|
||||||
|
$ sls_detector_put 1-hostname my-det2
|
||||||
|
|
||||||
|
|
||||||
|
# Further configuration
|
||||||
|
...
|
||||||
|
|
||||||
|
# Set number of frames for detector 1 to 19
|
||||||
|
$ sls_detector_put 1-frames 19
|
||||||
|
|
||||||
|
# Note that if we call sls_detector_get without specifying the index,
|
||||||
|
# it will return the configuration of detector 0
|
||||||
|
$ sls_detector_get frames
|
||||||
|
10
|
||||||
|
|
||||||
|
The detector index is added to the name of the shared memory segment, so in this case
|
||||||
|
the shared memory segments would be:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
|
||||||
|
#First detector
|
||||||
|
/dev/shm/slsDetectorPackage_detector_0
|
||||||
|
/dev/shm/slsDetectorPackage_detector_0_module_0
|
||||||
|
|
||||||
|
#Second detector
|
||||||
|
/dev/shm/slsDetectorPackage_detector_1
|
||||||
|
/dev/shm/slsDetectorPackage_detector_1_module_0
|
||||||
|
|
||||||
|
|
||||||
|
**Python**
|
||||||
|
|
||||||
|
The main difference between the command line and the Python API is that you set the index
|
||||||
|
when you create the detector object and you don't have to repeat it for every call.
|
||||||
|
|
||||||
|
The C++ API works int the same way.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from slsdet import Detector
|
||||||
|
|
||||||
|
|
||||||
|
# The same can be achieved in Python by creating a detector object with an index.
|
||||||
|
# Again we have two detectors (my-det and my-det2) that we want to use:
|
||||||
|
|
||||||
|
# Configure detector with index 0
|
||||||
|
d = Detector()
|
||||||
|
|
||||||
|
# If the detector has already been configured and has a shared memory
|
||||||
|
# segment, you can omit setting the hostname again
|
||||||
|
d.hostname = 'my-det'
|
||||||
|
|
||||||
|
#Further configuration
|
||||||
|
...
|
||||||
|
|
||||||
|
# Configure a second detector with index 1
|
||||||
|
d2 = Detector(1)
|
||||||
|
d2.hostname = 'my-det2'
|
||||||
|
|
||||||
|
d.frames = 10
|
||||||
|
d2.frames = 19
|
||||||
|
|
||||||
|
|
||||||
|
$SLSDETNAME
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
To avoid interfering with other users on shared PCs it is best to always set the SLSDETNAME environmental variable.
|
||||||
|
Imagining a fictive user: Anna, we can set SLSDETNAME from the shell before configuring the detector:
|
||||||
|
|
||||||
|
**Command line**
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
# Set the SLSDETNAME variable
|
||||||
|
$ export SLSDETNAME=Anna
|
||||||
|
|
||||||
|
# You can check that it is set
|
||||||
|
$ echo $SLSDETNAME
|
||||||
|
Anna
|
||||||
|
|
||||||
|
# Now configures a detector with index 0 and prefixed with the name Anna
|
||||||
|
# /dev/shm/slsDetectorPackage_detector_0_Anna
|
||||||
|
$ sls_detector_put hostname my-det
|
||||||
|
|
||||||
|
|
||||||
|
.. tip ::
|
||||||
|
|
||||||
|
Set SLSDETNAME in your .bashrc in order to not forget it when opening a new terminal.
|
||||||
|
|
||||||
|
|
||||||
|
**Python**
|
||||||
|
|
||||||
|
With python the best way is to set the SLSDETNAME from the command line before starting the python interpreter.
|
||||||
|
|
||||||
|
Bash:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ export SLSDETNAME=Anna
|
||||||
|
|
||||||
|
Python:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from slsdet import Detector
|
||||||
|
|
||||||
|
# Now configures a detector with index 0 and prefixed with the name Anna
|
||||||
|
# /dev/shm/slsDetectorPackage_detector_0_Anna
|
||||||
|
d = Detector()
|
||||||
|
d.hostname = 'my-det'
|
||||||
|
|
||||||
|
You can also set SLSDETNAME from within the Python interpreter, but you have to be aware that it will only
|
||||||
|
affect the current process and not the whole shell session.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import os
|
||||||
|
os.environ['SLSDETNAME'] = 'Anna'
|
||||||
|
|
||||||
|
# You can check that it is set
|
||||||
|
print(os.environ['SLSDETNAME']) # Output: Anna
|
||||||
|
|
||||||
|
#Now SLSDETNAME is set to Anna but as soon as you exit the python interpreter
|
||||||
|
# it will not be set anymore
|
||||||
|
|
||||||
|
.. note ::
|
||||||
|
|
||||||
|
Python has two ways of reading environment variables: `**os.environ**` as shown above which throws a
|
||||||
|
KeyError if the variable is not set and `os.getenv('SLSDETNAME')` which returns None if the variable is not set.
|
||||||
|
|
||||||
|
For more details see the official python documentation on: https://docs.python.org/3/library/os.html#os.environ
|
||||||
|
|
||||||
|
|
||||||
|
Checking for other detectors
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
If using shared accounts on a shared computer (which you anyway should not do), it is good practice to check
|
||||||
|
if there are other detectors configured by other users before configuring your own detector.
|
||||||
|
|
||||||
|
You can do this by listing the files in the shared memory directory `/dev/shm/` that start with `sls`. In this
|
||||||
|
example we can see that two single module detectors are configured one with index 0 and one with index 1.
|
||||||
|
SLSDETNAME is set to `Anna` so it makes sense to assume that she is the user that configured these detectors.
|
||||||
|
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
# List the files in /dev/shm that starts with sls
|
||||||
|
$ ls /dev/shm/sls*
|
||||||
|
/dev/shm/slsDetectorPackage_detector_0_Anna
|
||||||
|
/dev/shm/slsDetectorPackage_detector_0_module_0_Anna
|
||||||
|
/dev/shm/slsDetectorPackage_detector_1_Anna
|
||||||
|
/dev/shm/slsDetectorPackage_detector_1_module_0_Anna
|
||||||
|
|
||||||
|
We also provide a command: user, which gets information about the shared memory segment that
|
||||||
|
the client points to without doing any changes.
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
#in this case 3 simulated Mythen3 modules
|
||||||
|
$ sls_detector_get user
|
||||||
|
user
|
||||||
|
Hostname: localhost+localhost+localhost+
|
||||||
|
Type: Mythen3
|
||||||
|
PID: 1226078
|
||||||
|
User: l_msdetect
|
||||||
|
Date: Mon Jun 2 05:46:20 PM CEST 2025
|
||||||
|
|
||||||
|
|
||||||
|
Other considerations
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The shared memory is not the only way to interfere with other users. You also need to make sure that you are not
|
||||||
|
using the same:
|
||||||
|
|
||||||
|
* rx_tcpport
|
||||||
|
* Unique combination of udp_dstip and udp_dstport
|
||||||
|
* rx_zmqport
|
||||||
|
* zmqport
|
||||||
|
|
||||||
|
.. attention ::
|
||||||
|
|
||||||
|
The computer that you are using need to have enough resources to run multiple detectors at the same time.
|
||||||
|
This includes CPU and network bandwidth. Please coordinate with the other users!
|
||||||
|
|
@ -123,6 +123,47 @@ in a large detector.
|
|||||||
# Set exposure time for module 1, 5 and 7
|
# Set exposure time for module 1, 5 and 7
|
||||||
d.setExptime(0.1, [1,5,7])
|
d.setExptime(0.1, [1,5,7])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.. _py-module-index-label:
|
||||||
|
|
||||||
|
----------------------------------
|
||||||
|
Accessing individual modules
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
Using the C++ like API you can access individual modules in a large detector
|
||||||
|
by passing in the module index as an argument to the function.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
# Read the UDP destination port for all modules
|
||||||
|
>>> d.getDestinationUDPPort()
|
||||||
|
[50001, 50002, 50003]
|
||||||
|
|
||||||
|
|
||||||
|
# Read it for module 0 and 1
|
||||||
|
>>> d.getDestinationUDPPort([0, 1])
|
||||||
|
[50001, 50002]
|
||||||
|
|
||||||
|
>>> d.setDestinationUDPPort(50010, 1)
|
||||||
|
>>> d.getDestinationUDPPort()
|
||||||
|
[50001, 50010, 50003]
|
||||||
|
|
||||||
|
From the more pythonic API there is no way to read from only one module but you can read
|
||||||
|
and then use list slicing to get the values for the modules you are interested in.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
>>> d.udp_dstport
|
||||||
|
[50001, 50010, 50003]
|
||||||
|
>>> d.udp_dstport[0]
|
||||||
|
50001
|
||||||
|
|
||||||
|
#For some but not all properties you can also pass in a dictionary with module index as key
|
||||||
|
>>> ip = IpAddr('127.0.0.1')
|
||||||
|
>>> d.udp_dstip = {1:ip}
|
||||||
|
|
||||||
|
|
||||||
--------------------
|
--------------------
|
||||||
Finding functions
|
Finding functions
|
||||||
--------------------
|
--------------------
|
||||||
|
@ -1,25 +1,25 @@
|
|||||||
Receivers
|
Custom Receiver
|
||||||
=================
|
=================
|
||||||
|
|
||||||
Receiver processes can be run on same or different machines as the client, receives the data from the detector (via UDP packets).
|
The receiver essentially listens to UDP data packets sent out by the detector.
|
||||||
When using the slsReceiver/ slsMultiReceiver, they can be further configured by the client control software (via TCP/IP) to set file name, file path, progress of acquisition etc.
|
|
||||||
|
To know more about detector receiver setup in the config file, please check out :ref:`the detector-receiver UDP configuration in the config file<detector udp header config>` and the :ref:`detector udp format<detector udp header>`.
|
||||||
|
|
||||||
|
|
||||||
To know more about detector receiver configuration, please check out :ref:`detector udp header and udp commands in the config file <detector udp header>`
|
| Please note the following when using a custom receiver:
|
||||||
|
|
||||||
Custom Receiver
|
* **udp_dstmac** must be configured in the config file. This parameter is not required when using an in-built receiver.
|
||||||
----------------
|
|
||||||
|
|
||||||
| When using custom receiver with our package, ensure that **udp_dstmac** is also configured in the config file. This parameter is not required when using slsReceiver.
|
* Cannot use "auto" for **udp_dstip**.
|
||||||
|
|
||||||
| Cannot use "auto" for **udp_dstip**.
|
* No **rx_** commands in the config file. These commands are for configuring the slsReceiver.
|
||||||
|
|
||||||
| Also ensure that there are no **rx_** commands in the config file. These commands are for configuring the slsReceiver.
|
|
||||||
|
|
||||||
|
The main difference is the lack of **rx_** commands or file commands (eg. **f**write, **f**path) and the **udp_dstmac** is required in config file.
|
||||||
|
|
||||||
Example of a custom receiver config file
|
Example of a custom receiver config file
|
||||||
|
|
||||||
* The main difference is the lack of **rx_** commands or file commands (eg. fwrite, fpath) and the udp_dstmac is required in config file.
|
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
# detector hostname
|
# detector hostname
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
.. _Detector Server Upgrade:
|
.. _Detector Server Upgrade:
|
||||||
|
|
||||||
Upgrade
|
Upgrade
|
||||||
========
|
========
|
||||||
|
|
||||||
|
@ -1,16 +1,55 @@
|
|||||||
slsReceiver/ slsMultiReceiver
|
In-built Receiver
|
||||||
================================
|
================================
|
||||||
|
|
||||||
| One has to start the slsReceiver before loading config file or using any receiver commands (prefix: **rx_** )
|
|
||||||
|
|
||||||
|
|
||||||
|
The receiver essentially listens to UDP data packets sent out by the detector. It's main features are:
|
||||||
|
|
||||||
|
- **Listening**: Receives UDP data from the detector.
|
||||||
|
- **Writing to File**: Optionally writes received data to disk.
|
||||||
|
- **Streaming via ZMQ**: Optionally streams out the data using ZeroMQ.
|
||||||
|
|
||||||
|
Each of these operations runs asynchronously and in parallel for each UDP port.
|
||||||
|
|
||||||
|
|
||||||
|
.. note ::
|
||||||
|
|
||||||
|
* Can be run on the same or different machine as the client.
|
||||||
|
* Can be configured by the client. (set file name/ discard policy, get progress etc.)
|
||||||
|
* Has to be started before the client runs any receiver specific command.
|
||||||
|
|
||||||
|
|
||||||
|
Receiver Variants
|
||||||
|
-----------------
|
||||||
|
There are three main receiver types. How to start them is described :ref:`below<Starting up the Receiver>`.
|
||||||
|
|
||||||
|
+----------------------+--------------------+-----------------------------------------+--------------------------------+
|
||||||
|
| Receiver Type | slsReceiver | slsMultiReceiver |slsFrameSynchronizer |
|
||||||
|
+======================+====================+=========================================+================================+
|
||||||
|
| Modules Supported | 1 | Multiple | Multiple |
|
||||||
|
+----------------------+--------------------+-----------------------------------------+--------------------------------+
|
||||||
|
| Internal Architecture| Threads per porttt | Multiple child processes of slsReceiver | Multi-threading of slsReceiver |
|
||||||
|
+----------------------+--------------------+-----------------------------------------+--------------------------------+
|
||||||
|
| ZMQ Streaming | Disabled by default| Disabled by default | Enabled, not optional |
|
||||||
|
+----------------------+--------------------+-----------------------------------------+--------------------------------+
|
||||||
|
| ZMQ Synchronization | No | No | Yes, across ports |
|
||||||
|
+----------------------+--------------------+-----------------------------------------+--------------------------------+
|
||||||
|
| Image Reconstruction | No | No | No |
|
||||||
|
+----------------------+--------------------+-----------------------------------------+--------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.. _Starting up the Receiver:
|
||||||
|
|
||||||
|
Starting up the Receiver
|
||||||
|
-------------------------
|
||||||
For a Single Module
|
For a Single Module
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
# default port 1954
|
slsReceiver # default port 1954
|
||||||
slsReceiver
|
|
||||||
|
|
||||||
# custom port 2012
|
slsReceiver -t2012 # custom port 2012
|
||||||
slsReceiver -t2012
|
|
||||||
|
|
||||||
|
|
||||||
For Multiple Modules
|
For Multiple Modules
|
||||||
@ -18,57 +57,66 @@ For Multiple Modules
|
|||||||
|
|
||||||
# each receiver (for each module) requires a unique tcp port (if all on same machine)
|
# each receiver (for each module) requires a unique tcp port (if all on same machine)
|
||||||
|
|
||||||
# using slsReceiver in multiple consoles
|
# option 1 (one for each module)
|
||||||
slsReceiver
|
slsReceiver
|
||||||
slsReceiver -t1955
|
slsReceiver -t1955
|
||||||
|
|
||||||
# slsMultiReceiver [starting port] [number of receivers]
|
# option 2
|
||||||
slsMultiReceiver 2012 2
|
slsMultiReceiver 2012 2
|
||||||
|
|
||||||
# slsMultiReceiver [starting port] [number of receivers] [print each frame header for debugging]
|
# option 3
|
||||||
slsMultiReceiver 2012 2 1
|
slsFrameSynchronizer 2012 2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Client Commands
|
Client Commands
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
| One can remove **udp_dstmac** from the config file, as the slsReceiver fetches this from the **udp_ip**.
|
* Client commands to the receiver begin with **rx_** or **f_** (file commands).
|
||||||
|
|
||||||
| One can use "auto" for **udp_dstip** if one wants to use default ip of **rx_hostname**.
|
* **rx_hostname** has to be the first command to the receiver so the client knows which receiver process to communicate with.
|
||||||
|
|
||||||
| The first command to the receiver (**rx_** commands) should be **rx_hostname**. The following are the different ways to establish contact.
|
* Can use 'auto' for **udp_dstip** if using 1GbE interface or the :ref:`virtual simulators<Virtual Detector Servers>`.
|
||||||
|
|
||||||
|
|
||||||
|
To know more about detector receiver setup in the config file, please check out :ref:`the detector-receiver UDP configuration in the config file<detector udp header config>` and the :ref:`detector udp format<detector udp header>`.
|
||||||
|
|
||||||
|
|
||||||
|
The following are the different ways to establish contact using **rx_hostname** command.
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
# default receiver tcp port (1954)
|
# ---single module---
|
||||||
|
|
||||||
|
# default receiver port at 1954
|
||||||
rx_hostname xxx
|
rx_hostname xxx
|
||||||
|
|
||||||
# custom receiver port
|
# custom receiver port
|
||||||
rx_hostname xxx:1957
|
rx_hostname xxx:1957 # option 1
|
||||||
|
|
||||||
# custom receiver port
|
rx_tcpport 1957 # option 2
|
||||||
rx_tcpport 1954
|
|
||||||
rx_hostname xxx
|
rx_hostname xxx
|
||||||
|
|
||||||
# multi modules with custom ports
|
|
||||||
rx_hostname xxx:1955+xxx:1956+
|
|
||||||
|
|
||||||
|
# ---multi module---
|
||||||
|
|
||||||
# multi modules using increasing tcp ports when using multi detector command
|
# using increasing tcp ports
|
||||||
rx_tcpport 1955
|
rx_tcpport 1955
|
||||||
rx_hostname xxx
|
rx_hostname xxx
|
||||||
|
|
||||||
# or specify multi modules with custom ports on same rxr pc
|
# custom ports
|
||||||
0:rx_tcpport 1954
|
rx_hostname xxx:1955+xxx:1958+ # option 1
|
||||||
|
|
||||||
|
0:rx_tcpport 1954 # option 2
|
||||||
1:rx_tcpport 1955
|
1:rx_tcpport 1955
|
||||||
2:rx_tcpport 1956
|
2:rx_tcpport 1956
|
||||||
rx_hostname xxx
|
rx_hostname xxx
|
||||||
|
|
||||||
# multi modules with custom ports on different rxr pc
|
# custom ports on different receiver machines
|
||||||
0:rx_tcpport 1954
|
0:rx_tcpport 1954
|
||||||
0:rx_hostname xxx
|
0:rx_hostname xxx
|
||||||
1:rx_tcpport 1955
|
1:rx_tcpport 1955
|
||||||
1:rx_hostname yyy
|
1:rx_hostname yyyrxr
|
||||||
|
|
||||||
|
|
||||||
| Example commands:
|
| Example commands:
|
||||||
@ -91,6 +139,32 @@ Client Commands
|
|||||||
sls_detector_get -h rx_framescaught
|
sls_detector_get -h rx_framescaught
|
||||||
|
|
||||||
|
|
||||||
|
Example of a config file using in-built receiver
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
# detector hostname
|
||||||
|
hostname bchip052+bchip053+
|
||||||
|
|
||||||
|
# udp destination port (receiver)
|
||||||
|
# sets increasing destination udp ports starting at 50004
|
||||||
|
udp_dstport 50004
|
||||||
|
|
||||||
|
# udp destination ip (receiver)
|
||||||
|
0:udp_dstip 10.0.1.100
|
||||||
|
1:udp_dstip 10.0.2.100
|
||||||
|
|
||||||
|
# udp source ip (same subnet as udp_dstip)
|
||||||
|
0:udp_srcip 10.0.1.184
|
||||||
|
1:udp_srcip 10.0.2.184
|
||||||
|
|
||||||
|
# udp destination mac - not required (picked up from udp_dstip)
|
||||||
|
#udp_dstmac 22:47:d5:48:ad:ef
|
||||||
|
|
||||||
|
# connects to receivers at increasing tcp port starting at 1954
|
||||||
|
rx_hostname mpc3434
|
||||||
|
# same as rx_hostname mpc3434:1954+mpc3434:1955+
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Performance
|
Performance
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.. _detector udp header:
|
.. _detector udp header config:
|
||||||
|
|
||||||
|
|
||||||
Config file
|
Config file
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
.. _Virtual Detector Servers:
|
.. _Virtual Detector Servers:
|
||||||
|
|
||||||
Simulators
|
Simulators
|
||||||
===========
|
===========
|
||||||
|
|
||||||
|
@ -13,5 +13,5 @@ slsDetectorPackage/8.0.2_rh7 stable cmake/3.15.5 Qt/5.12.10
|
|||||||
slsDetectorPackage/8.0.2_rh8 stable cmake/3.15.5 Qt/5.12.10
|
slsDetectorPackage/8.0.2_rh8 stable cmake/3.15.5 Qt/5.12.10
|
||||||
slsDetectorPackage/9.0.0_rh8 stable cmake/3.15.5 Qt/5.12.10
|
slsDetectorPackage/9.0.0_rh8 stable cmake/3.15.5 Qt/5.12.10
|
||||||
slsDetectorPackage/9.1.0_rh8 stable cmake/3.15.5 Qt/5.12.10
|
slsDetectorPackage/9.1.0_rh8 stable cmake/3.15.5 Qt/5.12.10
|
||||||
|
slsDetectorPackage/9.1.1_rh8 stable cmake/3.15.5 Qt/5.12.10
|
||||||
|
slsDetectorPackage/9.2.0_rh8 stable cmake/3.15.5 Qt/5.12.10
|
||||||
|
@ -22,6 +22,7 @@ class SignalsTab(QtWidgets.QWidget):
|
|||||||
self.plotTab = None
|
self.plotTab = None
|
||||||
self.legend: LegendItem | None = None
|
self.legend: LegendItem | None = None
|
||||||
self.rx_dbitoffset = None
|
self.rx_dbitoffset = None
|
||||||
|
self.rx_dbitreorder = None
|
||||||
self.rx_dbitlist = None
|
self.rx_dbitlist = None
|
||||||
|
|
||||||
def refresh(self):
|
def refresh(self):
|
||||||
@ -29,6 +30,7 @@ class SignalsTab(QtWidgets.QWidget):
|
|||||||
self.updateDigitalBitEnable()
|
self.updateDigitalBitEnable()
|
||||||
self.updateIOOut()
|
self.updateIOOut()
|
||||||
self.getDBitOffset()
|
self.getDBitOffset()
|
||||||
|
self.getDBitReorder()
|
||||||
|
|
||||||
def connect_ui(self):
|
def connect_ui(self):
|
||||||
for i in range(Defines.signals.count):
|
for i in range(Defines.signals.count):
|
||||||
@ -49,6 +51,7 @@ class SignalsTab(QtWidgets.QWidget):
|
|||||||
partial(self.setIOOutRange, Defines.signals.half, Defines.signals.count))
|
partial(self.setIOOutRange, Defines.signals.half, Defines.signals.count))
|
||||||
self.view.lineEditPatIOCtrl.editingFinished.connect(self.setIOOutReg)
|
self.view.lineEditPatIOCtrl.editingFinished.connect(self.setIOOutReg)
|
||||||
self.view.spinBoxDBitOffset.editingFinished.connect(self.setDbitOffset)
|
self.view.spinBoxDBitOffset.editingFinished.connect(self.setDbitOffset)
|
||||||
|
self.view.checkBoxDBitReorder.stateChanged.connect(self.setDbitReorder)
|
||||||
|
|
||||||
def setup_ui(self):
|
def setup_ui(self):
|
||||||
self.plotTab = self.mainWindow.plotTab
|
self.plotTab = self.mainWindow.plotTab
|
||||||
@ -87,60 +90,79 @@ class SignalsTab(QtWidgets.QWidget):
|
|||||||
self.legend.addItem(plot, name)
|
self.legend.addItem(plot, name)
|
||||||
|
|
||||||
@recordOrApplyPedestal
|
@recordOrApplyPedestal
|
||||||
def _processWaveformData(self, data, aSamples, dSamples, rx_dbitlist, isPlottedArray, rx_dbitoffset, romode,
|
def _processWaveformData(self, data, aSamples, dSamples, rx_dbitreorder, rx_dbitlist, isPlottedArray, romode,
|
||||||
nADCEnabled):
|
nADCEnabled):
|
||||||
"""
|
|
||||||
transform raw waveform data into a processed numpy array
|
#transform raw waveform data into a processed numpy array
|
||||||
@param data: raw waveform data
|
#@param data: raw waveform data
|
||||||
"""
|
|
||||||
dbitoffset = rx_dbitoffset
|
start_digital_data = 0
|
||||||
if romode == 2:
|
if romode == 2:
|
||||||
dbitoffset += nADCEnabled * 2 * aSamples
|
start_digital_data += nADCEnabled * 2 * aSamples
|
||||||
digital_array = np.array(np.frombuffer(data, offset=dbitoffset, dtype=np.uint8))
|
digital_array = np.array(np.frombuffer(data, offset=start_digital_data, dtype=np.uint8))
|
||||||
|
if rx_dbitreorder:
|
||||||
|
samples_per_bit = np.empty((len(rx_dbitlist), dSamples), dtype=np.uint8) #stored per row all the corresponding signals of all samples
|
||||||
nbitsPerDBit = dSamples
|
nbitsPerDBit = dSamples
|
||||||
if nbitsPerDBit % 8 != 0:
|
if nbitsPerDBit % 8 != 0:
|
||||||
nbitsPerDBit += (8 - (dSamples % 8))
|
nbitsPerDBit += (8 - (dSamples % 8))
|
||||||
offset = 0
|
bit_index = 0
|
||||||
arr = []
|
for idx, i in enumerate(rx_dbitlist):
|
||||||
for i in rx_dbitlist:
|
|
||||||
# where numbits * numsamples is not a multiple of 8
|
# where numbits * numsamples is not a multiple of 8
|
||||||
if offset % 8 != 0:
|
if bit_index % 8 != 0:
|
||||||
offset += (8 - (offset % 8))
|
bit_index += (8 - (bit_index % 8))
|
||||||
if not isPlottedArray[i]:
|
if not isPlottedArray[i]:
|
||||||
offset += nbitsPerDBit
|
bit_index += nbitsPerDBit
|
||||||
return None
|
samples_per_bit[idx, :] = np.nan
|
||||||
waveform = np.zeros(dSamples)
|
continue
|
||||||
for iSample in range(dSamples):
|
for iSample in range(dSamples):
|
||||||
# all samples for digital bit together from slsReceiver
|
# all samples for digital bit together from slsReceiver
|
||||||
index = int(offset / 8)
|
index = int(bit_index / 8)
|
||||||
iBit = offset % 8
|
iBit = bit_index % 8
|
||||||
bit = (digital_array[index] >> iBit) & 1
|
bit = (digital_array[index] >> iBit) & 1
|
||||||
waveform[iSample] = bit
|
samples_per_bit[idx,iSample] = bit
|
||||||
offset += 1
|
bit_index += 1
|
||||||
arr.append(waveform)
|
return samples_per_bit
|
||||||
|
else:
|
||||||
|
nbitsPerSample = len(rx_dbitlist) if len(rx_dbitlist) % 8 == 0 else len(rx_dbitlist) + (8 - (len(rx_dbitlist) % 8))
|
||||||
|
bits_per_sample = np.empty((dSamples, len(rx_dbitlist)), dtype=np.uint8) #store per row all selected bits of a sample
|
||||||
|
for iSample in range(dSamples):
|
||||||
|
bit_index = nbitsPerSample * iSample
|
||||||
|
for idx, i in enumerate(rx_dbitlist):
|
||||||
|
if not isPlottedArray[i]:
|
||||||
|
bit_index += 1
|
||||||
|
bits_per_sample[iSample, idx] = np.nan
|
||||||
|
|
||||||
|
index = int(bit_index/8)
|
||||||
|
iBit = idx % 8
|
||||||
|
bit = (digital_array[index] >> iBit) & 1
|
||||||
|
bits_per_sample[iSample, idx] = bit
|
||||||
|
bit_index += 1
|
||||||
|
return bits_per_sample.T.copy()
|
||||||
|
|
||||||
|
|
||||||
return np.array(arr)
|
|
||||||
|
|
||||||
def processWaveformData(self, data, aSamples, dSamples):
|
def processWaveformData(self, data, aSamples, dSamples):
|
||||||
"""
|
|
||||||
view function
|
#view function
|
||||||
plots processed waveform data
|
#plots processed waveform data
|
||||||
data: raw waveform data
|
#data: raw waveform data
|
||||||
dsamples: digital samples
|
#dsamples: digital samples
|
||||||
asamples: analog samples
|
#asamples: analog samples
|
||||||
"""
|
|
||||||
|
self.refresh()
|
||||||
|
|
||||||
waveforms = {}
|
waveforms = {}
|
||||||
isPlottedArray = {i: getattr(self.view, f"checkBoxBIT{i}Plot").isChecked() for i in self.rx_dbitlist}
|
isPlottedArray = {i: getattr(self.view, f"checkBoxBIT{i}Plot").isChecked() for i in self.rx_dbitlist}
|
||||||
|
|
||||||
digital_array = self._processWaveformData(data, aSamples, dSamples, self.rx_dbitlist, isPlottedArray,
|
digital_array = self._processWaveformData(data, aSamples, dSamples, self.rx_dbitreorder, self.rx_dbitlist, isPlottedArray,
|
||||||
self.rx_dbitoffset, self.mainWindow.romode.value,
|
self.mainWindow.romode.value,
|
||||||
self.mainWindow.nADCEnabled)
|
self.mainWindow.nADCEnabled)
|
||||||
|
|
||||||
irow = 0
|
irow = 0
|
||||||
for idx, i in enumerate(self.rx_dbitlist):
|
for idx, i in enumerate(self.rx_dbitlist):
|
||||||
# bits enabled but not plotting
|
# bits enabled but not plotting
|
||||||
waveform = digital_array[idx]
|
waveform = digital_array[idx, :]
|
||||||
if waveform is None:
|
if np.isnan(waveform[0]):
|
||||||
continue
|
continue
|
||||||
self.mainWindow.digitalPlots[i].setData(waveform)
|
self.mainWindow.digitalPlots[i].setData(waveform)
|
||||||
plotName = getattr(self.view, f"labelBIT{i}").text()
|
plotName = getattr(self.view, f"labelBIT{i}").text()
|
||||||
@ -151,8 +173,10 @@ class SignalsTab(QtWidgets.QWidget):
|
|||||||
irow += 1
|
irow += 1
|
||||||
else:
|
else:
|
||||||
self.mainWindow.digitalPlots[i].setY(0)
|
self.mainWindow.digitalPlots[i].setY(0)
|
||||||
|
|
||||||
return waveforms
|
return waveforms
|
||||||
|
|
||||||
|
|
||||||
def initializeAllDigitalPlots(self):
|
def initializeAllDigitalPlots(self):
|
||||||
self.mainWindow.plotDigitalWaveform = pg.plot()
|
self.mainWindow.plotDigitalWaveform = pg.plot()
|
||||||
self.mainWindow.plotDigitalWaveform.addLegend(colCount=Defines.colCount)
|
self.mainWindow.plotDigitalWaveform.addLegend(colCount=Defines.colCount)
|
||||||
@ -360,14 +384,25 @@ class SignalsTab(QtWidgets.QWidget):
|
|||||||
self.view.spinBoxDBitOffset.setValue(self.rx_dbitoffset)
|
self.view.spinBoxDBitOffset.setValue(self.rx_dbitoffset)
|
||||||
self.view.spinBoxDBitOffset.editingFinished.connect(self.setDbitOffset)
|
self.view.spinBoxDBitOffset.editingFinished.connect(self.setDbitOffset)
|
||||||
|
|
||||||
|
def getDBitReorder(self):
|
||||||
|
self.view.checkBoxDBitReorder.stateChanged.disconnect()
|
||||||
|
self.rx_dbitreorder = self.det.rx_dbitreorder
|
||||||
|
self.view.checkBoxDBitReorder.setChecked(self.rx_dbitreorder)
|
||||||
|
self.view.checkBoxDBitReorder.stateChanged.connect(self.setDbitReorder)
|
||||||
|
|
||||||
|
|
||||||
def setDbitOffset(self):
|
def setDbitOffset(self):
|
||||||
self.det.rx_dbitoffset = self.view.spinBoxDBitOffset.value()
|
self.det.rx_dbitoffset = self.view.spinBoxDBitOffset.value()
|
||||||
|
|
||||||
|
def setDbitReorder(self):
|
||||||
|
self.det.rx_dbitreorder = self.view.checkBoxDBitReorder.isChecked()
|
||||||
|
|
||||||
def saveParameters(self) -> list:
|
def saveParameters(self) -> list:
|
||||||
commands = []
|
commands = []
|
||||||
dblist = [str(i) for i in range(Defines.signals.count) if getattr(self.view, f"checkBoxBIT{i}DB").isChecked()]
|
dblist = [str(i) for i in range(Defines.signals.count) if getattr(self.view, f"checkBoxBIT{i}DB").isChecked()]
|
||||||
if len(dblist) > 0:
|
if len(dblist) > 0:
|
||||||
commands.append(f"rx_dbitlist {', '.join(dblist)}")
|
commands.append(f"rx_dbitlist {', '.join(dblist)}")
|
||||||
commands.append(f"rx_dbitoffset {self.view.spinBoxDBitOffset.value()}")
|
commands.append(f"rx_dbitoffset {self.view.spinBoxDBitOffset.value()}")
|
||||||
|
commands.append(f"rx_dbitreorder {self.view.checkBoxDBitReorder.isChecked()}")
|
||||||
commands.append(f"patioctrl {self.view.lineEditPatIOCtrl.text()}")
|
commands.append(f"patioctrl {self.view.lineEditPatIOCtrl.text()}")
|
||||||
return commands
|
return commands
|
||||||
|
@ -6074,6 +6074,33 @@
|
|||||||
<enum>QFrame::Raised</enum>
|
<enum>QFrame::Raised</enum>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_17">
|
<layout class="QGridLayout" name="gridLayout_17">
|
||||||
|
<item row="0" column="4">
|
||||||
|
<widget class="QSpinBox" name="spinBoxDBitOffset">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>150</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>150</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">background-color: rgb(255, 255, 255);</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="0" column="3">
|
<item row="0" column="3">
|
||||||
<widget class="QLabel" name="label_66">
|
<widget class="QLabel" name="label_66">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
@ -6086,6 +6113,36 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="6">
|
||||||
|
<widget class="QCheckBox" name="checkBoxDBitReorder">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>DBit Reorder</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_48">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>50</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>IO Control Register:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="QLineEdit" name="lineEditPatIOCtrl">
|
<widget class="QLineEdit" name="lineEditPatIOCtrl">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@ -6133,50 +6190,18 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="4">
|
<item row="0" column="5">
|
||||||
<widget class="QSpinBox" name="spinBoxDBitOffset">
|
<spacer name="horizontalSpacer_22">
|
||||||
<property name="minimumSize">
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
<size>
|
<size>
|
||||||
<width>150</width>
|
<width>40</width>
|
||||||
<height>32</height>
|
<height>20</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximumSize">
|
</spacer>
|
||||||
<size>
|
|
||||||
<width>150</width>
|
|
||||||
<height>32</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="styleSheet">
|
|
||||||
<string notr="true">background-color: rgb(255, 255, 255);</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label_48">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>50</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>IO Control Register:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -1,27 +1,37 @@
|
|||||||
|
[tool.scikit-build.metadata.version]
|
||||||
|
provider = "scikit_build_core.metadata.regex"
|
||||||
|
input = "VERSION"
|
||||||
|
regex = '^(?P<version>\d+(?:\.\d+)*(?:[\.\+\w]+)?)$'
|
||||||
|
result = "{version}"
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["scikit-build-core>=0.10", "pybind11", "numpy"]
|
requires = [ "scikit-build-core>=0.10", "pybind11", "numpy",]
|
||||||
build-backend = "scikit_build_core.build"
|
build-backend = "scikit_build_core.build"
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "slsdet"
|
name = "slsdet"
|
||||||
version = "2025.3.19"
|
dynamic = ["version"]
|
||||||
|
dependencies = [
|
||||||
|
"numpy",
|
||||||
|
]
|
||||||
|
|
||||||
[tool.cibuildwheel]
|
[tool.cibuildwheel]
|
||||||
before-all = "uname -a"
|
before-all = "uname -a"
|
||||||
|
build = "cp{311,312,313}-manylinux_x86_64"
|
||||||
|
|
||||||
[tool.scikit-build]
|
[tool.scikit-build.build]
|
||||||
build.verbose = true
|
verbose = true
|
||||||
cmake.build-type = "Release"
|
|
||||||
install.components = ["python"]
|
|
||||||
|
|
||||||
|
[tool.scikit-build.cmake]
|
||||||
|
build-type = "Release"
|
||||||
|
|
||||||
|
[tool.scikit-build.install]
|
||||||
|
components = [ "python",]
|
||||||
|
|
||||||
[tool.scikit-build.cmake.define]
|
[tool.scikit-build.cmake.define]
|
||||||
#Only build the control software and python ext
|
|
||||||
SLS_USE_RECEIVER = "OFF"
|
SLS_USE_RECEIVER = "OFF"
|
||||||
SLS_USE_RECEIVER_BINARIES = "OFF"
|
SLS_USE_RECEIVER_BINARIES = "OFF"
|
||||||
SLS_USE_TEXTCLIENT = "OFF"
|
SLS_USE_TEXTCLIENT = "OFF"
|
||||||
SLS_BUILD_SHARED_LIBRARIES = "OFF"
|
SLS_BUILD_SHARED_LIBRARIES = "OFF"
|
||||||
|
|
||||||
SLS_USE_PYTHON = "ON"
|
SLS_USE_PYTHON = "ON"
|
||||||
SLS_INSTALL_PYTHONEXT = "ON"
|
SLS_INSTALL_PYTHONEXT = "ON"
|
@ -65,6 +65,9 @@ configure_file( scripts/test_virtual.py
|
|||||||
${CMAKE_BINARY_DIR}/test_virtual.py
|
${CMAKE_BINARY_DIR}/test_virtual.py
|
||||||
)
|
)
|
||||||
|
|
||||||
|
configure_file(scripts/frameSynchronizerPullSocket.py
|
||||||
|
${CMAKE_BINARY_DIR}/bin/frameSynchronizerPullSocket.py COPYONLY)
|
||||||
|
|
||||||
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/../VERSION
|
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/../VERSION
|
||||||
${CMAKE_BINARY_DIR}/bin/slsdet/VERSION
|
${CMAKE_BINARY_DIR}/bin/slsdet/VERSION
|
||||||
)
|
)
|
||||||
|
@ -3463,6 +3463,16 @@ class Detector(CppDetectorApi):
|
|||||||
def rx_dbitoffset(self, value):
|
def rx_dbitoffset(self, value):
|
||||||
ut.set_using_dict(self.setRxDbitOffset, value)
|
ut.set_using_dict(self.setRxDbitOffset, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
@element
|
||||||
|
def rx_dbitreorder(self):
|
||||||
|
"""[Ctb] Reorder digital data to group together all samples per signal. Default is 1. Setting to 0 means 'do not reorder' and to keep what the board spits out, which is that all signals in a sample are grouped together."""
|
||||||
|
return self.getRxDbitReorder()
|
||||||
|
|
||||||
|
@rx_dbitreorder.setter
|
||||||
|
def rx_dbitreorder(self, value):
|
||||||
|
ut.set_using_dict(self.setRxDbitReorder, value)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@element
|
@element
|
||||||
def maxadcphaseshift(self):
|
def maxadcphaseshift(self):
|
||||||
|
@ -1664,6 +1664,14 @@ void init_det(py::module &m) {
|
|||||||
(void (Detector::*)(int, sls::Positions)) &
|
(void (Detector::*)(int, sls::Positions)) &
|
||||||
Detector::setRxDbitOffset,
|
Detector::setRxDbitOffset,
|
||||||
py::arg(), py::arg() = Positions{});
|
py::arg(), py::arg() = Positions{});
|
||||||
|
CppDetectorApi.def("getRxDbitReorder",
|
||||||
|
(Result<bool>(Detector::*)(sls::Positions) const) &
|
||||||
|
Detector::getRxDbitReorder,
|
||||||
|
py::arg() = Positions{});
|
||||||
|
CppDetectorApi.def("setRxDbitReorder",
|
||||||
|
(void (Detector::*)(bool, sls::Positions)) &
|
||||||
|
Detector::setRxDbitReorder,
|
||||||
|
py::arg(), py::arg() = Positions{});
|
||||||
CppDetectorApi.def("setDigitalIODelay",
|
CppDetectorApi.def("setDigitalIODelay",
|
||||||
(void (Detector::*)(uint64_t, int, sls::Positions)) &
|
(void (Detector::*)(uint64_t, int, sls::Positions)) &
|
||||||
Detector::setDigitalIODelay,
|
Detector::setDigitalIODelay,
|
||||||
|
26
slsDetectorServers/compileAllServers.sh
Normal file → Executable file
26
slsDetectorServers/compileAllServers.sh
Normal file → Executable file
@ -1,8 +1,6 @@
|
|||||||
# SPDX-License-Identifier: LGPL-3.0-or-other
|
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||||
|
|
||||||
# empty branch = developer branch in updateAPIVersion.sh
|
|
||||||
branch=""
|
|
||||||
det_list=("ctbDetectorServer
|
det_list=("ctbDetectorServer
|
||||||
gotthard2DetectorServer
|
gotthard2DetectorServer
|
||||||
jungfrauDetectorServer
|
jungfrauDetectorServer
|
||||||
@ -10,7 +8,12 @@ det_list=("ctbDetectorServer
|
|||||||
moenchDetectorServer
|
moenchDetectorServer
|
||||||
xilinx_ctbDetectorServer"
|
xilinx_ctbDetectorServer"
|
||||||
)
|
)
|
||||||
usage="\nUsage: compileAllServers.sh [server|all(opt)] [branch(opt)]. \n\tNo arguments mean all servers with 'developer' branch. \n\tNo 'branch' input means 'developer branch'"
|
usage="\nUsage: compileAllServers.sh [server|all(opt)] [update_api(opt)]. \n\tNo arguments mean all servers with 'developer' branch. \n\tupdate_api if true updates the api to version in VERSION file"
|
||||||
|
|
||||||
|
update_api=true
|
||||||
|
target=version
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# arguments
|
# arguments
|
||||||
if [ $# -eq 0 ]; then
|
if [ $# -eq 0 ]; then
|
||||||
@ -34,15 +37,12 @@ elif [ $# -eq 1 ] || [ $# -eq 2 ]; then
|
|||||||
declare -a det=("${1}")
|
declare -a det=("${1}")
|
||||||
#echo "Compiling only $1"
|
#echo "Compiling only $1"
|
||||||
fi
|
fi
|
||||||
# branch
|
|
||||||
if [ $# -eq 2 ]; then
|
if [ $# -eq 2 ]; then
|
||||||
# arg in list
|
update_api=$2
|
||||||
if [[ $det_list == *$2* ]]; then
|
if not $update_api ; then
|
||||||
echo -e "Invalid argument 2: $2. $usage"
|
target=clean
|
||||||
return 1
|
|
||||||
fi
|
fi
|
||||||
branch+=$2
|
|
||||||
#echo "with branch $branch"
|
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo -e "Too many arguments.$usage"
|
echo -e "Too many arguments.$usage"
|
||||||
@ -53,6 +53,9 @@ declare -a deterror=("OK" "OK" "OK" "OK" "OK" "OK")
|
|||||||
|
|
||||||
echo -e "list is ${det[@]}"
|
echo -e "list is ${det[@]}"
|
||||||
|
|
||||||
|
if $update_api; then
|
||||||
|
echo "updating api to $(cat ../VERSION)"
|
||||||
|
fi
|
||||||
# compile each server
|
# compile each server
|
||||||
idet=0
|
idet=0
|
||||||
for i in ${det[@]}
|
for i in ${det[@]}
|
||||||
@ -62,14 +65,13 @@ do
|
|||||||
echo -e "Compiling $dir [$file]"
|
echo -e "Compiling $dir [$file]"
|
||||||
cd $dir
|
cd $dir
|
||||||
make clean
|
make clean
|
||||||
if make version API_BRANCH=$branch; then
|
if make $target; then
|
||||||
deterror[$idet]="OK"
|
deterror[$idet]="OK"
|
||||||
else
|
else
|
||||||
deterror[$idet]="FAIL"
|
deterror[$idet]="FAIL"
|
||||||
fi
|
fi
|
||||||
mv bin/$dir bin/$file
|
mv bin/$dir bin/$file
|
||||||
git add -f bin/$file
|
git add -f bin/$file
|
||||||
cp bin/$file /tftpboot/
|
|
||||||
cd ..
|
cd ..
|
||||||
echo -e "\n\n"
|
echo -e "\n\n"
|
||||||
((++idet))
|
((++idet))
|
||||||
|
@ -1,86 +0,0 @@
|
|||||||
# SPDX-License-Identifier: LGPL-3.0-or-other
|
|
||||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
|
||||||
|
|
||||||
# empty branch = developer branch in updateAPIVersion.sh
|
|
||||||
branch=""
|
|
||||||
det_list=("ctbDetectorServer"
|
|
||||||
"gotthard2DetectorServer"
|
|
||||||
"jungfrauDetectorServer"
|
|
||||||
"mythen3DetectorServer"
|
|
||||||
"moenchDetectorServer"
|
|
||||||
"xilinx_ctbDetectorServer"
|
|
||||||
)
|
|
||||||
usage="\nUsage: compileAllServers.sh [server|all(opt)] [branch(opt)]. \n\tNo arguments mean all servers with 'developer' branch. \n\tNo 'branch' input means 'developer branch'"
|
|
||||||
|
|
||||||
# arguments
|
|
||||||
if [ $# -eq 0 ]; then
|
|
||||||
# no argument, all servers
|
|
||||||
declare -a det=${det_list[@]}
|
|
||||||
echo "Compiling all servers"
|
|
||||||
elif [ $# -eq 1 ] || [ $# -eq 2 ]; then
|
|
||||||
# 'all' servers
|
|
||||||
if [[ $1 == "all" ]]; then
|
|
||||||
declare -a det=${det_list[@]}
|
|
||||||
echo "Compiling all servers"
|
|
||||||
else
|
|
||||||
# only one server
|
|
||||||
# arg not in list
|
|
||||||
if [[ $det_list != *$1* ]]; then
|
|
||||||
echo -e "Invalid argument 1: $1. $usage"
|
|
||||||
return -1
|
|
||||||
fi
|
|
||||||
declare -a det=("${1}")
|
|
||||||
#echo "Compiling only $1"
|
|
||||||
fi
|
|
||||||
# branch
|
|
||||||
if [ $# -eq 2 ]; then
|
|
||||||
# arg in list
|
|
||||||
if [[ $det_list == *$2* ]]; then
|
|
||||||
echo -e "Invalid argument 2: $2. $usage"
|
|
||||||
return -1
|
|
||||||
fi
|
|
||||||
branch+=$2
|
|
||||||
#echo "with branch $branch"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo -e "Too many arguments.$usage"
|
|
||||||
return -1
|
|
||||||
fi
|
|
||||||
|
|
||||||
declare -a deterror=("OK" "OK" "OK" "OK" "OK" "OK")
|
|
||||||
|
|
||||||
echo -e "list is ${det[@]}"
|
|
||||||
|
|
||||||
# compile each server
|
|
||||||
idet=0
|
|
||||||
for i in ${det[@]}
|
|
||||||
do
|
|
||||||
dir=$i
|
|
||||||
file="${i}_developer"
|
|
||||||
echo -e "Compiling $dir [$file]"
|
|
||||||
cd $dir
|
|
||||||
make clean
|
|
||||||
if make API_BRANCH=$branch; then
|
|
||||||
deterror[$idet]="OK"
|
|
||||||
else
|
|
||||||
deterror[$idet]="FAIL"
|
|
||||||
fi
|
|
||||||
mv bin/$dir bin/$file
|
|
||||||
git add -f bin/$file
|
|
||||||
cp bin/$file /tftpboot/
|
|
||||||
cd ..
|
|
||||||
echo -e "\n\n"
|
|
||||||
((++idet))
|
|
||||||
done
|
|
||||||
|
|
||||||
echo -e "Results:"
|
|
||||||
idet=0
|
|
||||||
for i in ${det[@]}
|
|
||||||
do
|
|
||||||
printf "%s\t\t= %s\n" "$i" "${deterror[$idet]}"
|
|
||||||
((++idet))
|
|
||||||
done
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
23
slsDetectorServers/compileEigerServer.sh
Normal file → Executable file
23
slsDetectorServers/compileEigerServer.sh
Normal file → Executable file
@ -3,21 +3,31 @@
|
|||||||
deterror="OK"
|
deterror="OK"
|
||||||
dir="eigerDetectorServer"
|
dir="eigerDetectorServer"
|
||||||
file="${dir}_developer"
|
file="${dir}_developer"
|
||||||
branch=""
|
|
||||||
|
usage="\nUsage: compileAllServers.sh [update_api(opt)]. \n\t update_api if true updates the api to version in VERSION file"
|
||||||
|
|
||||||
|
update_api=true
|
||||||
|
target=version
|
||||||
|
|
||||||
# arguments
|
# arguments
|
||||||
if [ $# -eq 1 ]; then
|
if [ $# -eq 1 ]; then
|
||||||
branch+=$1
|
update_api=$1
|
||||||
#echo "with branch $branch"
|
if not $update_api ; then
|
||||||
|
target=clean
|
||||||
|
|
||||||
|
fi
|
||||||
elif [ ! $# -eq 0 ]; then
|
elif [ ! $# -eq 0 ]; then
|
||||||
echo -e "Only one optional argument allowed for branch."
|
echo -e "Only one optional argument allowed for update_api."
|
||||||
return -1
|
return -1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if $update_api; then
|
||||||
|
echo "updating api to $(cat ../VERSION)"
|
||||||
|
fi
|
||||||
|
|
||||||
echo -e "Compiling $dir [$file]"
|
echo -e "Compiling $dir [$file]"
|
||||||
cd $dir
|
cd $dir
|
||||||
make clean
|
if make $target; then
|
||||||
if make version API_BRANCH=$branch; then
|
|
||||||
deterror="OK"
|
deterror="OK"
|
||||||
else
|
else
|
||||||
deterror="FAIL"
|
deterror="FAIL"
|
||||||
@ -25,7 +35,6 @@ fi
|
|||||||
|
|
||||||
mv bin/$dir bin/$file
|
mv bin/$dir bin/$file
|
||||||
git add -f bin/$file
|
git add -f bin/$file
|
||||||
cp bin/$file /tftpboot/
|
|
||||||
cd ..
|
cd ..
|
||||||
echo -e "\n\n"
|
echo -e "\n\n"
|
||||||
printf "Result:\t\t= %s\n" "${deterror}"
|
printf "Result:\t\t= %s\n" "${deterror}"
|
||||||
|
@ -25,11 +25,10 @@ version: clean versioning $(PROGS)
|
|||||||
|
|
||||||
boot: $(OBJS)
|
boot: $(OBJS)
|
||||||
|
|
||||||
version_branch=$(API_BRANCH)
|
|
||||||
version_name=APICTB
|
version_name=APICTB
|
||||||
version_path=slsDetectorServers/ctbDetectorServer
|
version_path=slsDetectorServers/ctbDetectorServer
|
||||||
versioning:
|
versioning:
|
||||||
cd ../../ && echo $(PWD) && echo `tput setaf 6; ./updateAPIVersion.sh $(version_name) $(version_path) $(version_branch); tput sgr0;`
|
cd ../../ && echo $(PWD) && echo `tput setaf 6; python updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
|
||||||
|
|
||||||
|
|
||||||
$(PROGS): $(OBJS)
|
$(PROGS): $(OBJS)
|
||||||
|
Binary file not shown.
@ -15,6 +15,8 @@
|
|||||||
#include "loadPattern.h"
|
#include "loadPattern.h"
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h> // usleep
|
#include <unistd.h> // usleep
|
||||||
#ifdef VIRTUAL
|
#ifdef VIRTUAL
|
||||||
@ -92,6 +94,10 @@ void basictests() {
|
|||||||
LOG(logINFOBLUE, ("********* Chip Test Board Virtual Server *********\n"));
|
LOG(logINFOBLUE, ("********* Chip Test Board Virtual Server *********\n"));
|
||||||
#else
|
#else
|
||||||
LOG(logINFOBLUE, ("************* Chip Test Board Server *************\n"));
|
LOG(logINFOBLUE, ("************* Chip Test Board Server *************\n"));
|
||||||
|
initError = enableBlackfinAMCExternalAccessExtension(initErrorMessage);
|
||||||
|
if (initError == FAIL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
initError = defineGPIOpins(initErrorMessage);
|
initError = defineGPIOpins(initErrorMessage);
|
||||||
if (initError == FAIL) {
|
if (initError == FAIL) {
|
||||||
return;
|
return;
|
||||||
@ -437,6 +443,32 @@ uint32_t getDetectorIP() {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int enableBlackfinAMCExternalAccessExtension(char *mess) {
|
||||||
|
unsigned int value;
|
||||||
|
const char *file_path = BFIN_AMC_ACCESS_EXTENSION_FNAME;
|
||||||
|
FILE *file = fopen(file_path, "r");
|
||||||
|
if (!file) {
|
||||||
|
strcpy(mess, "Failed to enable blackfin AMC access extension. Could "
|
||||||
|
"not read EBIU_AMBCTL1\n");
|
||||||
|
LOG(logERROR, (mess));
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
fscanf(file, "%x", &value);
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
value |= BFIN_AMC_ACCESS_EXTENSION_ENA_VAL;
|
||||||
|
file = fopen(file_path, "w");
|
||||||
|
if (!file) {
|
||||||
|
strcpy(mess, "Failed to enable blackfin AMC access extension. Could "
|
||||||
|
"not write EBIU_AMBCTL1\n");
|
||||||
|
LOG(logERROR, (mess));
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
fprintf(file, "0x%x", value);
|
||||||
|
fclose(file);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* initialization */
|
/* initialization */
|
||||||
|
|
||||||
void initControlServer() {
|
void initControlServer() {
|
||||||
@ -2258,11 +2290,23 @@ void *start_timer(void *arg) {
|
|||||||
int packetsPerFrame = ceil((double)imageSize / (double)dataSize);
|
int packetsPerFrame = ceil((double)imageSize / (double)dataSize);
|
||||||
|
|
||||||
// Generate Data
|
// Generate Data
|
||||||
char imageData[imageSize];
|
char *imageData = (char *)malloc(imageSize);
|
||||||
memset(imageData, 0, imageSize);
|
memset(imageData, 0, imageSize);
|
||||||
|
|
||||||
|
if (imageData == NULL) {
|
||||||
|
LOG(logERROR, ("Can not allocate image Data RAM."
|
||||||
|
"Probable cause: Memory Leak.\n"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/*
|
||||||
for (int i = 0; i < imageSize; i += sizeof(uint16_t)) {
|
for (int i = 0; i < imageSize; i += sizeof(uint16_t)) {
|
||||||
*((uint16_t *)(imageData + i)) = i;
|
*((uint16_t *)(imageData + i)) = i;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (int i = 0; i < imageSize; i += 2 * sizeof(uint64_t)) {
|
||||||
|
*((uint64_t *)(imageData + i)) = 0xffffffffffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
// Send data
|
// Send data
|
||||||
uint64_t frameNr = 0;
|
uint64_t frameNr = 0;
|
||||||
@ -2319,6 +2363,8 @@ void *start_timer(void *arg) {
|
|||||||
setNextFrameNumber(frameNr + numFrames);
|
setNextFrameNumber(frameNr + numFrames);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(imageData);
|
||||||
|
|
||||||
closeUDPSocket(0);
|
closeUDPSocket(0);
|
||||||
|
|
||||||
sharedMemory_setStatus(IDLE);
|
sharedMemory_setStatus(IDLE);
|
||||||
|
@ -25,11 +25,10 @@ version: clean versioning $(PROGS) #hv9m_blackfin_server
|
|||||||
|
|
||||||
boot: $(OBJS)
|
boot: $(OBJS)
|
||||||
|
|
||||||
version_branch=$(API_BRANCH)
|
|
||||||
version_name=APIEIGER
|
version_name=APIEIGER
|
||||||
version_path=slsDetectorServers/eigerDetectorServer
|
version_path=slsDetectorServers/eigerDetectorServer
|
||||||
versioning:
|
versioning:
|
||||||
cd ../../ && echo $(PWD) && echo `tput setaf 6; ./updateAPIVersion.sh $(version_name) $(version_path) $(version_branch); tput sgr0;`
|
cd ../../ && echo $(PWD) && echo `tput setaf 6; python updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
|
||||||
|
|
||||||
|
|
||||||
$(PROGS): $(OBJS)
|
$(PROGS): $(OBJS)
|
||||||
|
@ -24,11 +24,10 @@ version: clean versioning $(PROGS)
|
|||||||
|
|
||||||
boot: $(OBJS)
|
boot: $(OBJS)
|
||||||
|
|
||||||
version_branch=$(API_BRANCH)
|
|
||||||
version_name=APIGOTTHARD2
|
version_name=APIGOTTHARD2
|
||||||
version_path=slsDetectorServers/gotthard2DetectorServer
|
version_path=slsDetectorServers/gotthard2DetectorServer
|
||||||
versioning:
|
versioning:
|
||||||
cd ../../ && echo $(PWD) && echo `tput setaf 6; ./updateAPIVersion.sh $(version_name) $(version_path) $(version_branch); tput sgr0;`
|
cd ../../ && echo $(PWD) && echo `tput setaf 6; python updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
|
||||||
|
|
||||||
|
|
||||||
$(PROGS): $(OBJS)
|
$(PROGS): $(OBJS)
|
||||||
|
@ -24,11 +24,10 @@ version: clean versioning $(PROGS)
|
|||||||
|
|
||||||
boot: $(OBJS)
|
boot: $(OBJS)
|
||||||
|
|
||||||
version_branch=$(API_BRANCH)
|
|
||||||
version_name=APIJUNGFRAU
|
version_name=APIJUNGFRAU
|
||||||
version_path=slsDetectorServers/jungfrauDetectorServer
|
version_path=slsDetectorServers/jungfrauDetectorServer
|
||||||
versioning:
|
versioning:
|
||||||
cd ../../ && echo $(PWD) && echo `tput setaf 6; ./updateAPIVersion.sh $(version_name) $(version_path) $(version_branch); tput sgr0;`
|
cd ../../ && echo $(PWD) && echo `tput setaf 6; python updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
|
||||||
|
|
||||||
|
|
||||||
$(PROGS): $(OBJS)
|
$(PROGS): $(OBJS)
|
||||||
|
@ -24,11 +24,10 @@ version: clean versioning $(PROGS)
|
|||||||
|
|
||||||
boot: $(OBJS)
|
boot: $(OBJS)
|
||||||
|
|
||||||
version_branch=$(API_BRANCH)
|
|
||||||
version_name=APIMOENCH
|
version_name=APIMOENCH
|
||||||
version_path=slsDetectorServers/moenchDetectorServer
|
version_path=slsDetectorServers/moenchDetectorServer
|
||||||
versioning:
|
versioning:
|
||||||
cd ../../ && echo $(PWD) && echo `tput setaf 6; ./updateAPIVersion.sh $(version_name) $(version_path) $(version_branch); tput sgr0;`
|
cd ../../ && echo $(PWD) && echo `tput setaf 6; python updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
|
||||||
|
|
||||||
|
|
||||||
$(PROGS): $(OBJS)
|
$(PROGS): $(OBJS)
|
||||||
|
@ -25,11 +25,10 @@ version: clean versioning $(PROGS)
|
|||||||
|
|
||||||
boot: $(OBJS)
|
boot: $(OBJS)
|
||||||
|
|
||||||
version_branch=$(API_BRANCH)
|
|
||||||
version_name=APIMYTHEN3
|
version_name=APIMYTHEN3
|
||||||
version_path=slsDetectorServers/mythen3DetectorServer
|
version_path=slsDetectorServers/mythen3DetectorServer
|
||||||
versioning:
|
versioning:
|
||||||
cd ../../ && echo $(PWD) && echo `tput setaf 6; ./updateAPIVersion.sh $(version_name) $(version_path) $(version_branch); tput sgr0;`
|
cd ../../ && echo $(PWD) && echo `tput setaf 6; python updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
|
||||||
|
|
||||||
|
|
||||||
$(PROGS): $(OBJS)
|
$(PROGS): $(OBJS)
|
||||||
|
Binary file not shown.
@ -304,7 +304,7 @@ patternParameters *setChannelRegisterChip(int ichip, char *mask,
|
|||||||
chanReg |= (0x1 << (3 + icounter));
|
chanReg |= (0x1 << (3 + icounter));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
chanReg /= 2;
|
||||||
// deserialize
|
// deserialize
|
||||||
if (chanReg & CHAN_REG_BAD_CHANNEL_MSK) {
|
if (chanReg & CHAN_REG_BAD_CHANNEL_MSK) {
|
||||||
LOG(logINFOBLUE,
|
LOG(logINFOBLUE,
|
||||||
|
@ -5,6 +5,23 @@
|
|||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
/** enable support for ARDY signal on interface to FPGA
|
||||||
|
* needed to properly translate avalon_mm_waitrequest in the CTB firmware
|
||||||
|
* https://www.analog.com/media/en/dsp-documentation/processor-manuals/bf537_hwr_Rev3.2.pdf
|
||||||
|
* page 274
|
||||||
|
* */
|
||||||
|
#define BFIN_EBIU_AMBCTL1_B2_ARDY_ENA_OFST (0)
|
||||||
|
#define BFIN_EBIU_AMBCTL1_B2_ARDY_ENA_MSK \
|
||||||
|
(1 << BFIN_EBIU_AMBCTL1_B2_ARDY_ENA_OFST)
|
||||||
|
#define BFIN_EBIU_AMBCTL1_B2_ARDY_POL_OFST (1)
|
||||||
|
#define BFIN_EBIU_AMBCTL1_B2_ARDY_POL_MSK \
|
||||||
|
(1 << BFIN_EBIU_AMBCTL1_B2_ARDY_POL_OFST)
|
||||||
|
|
||||||
|
#define BFIN_AMC_ACCESS_EXTENSION_ENA_VAL \
|
||||||
|
(BFIN_EBIU_AMBCTL1_B2_ARDY_ENA_MSK | BFIN_EBIU_AMBCTL1_B2_ARDY_POL_MSK)
|
||||||
|
#define BFIN_AMC_ACCESS_EXTENSION_FNAME \
|
||||||
|
"/sys/kernel/debug/blackfin/ebiu_amc/EBIU_AMBCTL1"
|
||||||
|
|
||||||
/** I2C defines */
|
/** I2C defines */
|
||||||
#define I2C_CLOCK_MHZ (131.25)
|
#define I2C_CLOCK_MHZ (131.25)
|
||||||
|
|
||||||
|
@ -113,6 +113,10 @@ void setModuleId(int modid);
|
|||||||
u_int64_t getDetectorMAC();
|
u_int64_t getDetectorMAC();
|
||||||
u_int32_t getDetectorIP();
|
u_int32_t getDetectorIP();
|
||||||
|
|
||||||
|
#if defined(CHIPTESTBOARDD)
|
||||||
|
int enableBlackfinAMCExternalAccessExtension(char *mess);
|
||||||
|
#endif
|
||||||
|
|
||||||
// initialization
|
// initialization
|
||||||
void initControlServer();
|
void initControlServer();
|
||||||
void initStopServer();
|
void initStopServer();
|
||||||
|
@ -36,11 +36,10 @@ version: clean versioning $(PROGS)
|
|||||||
|
|
||||||
boot: $(OBJS)
|
boot: $(OBJS)
|
||||||
|
|
||||||
version_branch=$(API_BRANCH)
|
|
||||||
version_name=APIXILINXCTB
|
version_name=APIXILINXCTB
|
||||||
version_path=slsDetectorServers/xilinx_ctbDetectorServer
|
version_path=slsDetectorServers/xilinx_ctbDetectorServer
|
||||||
versioning:
|
versioning:
|
||||||
cd ../../ && echo $(PWD) && echo `tput setaf 6; ./updateAPIVersion.sh $(version_name) $(version_path) $(version_branch); tput sgr0;`
|
cd ../../ && echo $(PWD) && echo `tput setaf 6; python updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
|
||||||
|
|
||||||
|
|
||||||
$(PROGS): $(OBJS)
|
$(PROGS): $(OBJS)
|
||||||
|
@ -1537,8 +1537,12 @@ void *start_timer(void *arg) {
|
|||||||
packetSize, packetsPerFrame));
|
packetSize, packetsPerFrame));
|
||||||
|
|
||||||
// Generate Data
|
// Generate Data
|
||||||
char imageData[imageSize];
|
char *imageData = (char *)malloc(imageSize);
|
||||||
memset(imageData, 0, imageSize);
|
memset(imageData, 0, imageSize);
|
||||||
|
if (imageData == NULL) {
|
||||||
|
LOG(logERROR, ("Can not allocate image.\n"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
for (int i = 0; i < imageSize; i += sizeof(uint16_t)) {
|
for (int i = 0; i < imageSize; i += sizeof(uint16_t)) {
|
||||||
*((uint16_t *)(imageData + i)) = i;
|
*((uint16_t *)(imageData + i)) = i;
|
||||||
}
|
}
|
||||||
@ -1561,6 +1565,7 @@ void *start_timer(void *arg) {
|
|||||||
usleep(expUs);
|
usleep(expUs);
|
||||||
|
|
||||||
int srcOffset = 0;
|
int srcOffset = 0;
|
||||||
|
int dataSent = 0;
|
||||||
// loop packet
|
// loop packet
|
||||||
for (int i = 0; i != packetsPerFrame; ++i) {
|
for (int i = 0; i != packetsPerFrame; ++i) {
|
||||||
|
|
||||||
@ -1577,10 +1582,12 @@ void *start_timer(void *arg) {
|
|||||||
header->column = detPos[X];
|
header->column = detPos[X];
|
||||||
|
|
||||||
// fill data
|
// fill data
|
||||||
|
int remaining = imageSize - dataSent;
|
||||||
|
int dataSize = remaining < maxDataSize ? remaining : maxDataSize;
|
||||||
memcpy(packetData + sizeof(sls_detector_header),
|
memcpy(packetData + sizeof(sls_detector_header),
|
||||||
imageData + srcOffset,
|
imageData + srcOffset, dataSize);
|
||||||
(imageSize < maxDataSize ? imageSize : maxDataSize));
|
srcOffset += dataSize;
|
||||||
srcOffset += maxDataSize;
|
dataSent += dataSize;
|
||||||
|
|
||||||
sendUDPPacket(0, 0, packetData, packetSize);
|
sendUDPPacket(0, 0, packetData, packetSize);
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,6 @@ if(SLS_USE_TEXTCLIENT)
|
|||||||
target_link_libraries(${val1}
|
target_link_libraries(${val1}
|
||||||
slsDetectorStatic
|
slsDetectorStatic
|
||||||
pthread
|
pthread
|
||||||
rt
|
|
||||||
)
|
)
|
||||||
SET_SOURCE_FILES_PROPERTIES( src/Caller.cpp PROPERTIES COMPILE_FLAGS "-Wno-unused-variable -Wno-unused-but-set-variable")
|
SET_SOURCE_FILES_PROPERTIES( src/Caller.cpp PROPERTIES COMPILE_FLAGS "-Wno-unused-variable -Wno-unused-but-set-variable")
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ _sd() {
|
|||||||
local IS_PATH=0
|
local IS_PATH=0
|
||||||
|
|
||||||
|
|
||||||
local SLS_COMMANDS=" acquire activate adcclk adcenable adcenable10g adcindex adcinvert adclist adcname adcphase adcpipeline adcreg adcvpp apulse asamples autocompdisable badchannels blockingtrigger burstmode burstperiod bursts burstsl bustest cdsgain chipversion clearbit clearbusy clientversion clkdiv clkfreq clkphase collectionmode column compdisabletime confadc config configtransceiver counters currentsource dac dacindex daclist dacname dacvalues datastream dbitclk dbitphase dbitpipeline defaultdac defaultpattern delay delayl detectorserverversion detsize diodelay dpulse dr drlist dsamples execcommand exptime exptime1 exptime2 exptime3 extrastoragecells extsampling extsamplingsrc extsig fformat filtercells filterresistor findex firmwaretest firmwareversion fliprows flowcontrol10g fmaster fname foverwrite fpath framecounter frames framesl frametime free fwrite gaincaps gainmode gappixels gatedelay gatedelay1 gatedelay2 gatedelay3 gates getbit hardwareversion highvoltage hostname im_a im_b im_c im_d im_io imagetest initialchecks inj_ch interpolation interruptsubframe kernelversion lastclient led lock master maxadcphaseshift maxclkphaseshift maxdbitphaseshift measuredperiod measuredsubperiod moduleid nextframenumber nmod numinterfaces overflow packageversion parallel parameters partialreset patfname patioctrl patlimits patloop patloop0 patloop1 patloop2 patmask patnloop patnloop0 patnloop1 patnloop2 patsetbit pattern patternstart patwait patwait0 patwait1 patwait2 patwaittime patwaittime0 patwaittime1 patwaittime2 patword pedestalmode period periodl polarity port powerchip powerindex powerlist powername powervalues programfpga pulse pulsechip pulsenmove pumpprobe quad ratecorr readnrows readout readoutspeed readoutspeedlist rebootcontroller reg resetdacs resetfpga romode row runclk runtime rx_arping rx_clearroi rx_dbitlist rx_dbitoffset rx_discardpolicy rx_fifodepth rx_frameindex rx_framescaught rx_framesperfile rx_hostname rx_jsonaddheader rx_jsonpara rx_lastclient rx_lock rx_missingpackets rx_padding rx_printconfig rx_realudpsocksize rx_roi rx_silent rx_start rx_status rx_stop rx_tcpport rx_threads rx_udpsocksize rx_version rx_zmqfreq rx_zmqhwm rx_zmqip rx_zmqport rx_zmqstartfnum rx_zmqstream samples savepattern scan scanerrmsg selinterface serialnumber setbit settings settingslist settingspath signalindex signallist signalname sleep slowadc slowadcindex slowadclist slowadcname slowadcvalues start status stop stopport storagecell_delay storagecell_start subdeadtime subexptime sync syncclk temp_10ge temp_adc temp_control temp_dcdc temp_event temp_fpga temp_fpgaext temp_fpgafl temp_fpgafr temp_slowadc temp_sodl temp_sodr temp_threshold templist tempvalues tengiga threshold thresholdnotb timing timing_info_decoder timinglist timingsource top transceiverenable trigger triggers triggersl trimbits trimen trimval tsamples txdelay txdelay_frame txdelay_left txdelay_right type udp_cleardst udp_dstip udp_dstip2 udp_dstlist udp_dstmac udp_dstmac2 udp_dstport udp_dstport2 udp_firstdst udp_numdst udp_reconfigure udp_srcip udp_srcip2 udp_srcmac udp_srcmac2 udp_validate update updatedetectorserver updatekernel updatemode user v_a v_b v_c v_chip v_d v_io v_limit vchip_comp_adc vchip_comp_fe vchip_cs vchip_opa_1st vchip_opa_fd vchip_ref_comp_fe versions veto vetoalg vetofile vetophoton vetoref vetostream virtual vm_a vm_b vm_c vm_d vm_io zmqhwm zmqip zmqport "
|
local SLS_COMMANDS=" acquire activate adcclk adcenable adcenable10g adcindex adcinvert adclist adcname adcphase adcpipeline adcreg adcvpp apulse asamples autocompdisable badchannels blockingtrigger burstmode burstperiod bursts burstsl bustest cdsgain chipversion clearbit clearbusy clientversion clkdiv clkfreq clkphase collectionmode column compdisabletime confadc config configtransceiver counters currentsource dac dacindex daclist dacname dacvalues datastream dbitclk dbitphase dbitpipeline defaultdac defaultpattern delay delayl detectorserverversion detsize diodelay dpulse dr drlist dsamples execcommand exptime exptime1 exptime2 exptime3 extrastoragecells extsampling extsamplingsrc extsig fformat filtercells filterresistor findex firmwaretest firmwareversion fliprows flowcontrol10g fmaster fname foverwrite fpath framecounter frames framesl frametime free fwrite gaincaps gainmode gappixels gatedelay gatedelay1 gatedelay2 gatedelay3 gates getbit hardwareversion highvoltage hostname im_a im_b im_c im_d im_io imagetest initialchecks inj_ch interpolation interruptsubframe kernelversion lastclient led lock master maxadcphaseshift maxclkphaseshift maxdbitphaseshift measuredperiod measuredsubperiod moduleid nextframenumber nmod numinterfaces overflow packageversion parallel parameters partialreset patfname patioctrl patlimits patloop patloop0 patloop1 patloop2 patmask patnloop patnloop0 patnloop1 patnloop2 patsetbit pattern patternstart patwait patwait0 patwait1 patwait2 patwaittime patwaittime0 patwaittime1 patwaittime2 patword pedestalmode period periodl polarity port powerchip powerindex powerlist powername powervalues programfpga pulse pulsechip pulsenmove pumpprobe quad ratecorr readnrows readout readoutspeed readoutspeedlist rebootcontroller reg resetdacs resetfpga romode row runclk runtime rx_arping rx_clearroi rx_dbitlist rx_dbitoffset rx_dbitreorder rx_discardpolicy rx_fifodepth rx_frameindex rx_framescaught rx_framesperfile rx_hostname rx_jsonaddheader rx_jsonpara rx_lastclient rx_lock rx_missingpackets rx_padding rx_printconfig rx_realudpsocksize rx_roi rx_silent rx_start rx_status rx_stop rx_tcpport rx_threads rx_udpsocksize rx_version rx_zmqfreq rx_zmqhwm rx_zmqip rx_zmqport rx_zmqstartfnum rx_zmqstream samples savepattern scan scanerrmsg selinterface serialnumber setbit settings settingslist settingspath signalindex signallist signalname sleep slowadc slowadcindex slowadclist slowadcname slowadcvalues start status stop stopport storagecell_delay storagecell_start subdeadtime subexptime sync syncclk temp_10ge temp_adc temp_control temp_dcdc temp_event temp_fpga temp_fpgaext temp_fpgafl temp_fpgafr temp_slowadc temp_sodl temp_sodr temp_threshold templist tempvalues tengiga threshold thresholdnotb timing timing_info_decoder timinglist timingsource top transceiverenable trigger triggers triggersl trimbits trimen trimval tsamples txdelay txdelay_frame txdelay_left txdelay_right type udp_cleardst udp_dstip udp_dstip2 udp_dstlist udp_dstmac udp_dstmac2 udp_dstport udp_dstport2 udp_firstdst udp_numdst udp_reconfigure udp_srcip udp_srcip2 udp_srcmac udp_srcmac2 udp_validate update updatedetectorserver updatekernel updatemode user v_a v_b v_c v_chip v_d v_io v_limit vchip_comp_adc vchip_comp_fe vchip_cs vchip_opa_1st vchip_opa_fd vchip_ref_comp_fe versions veto vetoalg vetofile vetophoton vetoref vetostream virtual vm_a vm_b vm_c vm_d vm_io zmqhwm zmqip zmqport "
|
||||||
__acquire() {
|
__acquire() {
|
||||||
FCN_RETURN=""
|
FCN_RETURN=""
|
||||||
return 0
|
return 0
|
||||||
@ -2088,6 +2088,15 @@ fi
|
|||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
__rx_dbitreorder() {
|
||||||
|
FCN_RETURN=""
|
||||||
|
if [[ ${IS_GET} -eq 0 ]]; then
|
||||||
|
if [[ "${cword}" == "2" ]]; then
|
||||||
|
FCN_RETURN="0 1"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
__rx_discardpolicy() {
|
__rx_discardpolicy() {
|
||||||
FCN_RETURN=""
|
FCN_RETURN=""
|
||||||
if [[ ${IS_GET} -eq 0 ]]; then
|
if [[ ${IS_GET} -eq 0 ]]; then
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
_sd() {
|
_sd() {
|
||||||
|
|
||||||
|
|
||||||
local SLS_COMMANDS=" acquire activate adcclk adcenable adcenable10g adcindex adcinvert adclist adcname adcphase adcpipeline adcreg adcvpp apulse asamples autocompdisable badchannels blockingtrigger burstmode burstperiod bursts burstsl bustest cdsgain chipversion clearbit clearbusy clientversion clkdiv clkfreq clkphase collectionmode column compdisabletime confadc config configtransceiver counters currentsource dac dacindex daclist dacname dacvalues datastream dbitclk dbitphase dbitpipeline defaultdac defaultpattern delay delayl detectorserverversion detsize diodelay dpulse dr drlist dsamples execcommand exptime exptime1 exptime2 exptime3 extrastoragecells extsampling extsamplingsrc extsig fformat filtercells filterresistor findex firmwaretest firmwareversion fliprows flowcontrol10g fmaster fname foverwrite fpath framecounter frames framesl frametime free fwrite gaincaps gainmode gappixels gatedelay gatedelay1 gatedelay2 gatedelay3 gates getbit hardwareversion highvoltage hostname im_a im_b im_c im_d im_io imagetest initialchecks inj_ch interpolation interruptsubframe kernelversion lastclient led lock master maxadcphaseshift maxclkphaseshift maxdbitphaseshift measuredperiod measuredsubperiod moduleid nextframenumber nmod numinterfaces overflow packageversion parallel parameters partialreset patfname patioctrl patlimits patloop patloop0 patloop1 patloop2 patmask patnloop patnloop0 patnloop1 patnloop2 patsetbit pattern patternstart patwait patwait0 patwait1 patwait2 patwaittime patwaittime0 patwaittime1 patwaittime2 patword pedestalmode period periodl polarity port powerchip powerindex powerlist powername powervalues programfpga pulse pulsechip pulsenmove pumpprobe quad ratecorr readnrows readout readoutspeed readoutspeedlist rebootcontroller reg resetdacs resetfpga romode row runclk runtime rx_arping rx_clearroi rx_dbitlist rx_dbitoffset rx_discardpolicy rx_fifodepth rx_frameindex rx_framescaught rx_framesperfile rx_hostname rx_jsonaddheader rx_jsonpara rx_lastclient rx_lock rx_missingpackets rx_padding rx_printconfig rx_realudpsocksize rx_roi rx_silent rx_start rx_status rx_stop rx_tcpport rx_threads rx_udpsocksize rx_version rx_zmqfreq rx_zmqhwm rx_zmqip rx_zmqport rx_zmqstartfnum rx_zmqstream samples savepattern scan scanerrmsg selinterface serialnumber setbit settings settingslist settingspath signalindex signallist signalname sleep slowadc slowadcindex slowadclist slowadcname slowadcvalues start status stop stopport storagecell_delay storagecell_start subdeadtime subexptime sync syncclk temp_10ge temp_adc temp_control temp_dcdc temp_event temp_fpga temp_fpgaext temp_fpgafl temp_fpgafr temp_slowadc temp_sodl temp_sodr temp_threshold templist tempvalues tengiga threshold thresholdnotb timing timing_info_decoder timinglist timingsource top transceiverenable trigger triggers triggersl trimbits trimen trimval tsamples txdelay txdelay_frame txdelay_left txdelay_right type udp_cleardst udp_dstip udp_dstip2 udp_dstlist udp_dstmac udp_dstmac2 udp_dstport udp_dstport2 udp_firstdst udp_numdst udp_reconfigure udp_srcip udp_srcip2 udp_srcmac udp_srcmac2 udp_validate update updatedetectorserver updatekernel updatemode user v_a v_b v_c v_chip v_d v_io v_limit vchip_comp_adc vchip_comp_fe vchip_cs vchip_opa_1st vchip_opa_fd vchip_ref_comp_fe versions veto vetoalg vetofile vetophoton vetoref vetostream virtual vm_a vm_b vm_c vm_d vm_io zmqhwm zmqip zmqport "
|
local SLS_COMMANDS=" acquire activate adcclk adcenable adcenable10g adcindex adcinvert adclist adcname adcphase adcpipeline adcreg adcvpp apulse asamples autocompdisable badchannels blockingtrigger burstmode burstperiod bursts burstsl bustest cdsgain chipversion clearbit clearbusy clientversion clkdiv clkfreq clkphase collectionmode column compdisabletime confadc config configtransceiver counters currentsource dac dacindex daclist dacname dacvalues datastream dbitclk dbitphase dbitpipeline defaultdac defaultpattern delay delayl detectorserverversion detsize diodelay dpulse dr drlist dsamples execcommand exptime exptime1 exptime2 exptime3 extrastoragecells extsampling extsamplingsrc extsig fformat filtercells filterresistor findex firmwaretest firmwareversion fliprows flowcontrol10g fmaster fname foverwrite fpath framecounter frames framesl frametime free fwrite gaincaps gainmode gappixels gatedelay gatedelay1 gatedelay2 gatedelay3 gates getbit hardwareversion highvoltage hostname im_a im_b im_c im_d im_io imagetest initialchecks inj_ch interpolation interruptsubframe kernelversion lastclient led lock master maxadcphaseshift maxclkphaseshift maxdbitphaseshift measuredperiod measuredsubperiod moduleid nextframenumber nmod numinterfaces overflow packageversion parallel parameters partialreset patfname patioctrl patlimits patloop patloop0 patloop1 patloop2 patmask patnloop patnloop0 patnloop1 patnloop2 patsetbit pattern patternstart patwait patwait0 patwait1 patwait2 patwaittime patwaittime0 patwaittime1 patwaittime2 patword pedestalmode period periodl polarity port powerchip powerindex powerlist powername powervalues programfpga pulse pulsechip pulsenmove pumpprobe quad ratecorr readnrows readout readoutspeed readoutspeedlist rebootcontroller reg resetdacs resetfpga romode row runclk runtime rx_arping rx_clearroi rx_dbitlist rx_dbitoffset rx_dbitreorder rx_discardpolicy rx_fifodepth rx_frameindex rx_framescaught rx_framesperfile rx_hostname rx_jsonaddheader rx_jsonpara rx_lastclient rx_lock rx_missingpackets rx_padding rx_printconfig rx_realudpsocksize rx_roi rx_silent rx_start rx_status rx_stop rx_tcpport rx_threads rx_udpsocksize rx_version rx_zmqfreq rx_zmqhwm rx_zmqip rx_zmqport rx_zmqstartfnum rx_zmqstream samples savepattern scan scanerrmsg selinterface serialnumber setbit settings settingslist settingspath signalindex signallist signalname sleep slowadc slowadcindex slowadclist slowadcname slowadcvalues start status stop stopport storagecell_delay storagecell_start subdeadtime subexptime sync syncclk temp_10ge temp_adc temp_control temp_dcdc temp_event temp_fpga temp_fpgaext temp_fpgafl temp_fpgafr temp_slowadc temp_sodl temp_sodr temp_threshold templist tempvalues tengiga threshold thresholdnotb timing timing_info_decoder timinglist timingsource top transceiverenable trigger triggers triggersl trimbits trimen trimval tsamples txdelay txdelay_frame txdelay_left txdelay_right type udp_cleardst udp_dstip udp_dstip2 udp_dstlist udp_dstmac udp_dstmac2 udp_dstport udp_dstport2 udp_firstdst udp_numdst udp_reconfigure udp_srcip udp_srcip2 udp_srcmac udp_srcmac2 udp_validate update updatedetectorserver updatekernel updatemode user v_a v_b v_c v_chip v_d v_io v_limit vchip_comp_adc vchip_comp_fe vchip_cs vchip_opa_1st vchip_opa_fd vchip_ref_comp_fe versions veto vetoalg vetofile vetophoton vetoref vetostream virtual vm_a vm_b vm_c vm_d vm_io zmqhwm zmqip zmqport "
|
||||||
__acquire() {
|
__acquire() {
|
||||||
FCN_RETURN=""
|
FCN_RETURN=""
|
||||||
return 0
|
return 0
|
||||||
@ -2012,6 +2012,15 @@ fi
|
|||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
__rx_dbitreorder() {
|
||||||
|
FCN_RETURN=""
|
||||||
|
if [[ ${IS_GET} -eq 0 ]]; then
|
||||||
|
if [[ "${cword}" == "2" ]]; then
|
||||||
|
FCN_RETURN="0 1"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
__rx_discardpolicy() {
|
__rx_discardpolicy() {
|
||||||
FCN_RETURN=""
|
FCN_RETURN=""
|
||||||
if [[ ${IS_GET} -eq 0 ]]; then
|
if [[ ${IS_GET} -eq 0 ]]; then
|
||||||
|
@ -1412,6 +1412,18 @@ lock:
|
|||||||
function: setDetectorLock
|
function: setDetectorLock
|
||||||
input_types: [ bool ]
|
input_types: [ bool ]
|
||||||
|
|
||||||
|
|
||||||
|
rx_dbitreorder:
|
||||||
|
help: "[0, 1]\n\t[Ctb] Reorder digital data such that it groups each signal (0-63) from all the different samples together . Default is 1. Setting to 0 means 'do not reorder' and to keep what the board spits out, which is that all signals in a sample are grouped together."
|
||||||
|
inherit_actions: INTEGER_COMMAND_VEC_ID
|
||||||
|
actions:
|
||||||
|
GET:
|
||||||
|
function: getRxDbitReorder
|
||||||
|
PUT:
|
||||||
|
function: setRxDbitReorder
|
||||||
|
input_types: [ bool ]
|
||||||
|
|
||||||
|
|
||||||
################# INTEGER_COMMAND_VEC_ID_GET #################
|
################# INTEGER_COMMAND_VEC_ID_GET #################
|
||||||
|
|
||||||
master:
|
master:
|
||||||
|
@ -8305,6 +8305,48 @@ rx_dbitoffset:
|
|||||||
help: "[n_bytes]\n\t[Ctb] Offset in bytes in digital data to skip in receiver."
|
help: "[n_bytes]\n\t[Ctb] Offset in bytes in digital data to skip in receiver."
|
||||||
infer_action: true
|
infer_action: true
|
||||||
template: true
|
template: true
|
||||||
|
rx_dbitreorder:
|
||||||
|
actions:
|
||||||
|
GET:
|
||||||
|
args:
|
||||||
|
- arg_types: []
|
||||||
|
argc: 0
|
||||||
|
cast_input: []
|
||||||
|
check_det_id: false
|
||||||
|
convert_det_id: true
|
||||||
|
function: getRxDbitReorder
|
||||||
|
input: []
|
||||||
|
input_types: []
|
||||||
|
output:
|
||||||
|
- OutString(t)
|
||||||
|
require_det_id: true
|
||||||
|
store_result_in_t: true
|
||||||
|
PUT:
|
||||||
|
args:
|
||||||
|
- arg_types:
|
||||||
|
- bool
|
||||||
|
argc: 1
|
||||||
|
cast_input:
|
||||||
|
- true
|
||||||
|
check_det_id: false
|
||||||
|
convert_det_id: true
|
||||||
|
function: setRxDbitReorder
|
||||||
|
input:
|
||||||
|
- args[0]
|
||||||
|
input_types:
|
||||||
|
- bool
|
||||||
|
output:
|
||||||
|
- args.front()
|
||||||
|
require_det_id: true
|
||||||
|
store_result_in_t: false
|
||||||
|
command_name: rx_dbitreorder
|
||||||
|
function_alias: rx_dbitreorder
|
||||||
|
help: "[0, 1]\n\t[Ctb] Reorder digital data such that it groups each signal (0-63)\
|
||||||
|
\ from all the different samples together . Default is 1. Setting to 0 means 'do\
|
||||||
|
\ not reorder' and to keep what the board spits out, which is that all signals\
|
||||||
|
\ in a sample are grouped together."
|
||||||
|
infer_action: true
|
||||||
|
template: true
|
||||||
rx_discardpolicy:
|
rx_discardpolicy:
|
||||||
actions:
|
actions:
|
||||||
GET:
|
GET:
|
||||||
|
@ -1729,6 +1729,16 @@ class Detector {
|
|||||||
/** [CTB] Set number of bytes of digital data to skip in the Receiver */
|
/** [CTB] Set number of bytes of digital data to skip in the Receiver */
|
||||||
void setRxDbitOffset(int value, Positions pos = {});
|
void setRxDbitOffset(int value, Positions pos = {});
|
||||||
|
|
||||||
|
/** [CTB] */
|
||||||
|
Result<bool> getRxDbitReorder(Positions pos = {}) const;
|
||||||
|
|
||||||
|
/** [CTB] Reorder digital data such that it groups each signal (0-63)
|
||||||
|
* from all the different samples together.
|
||||||
|
* Default is true. Setting to false means 'do not reorder' and to keep what
|
||||||
|
* the board spits out, which is that all signals in a sample are grouped
|
||||||
|
* together */
|
||||||
|
void setRxDbitReorder(bool reorder, Positions pos = {});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [CTB] Set Digital IO Delay
|
* [CTB] Set Digital IO Delay
|
||||||
* cannot get
|
* cannot get
|
||||||
|
@ -10700,6 +10700,68 @@ std::string Caller::rx_dbitoffset(int action) {
|
|||||||
return os.str();
|
return os.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Caller::rx_dbitreorder(int action) {
|
||||||
|
|
||||||
|
std::ostringstream os;
|
||||||
|
// print help
|
||||||
|
if (action == slsDetectorDefs::HELP_ACTION) {
|
||||||
|
os << R"V0G0N([0, 1]
|
||||||
|
[Ctb] Reorder digital data such that it groups each signal (0-63) from all the different samples together . Default is 1. Setting to 0 means 'do not reorder' and to keep what the board spits out, which is that all signals in a sample are grouped together. )V0G0N"
|
||||||
|
<< std::endl;
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if action and arguments are valid
|
||||||
|
if (action == slsDetectorDefs::GET_ACTION) {
|
||||||
|
if (1 && args.size() != 0) {
|
||||||
|
throw RuntimeError("Wrong number of arguments for action GET");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.size() == 0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (action == slsDetectorDefs::PUT_ACTION) {
|
||||||
|
if (1 && args.size() != 1) {
|
||||||
|
throw RuntimeError("Wrong number of arguments for action PUT");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.size() == 1) {
|
||||||
|
try {
|
||||||
|
StringTo<bool>(args[0]);
|
||||||
|
} catch (...) {
|
||||||
|
throw RuntimeError("Could not convert argument 0 to bool");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
|
||||||
|
throw RuntimeError("INTERNAL ERROR: Invalid action: supported actions "
|
||||||
|
"are ['GET', 'PUT']");
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate code for each action
|
||||||
|
if (action == slsDetectorDefs::GET_ACTION) {
|
||||||
|
if (args.size() == 0) {
|
||||||
|
auto t = det->getRxDbitReorder(std::vector<int>{det_id});
|
||||||
|
os << OutString(t) << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == slsDetectorDefs::PUT_ACTION) {
|
||||||
|
if (args.size() == 1) {
|
||||||
|
auto arg0 = StringTo<bool>(args[0]);
|
||||||
|
det->setRxDbitReorder(arg0, std::vector<int>{det_id});
|
||||||
|
os << args.front() << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
std::string Caller::rx_discardpolicy(int action) {
|
std::string Caller::rx_discardpolicy(int action) {
|
||||||
|
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
|
@ -236,6 +236,7 @@ class Caller {
|
|||||||
std::string rx_clearroi(int action);
|
std::string rx_clearroi(int action);
|
||||||
std::string rx_dbitlist(int action);
|
std::string rx_dbitlist(int action);
|
||||||
std::string rx_dbitoffset(int action);
|
std::string rx_dbitoffset(int action);
|
||||||
|
std::string rx_dbitreorder(int action);
|
||||||
std::string rx_discardpolicy(int action);
|
std::string rx_discardpolicy(int action);
|
||||||
std::string rx_fifodepth(int action);
|
std::string rx_fifodepth(int action);
|
||||||
std::string rx_frameindex(int action);
|
std::string rx_frameindex(int action);
|
||||||
@ -582,6 +583,7 @@ class Caller {
|
|||||||
{"rx_clearroi", &Caller::rx_clearroi},
|
{"rx_clearroi", &Caller::rx_clearroi},
|
||||||
{"rx_dbitlist", &Caller::rx_dbitlist},
|
{"rx_dbitlist", &Caller::rx_dbitlist},
|
||||||
{"rx_dbitoffset", &Caller::rx_dbitoffset},
|
{"rx_dbitoffset", &Caller::rx_dbitoffset},
|
||||||
|
{"rx_dbitreorder", &Caller::rx_dbitreorder},
|
||||||
{"rx_discardpolicy", &Caller::rx_discardpolicy},
|
{"rx_discardpolicy", &Caller::rx_discardpolicy},
|
||||||
{"rx_fifodepth", &Caller::rx_fifodepth},
|
{"rx_fifodepth", &Caller::rx_fifodepth},
|
||||||
{"rx_frameindex", &Caller::rx_frameindex},
|
{"rx_frameindex", &Caller::rx_frameindex},
|
||||||
|
@ -2277,6 +2277,14 @@ void Detector::setRxDbitOffset(int value, Positions pos) {
|
|||||||
pimpl->Parallel(&Module::setReceiverDbitOffset, pos, value);
|
pimpl->Parallel(&Module::setReceiverDbitOffset, pos, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<bool> Detector::getRxDbitReorder(Positions pos) const {
|
||||||
|
return pimpl->Parallel(&Module::getReceiverDbitReorder, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Detector::setRxDbitReorder(bool reorder, Positions pos) {
|
||||||
|
pimpl->Parallel(&Module::setReceiverDbitReorder, pos, reorder);
|
||||||
|
}
|
||||||
|
|
||||||
void Detector::setDigitalIODelay(uint64_t pinMask, int delay, Positions pos) {
|
void Detector::setDigitalIODelay(uint64_t pinMask, int delay, Positions pos) {
|
||||||
pimpl->Parallel(&Module::setDigitalIODelay, pos, pinMask, delay);
|
pimpl->Parallel(&Module::setDigitalIODelay, pos, pinMask, delay);
|
||||||
}
|
}
|
||||||
|
@ -2509,6 +2509,15 @@ void Module::setReceiverDbitOffset(int value) {
|
|||||||
sendToReceiver(F_SET_RECEIVER_DBIT_OFFSET, value, nullptr);
|
sendToReceiver(F_SET_RECEIVER_DBIT_OFFSET, value, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Module::getReceiverDbitReorder() const {
|
||||||
|
return sendToReceiver<int>(F_GET_RECEIVER_DBIT_REORDER);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::setReceiverDbitReorder(bool reorder) {
|
||||||
|
sendToReceiver(F_SET_RECEIVER_DBIT_REORDER, static_cast<int>(reorder),
|
||||||
|
nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
void Module::setDigitalIODelay(uint64_t pinMask, int delay) {
|
void Module::setDigitalIODelay(uint64_t pinMask, int delay) {
|
||||||
uint64_t args[]{pinMask, static_cast<uint64_t>(delay)};
|
uint64_t args[]{pinMask, static_cast<uint64_t>(delay)};
|
||||||
sendToDetector(F_DIGITAL_IO_DELAY, args, nullptr);
|
sendToDetector(F_DIGITAL_IO_DELAY, args, nullptr);
|
||||||
|
@ -510,6 +510,8 @@ class Module : public virtual slsDetectorDefs {
|
|||||||
void setReceiverDbitList(std::vector<int> list);
|
void setReceiverDbitList(std::vector<int> list);
|
||||||
int getReceiverDbitOffset() const;
|
int getReceiverDbitOffset() const;
|
||||||
void setReceiverDbitOffset(int value);
|
void setReceiverDbitOffset(int value);
|
||||||
|
bool getReceiverDbitReorder() const;
|
||||||
|
void setReceiverDbitReorder(bool value);
|
||||||
void setDigitalIODelay(uint64_t pinMask, int delay);
|
void setDigitalIODelay(uint64_t pinMask, int delay);
|
||||||
bool getLEDEnable() const;
|
bool getLEDEnable() const;
|
||||||
void setLEDEnable(bool enable);
|
void setLEDEnable(bool enable);
|
||||||
|
@ -2568,6 +2568,22 @@ int InferAction::rx_dbitoffset() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int InferAction::rx_dbitreorder() {
|
||||||
|
|
||||||
|
if (args.size() == 0) {
|
||||||
|
return slsDetectorDefs::GET_ACTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.size() == 1) {
|
||||||
|
return slsDetectorDefs::PUT_ACTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
|
||||||
|
throw RuntimeError("Could not infer action: Wrong number of arguments");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int InferAction::rx_discardpolicy() {
|
int InferAction::rx_discardpolicy() {
|
||||||
|
|
||||||
if (args.size() == 0) {
|
if (args.size() == 0) {
|
||||||
|
@ -193,6 +193,7 @@ class InferAction {
|
|||||||
int rx_clearroi();
|
int rx_clearroi();
|
||||||
int rx_dbitlist();
|
int rx_dbitlist();
|
||||||
int rx_dbitoffset();
|
int rx_dbitoffset();
|
||||||
|
int rx_dbitreorder();
|
||||||
int rx_discardpolicy();
|
int rx_discardpolicy();
|
||||||
int rx_fifodepth();
|
int rx_fifodepth();
|
||||||
int rx_frameindex();
|
int rx_frameindex();
|
||||||
@ -527,6 +528,7 @@ class InferAction {
|
|||||||
{"rx_clearroi", &InferAction::rx_clearroi},
|
{"rx_clearroi", &InferAction::rx_clearroi},
|
||||||
{"rx_dbitlist", &InferAction::rx_dbitlist},
|
{"rx_dbitlist", &InferAction::rx_dbitlist},
|
||||||
{"rx_dbitoffset", &InferAction::rx_dbitoffset},
|
{"rx_dbitoffset", &InferAction::rx_dbitoffset},
|
||||||
|
{"rx_dbitreorder", &InferAction::rx_dbitreorder},
|
||||||
{"rx_discardpolicy", &InferAction::rx_discardpolicy},
|
{"rx_discardpolicy", &InferAction::rx_discardpolicy},
|
||||||
{"rx_fifodepth", &InferAction::rx_fifodepth},
|
{"rx_fifodepth", &InferAction::rx_fifodepth},
|
||||||
{"rx_frameindex", &InferAction::rx_frameindex},
|
{"rx_frameindex", &InferAction::rx_frameindex},
|
||||||
|
@ -17,6 +17,119 @@ namespace sls {
|
|||||||
using test::GET;
|
using test::GET;
|
||||||
using test::PUT;
|
using test::PUT;
|
||||||
|
|
||||||
|
TEST_CASE("ctb_acquire_check_file_size", "[.cmdcall]") {
|
||||||
|
Detector det;
|
||||||
|
Caller caller(&det);
|
||||||
|
auto det_type =
|
||||||
|
det.getDetectorType().tsquash("Inconsistent detector types to test");
|
||||||
|
|
||||||
|
if (det_type == defs::CHIPTESTBOARD ||
|
||||||
|
det_type == defs::XILINX_CHIPTESTBOARD) {
|
||||||
|
int num_frames_to_acquire = 2;
|
||||||
|
// all the test cases
|
||||||
|
{
|
||||||
|
testCtbAcquireInfo test_ctb_config;
|
||||||
|
test_ctb_config.readout_mode = defs::ANALOG_AND_DIGITAL;
|
||||||
|
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
|
||||||
|
test_ctb_config, num_frames_to_acquire, det, caller));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
testCtbAcquireInfo test_ctb_config;
|
||||||
|
test_ctb_config.readout_mode = defs::ANALOG_AND_DIGITAL;
|
||||||
|
test_ctb_config.dbit_offset = 16;
|
||||||
|
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
|
||||||
|
test_ctb_config, num_frames_to_acquire, det, caller));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
testCtbAcquireInfo test_ctb_config;
|
||||||
|
test_ctb_config.readout_mode = defs::ANALOG_AND_DIGITAL;
|
||||||
|
test_ctb_config.dbit_reorder = true;
|
||||||
|
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
|
||||||
|
test_ctb_config, num_frames_to_acquire, det, caller));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
testCtbAcquireInfo test_ctb_config;
|
||||||
|
test_ctb_config.readout_mode = defs::ANALOG_AND_DIGITAL;
|
||||||
|
test_ctb_config.dbit_offset = 16;
|
||||||
|
test_ctb_config.dbit_reorder = true;
|
||||||
|
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
|
||||||
|
test_ctb_config, num_frames_to_acquire, det, caller));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
testCtbAcquireInfo test_ctb_config;
|
||||||
|
test_ctb_config.readout_mode = defs::ANALOG_AND_DIGITAL;
|
||||||
|
test_ctb_config.dbit_offset = 16;
|
||||||
|
test_ctb_config.dbit_list.clear();
|
||||||
|
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
|
||||||
|
test_ctb_config, num_frames_to_acquire, det, caller));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
testCtbAcquireInfo test_ctb_config;
|
||||||
|
test_ctb_config.readout_mode = defs::ANALOG_AND_DIGITAL;
|
||||||
|
test_ctb_config.dbit_offset = 16;
|
||||||
|
test_ctb_config.dbit_list.clear();
|
||||||
|
test_ctb_config.dbit_reorder = true;
|
||||||
|
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
|
||||||
|
test_ctb_config, num_frames_to_acquire, det, caller));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
testCtbAcquireInfo test_ctb_config;
|
||||||
|
test_ctb_config.readout_mode = defs::DIGITAL_AND_TRANSCEIVER;
|
||||||
|
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
|
||||||
|
test_ctb_config, num_frames_to_acquire, det, caller));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
testCtbAcquireInfo test_ctb_config;
|
||||||
|
test_ctb_config.readout_mode = defs::DIGITAL_AND_TRANSCEIVER;
|
||||||
|
test_ctb_config.dbit_offset = 16;
|
||||||
|
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
|
||||||
|
test_ctb_config, num_frames_to_acquire, det, caller));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
testCtbAcquireInfo test_ctb_config;
|
||||||
|
test_ctb_config.readout_mode = defs::DIGITAL_AND_TRANSCEIVER;
|
||||||
|
test_ctb_config.dbit_list.clear();
|
||||||
|
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
|
||||||
|
test_ctb_config, num_frames_to_acquire, det, caller));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
testCtbAcquireInfo test_ctb_config;
|
||||||
|
test_ctb_config.readout_mode = defs::DIGITAL_AND_TRANSCEIVER;
|
||||||
|
test_ctb_config.dbit_offset = 16;
|
||||||
|
test_ctb_config.dbit_list.clear();
|
||||||
|
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
|
||||||
|
test_ctb_config, num_frames_to_acquire, det, caller));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
testCtbAcquireInfo test_ctb_config;
|
||||||
|
test_ctb_config.readout_mode = defs::DIGITAL_AND_TRANSCEIVER;
|
||||||
|
test_ctb_config.dbit_offset = 16;
|
||||||
|
test_ctb_config.dbit_list.clear();
|
||||||
|
test_ctb_config.dbit_reorder = true;
|
||||||
|
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
|
||||||
|
test_ctb_config, num_frames_to_acquire, det, caller));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
testCtbAcquireInfo test_ctb_config;
|
||||||
|
test_ctb_config.readout_mode = defs::TRANSCEIVER_ONLY;
|
||||||
|
test_ctb_config.dbit_offset = 16;
|
||||||
|
test_ctb_config.dbit_list.clear();
|
||||||
|
test_ctb_config.dbit_reorder = true;
|
||||||
|
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
|
||||||
|
test_ctb_config, num_frames_to_acquire, det, caller));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
testCtbAcquireInfo test_ctb_config;
|
||||||
|
test_ctb_config.readout_mode = defs::ANALOG_ONLY;
|
||||||
|
test_ctb_config.dbit_offset = 16;
|
||||||
|
test_ctb_config.dbit_list.clear();
|
||||||
|
test_ctb_config.dbit_reorder = true;
|
||||||
|
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
|
||||||
|
test_ctb_config, num_frames_to_acquire, det, caller));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* dacs */
|
/* dacs */
|
||||||
|
|
||||||
TEST_CASE("dacname", "[.cmdcall]") {
|
TEST_CASE("dacname", "[.cmdcall]") {
|
||||||
|
@ -17,6 +17,70 @@ namespace sls {
|
|||||||
using test::GET;
|
using test::GET;
|
||||||
using test::PUT;
|
using test::PUT;
|
||||||
|
|
||||||
|
TEST_CASE("eiger_acquire_check_file_size", "[.cmdcall]") {
|
||||||
|
Detector det;
|
||||||
|
Caller caller(&det);
|
||||||
|
auto det_type =
|
||||||
|
det.getDetectorType().tsquash("Inconsistent detector types to test");
|
||||||
|
|
||||||
|
if (det_type == defs::EIGER) {
|
||||||
|
|
||||||
|
// save previous state
|
||||||
|
testFileInfo prev_file_info = get_file_state(det);
|
||||||
|
testCommonDetAcquireInfo prev_det_config_info =
|
||||||
|
get_common_acquire_config_state(det);
|
||||||
|
|
||||||
|
// save previous specific det type config
|
||||||
|
auto exptime = det.getExptime().tsquash("inconsistent exptime to test");
|
||||||
|
auto n_rows =
|
||||||
|
det.getReadNRows().tsquash("inconsistent number of rows to test");
|
||||||
|
auto dynamic_range =
|
||||||
|
det.getDynamicRange().tsquash("inconsistent dynamic range to test");
|
||||||
|
REQUIRE(false ==
|
||||||
|
det.getTenGiga().tsquash("inconsistent 10Giga to test"));
|
||||||
|
|
||||||
|
// defaults
|
||||||
|
int num_frames_to_acquire = 2;
|
||||||
|
testFileInfo test_file_info;
|
||||||
|
set_file_state(det, test_file_info);
|
||||||
|
testCommonDetAcquireInfo det_config;
|
||||||
|
det_config.num_frames_to_acquire = num_frames_to_acquire;
|
||||||
|
set_common_acquire_config_state(det, det_config);
|
||||||
|
|
||||||
|
// set default specific det type config
|
||||||
|
det.setExptime(std::chrono::microseconds{200});
|
||||||
|
det.setReadNRows(256);
|
||||||
|
det.setDynamicRange(16);
|
||||||
|
|
||||||
|
// acquire
|
||||||
|
test_acquire_with_receiver(caller, det);
|
||||||
|
|
||||||
|
// check frames caught
|
||||||
|
test_frames_caught(det, num_frames_to_acquire);
|
||||||
|
|
||||||
|
// check file size (assuming local pc)
|
||||||
|
{
|
||||||
|
detParameters par(det_type);
|
||||||
|
// data split into half due to 2 udp interfaces per half module
|
||||||
|
int num_chips = (par.nChipX / 2);
|
||||||
|
int bytes_per_pixel = (dynamic_range / 8);
|
||||||
|
size_t expected_image_size =
|
||||||
|
par.nChanX * par.nChanY * num_chips * bytes_per_pixel;
|
||||||
|
test_acquire_binary_file_size(test_file_info, num_frames_to_acquire,
|
||||||
|
expected_image_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// restore previous state
|
||||||
|
set_file_state(det, prev_file_info);
|
||||||
|
set_common_acquire_config_state(det, prev_det_config_info);
|
||||||
|
|
||||||
|
// restore previous specific det type config
|
||||||
|
det.setExptime(exptime);
|
||||||
|
det.setReadNRows(n_rows);
|
||||||
|
det.setDynamicRange(dynamic_range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** temperature */
|
/** temperature */
|
||||||
|
|
||||||
TEST_CASE("temp_fpgaext", "[.cmdcall]") {
|
TEST_CASE("temp_fpgaext", "[.cmdcall]") {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "Caller.h"
|
#include "Caller.h"
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
#include "sls/Detector.h"
|
#include "sls/Detector.h"
|
||||||
|
#include "sls/logger.h"
|
||||||
#include "tests/globals.h"
|
#include "tests/globals.h"
|
||||||
|
|
||||||
namespace sls {
|
namespace sls {
|
||||||
@ -88,4 +89,227 @@ void test_onchip_dac_caller(defs::dacIndex index, const std::string &dacname,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testFileInfo get_file_state(const Detector &det) {
|
||||||
|
return testFileInfo{
|
||||||
|
det.getFilePath().tsquash("Inconsistent file path"),
|
||||||
|
det.getFileNamePrefix().tsquash("Inconsistent file prefix"),
|
||||||
|
det.getAcquisitionIndex().tsquash(
|
||||||
|
"Inconsistent file acquisition index"),
|
||||||
|
det.getFileWrite().tsquash("Inconsistent file write state"),
|
||||||
|
det.getFileOverWrite().tsquash("Inconsistent file overwrite state"),
|
||||||
|
det.getFileFormat().tsquash("Inconsistent file format")};
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_file_state(Detector &det, const testFileInfo &file_info) {
|
||||||
|
if (!file_info.file_path.empty())
|
||||||
|
det.setFilePath(file_info.file_path);
|
||||||
|
det.setFileNamePrefix(file_info.file_prefix);
|
||||||
|
det.setAcquisitionIndex(file_info.file_acq_index);
|
||||||
|
det.setFileWrite(file_info.file_write);
|
||||||
|
det.setFileOverWrite(file_info.file_overwrite);
|
||||||
|
det.setFileFormat(file_info.file_format);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_acquire_binary_file_size(const testFileInfo &file_info,
|
||||||
|
uint64_t num_frames_to_acquire,
|
||||||
|
uint64_t expected_image_size) {
|
||||||
|
assert(file_info.file_format == defs::BINARY);
|
||||||
|
std::string fname = file_info.file_path + "/" + file_info.file_prefix +
|
||||||
|
"_d0_f0_" + std::to_string(file_info.file_acq_index) +
|
||||||
|
".raw";
|
||||||
|
uint64_t expected_file_size =
|
||||||
|
num_frames_to_acquire *
|
||||||
|
(expected_image_size + sizeof(defs::sls_receiver_header));
|
||||||
|
auto actual_file_size = std::filesystem::file_size(fname);
|
||||||
|
REQUIRE(actual_file_size == expected_file_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_frames_caught(const Detector &det, int num_frames_to_acquire) {
|
||||||
|
auto frames_caught = det.getFramesCaught().tsquash(
|
||||||
|
"Inconsistent number of frames caught")[0];
|
||||||
|
REQUIRE(frames_caught == num_frames_to_acquire);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_acquire_with_receiver(Caller &caller, const Detector &det) {
|
||||||
|
REQUIRE_NOTHROW(caller.call("rx_start", {}, -1, PUT));
|
||||||
|
REQUIRE_NOTHROW(caller.call("start", {}, -1, PUT));
|
||||||
|
bool idle = false;
|
||||||
|
while (!idle) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
REQUIRE_NOTHROW(caller.call("status", {}, -1, GET));
|
||||||
|
auto statusList = det.getDetectorStatus();
|
||||||
|
if (statusList.any(defs::ERROR)) {
|
||||||
|
throw std::runtime_error("error status while acquiring");
|
||||||
|
}
|
||||||
|
if (statusList.contains_only(defs::IDLE, defs::STOPPED)) {
|
||||||
|
idle = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
REQUIRE_NOTHROW(caller.call("rx_stop", {}, -1, PUT));
|
||||||
|
}
|
||||||
|
|
||||||
|
testCommonDetAcquireInfo get_common_acquire_config_state(const Detector &det) {
|
||||||
|
return testCommonDetAcquireInfo{
|
||||||
|
det.getTimingMode().tsquash("Inconsistent timing mode"),
|
||||||
|
det.getNumberOfFrames().tsquash("Inconsistent number of frames"),
|
||||||
|
det.getNumberOfTriggers().tsquash("Inconsistent number of triggers"),
|
||||||
|
det.getPeriod().tsquash("Inconsistent period")};
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_common_acquire_config_state(
|
||||||
|
Detector &det, const testCommonDetAcquireInfo &det_config_info) {
|
||||||
|
det.setTimingMode(det_config_info.timing_mode);
|
||||||
|
det.setNumberOfFrames(det_config_info.num_frames_to_acquire);
|
||||||
|
det.setNumberOfTriggers(det_config_info.num_triggers);
|
||||||
|
det.setPeriod(det_config_info.period);
|
||||||
|
}
|
||||||
|
|
||||||
|
testCtbAcquireInfo get_ctb_config_state(const Detector &det) {
|
||||||
|
testCtbAcquireInfo ctb_config_info{
|
||||||
|
det.getReadoutMode().tsquash("inconsistent readout mode to test"),
|
||||||
|
true,
|
||||||
|
det.getNumberOfAnalogSamples().tsquash(
|
||||||
|
"inconsistent number of analog samples to test"),
|
||||||
|
det.getNumberOfDigitalSamples().tsquash(
|
||||||
|
"inconsistent number of digital samples to test"),
|
||||||
|
det.getNumberOfTransceiverSamples().tsquash(
|
||||||
|
"inconsistent number of transceiver samples to test"),
|
||||||
|
0,
|
||||||
|
det.getTenGigaADCEnableMask().tsquash(
|
||||||
|
"inconsistent ten giga adc enable mask to test"),
|
||||||
|
det.getRxDbitOffset().tsquash("inconsistent rx dbit offset to test"),
|
||||||
|
det.getRxDbitList().tsquash("inconsistent rx dbit list to test"),
|
||||||
|
det.getRxDbitReorder().tsquash("inconsistent rx dbit reorder to test"),
|
||||||
|
det.getTransceiverEnableMask().tsquash(
|
||||||
|
"inconsistent transceiver mask to test")};
|
||||||
|
|
||||||
|
if (det.getDetectorType().tsquash("inconsistent detector type to test") ==
|
||||||
|
slsDetectorDefs::CHIPTESTBOARD) {
|
||||||
|
ctb_config_info.ten_giga =
|
||||||
|
det.getTenGiga().tsquash("inconsistent ten giga enable to test");
|
||||||
|
ctb_config_info.adc_enable_1g = det.getADCEnableMask().tsquash(
|
||||||
|
"inconsistent adc enable mask to test");
|
||||||
|
}
|
||||||
|
return ctb_config_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_ctb_config_state(Detector &det,
|
||||||
|
const testCtbAcquireInfo &ctb_config_info) {
|
||||||
|
det.setReadoutMode(ctb_config_info.readout_mode);
|
||||||
|
if (det.getDetectorType().tsquash("inconsistent detector type to test") ==
|
||||||
|
slsDetectorDefs::CHIPTESTBOARD) {
|
||||||
|
det.setTenGiga(ctb_config_info.ten_giga);
|
||||||
|
det.setADCEnableMask(ctb_config_info.adc_enable_1g);
|
||||||
|
}
|
||||||
|
det.setNumberOfAnalogSamples(ctb_config_info.num_adc_samples);
|
||||||
|
det.setNumberOfDigitalSamples(ctb_config_info.num_dbit_samples);
|
||||||
|
det.setNumberOfTransceiverSamples(ctb_config_info.num_trans_samples);
|
||||||
|
det.setTenGigaADCEnableMask(ctb_config_info.adc_enable_10g);
|
||||||
|
det.setRxDbitOffset(ctb_config_info.dbit_offset);
|
||||||
|
det.setRxDbitList(ctb_config_info.dbit_list);
|
||||||
|
det.setRxDbitReorder(ctb_config_info.dbit_reorder);
|
||||||
|
det.setTransceiverEnableMask(ctb_config_info.transceiver_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t calculate_ctb_image_size(const testCtbAcquireInfo &test_info) {
|
||||||
|
uint64_t num_analog_bytes = 0, num_digital_bytes = 0,
|
||||||
|
num_transceiver_bytes = 0;
|
||||||
|
if (test_info.readout_mode == defs::ANALOG_ONLY ||
|
||||||
|
test_info.readout_mode == defs::ANALOG_AND_DIGITAL) {
|
||||||
|
uint32_t adc_enable_mask =
|
||||||
|
(test_info.ten_giga ? test_info.adc_enable_10g
|
||||||
|
: test_info.adc_enable_1g);
|
||||||
|
int num_analog_chans = __builtin_popcount(adc_enable_mask);
|
||||||
|
const int num_bytes_per_sample = 2;
|
||||||
|
num_analog_bytes =
|
||||||
|
num_analog_chans * num_bytes_per_sample * test_info.num_adc_samples;
|
||||||
|
LOG(logDEBUG1) << "[Analog Databytes: " << num_analog_bytes << ']';
|
||||||
|
}
|
||||||
|
|
||||||
|
// digital channels
|
||||||
|
if (test_info.readout_mode == defs::DIGITAL_ONLY ||
|
||||||
|
test_info.readout_mode == defs::ANALOG_AND_DIGITAL ||
|
||||||
|
test_info.readout_mode == defs::DIGITAL_AND_TRANSCEIVER) {
|
||||||
|
int num_digital_samples = test_info.num_dbit_samples;
|
||||||
|
if (test_info.dbit_offset > 0) {
|
||||||
|
uint64_t num_digital_bytes_reserved =
|
||||||
|
num_digital_samples * sizeof(uint64_t);
|
||||||
|
num_digital_bytes_reserved -= test_info.dbit_offset;
|
||||||
|
num_digital_samples = num_digital_bytes_reserved / sizeof(uint64_t);
|
||||||
|
}
|
||||||
|
int num_digital_chans = test_info.dbit_list.size();
|
||||||
|
if (num_digital_chans == 0) {
|
||||||
|
num_digital_chans = 64;
|
||||||
|
}
|
||||||
|
if (!test_info.dbit_reorder) {
|
||||||
|
uint32_t num_bits_per_sample = num_digital_chans;
|
||||||
|
if (num_bits_per_sample % 8 != 0) {
|
||||||
|
num_bits_per_sample += (8 - (num_bits_per_sample % 8));
|
||||||
|
}
|
||||||
|
num_digital_bytes = (num_bits_per_sample / 8) * num_digital_samples;
|
||||||
|
} else {
|
||||||
|
uint32_t num_bits_per_bit = num_digital_samples;
|
||||||
|
if (num_bits_per_bit % 8 != 0) {
|
||||||
|
num_bits_per_bit += (8 - (num_bits_per_bit % 8));
|
||||||
|
}
|
||||||
|
num_digital_bytes = num_digital_chans * (num_bits_per_bit / 8);
|
||||||
|
}
|
||||||
|
LOG(logDEBUG1) << "[Digital Databytes: " << num_digital_bytes << ']';
|
||||||
|
}
|
||||||
|
// transceiver channels
|
||||||
|
if (test_info.readout_mode == defs::TRANSCEIVER_ONLY ||
|
||||||
|
test_info.readout_mode == defs::DIGITAL_AND_TRANSCEIVER) {
|
||||||
|
int num_transceiver_chans =
|
||||||
|
__builtin_popcount(test_info.transceiver_mask);
|
||||||
|
const int num_bytes_per_channel = 8;
|
||||||
|
num_transceiver_bytes = num_transceiver_chans * num_bytes_per_channel *
|
||||||
|
test_info.num_trans_samples;
|
||||||
|
LOG(logDEBUG1) << "[Transceiver Databytes: " << num_transceiver_bytes
|
||||||
|
<< ']';
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t image_size =
|
||||||
|
num_analog_bytes + num_digital_bytes + num_transceiver_bytes;
|
||||||
|
LOG(logDEBUG1) << "Expected image size: " << image_size;
|
||||||
|
return image_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_ctb_acquire_with_receiver(const testCtbAcquireInfo &test_info,
|
||||||
|
int64_t num_frames_to_acquire,
|
||||||
|
Detector &det, Caller &caller) {
|
||||||
|
|
||||||
|
// save previous state
|
||||||
|
testFileInfo prev_file_info = get_file_state(det);
|
||||||
|
testCommonDetAcquireInfo prev_det_config_info =
|
||||||
|
// overwrite exptime if not using virtual ctb server
|
||||||
|
get_common_acquire_config_state(det);
|
||||||
|
testCtbAcquireInfo prev_ctb_config_info = get_ctb_config_state(det);
|
||||||
|
|
||||||
|
// defaults
|
||||||
|
testFileInfo test_file_info;
|
||||||
|
set_file_state(det, test_file_info);
|
||||||
|
testCommonDetAcquireInfo det_config;
|
||||||
|
det_config.num_frames_to_acquire = num_frames_to_acquire;
|
||||||
|
set_common_acquire_config_state(det, det_config);
|
||||||
|
|
||||||
|
// set ctb config
|
||||||
|
set_ctb_config_state(det, test_info);
|
||||||
|
|
||||||
|
// acquire
|
||||||
|
REQUIRE_NOTHROW(test_acquire_with_receiver(caller, det));
|
||||||
|
|
||||||
|
// check frames caught
|
||||||
|
REQUIRE_NOTHROW(test_frames_caught(det, num_frames_to_acquire));
|
||||||
|
|
||||||
|
// check file size (assuming local pc)
|
||||||
|
uint64_t expected_image_size = calculate_ctb_image_size(test_info);
|
||||||
|
REQUIRE_NOTHROW(test_acquire_binary_file_size(
|
||||||
|
test_file_info, num_frames_to_acquire, expected_image_size));
|
||||||
|
|
||||||
|
// restore previous state
|
||||||
|
set_file_state(det, prev_file_info);
|
||||||
|
set_common_acquire_config_state(det, prev_det_config_info);
|
||||||
|
set_ctb_config_state(det, prev_ctb_config_info);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sls
|
} // namespace sls
|
||||||
|
@ -1,9 +1,46 @@
|
|||||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
class Caller;
|
||||||
|
#include "sls/Detector.h"
|
||||||
#include "sls/sls_detector_defs.h"
|
#include "sls/sls_detector_defs.h"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
namespace sls {
|
namespace sls {
|
||||||
|
struct testFileInfo {
|
||||||
|
std::string file_path{"/tmp"};
|
||||||
|
std::string file_prefix{"sls_test"};
|
||||||
|
int64_t file_acq_index{0};
|
||||||
|
bool file_write{true};
|
||||||
|
bool file_overwrite{true};
|
||||||
|
slsDetectorDefs::fileFormat file_format{slsDetectorDefs::BINARY};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct testCommonDetAcquireInfo {
|
||||||
|
slsDetectorDefs::timingMode timing_mode{slsDetectorDefs::AUTO_TIMING};
|
||||||
|
int64_t num_frames_to_acquire{2};
|
||||||
|
int64_t num_triggers{1};
|
||||||
|
std::chrono::nanoseconds period{std::chrono::milliseconds{2}};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct testCtbAcquireInfo {
|
||||||
|
defs::readoutMode readout_mode{defs::ANALOG_AND_DIGITAL};
|
||||||
|
bool ten_giga{false};
|
||||||
|
int num_adc_samples{5000};
|
||||||
|
int num_dbit_samples{6000};
|
||||||
|
int num_trans_samples{288};
|
||||||
|
uint32_t adc_enable_1g{0xFFFFFF00};
|
||||||
|
uint32_t adc_enable_10g{0xFF00FFFF};
|
||||||
|
int dbit_offset{0};
|
||||||
|
std::vector<int> dbit_list{0, 12, 2, 43};
|
||||||
|
bool dbit_reorder{false};
|
||||||
|
uint32_t transceiver_mask{0x3};
|
||||||
|
};
|
||||||
|
|
||||||
void test_valid_port_caller(const std::string &command,
|
void test_valid_port_caller(const std::string &command,
|
||||||
const std::vector<std::string> &arguments,
|
const std::vector<std::string> &arguments,
|
||||||
int detector_id, int action);
|
int detector_id, int action);
|
||||||
@ -13,4 +50,26 @@ void test_dac_caller(slsDetectorDefs::dacIndex index,
|
|||||||
void test_onchip_dac_caller(slsDetectorDefs::dacIndex index,
|
void test_onchip_dac_caller(slsDetectorDefs::dacIndex index,
|
||||||
const std::string &dacname, int dacvalue);
|
const std::string &dacname, int dacvalue);
|
||||||
|
|
||||||
|
testFileInfo get_file_state(const Detector &det);
|
||||||
|
void set_file_state(Detector &det, const testFileInfo &file_info);
|
||||||
|
void test_acquire_binary_file_size(const testFileInfo &file_info,
|
||||||
|
uint64_t num_frames_to_acquire,
|
||||||
|
uint64_t expected_image_size);
|
||||||
|
|
||||||
|
void test_frames_caught(const Detector &det, int num_frames_to_acquire);
|
||||||
|
|
||||||
|
void test_acquire_with_receiver(Caller &caller, const Detector &det);
|
||||||
|
|
||||||
|
testCommonDetAcquireInfo get_common_acquire_config_state(const Detector &det);
|
||||||
|
void set_common_acquire_config_state(
|
||||||
|
Detector &det, const testCommonDetAcquireInfo &det_config_info);
|
||||||
|
|
||||||
|
testCtbAcquireInfo get_ctb_config_state(const Detector &det);
|
||||||
|
void set_ctb_config_state(Detector &det,
|
||||||
|
const testCtbAcquireInfo &ctb_config_info);
|
||||||
|
uint64_t calculate_ctb_image_size(const testCtbAcquireInfo &test_info);
|
||||||
|
void test_ctb_acquire_with_receiver(const testCtbAcquireInfo &test_info,
|
||||||
|
int64_t num_frames_to_acquire,
|
||||||
|
Detector &det, Caller &caller);
|
||||||
|
|
||||||
} // namespace sls
|
} // namespace sls
|
||||||
|
@ -17,6 +17,69 @@ namespace sls {
|
|||||||
using test::GET;
|
using test::GET;
|
||||||
using test::PUT;
|
using test::PUT;
|
||||||
|
|
||||||
|
TEST_CASE("gotthard2_acquire_check_file_size", "[.cmdcall]") {
|
||||||
|
Detector det;
|
||||||
|
Caller caller(&det);
|
||||||
|
auto det_type =
|
||||||
|
det.getDetectorType().tsquash("Inconsistent detector types to test");
|
||||||
|
|
||||||
|
if (det_type == defs::GOTTHARD2) {
|
||||||
|
|
||||||
|
// save previous state
|
||||||
|
testFileInfo prev_file_info = get_file_state(det);
|
||||||
|
testCommonDetAcquireInfo prev_det_config_info =
|
||||||
|
get_common_acquire_config_state(det);
|
||||||
|
|
||||||
|
// save previous specific det type config
|
||||||
|
auto exptime = det.getExptime().tsquash("inconsistent exptime to test");
|
||||||
|
auto burst_mode =
|
||||||
|
det.getBurstMode().tsquash("inconsistent burst mode to test");
|
||||||
|
auto number_of_bursts = det.getNumberOfBursts().tsquash(
|
||||||
|
"inconsistent number of bursts to test");
|
||||||
|
auto burst_period =
|
||||||
|
det.getBurstPeriod().tsquash("inconsistent burst period to test");
|
||||||
|
|
||||||
|
// defaults
|
||||||
|
int num_frames_to_acquire = 2;
|
||||||
|
testFileInfo test_file_info;
|
||||||
|
set_file_state(det, test_file_info);
|
||||||
|
testCommonDetAcquireInfo det_config;
|
||||||
|
det_config.num_frames_to_acquire = num_frames_to_acquire;
|
||||||
|
set_common_acquire_config_state(det, det_config);
|
||||||
|
|
||||||
|
// set default specific det type config
|
||||||
|
det.setExptime(std::chrono::microseconds{200});
|
||||||
|
det.setBurstMode(defs::CONTINUOUS_EXTERNAL);
|
||||||
|
det.setNumberOfBursts(1);
|
||||||
|
det.setBurstPeriod(std::chrono::milliseconds{0});
|
||||||
|
|
||||||
|
// acquire
|
||||||
|
test_acquire_with_receiver(caller, det);
|
||||||
|
|
||||||
|
// check frames caught
|
||||||
|
test_frames_caught(det, num_frames_to_acquire);
|
||||||
|
|
||||||
|
// check file size (assuming local pc)
|
||||||
|
{
|
||||||
|
detParameters par(det_type);
|
||||||
|
int bytes_per_pixel = det.getDynamicRange().squash() / 8;
|
||||||
|
size_t expected_image_size =
|
||||||
|
par.nChanX * par.nChipX * bytes_per_pixel;
|
||||||
|
test_acquire_binary_file_size(test_file_info, num_frames_to_acquire,
|
||||||
|
expected_image_size);
|
||||||
|
}
|
||||||
|
// restore previous state
|
||||||
|
set_file_state(det, prev_file_info);
|
||||||
|
set_common_acquire_config_state(det, prev_det_config_info);
|
||||||
|
|
||||||
|
// restore previous specific det type config
|
||||||
|
det.setExptime(exptime);
|
||||||
|
det.setBurstMode(burst_mode);
|
||||||
|
det.setNumberOfBursts(number_of_bursts);
|
||||||
|
det.setBurstPeriod(burst_period);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// time specific measurements for gotthard2
|
// time specific measurements for gotthard2
|
||||||
TEST_CASE("timegotthard2", "[.cmdcall]") {
|
TEST_CASE("timegotthard2", "[.cmdcall]") {
|
||||||
Detector det;
|
Detector det;
|
||||||
|
@ -15,6 +15,65 @@ namespace sls {
|
|||||||
using test::GET;
|
using test::GET;
|
||||||
using test::PUT;
|
using test::PUT;
|
||||||
|
|
||||||
|
TEST_CASE("jungfrau_acquire_check_file_size", "[.cmdcall]") {
|
||||||
|
Detector det;
|
||||||
|
Caller caller(&det);
|
||||||
|
auto det_type =
|
||||||
|
det.getDetectorType().tsquash("Inconsistent detector types to test");
|
||||||
|
|
||||||
|
if (det_type == defs::JUNGFRAU) {
|
||||||
|
|
||||||
|
// save previous state
|
||||||
|
testFileInfo prev_file_info = get_file_state(det);
|
||||||
|
testCommonDetAcquireInfo prev_det_config_info =
|
||||||
|
get_common_acquire_config_state(det);
|
||||||
|
|
||||||
|
// save previous specific det type config
|
||||||
|
auto exptime = det.getExptime().tsquash("inconsistent exptime to test");
|
||||||
|
auto num_udp_interfaces = det.getNumberofUDPInterfaces().tsquash(
|
||||||
|
"inconsistent number of udp interfaces");
|
||||||
|
auto n_rows =
|
||||||
|
det.getReadNRows().tsquash("inconsistent number of rows to test");
|
||||||
|
|
||||||
|
// defaults
|
||||||
|
int num_frames_to_acquire = 2;
|
||||||
|
testFileInfo test_file_info;
|
||||||
|
set_file_state(det, test_file_info);
|
||||||
|
testCommonDetAcquireInfo det_config;
|
||||||
|
det_config.num_frames_to_acquire = num_frames_to_acquire;
|
||||||
|
set_common_acquire_config_state(det, det_config);
|
||||||
|
|
||||||
|
// set default specific det type config
|
||||||
|
det.setExptime(std::chrono::microseconds{200});
|
||||||
|
det.setReadNRows(512);
|
||||||
|
|
||||||
|
// acquire
|
||||||
|
test_acquire_with_receiver(caller, det);
|
||||||
|
|
||||||
|
// check frames caught
|
||||||
|
test_frames_caught(det, num_frames_to_acquire);
|
||||||
|
|
||||||
|
// check file size (assuming local pc)
|
||||||
|
{
|
||||||
|
detParameters par(det_type);
|
||||||
|
int bytes_per_pixel = det.getDynamicRange().squash() / 8;
|
||||||
|
// if 2 udp interfaces, data split into half
|
||||||
|
size_t expected_image_size = (par.nChanX * par.nChanY * par.nChipX *
|
||||||
|
par.nChipY * bytes_per_pixel) /
|
||||||
|
num_udp_interfaces;
|
||||||
|
test_acquire_binary_file_size(test_file_info, num_frames_to_acquire,
|
||||||
|
expected_image_size);
|
||||||
|
}
|
||||||
|
// restore previous state
|
||||||
|
set_file_state(det, prev_file_info);
|
||||||
|
set_common_acquire_config_state(det, prev_det_config_info);
|
||||||
|
|
||||||
|
// restore previous specific det type config
|
||||||
|
det.setExptime(exptime);
|
||||||
|
det.setReadNRows(n_rows);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* dacs */
|
/* dacs */
|
||||||
|
|
||||||
TEST_CASE("Setting and reading back Jungfrau dacs", "[.cmdcall][.dacs]") {
|
TEST_CASE("Setting and reading back Jungfrau dacs", "[.cmdcall][.dacs]") {
|
||||||
|
@ -15,6 +15,66 @@ namespace sls {
|
|||||||
using test::GET;
|
using test::GET;
|
||||||
using test::PUT;
|
using test::PUT;
|
||||||
|
|
||||||
|
TEST_CASE("moench_acquire_check_file_size", "[.cmdcall]") {
|
||||||
|
Detector det;
|
||||||
|
Caller caller(&det);
|
||||||
|
auto det_type =
|
||||||
|
det.getDetectorType().tsquash("Inconsistent detector types to test");
|
||||||
|
|
||||||
|
if (det_type == defs::MOENCH) {
|
||||||
|
|
||||||
|
// save previous state
|
||||||
|
testFileInfo prev_file_info = get_file_state(det);
|
||||||
|
testCommonDetAcquireInfo prev_det_config_info =
|
||||||
|
get_common_acquire_config_state(det);
|
||||||
|
|
||||||
|
// save previous specific det type config
|
||||||
|
auto exptime = det.getExptime().tsquash("inconsistent exptime to test");
|
||||||
|
auto num_udp_interfaces = det.getNumberofUDPInterfaces().tsquash(
|
||||||
|
"inconsistent number of udp interfaces");
|
||||||
|
auto n_rows =
|
||||||
|
det.getReadNRows().tsquash("inconsistent number of rows to test");
|
||||||
|
|
||||||
|
// defaults
|
||||||
|
int num_frames_to_acquire = 2;
|
||||||
|
testFileInfo test_file_info;
|
||||||
|
set_file_state(det, test_file_info);
|
||||||
|
testCommonDetAcquireInfo det_config;
|
||||||
|
det_config.num_frames_to_acquire = num_frames_to_acquire;
|
||||||
|
set_common_acquire_config_state(det, det_config);
|
||||||
|
|
||||||
|
// set default specific det type config
|
||||||
|
det.setExptime(std::chrono::microseconds{200});
|
||||||
|
det.setReadNRows(400);
|
||||||
|
|
||||||
|
// acquire
|
||||||
|
test_acquire_with_receiver(caller, det);
|
||||||
|
|
||||||
|
// check frames caught
|
||||||
|
test_frames_caught(det, num_frames_to_acquire);
|
||||||
|
|
||||||
|
// check file size (assuming local pc)
|
||||||
|
{
|
||||||
|
detParameters par(det_type);
|
||||||
|
int bytes_per_pixel = det.getDynamicRange().squash() / 8;
|
||||||
|
// if 2 udp interfaces, data split into half
|
||||||
|
size_t expected_image_size = (par.nChanX * par.nChanY * par.nChipX *
|
||||||
|
par.nChipY * bytes_per_pixel) /
|
||||||
|
num_udp_interfaces;
|
||||||
|
test_acquire_binary_file_size(test_file_info, num_frames_to_acquire,
|
||||||
|
expected_image_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// restore previous state
|
||||||
|
set_file_state(det, prev_file_info);
|
||||||
|
set_common_acquire_config_state(det, prev_det_config_info);
|
||||||
|
|
||||||
|
// restore previous specific det type config
|
||||||
|
det.setExptime(exptime);
|
||||||
|
det.setReadNRows(n_rows);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* dacs */
|
/* dacs */
|
||||||
|
|
||||||
TEST_CASE("Setting and reading back moench dacs", "[.cmdcall][.dacs]") {
|
TEST_CASE("Setting and reading back moench dacs", "[.cmdcall][.dacs]") {
|
||||||
|
@ -17,6 +17,74 @@ namespace sls {
|
|||||||
using test::GET;
|
using test::GET;
|
||||||
using test::PUT;
|
using test::PUT;
|
||||||
|
|
||||||
|
TEST_CASE("mythen3_acquire_check_file_size", "[.cmdcall]") {
|
||||||
|
Detector det;
|
||||||
|
Caller caller(&det);
|
||||||
|
auto det_type =
|
||||||
|
det.getDetectorType().tsquash("Inconsistent detector types to test");
|
||||||
|
|
||||||
|
if (det_type == defs::MYTHEN3) {
|
||||||
|
|
||||||
|
// save previous state
|
||||||
|
testFileInfo prev_file_info = get_file_state(det);
|
||||||
|
testCommonDetAcquireInfo prev_det_config_info =
|
||||||
|
get_common_acquire_config_state(det);
|
||||||
|
|
||||||
|
// save previous specific det type config
|
||||||
|
auto exptime =
|
||||||
|
det.getExptimeForAllGates().tsquash("inconsistent exptime to test");
|
||||||
|
auto dynamic_range =
|
||||||
|
det.getDynamicRange().tsquash("inconsistent dynamic range to test");
|
||||||
|
uint32_t counter_mask =
|
||||||
|
det.getCounterMask().tsquash("inconsistent counter mask to test");
|
||||||
|
|
||||||
|
// defaults
|
||||||
|
int num_frames_to_acquire = 2;
|
||||||
|
testFileInfo test_file_info;
|
||||||
|
set_file_state(det, test_file_info);
|
||||||
|
testCommonDetAcquireInfo det_config;
|
||||||
|
det_config.num_frames_to_acquire = num_frames_to_acquire;
|
||||||
|
set_common_acquire_config_state(det, det_config);
|
||||||
|
|
||||||
|
// set default specific det type config
|
||||||
|
det.setExptime(-1, std::chrono::microseconds{200});
|
||||||
|
int test_dynamic_range = 16;
|
||||||
|
det.setDynamicRange(test_dynamic_range);
|
||||||
|
int test_counter_mask = 0x3;
|
||||||
|
int num_counters = __builtin_popcount(test_counter_mask);
|
||||||
|
det.setCounterMask(test_counter_mask);
|
||||||
|
|
||||||
|
// acquire
|
||||||
|
test_acquire_with_receiver(caller, det);
|
||||||
|
|
||||||
|
// check frames caught
|
||||||
|
test_frames_caught(det, num_frames_to_acquire);
|
||||||
|
|
||||||
|
// check file size (assuming local pc)
|
||||||
|
{
|
||||||
|
detParameters par(det_type);
|
||||||
|
int bytes_per_pixel = test_dynamic_range / 8;
|
||||||
|
int num_channels_per_counter = par.nChanX / 3;
|
||||||
|
size_t expected_image_size = num_channels_per_counter *
|
||||||
|
num_counters * par.nChipX *
|
||||||
|
bytes_per_pixel;
|
||||||
|
test_acquire_binary_file_size(test_file_info, num_frames_to_acquire,
|
||||||
|
expected_image_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// restore previous state
|
||||||
|
set_file_state(det, prev_file_info);
|
||||||
|
set_common_acquire_config_state(det, prev_det_config_info);
|
||||||
|
|
||||||
|
// restore previous specific det type config
|
||||||
|
for (int iGate = 0; iGate < 3; ++iGate) {
|
||||||
|
det.setExptime(iGate, exptime[iGate]);
|
||||||
|
}
|
||||||
|
det.setDynamicRange(dynamic_range);
|
||||||
|
det.setCounterMask(counter_mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* dacs */
|
/* dacs */
|
||||||
|
|
||||||
TEST_CASE("Setting and reading back MYTHEN3 dacs", "[.cmdcall][.dacs]") {
|
TEST_CASE("Setting and reading back MYTHEN3 dacs", "[.cmdcall][.dacs]") {
|
||||||
|
@ -445,6 +445,7 @@ TEST_CASE("rx_arping", "[.cmdcall][.rx]") {
|
|||||||
Detector det;
|
Detector det;
|
||||||
Caller caller(&det);
|
Caller caller(&det);
|
||||||
auto prev_val = det.getRxArping();
|
auto prev_val = det.getRxArping();
|
||||||
|
if (det.getDestinationUDPIP()[0].str() != "127.0.0.1") {
|
||||||
{
|
{
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
caller.call("rx_arping", {"1"}, -1, PUT, oss);
|
caller.call("rx_arping", {"1"}, -1, PUT, oss);
|
||||||
@ -463,6 +464,7 @@ TEST_CASE("rx_arping", "[.cmdcall][.rx]") {
|
|||||||
for (int i = 0; i != det.size(); ++i) {
|
for (int i = 0; i != det.size(); ++i) {
|
||||||
det.setRxArping(prev_val[i], {i});
|
det.setRxArping(prev_val[i], {i});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("rx_roi", "[.cmdcall]") {
|
TEST_CASE("rx_roi", "[.cmdcall]") {
|
||||||
@ -583,6 +585,9 @@ TEST_CASE("fpath", "[.cmdcall]") {
|
|||||||
REQUIRE(oss.str() == "fpath /tmp\n");
|
REQUIRE(oss.str() == "fpath /tmp\n");
|
||||||
}
|
}
|
||||||
for (int i = 0; i != det.size(); ++i) {
|
for (int i = 0; i != det.size(); ++i) {
|
||||||
|
if (prev_val[i].empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
det.setFilePath(prev_val[i], {i});
|
det.setFilePath(prev_val[i], {i});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -956,6 +961,37 @@ TEST_CASE("rx_dbitoffset", "[.cmdcall][.rx]") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("rx_dbitreorder", "[.cmdcall][.rx]") {
|
||||||
|
Detector det;
|
||||||
|
Caller caller(&det);
|
||||||
|
auto det_type = det.getDetectorType().squash();
|
||||||
|
if (det_type == defs::CHIPTESTBOARD ||
|
||||||
|
det_type == defs::XILINX_CHIPTESTBOARD) {
|
||||||
|
auto prev_val = det.getRxDbitReorder();
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
caller.call("rx_dbitreorder", {"0"}, -1, PUT, oss);
|
||||||
|
REQUIRE(oss.str() == "rx_dbitreorder 0\n");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
caller.call("rx_dbitreorder", {"1"}, -1, PUT, oss);
|
||||||
|
REQUIRE(oss.str() == "rx_dbitreorder 1\n");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
caller.call("rx_dbitreorder", {}, -1, GET, oss);
|
||||||
|
REQUIRE(oss.str() == "rx_dbitreorder 1\n");
|
||||||
|
}
|
||||||
|
REQUIRE_THROWS(caller.call("rx_dbitreorder", {"15"}, -1, PUT));
|
||||||
|
for (int i = 0; i != det.size(); ++i) {
|
||||||
|
det.setRxDbitReorder(prev_val[i], {i});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
REQUIRE_THROWS(caller.call("rx_dbitreorder", {}, -1, GET));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("rx_jsonaddheader", "[.cmdcall][.rx]") {
|
TEST_CASE("rx_jsonaddheader", "[.cmdcall][.rx]") {
|
||||||
Detector det;
|
Detector det;
|
||||||
Caller caller(&det);
|
Caller caller(&det);
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include "tests/globals.h"
|
#include "tests/globals.h"
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
namespace sls {
|
namespace sls {
|
||||||
|
|
||||||
|
@ -18,11 +18,16 @@ struct Data {
|
|||||||
constexpr int shm_id = 10;
|
constexpr int shm_id = 10;
|
||||||
|
|
||||||
TEST_CASE("Create SharedMemory read and write", "[detector]") {
|
TEST_CASE("Create SharedMemory read and write", "[detector]") {
|
||||||
|
const char *env_p = std::getenv("SLSDETNAME");
|
||||||
|
std::string env_name = env_p ? ("_" + std::string(env_p)) : "";
|
||||||
|
|
||||||
SharedMemory<Data> shm(shm_id, -1);
|
SharedMemory<Data> shm(shm_id, -1);
|
||||||
|
if (shm.exists()) {
|
||||||
|
shm.removeSharedMemory();
|
||||||
|
}
|
||||||
shm.createSharedMemory();
|
shm.createSharedMemory();
|
||||||
CHECK(shm.getName() == std::string("/slsDetectorPackage_detector_") +
|
CHECK(shm.getName() == std::string("/slsDetectorPackage_detector_") +
|
||||||
std::to_string(shm_id));
|
std::to_string(shm_id) + env_name);
|
||||||
|
|
||||||
shm()->x = 3;
|
shm()->x = 3;
|
||||||
shm()->y = 5.7;
|
shm()->y = 5.7;
|
||||||
@ -90,10 +95,12 @@ TEST_CASE("Open two shared memories to the same place", "[detector]") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Move SharedMemory", "[detector]") {
|
TEST_CASE("Move SharedMemory", "[detector]") {
|
||||||
|
const char *env_p = std::getenv("SLSDETNAME");
|
||||||
|
std::string env_name = env_p ? ("_" + std::string(env_p)) : "";
|
||||||
|
|
||||||
SharedMemory<Data> shm(shm_id, -1);
|
SharedMemory<Data> shm(shm_id, -1);
|
||||||
CHECK(shm.getName() == std::string("/slsDetectorPackage_detector_") +
|
CHECK(shm.getName() == std::string("/slsDetectorPackage_detector_") +
|
||||||
std::to_string(shm_id));
|
std::to_string(shm_id) + env_name);
|
||||||
shm.createSharedMemory();
|
shm.createSharedMemory();
|
||||||
shm()->x = 9;
|
shm()->x = 9;
|
||||||
|
|
||||||
@ -104,15 +111,19 @@ TEST_CASE("Move SharedMemory", "[detector]") {
|
|||||||
REQUIRE_THROWS(
|
REQUIRE_THROWS(
|
||||||
shm()); // trying to access should throw instead of returning a nullptr
|
shm()); // trying to access should throw instead of returning a nullptr
|
||||||
CHECK(shm2.getName() == std::string("/slsDetectorPackage_detector_") +
|
CHECK(shm2.getName() == std::string("/slsDetectorPackage_detector_") +
|
||||||
std::to_string(shm_id));
|
std::to_string(shm_id) + env_name);
|
||||||
shm2.removeSharedMemory();
|
shm2.removeSharedMemory();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Create several shared memories", "[detector]") {
|
TEST_CASE("Create several shared memories", "[detector]") {
|
||||||
|
const char *env_p = std::getenv("SLSDETNAME");
|
||||||
|
std::string env_name = env_p ? ("_" + std::string(env_p)) : "";
|
||||||
|
|
||||||
constexpr int N = 5;
|
constexpr int N = 5;
|
||||||
std::vector<SharedMemory<int>> v;
|
std::vector<SharedMemory<int>> v;
|
||||||
v.reserve(N);
|
v.reserve(N);
|
||||||
for (int i = 0; i != N; ++i) {
|
for (int i = 0; i != N; ++i) {
|
||||||
|
std::cout << "i:" << i << std::endl;
|
||||||
v.emplace_back(shm_id + i, -1);
|
v.emplace_back(shm_id + i, -1);
|
||||||
CHECK(v[i].exists() == false);
|
CHECK(v[i].exists() == false);
|
||||||
v[i].createSharedMemory();
|
v[i].createSharedMemory();
|
||||||
@ -123,7 +134,7 @@ TEST_CASE("Create several shared memories", "[detector]") {
|
|||||||
for (int i = 0; i != N; ++i) {
|
for (int i = 0; i != N; ++i) {
|
||||||
CHECK(*v[i]() == i);
|
CHECK(*v[i]() == i);
|
||||||
CHECK(v[i].getName() == std::string("/slsDetectorPackage_detector_") +
|
CHECK(v[i].getName() == std::string("/slsDetectorPackage_detector_") +
|
||||||
std::to_string(i + shm_id));
|
std::to_string(i + shm_id) + env_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i != N; ++i) {
|
for (int i = 0; i != N; ++i) {
|
||||||
@ -133,8 +144,12 @@ TEST_CASE("Create several shared memories", "[detector]") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Create create a shared memory with a tag") {
|
TEST_CASE("Create create a shared memory with a tag") {
|
||||||
|
const char *env_p = std::getenv("SLSDETNAME");
|
||||||
|
std::string env_name = env_p ? ("_" + std::string(env_p)) : "";
|
||||||
|
|
||||||
SharedMemory<int> shm(0, -1, "ctbdacs");
|
SharedMemory<int> shm(0, -1, "ctbdacs");
|
||||||
REQUIRE(shm.getName() == "/slsDetectorPackage_detector_0_ctbdacs");
|
REQUIRE(shm.getName() ==
|
||||||
|
"/slsDetectorPackage_detector_0" + env_name + "_ctbdacs");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Create create a shared memory with a tag when SLSDETNAME is set") {
|
TEST_CASE("Create create a shared memory with a tag when SLSDETNAME is set") {
|
||||||
|
@ -218,6 +218,8 @@ int ClientInterface::functionTable(){
|
|||||||
flist[F_RECEIVER_SET_TRANSCEIVER_MASK] = &ClientInterface::set_transceiver_mask;
|
flist[F_RECEIVER_SET_TRANSCEIVER_MASK] = &ClientInterface::set_transceiver_mask;
|
||||||
flist[F_RECEIVER_SET_ROW] = &ClientInterface::set_row;
|
flist[F_RECEIVER_SET_ROW] = &ClientInterface::set_row;
|
||||||
flist[F_RECEIVER_SET_COLUMN] = &ClientInterface::set_column;
|
flist[F_RECEIVER_SET_COLUMN] = &ClientInterface::set_column;
|
||||||
|
flist[F_GET_RECEIVER_DBIT_REORDER] = &ClientInterface::get_dbit_reorder;
|
||||||
|
flist[F_SET_RECEIVER_DBIT_REORDER] = &ClientInterface::set_dbit_reorder;
|
||||||
|
|
||||||
|
|
||||||
for (int i = NUM_DET_FUNCTIONS + 1; i < NUM_REC_FUNCTIONS ; i++) {
|
for (int i = NUM_DET_FUNCTIONS + 1; i < NUM_REC_FUNCTIONS ; i++) {
|
||||||
@ -1789,4 +1791,25 @@ int ClientInterface::set_column(Interface &socket) {
|
|||||||
return socket.Send(OK);
|
return socket.Send(OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ClientInterface::get_dbit_reorder(Interface &socket) {
|
||||||
|
if (detType != CHIPTESTBOARD && detType != XILINX_CHIPTESTBOARD)
|
||||||
|
functionNotImplemented();
|
||||||
|
int retval = impl()->getDbitReorder();
|
||||||
|
LOG(logDEBUG1) << "Dbit reorder retval: " << retval;
|
||||||
|
return socket.sendResult(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ClientInterface::set_dbit_reorder(Interface &socket) {
|
||||||
|
auto arg = socket.Receive<int>();
|
||||||
|
if (detType != CHIPTESTBOARD && detType != XILINX_CHIPTESTBOARD)
|
||||||
|
functionNotImplemented();
|
||||||
|
if (arg < 0) {
|
||||||
|
throw RuntimeError("Invalid dbit reorder: " + std::to_string(arg));
|
||||||
|
}
|
||||||
|
verifyIdle(socket);
|
||||||
|
LOG(logDEBUG1) << "Setting Dbit reorder: " << arg;
|
||||||
|
impl()->setDbitReorder(arg);
|
||||||
|
return socket.Send(OK);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sls
|
} // namespace sls
|
||||||
|
@ -164,6 +164,8 @@ class ClientInterface : private virtual slsDetectorDefs {
|
|||||||
int set_transceiver_mask(ServerInterface &socket);
|
int set_transceiver_mask(ServerInterface &socket);
|
||||||
int set_row(ServerInterface &socket);
|
int set_row(ServerInterface &socket);
|
||||||
int set_column(ServerInterface &socket);
|
int set_column(ServerInterface &socket);
|
||||||
|
int get_dbit_reorder(ServerInterface &socket);
|
||||||
|
int set_dbit_reorder(ServerInterface &socket);
|
||||||
|
|
||||||
Implementation *impl() {
|
Implementation *impl() {
|
||||||
if (receiver != nullptr) {
|
if (receiver != nullptr) {
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
namespace sls {
|
namespace sls {
|
||||||
|
|
||||||
@ -71,12 +72,6 @@ void DataProcessor::SetStreamingStartFnum(uint32_t value) {
|
|||||||
|
|
||||||
void DataProcessor::SetFramePadding(bool enable) { framePadding = enable; }
|
void DataProcessor::SetFramePadding(bool enable) { framePadding = enable; }
|
||||||
|
|
||||||
void DataProcessor::SetCtbDbitList(std::vector<int> value) {
|
|
||||||
ctbDbitList = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataProcessor::SetCtbDbitOffset(int value) { ctbDbitOffset = value; }
|
|
||||||
|
|
||||||
void DataProcessor::SetQuadEnable(bool value) { quadEnable = value; }
|
void DataProcessor::SetQuadEnable(bool value) { quadEnable = value; }
|
||||||
|
|
||||||
void DataProcessor::SetFlipRows(bool fd) {
|
void DataProcessor::SetFlipRows(bool fd) {
|
||||||
@ -213,8 +208,9 @@ std::string DataProcessor::CreateVirtualFile(
|
|||||||
"Skipping virtual hdf5 file since rx_roi is enabled.");
|
"Skipping virtual hdf5 file since rx_roi is enabled.");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool gotthard25um =
|
bool gotthard25um = ((generalData->detType == GOTTHARD ||
|
||||||
(generalData->detType == GOTTHARD2 && (numModX * numModY) == 2);
|
generalData->detType == GOTTHARD2) &&
|
||||||
|
(numModX * numModY) == 2);
|
||||||
|
|
||||||
// 0 for infinite files
|
// 0 for infinite files
|
||||||
uint32_t framesPerFile =
|
uint32_t framesPerFile =
|
||||||
@ -299,7 +295,7 @@ void DataProcessor::ThreadExecution() {
|
|||||||
memImage->data);
|
memImage->data);
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
fifo->FreeAddress(buffer);
|
fifo->FreeAddress(buffer);
|
||||||
return;
|
throw RuntimeError(e.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
// stream (if time/freq to stream) or free
|
// stream (if time/freq to stream) or free
|
||||||
@ -332,6 +328,7 @@ void DataProcessor::StopProcessing(char *buf) {
|
|||||||
|
|
||||||
void DataProcessor::ProcessAnImage(sls_receiver_header &header, size_t &size,
|
void DataProcessor::ProcessAnImage(sls_receiver_header &header, size_t &size,
|
||||||
size_t &firstImageIndex, char *data) {
|
size_t &firstImageIndex, char *data) {
|
||||||
|
|
||||||
uint64_t fnum = header.detHeader.frameNumber;
|
uint64_t fnum = header.detHeader.frameNumber;
|
||||||
LOG(logDEBUG1) << "DataProcessing " << index << ": fnum:" << fnum;
|
LOG(logDEBUG1) << "DataProcessing " << index << ": fnum:" << fnum;
|
||||||
currentFrameIndex = fnum;
|
currentFrameIndex = fnum;
|
||||||
@ -355,9 +352,20 @@ void DataProcessor::ProcessAnImage(sls_receiver_header &header, size_t &size,
|
|||||||
if (framePadding && nump < generalData->packetsPerFrame)
|
if (framePadding && nump < generalData->packetsPerFrame)
|
||||||
PadMissingPackets(header, data);
|
PadMissingPackets(header, data);
|
||||||
|
|
||||||
// rearrange ctb digital bits (if ctbDbitlist is not empty)
|
if (generalData->readoutType == slsDetectorDefs::DIGITAL_ONLY ||
|
||||||
if (!ctbDbitList.empty()) {
|
generalData->readoutType == slsDetectorDefs::ANALOG_AND_DIGITAL ||
|
||||||
RearrangeDbitData(size, data);
|
generalData->readoutType == slsDetectorDefs::DIGITAL_AND_TRANSCEIVER) {
|
||||||
|
// rearrange ctb digital bits
|
||||||
|
if (!generalData->ctbDbitList.empty()) {
|
||||||
|
ArrangeDbitData(size, data);
|
||||||
|
} else if (generalData->ctbDbitReorder) {
|
||||||
|
std::vector<int> ctbDbitList(64);
|
||||||
|
std::iota(ctbDbitList.begin(), ctbDbitList.end(), 0);
|
||||||
|
generalData->SetctbDbitList(ctbDbitList);
|
||||||
|
ArrangeDbitData(size, data);
|
||||||
|
} else if (generalData->ctbDbitOffset > 0) {
|
||||||
|
RemoveTrailingBits(size, data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 'stream Image' check has to be done here before crop image
|
// 'stream Image' check has to be done here before crop image
|
||||||
@ -519,11 +527,53 @@ void DataProcessor::PadMissingPackets(sls_receiver_header header, char *data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DataProcessor::RemoveTrailingBits(size_t &size, char *data) {
|
||||||
|
|
||||||
|
if (!(generalData->detType == slsDetectorDefs::CHIPTESTBOARD ||
|
||||||
|
generalData->detType == slsDetectorDefs::XILINX_CHIPTESTBOARD)) {
|
||||||
|
throw std::runtime_error("behavior undefined for detector " +
|
||||||
|
std::to_string(generalData->detType));
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t nAnalogDataBytes = generalData->GetNumberOfAnalogDatabytes();
|
||||||
|
const size_t nDigitalDataBytes = generalData->GetNumberOfDigitalDatabytes();
|
||||||
|
const size_t nTransceiverDataBytes =
|
||||||
|
generalData->GetNumberOfTransceiverDatabytes();
|
||||||
|
const size_t ctbDbitOffset = generalData->ctbDbitOffset;
|
||||||
|
|
||||||
|
const size_t ctbDigitalDataBytes = nDigitalDataBytes - ctbDbitOffset;
|
||||||
|
|
||||||
|
// no digital data
|
||||||
|
if (ctbDigitalDataBytes == 0) {
|
||||||
|
LOG(logWARNING)
|
||||||
|
<< "No digital data for call back, yet ctbDbitOffset is non zero.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update size and copy data
|
||||||
|
memmove(data + nAnalogDataBytes, data + nAnalogDataBytes + ctbDbitOffset,
|
||||||
|
ctbDigitalDataBytes + nTransceiverDataBytes);
|
||||||
|
|
||||||
|
size = nAnalogDataBytes + ctbDigitalDataBytes + nTransceiverDataBytes;
|
||||||
|
}
|
||||||
|
|
||||||
/** ctb specific */
|
/** ctb specific */
|
||||||
void DataProcessor::RearrangeDbitData(size_t &size, char *data) {
|
void DataProcessor::ArrangeDbitData(size_t &size, char *data) {
|
||||||
int nAnalogDataBytes = generalData->GetNumberOfAnalogDatabytes();
|
|
||||||
int nDigitalDataBytes = generalData->GetNumberOfDigitalDatabytes();
|
if (!(generalData->detType == slsDetectorDefs::CHIPTESTBOARD ||
|
||||||
int nTransceiverDataBytes = generalData->GetNumberOfTransceiverDatabytes();
|
generalData->detType == slsDetectorDefs::XILINX_CHIPTESTBOARD)) {
|
||||||
|
throw std::runtime_error("behavior undefined for detector " +
|
||||||
|
std::to_string(generalData->detType));
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t nAnalogDataBytes = generalData->GetNumberOfAnalogDatabytes();
|
||||||
|
const size_t nDigitalDataBytes = generalData->GetNumberOfDigitalDatabytes();
|
||||||
|
const size_t nTransceiverDataBytes =
|
||||||
|
generalData->GetNumberOfTransceiverDatabytes();
|
||||||
|
const size_t ctbDbitOffset = generalData->ctbDbitOffset;
|
||||||
|
const bool ctbDbitReorder = generalData->ctbDbitReorder;
|
||||||
|
const auto ctbDbitList = generalData->ctbDbitList;
|
||||||
|
|
||||||
// TODO! (Erik) Refactor and add tests
|
// TODO! (Erik) Refactor and add tests
|
||||||
int ctbDigitalDataBytes = nDigitalDataBytes - ctbDbitOffset;
|
int ctbDigitalDataBytes = nDigitalDataBytes - ctbDbitOffset;
|
||||||
|
|
||||||
@ -534,19 +584,35 @@ void DataProcessor::RearrangeDbitData(size_t &size, char *data) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *source = (data + nAnalogDataBytes + ctbDbitOffset);
|
||||||
|
|
||||||
const int numDigitalSamples = (ctbDigitalDataBytes / sizeof(uint64_t));
|
const int numDigitalSamples = (ctbDigitalDataBytes / sizeof(uint64_t));
|
||||||
|
|
||||||
// const int numResult8Bits = ceil((numDigitalSamples * ctbDbitList.size())
|
int totalNumBytes =
|
||||||
// / 8.00);
|
0; // number of bytes for selected digital data given by dtbDbitList
|
||||||
int numBitsPerDbit = numDigitalSamples;
|
|
||||||
|
// store each selected bit from all samples consecutively
|
||||||
|
if (ctbDbitReorder) {
|
||||||
|
size_t numBitsPerDbit =
|
||||||
|
numDigitalSamples; // num bits per selected digital
|
||||||
|
// Bit for all samples
|
||||||
if ((numBitsPerDbit % 8) != 0)
|
if ((numBitsPerDbit % 8) != 0)
|
||||||
numBitsPerDbit += (8 - (numDigitalSamples % 8));
|
numBitsPerDbit += (8 - (numDigitalSamples % 8));
|
||||||
const int totalNumBytes = (numBitsPerDbit / 8) * ctbDbitList.size();
|
totalNumBytes = (numBitsPerDbit / 8) * ctbDbitList.size();
|
||||||
std::vector<uint8_t> result(totalNumBytes);
|
}
|
||||||
|
// store all selected bits from one sample consecutively
|
||||||
|
else {
|
||||||
|
size_t numBitsPerSample =
|
||||||
|
ctbDbitList.size(); // num bits for all selected bits per sample
|
||||||
|
if ((numBitsPerSample % 8) != 0)
|
||||||
|
numBitsPerSample += (8 - (numBitsPerSample % 8));
|
||||||
|
totalNumBytes = (numBitsPerSample / 8) * numDigitalSamples;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> result(totalNumBytes, 0);
|
||||||
uint8_t *dest = &result[0];
|
uint8_t *dest = &result[0];
|
||||||
|
|
||||||
auto *source = (uint64_t *)(data + nAnalogDataBytes + ctbDbitOffset);
|
if (ctbDbitReorder) {
|
||||||
|
|
||||||
// loop through digital bit enable vector
|
// loop through digital bit enable vector
|
||||||
int bitoffset = 0;
|
int bitoffset = 0;
|
||||||
for (auto bi : ctbDbitList) {
|
for (auto bi : ctbDbitList) {
|
||||||
@ -556,10 +622,39 @@ void DataProcessor::RearrangeDbitData(size_t &size, char *data) {
|
|||||||
++dest;
|
++dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t byte_index = bi / 8;
|
||||||
|
|
||||||
// loop through the frame digital data
|
// loop through the frame digital data
|
||||||
for (auto *ptr = source; ptr < (source + numDigitalSamples);) {
|
for (auto *ptr = source + byte_index;
|
||||||
|
ptr < (source + 8 * numDigitalSamples); ptr += 8) {
|
||||||
// get selected bit from each 8 bit
|
// get selected bit from each 8 bit
|
||||||
uint8_t bit = (*ptr++ >> bi) & 1;
|
uint8_t bit = (*ptr >> bi % 8) & 1;
|
||||||
|
*dest |= bit << bitoffset; // stored as least significant
|
||||||
|
++bitoffset;
|
||||||
|
// extract destination in 8 bit batches
|
||||||
|
if (bitoffset == 8) {
|
||||||
|
bitoffset = 0;
|
||||||
|
++dest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// loop through the digital data
|
||||||
|
int bitoffset = 0;
|
||||||
|
for (auto *ptr = source; ptr < (source + 8 * numDigitalSamples);
|
||||||
|
ptr += 8) {
|
||||||
|
// where bit enable vector size is not a multiple of 8
|
||||||
|
if (bitoffset != 0) {
|
||||||
|
bitoffset = 0;
|
||||||
|
++dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
// loop through digital bit enable vector
|
||||||
|
for (auto bi : ctbDbitList) {
|
||||||
|
// get selected bit from each 64 bit
|
||||||
|
uint8_t byte_index = bi / 8;
|
||||||
|
|
||||||
|
uint8_t bit = (*(ptr + byte_index) >> (bi % 8)) & 1;
|
||||||
*dest |= bit << bitoffset;
|
*dest |= bit << bitoffset;
|
||||||
++bitoffset;
|
++bitoffset;
|
||||||
// extract destination in 8 bit batches
|
// extract destination in 8 bit batches
|
||||||
@ -569,17 +664,26 @@ void DataProcessor::RearrangeDbitData(size_t &size, char *data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size = totalNumBytes * sizeof(uint8_t) + nAnalogDataBytes +
|
||||||
|
nTransceiverDataBytes;
|
||||||
|
|
||||||
|
// check if size changed, if so move transceiver data to avoid gap in memory
|
||||||
|
if (size != nAnalogDataBytes + nDigitalDataBytes + nTransceiverDataBytes)
|
||||||
|
memmove(data + nAnalogDataBytes + totalNumBytes * sizeof(uint8_t),
|
||||||
|
data + nAnalogDataBytes + nDigitalDataBytes,
|
||||||
|
nTransceiverDataBytes);
|
||||||
|
|
||||||
// copy back to memory and update size
|
// copy back to memory and update size
|
||||||
memcpy(data + nAnalogDataBytes, result.data(),
|
memcpy(data + nAnalogDataBytes, result.data(),
|
||||||
totalNumBytes * sizeof(uint8_t));
|
totalNumBytes * sizeof(uint8_t));
|
||||||
size = totalNumBytes * sizeof(uint8_t) + nAnalogDataBytes + ctbDbitOffset +
|
|
||||||
nTransceiverDataBytes;
|
LOG(logDEBUG1) << "nDigitalDataBytes: " << totalNumBytes
|
||||||
LOG(logDEBUG1) << "totalNumBytes: " << totalNumBytes
|
|
||||||
<< " nAnalogDataBytes:" << nAnalogDataBytes
|
<< " nAnalogDataBytes:" << nAnalogDataBytes
|
||||||
<< " ctbDbitOffset:" << ctbDbitOffset
|
<< " ctbDbitOffset:" << ctbDbitOffset
|
||||||
<< " nTransceiverDataBytes:" << nTransceiverDataBytes
|
<< " nTransceiverDataBytes:" << nTransceiverDataBytes
|
||||||
<< " size:" << size;
|
<< " toal size:" << size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataProcessor::CropImage(size_t &size, char *data) {
|
void DataProcessor::CropImage(size_t &size, char *data) {
|
||||||
|
@ -45,8 +45,6 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject {
|
|||||||
void SetStreamingTimerInMs(uint32_t value);
|
void SetStreamingTimerInMs(uint32_t value);
|
||||||
void SetStreamingStartFnum(uint32_t value);
|
void SetStreamingStartFnum(uint32_t value);
|
||||||
void SetFramePadding(bool enable);
|
void SetFramePadding(bool enable);
|
||||||
void SetCtbDbitList(std::vector<int> value);
|
|
||||||
void SetCtbDbitOffset(int value);
|
|
||||||
void SetQuadEnable(bool value);
|
void SetQuadEnable(bool value);
|
||||||
void SetFlipRows(bool fd);
|
void SetFlipRows(bool fd);
|
||||||
void SetNumberofTotalFrames(uint64_t value);
|
void SetNumberofTotalFrames(uint64_t value);
|
||||||
@ -91,6 +89,20 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject {
|
|||||||
size_t &, void *),
|
size_t &, void *),
|
||||||
void *arg);
|
void *arg);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* Align corresponding digital bits together (CTB only if ctbDbitlist is not
|
||||||
|
* empty)
|
||||||
|
* set variable reorder to true if data should be rearranged such that
|
||||||
|
* it groups each signal (0-63) from all the different samples together
|
||||||
|
*/
|
||||||
|
void ArrangeDbitData(size_t &size, char *data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* remove trailing bits in digital data stream
|
||||||
|
*/
|
||||||
|
void RemoveTrailingBits(size_t &size, char *data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void RecordFirstIndex(uint64_t fnum);
|
void RecordFirstIndex(uint64_t fnum);
|
||||||
|
|
||||||
@ -137,12 +149,6 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject {
|
|||||||
|
|
||||||
void PadMissingPackets(sls_receiver_header header, char *data);
|
void PadMissingPackets(sls_receiver_header header, char *data);
|
||||||
|
|
||||||
/**
|
|
||||||
* Align corresponding digital bits together (CTB only if ctbDbitlist is not
|
|
||||||
* empty)
|
|
||||||
*/
|
|
||||||
void RearrangeDbitData(size_t &size, char *data);
|
|
||||||
|
|
||||||
void CropImage(size_t &size, char *data);
|
void CropImage(size_t &size, char *data);
|
||||||
|
|
||||||
static const std::string typeName;
|
static const std::string typeName;
|
||||||
@ -164,8 +170,6 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject {
|
|||||||
uint32_t currentFreqCount{0};
|
uint32_t currentFreqCount{0};
|
||||||
struct timespec timerbegin {};
|
struct timespec timerbegin {};
|
||||||
bool framePadding;
|
bool framePadding;
|
||||||
std::vector<int> ctbDbitList;
|
|
||||||
int ctbDbitOffset;
|
|
||||||
std::atomic<bool> startedFlag{false};
|
std::atomic<bool> startedFlag{false};
|
||||||
std::atomic<uint64_t> firstIndex{0};
|
std::atomic<uint64_t> firstIndex{0};
|
||||||
bool quadEnable{false};
|
bool quadEnable{false};
|
||||||
|
@ -93,11 +93,11 @@ void zmq_free(void *data, void *hint) { delete[] static_cast<char *>(data); }
|
|||||||
void print_frames(const PortFrameMap &frame_port_map) {
|
void print_frames(const PortFrameMap &frame_port_map) {
|
||||||
LOG(sls::logDEBUG) << "Printing frames";
|
LOG(sls::logDEBUG) << "Printing frames";
|
||||||
for (const auto &it : frame_port_map) {
|
for (const auto &it : frame_port_map) {
|
||||||
uint16_t udpPort = it.first;
|
const uint16_t udpPort = it.first;
|
||||||
const auto &frame_map = it.second;
|
const auto &frame_map = it.second;
|
||||||
LOG(sls::logDEBUG) << "UDP port: " << udpPort;
|
LOG(sls::logDEBUG) << "UDP port: " << udpPort;
|
||||||
for (const auto &frame : frame_map) {
|
for (const auto &frame : frame_map) {
|
||||||
uint64_t fnum = frame.first;
|
const uint64_t fnum = frame.first;
|
||||||
const auto &msg_list = frame.second;
|
const auto &msg_list = frame.second;
|
||||||
LOG(sls::logDEBUG)
|
LOG(sls::logDEBUG)
|
||||||
<< " acq index: " << fnum << '[' << msg_list.size() << ']';
|
<< " acq index: " << fnum << '[' << msg_list.size() << ']';
|
||||||
@ -116,30 +116,26 @@ std::set<uint64_t> get_valid_fnums(const PortFrameMap &port_frame_map) {
|
|||||||
|
|
||||||
// collect all unique frame numbers from all ports
|
// collect all unique frame numbers from all ports
|
||||||
std::set<uint64_t> unique_fnums;
|
std::set<uint64_t> unique_fnums;
|
||||||
for (auto it = port_frame_map.begin(); it != port_frame_map.begin(); ++it) {
|
for (const auto &it : port_frame_map) {
|
||||||
const FrameMap &frame_map = it->second;
|
const FrameMap &frame_map = it.second;
|
||||||
for (auto frame = frame_map.begin(); frame != frame_map.end();
|
for (const auto &frame : frame_map) {
|
||||||
++frame) {
|
unique_fnums.insert(frame.first);
|
||||||
unique_fnums.insert(frame->first);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// collect valid frame numbers
|
// collect valid frame numbers
|
||||||
for (auto &fnum : unique_fnums) {
|
for (auto &fnum : unique_fnums) {
|
||||||
bool is_valid = true;
|
bool is_valid = true;
|
||||||
for (auto it = port_frame_map.begin(); it != port_frame_map.end();
|
for (const auto &it : port_frame_map) {
|
||||||
++it) {
|
const uint16_t port = it.first;
|
||||||
uint16_t port = it->first;
|
const FrameMap &frame_map = it.second;
|
||||||
const FrameMap &frame_map = it->second;
|
|
||||||
auto frame = frame_map.find(fnum);
|
auto frame = frame_map.find(fnum);
|
||||||
// invalid: fnum missing in one port
|
// invalid: fnum missing in one port
|
||||||
if (frame == frame_map.end()) {
|
if (frame == frame_map.end()) {
|
||||||
LOG(sls::logDEBUG)
|
LOG(sls::logDEBUG)
|
||||||
<< "Fnum " << fnum << " is missing in port " << port;
|
<< "Fnum " << fnum << " is missing in port " << port;
|
||||||
// invalid: fnum greater than all in that port
|
auto upper_frame = frame_map.upper_bound(fnum);
|
||||||
auto last_frame = std::prev(frame_map.end());
|
if (upper_frame == frame_map.end()) {
|
||||||
auto last_fnum = last_frame->first;
|
|
||||||
if (fnum > last_fnum) {
|
|
||||||
LOG(sls::logDEBUG) << "And no larger fnum found. Fnum "
|
LOG(sls::logDEBUG) << "And no larger fnum found. Fnum "
|
||||||
<< fnum << " is invalid.\n";
|
<< fnum << " is invalid.\n";
|
||||||
is_valid = false;
|
is_valid = false;
|
||||||
@ -209,18 +205,26 @@ void Correlate(FrameStatus *stat) {
|
|||||||
// sending all valid fnum data packets
|
// sending all valid fnum data packets
|
||||||
for (const auto &fnum : valid_fnums) {
|
for (const auto &fnum : valid_fnums) {
|
||||||
ZmqMsgList msg_list;
|
ZmqMsgList msg_list;
|
||||||
PortFrameMap &port_frame_map = stat->frames;
|
for (const auto &it : stat->frames) {
|
||||||
for (auto it = port_frame_map.begin();
|
const uint16_t port = it.first;
|
||||||
it != port_frame_map.end(); ++it) {
|
const FrameMap &frame_map = it.second;
|
||||||
uint16_t port = it->first;
|
|
||||||
const FrameMap &frame_map = it->second;
|
|
||||||
auto frame = frame_map.find(fnum);
|
auto frame = frame_map.find(fnum);
|
||||||
if (frame != frame_map.end()) {
|
if (frame != frame_map.end()) {
|
||||||
msg_list.insert(msg_list.end(),
|
msg_list.insert(msg_list.end(),
|
||||||
stat->frames[port][fnum].begin(),
|
stat->frames[port][fnum].begin(),
|
||||||
stat->frames[port][fnum].end());
|
stat->frames[port][fnum].end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG(printHeadersLevel)
|
||||||
|
<< "Sending data packets for fnum " << fnum;
|
||||||
|
zmq_send_multipart(socket, msg_list);
|
||||||
// clean up
|
// clean up
|
||||||
for (zmq_msg_t *msg : stat->frames[port][fnum]) {
|
for (const auto &it : stat->frames) {
|
||||||
|
const uint16_t port = it.first;
|
||||||
|
const FrameMap &frame_map = it.second;
|
||||||
|
auto frame = frame_map.find(fnum);
|
||||||
|
if (frame != frame_map.end()) {
|
||||||
|
for (zmq_msg_t *msg : frame->second) {
|
||||||
if (msg) {
|
if (msg) {
|
||||||
zmq_msg_close(msg);
|
zmq_msg_close(msg);
|
||||||
delete msg;
|
delete msg;
|
||||||
@ -229,9 +233,6 @@ void Correlate(FrameStatus *stat) {
|
|||||||
stat->frames[port].erase(fnum);
|
stat->frames[port].erase(fnum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOG(printHeadersLevel)
|
|
||||||
<< "Sending data packets for fnum " << fnum;
|
|
||||||
zmq_send_multipart(socket, msg_list);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// sending all end packets
|
// sending all end packets
|
||||||
@ -245,6 +246,21 @@ void Correlate(FrameStatus *stat) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
stat->ends.clear();
|
stat->ends.clear();
|
||||||
|
// clean up old frames
|
||||||
|
for (auto &it : stat->frames) {
|
||||||
|
FrameMap &frame_map = it.second;
|
||||||
|
for (auto &frame : frame_map) {
|
||||||
|
for (zmq_msg_t *msg : frame.second) {
|
||||||
|
if (msg) {
|
||||||
|
zmq_msg_close(msg);
|
||||||
|
delete msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
frame.second.clear();
|
||||||
|
}
|
||||||
|
frame_map.clear();
|
||||||
|
}
|
||||||
|
stat->frames.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,9 @@ class GeneralData {
|
|||||||
uint32_t nAnalogSamples{0};
|
uint32_t nAnalogSamples{0};
|
||||||
uint32_t nDigitalSamples{0};
|
uint32_t nDigitalSamples{0};
|
||||||
uint32_t nTransceiverSamples{0};
|
uint32_t nTransceiverSamples{0};
|
||||||
|
std::vector<int> ctbDbitList{};
|
||||||
|
int ctbDbitOffset{0};
|
||||||
|
bool ctbDbitReorder{false};
|
||||||
slsDetectorDefs::readoutMode readoutType{slsDetectorDefs::ANALOG_ONLY};
|
slsDetectorDefs::readoutMode readoutType{slsDetectorDefs::ANALOG_ONLY};
|
||||||
uint32_t adcEnableMaskOneGiga{BIT32_MASK};
|
uint32_t adcEnableMaskOneGiga{BIT32_MASK};
|
||||||
uint32_t adcEnableMaskTenGiga{BIT32_MASK};
|
uint32_t adcEnableMaskTenGiga{BIT32_MASK};
|
||||||
@ -148,6 +151,18 @@ class GeneralData {
|
|||||||
virtual void SetTransceiverEnableMask(int n) {
|
virtual void SetTransceiverEnableMask(int n) {
|
||||||
ThrowGenericError("SetTransceiverEnableMask");
|
ThrowGenericError("SetTransceiverEnableMask");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
virtual void SetctbDbitOffset(const int n) {
|
||||||
|
ThrowGenericError("SetctbDbitOffset");
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void SetctbDbitList(const std::vector<int> &value) {
|
||||||
|
ThrowGenericError("SetctbDbitList");
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void SetctbDbitReorder(const bool reorder) {
|
||||||
|
ThrowGenericError("SetctbDbitReorder");
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
class EigerData : public GeneralData {
|
class EigerData : public GeneralData {
|
||||||
@ -387,6 +402,7 @@ class ChipTestBoardData : public GeneralData {
|
|||||||
framesPerFile = CTB_MAX_FRAMES_PER_FILE;
|
framesPerFile = CTB_MAX_FRAMES_PER_FILE;
|
||||||
fifoDepth = 2500;
|
fifoDepth = 2500;
|
||||||
standardheader = true;
|
standardheader = true;
|
||||||
|
ctbDbitReorder = true;
|
||||||
UpdateImageSize();
|
UpdateImageSize();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -412,6 +428,12 @@ class ChipTestBoardData : public GeneralData {
|
|||||||
UpdateImageSize();
|
UpdateImageSize();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void SetctbDbitOffset(const int value) { ctbDbitOffset = value; }
|
||||||
|
|
||||||
|
void SetctbDbitList(const std::vector<int> &value) { ctbDbitList = value; }
|
||||||
|
|
||||||
|
void SetctbDbitReorder(const bool value) { ctbDbitReorder = value; }
|
||||||
|
|
||||||
void SetOneGigaAdcEnableMask(int n) {
|
void SetOneGigaAdcEnableMask(int n) {
|
||||||
adcEnableMaskOneGiga = n;
|
adcEnableMaskOneGiga = n;
|
||||||
UpdateImageSize();
|
UpdateImageSize();
|
||||||
@ -443,6 +465,7 @@ class ChipTestBoardData : public GeneralData {
|
|||||||
nDigitalBytes = 0;
|
nDigitalBytes = 0;
|
||||||
nTransceiverBytes = 0;
|
nTransceiverBytes = 0;
|
||||||
int nAnalogChans = 0, nDigitalChans = 0, nTransceiverChans = 0;
|
int nAnalogChans = 0, nDigitalChans = 0, nTransceiverChans = 0;
|
||||||
|
uint64_t digital_bytes_reserved = 0;
|
||||||
|
|
||||||
// analog channels (normal, analog/digital readout)
|
// analog channels (normal, analog/digital readout)
|
||||||
if (readoutType == slsDetectorDefs::ANALOG_ONLY ||
|
if (readoutType == slsDetectorDefs::ANALOG_ONLY ||
|
||||||
@ -461,7 +484,12 @@ class ChipTestBoardData : public GeneralData {
|
|||||||
readoutType == slsDetectorDefs::ANALOG_AND_DIGITAL ||
|
readoutType == slsDetectorDefs::ANALOG_AND_DIGITAL ||
|
||||||
readoutType == slsDetectorDefs::DIGITAL_AND_TRANSCEIVER) {
|
readoutType == slsDetectorDefs::DIGITAL_AND_TRANSCEIVER) {
|
||||||
nDigitalChans = NCHAN_DIGITAL;
|
nDigitalChans = NCHAN_DIGITAL;
|
||||||
nDigitalBytes = (sizeof(uint64_t) * nDigitalSamples);
|
// allocate enough memory to support reordering of digital bits
|
||||||
|
uint32_t num_bytes_per_bit = (nDigitalSamples % 8 == 0)
|
||||||
|
? nDigitalSamples / 8
|
||||||
|
: nDigitalSamples / 8 + 1;
|
||||||
|
digital_bytes_reserved = 64 * num_bytes_per_bit;
|
||||||
|
nDigitalBytes = sizeof(uint64_t) * nDigitalSamples;
|
||||||
LOG(logDEBUG1) << "Number of Digital Channels:" << nDigitalChans
|
LOG(logDEBUG1) << "Number of Digital Channels:" << nDigitalChans
|
||||||
<< " Databytes: " << nDigitalBytes;
|
<< " Databytes: " << nDigitalBytes;
|
||||||
}
|
}
|
||||||
@ -480,7 +508,7 @@ class ChipTestBoardData : public GeneralData {
|
|||||||
nPixelsX = nAnalogChans + nDigitalChans + nTransceiverChans;
|
nPixelsX = nAnalogChans + nDigitalChans + nTransceiverChans;
|
||||||
dataSize = tengigaEnable ? 8144 : UDP_PACKET_DATA_BYTES;
|
dataSize = tengigaEnable ? 8144 : UDP_PACKET_DATA_BYTES;
|
||||||
packetSize = headerSizeinPacket + dataSize;
|
packetSize = headerSizeinPacket + dataSize;
|
||||||
imageSize = nAnalogBytes + nDigitalBytes + nTransceiverBytes;
|
imageSize = nAnalogBytes + digital_bytes_reserved + nTransceiverBytes;
|
||||||
packetsPerFrame = ceil((double)imageSize / (double)dataSize);
|
packetsPerFrame = ceil((double)imageSize / (double)dataSize);
|
||||||
|
|
||||||
LOG(logDEBUG1) << "Total Number of Channels:" << nPixelsX
|
LOG(logDEBUG1) << "Total Number of Channels:" << nPixelsX
|
||||||
@ -512,6 +540,7 @@ class XilinxChipTestBoardData : public GeneralData {
|
|||||||
dataSize = 8144;
|
dataSize = 8144;
|
||||||
packetSize = headerSizeinPacket + dataSize;
|
packetSize = headerSizeinPacket + dataSize;
|
||||||
tengigaEnable = true;
|
tengigaEnable = true;
|
||||||
|
ctbDbitReorder = true;
|
||||||
UpdateImageSize();
|
UpdateImageSize();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -537,6 +566,12 @@ class XilinxChipTestBoardData : public GeneralData {
|
|||||||
UpdateImageSize();
|
UpdateImageSize();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void SetctbDbitOffset(const int value) { ctbDbitOffset = value; }
|
||||||
|
|
||||||
|
void SetctbDbitList(const std::vector<int> &value) { ctbDbitList = value; }
|
||||||
|
|
||||||
|
void SetctbDbitReorder(const bool value) { ctbDbitReorder = value; }
|
||||||
|
|
||||||
void SetOneGigaAdcEnableMask(int n) {
|
void SetOneGigaAdcEnableMask(int n) {
|
||||||
adcEnableMaskOneGiga = n;
|
adcEnableMaskOneGiga = n;
|
||||||
UpdateImageSize();
|
UpdateImageSize();
|
||||||
@ -563,6 +598,7 @@ class XilinxChipTestBoardData : public GeneralData {
|
|||||||
nDigitalBytes = 0;
|
nDigitalBytes = 0;
|
||||||
nTransceiverBytes = 0;
|
nTransceiverBytes = 0;
|
||||||
int nAnalogChans = 0, nDigitalChans = 0, nTransceiverChans = 0;
|
int nAnalogChans = 0, nDigitalChans = 0, nTransceiverChans = 0;
|
||||||
|
uint64_t digital_bytes_reserved = 0;
|
||||||
|
|
||||||
// analog channels (normal, analog/digital readout)
|
// analog channels (normal, analog/digital readout)
|
||||||
if (readoutType == slsDetectorDefs::ANALOG_ONLY ||
|
if (readoutType == slsDetectorDefs::ANALOG_ONLY ||
|
||||||
@ -580,7 +616,11 @@ class XilinxChipTestBoardData : public GeneralData {
|
|||||||
readoutType == slsDetectorDefs::ANALOG_AND_DIGITAL ||
|
readoutType == slsDetectorDefs::ANALOG_AND_DIGITAL ||
|
||||||
readoutType == slsDetectorDefs::DIGITAL_AND_TRANSCEIVER) {
|
readoutType == slsDetectorDefs::DIGITAL_AND_TRANSCEIVER) {
|
||||||
nDigitalChans = NCHAN_DIGITAL;
|
nDigitalChans = NCHAN_DIGITAL;
|
||||||
nDigitalBytes = (sizeof(uint64_t) * nDigitalSamples);
|
uint32_t num_bytes_per_bit = (nDigitalSamples % 8 == 0)
|
||||||
|
? nDigitalSamples / 8
|
||||||
|
: nDigitalSamples / 8 + 1;
|
||||||
|
digital_bytes_reserved = 64 * num_bytes_per_bit;
|
||||||
|
nDigitalBytes = sizeof(uint64_t) * nDigitalSamples;
|
||||||
LOG(logDEBUG1) << "Number of Digital Channels:" << nDigitalChans
|
LOG(logDEBUG1) << "Number of Digital Channels:" << nDigitalChans
|
||||||
<< " Databytes: " << nDigitalBytes;
|
<< " Databytes: " << nDigitalBytes;
|
||||||
}
|
}
|
||||||
@ -598,7 +638,7 @@ class XilinxChipTestBoardData : public GeneralData {
|
|||||||
}
|
}
|
||||||
nPixelsX = nAnalogChans + nDigitalChans + nTransceiverChans;
|
nPixelsX = nAnalogChans + nDigitalChans + nTransceiverChans;
|
||||||
|
|
||||||
imageSize = nAnalogBytes + nDigitalBytes + nTransceiverBytes;
|
imageSize = nAnalogBytes + digital_bytes_reserved + nTransceiverBytes;
|
||||||
packetsPerFrame = ceil((double)imageSize / (double)dataSize);
|
packetsPerFrame = ceil((double)imageSize / (double)dataSize);
|
||||||
|
|
||||||
LOG(logDEBUG1) << "Total Number of Channels:" << nPixelsX
|
LOG(logDEBUG1) << "Total Number of Channels:" << nPixelsX
|
||||||
|
@ -200,8 +200,6 @@ void Implementation::SetupDataProcessor(int i) {
|
|||||||
dataProcessor[i]->SetStreamingTimerInMs(streamingTimerInMs);
|
dataProcessor[i]->SetStreamingTimerInMs(streamingTimerInMs);
|
||||||
dataProcessor[i]->SetStreamingStartFnum(streamingStartFnum);
|
dataProcessor[i]->SetStreamingStartFnum(streamingStartFnum);
|
||||||
dataProcessor[i]->SetFramePadding(framePadding);
|
dataProcessor[i]->SetFramePadding(framePadding);
|
||||||
dataProcessor[i]->SetCtbDbitList(ctbDbitList);
|
|
||||||
dataProcessor[i]->SetCtbDbitOffset(ctbDbitOffset);
|
|
||||||
dataProcessor[i]->SetQuadEnable(quadEnable);
|
dataProcessor[i]->SetQuadEnable(quadEnable);
|
||||||
dataProcessor[i]->SetFlipRows(flipRows);
|
dataProcessor[i]->SetFlipRows(flipRows);
|
||||||
dataProcessor[i]->SetNumberofTotalFrames(numberOfTotalFrames);
|
dataProcessor[i]->SetNumberofTotalFrames(numberOfTotalFrames);
|
||||||
@ -990,9 +988,11 @@ void Implementation::StartMasterWriter() {
|
|||||||
? 1
|
? 1
|
||||||
: 0;
|
: 0;
|
||||||
masterAttributes.digitalSamples = generalData->nDigitalSamples;
|
masterAttributes.digitalSamples = generalData->nDigitalSamples;
|
||||||
masterAttributes.dbitoffset = ctbDbitOffset;
|
masterAttributes.dbitoffset = generalData->ctbDbitOffset;
|
||||||
|
masterAttributes.dbitreorder = generalData->ctbDbitReorder;
|
||||||
masterAttributes.dbitlist = 0;
|
masterAttributes.dbitlist = 0;
|
||||||
for (auto &i : ctbDbitList) {
|
|
||||||
|
for (auto &i : generalData->ctbDbitList) {
|
||||||
masterAttributes.dbitlist |= (static_cast<uint64_t>(1) << i);
|
masterAttributes.dbitlist |= (static_cast<uint64_t>(1) << i);
|
||||||
}
|
}
|
||||||
masterAttributes.transceiverSamples =
|
masterAttributes.transceiverSamples =
|
||||||
@ -1748,22 +1748,29 @@ void Implementation::setTenGigaADCEnableMask(uint32_t mask) {
|
|||||||
LOG(logINFO) << "Packets per Frame: " << (generalData->packetsPerFrame);
|
LOG(logINFO) << "Packets per Frame: " << (generalData->packetsPerFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> Implementation::getDbitList() const { return ctbDbitList; }
|
std::vector<int> Implementation::getDbitList() const {
|
||||||
|
return generalData->ctbDbitList;
|
||||||
void Implementation::setDbitList(const std::vector<int> &v) {
|
|
||||||
ctbDbitList = v;
|
|
||||||
for (const auto &it : dataProcessor)
|
|
||||||
it->SetCtbDbitList(ctbDbitList);
|
|
||||||
LOG(logINFO) << "Dbit list: " << ToString(ctbDbitList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Implementation::getDbitOffset() const { return ctbDbitOffset; }
|
void Implementation::setDbitList(const std::vector<int> &v) {
|
||||||
|
generalData->SetctbDbitList(v);
|
||||||
|
LOG(logINFO) << "Dbit list: " << ToString(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Implementation::getDbitOffset() const { return generalData->ctbDbitOffset; }
|
||||||
|
|
||||||
void Implementation::setDbitOffset(const int s) {
|
void Implementation::setDbitOffset(const int s) {
|
||||||
ctbDbitOffset = s;
|
generalData->SetctbDbitOffset(s);
|
||||||
for (const auto &it : dataProcessor)
|
LOG(logINFO) << "Dbit offset: " << s;
|
||||||
it->SetCtbDbitOffset(ctbDbitOffset);
|
}
|
||||||
LOG(logINFO) << "Dbit offset: " << ctbDbitOffset;
|
|
||||||
|
bool Implementation::getDbitReorder() const {
|
||||||
|
return generalData->ctbDbitReorder;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Implementation::setDbitReorder(const bool reorder) {
|
||||||
|
generalData->SetctbDbitReorder(reorder);
|
||||||
|
LOG(logINFO) << "Dbit reorder: " << reorder;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Implementation::getTransceiverEnableMask() const {
|
uint32_t Implementation::getTransceiverEnableMask() const {
|
||||||
|
@ -252,6 +252,10 @@ class Implementation : private virtual slsDetectorDefs {
|
|||||||
int getDbitOffset() const;
|
int getDbitOffset() const;
|
||||||
/* [Ctb] */
|
/* [Ctb] */
|
||||||
void setDbitOffset(const int s);
|
void setDbitOffset(const int s);
|
||||||
|
bool getDbitReorder() const;
|
||||||
|
/* [Ctb] */
|
||||||
|
void setDbitReorder(const bool reorder);
|
||||||
|
|
||||||
uint32_t getTransceiverEnableMask() const;
|
uint32_t getTransceiverEnableMask() const;
|
||||||
/* [Ctb] */
|
/* [Ctb] */
|
||||||
void setTransceiverEnableMask(const uint32_t mask);
|
void setTransceiverEnableMask(const uint32_t mask);
|
||||||
@ -366,8 +370,6 @@ class Implementation : private virtual slsDetectorDefs {
|
|||||||
int thresholdEnergyeV{-1};
|
int thresholdEnergyeV{-1};
|
||||||
std::array<int, 3> thresholdAllEnergyeV = {{-1, -1, -1}};
|
std::array<int, 3> thresholdAllEnergyeV = {{-1, -1, -1}};
|
||||||
std::vector<int64_t> rateCorrections;
|
std::vector<int64_t> rateCorrections;
|
||||||
std::vector<int> ctbDbitList;
|
|
||||||
int ctbDbitOffset{0};
|
|
||||||
|
|
||||||
// callbacks
|
// callbacks
|
||||||
void (*startAcquisitionCallBack)(const startCallbackHeader,
|
void (*startAcquisitionCallBack)(const startCallbackHeader,
|
||||||
|
@ -551,6 +551,13 @@ void MasterAttributes::WriteHDF5DbitOffset(H5::H5File *fd, H5::Group *group) {
|
|||||||
dataset.write(&dbitoffset, H5::PredType::NATIVE_INT);
|
dataset.write(&dbitoffset, H5::PredType::NATIVE_INT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MasterAttributes::WriteHDF5DbitReorder(H5::H5File *fd, H5::Group *group) {
|
||||||
|
H5::DataSpace dataspace = H5::DataSpace(H5S_SCALAR);
|
||||||
|
H5::DataSet dataset = group->createDataSet(
|
||||||
|
"Dbit Reorder", H5::PredType::NATIVE_INT, dataspace);
|
||||||
|
dataset.write(&dbitreorder, H5::PredType::NATIVE_INT);
|
||||||
|
}
|
||||||
|
|
||||||
void MasterAttributes::WriteHDF5DbitList(H5::H5File *fd, H5::Group *group) {
|
void MasterAttributes::WriteHDF5DbitList(H5::H5File *fd, H5::Group *group) {
|
||||||
H5::DataSpace dataspace = H5::DataSpace(H5S_SCALAR);
|
H5::DataSpace dataspace = H5::DataSpace(H5S_SCALAR);
|
||||||
H5::DataSet dataset = group->createDataSet(
|
H5::DataSet dataset = group->createDataSet(
|
||||||
@ -744,6 +751,8 @@ void MasterAttributes::GetCtbBinaryAttributes(
|
|||||||
w->Uint(digitalSamples);
|
w->Uint(digitalSamples);
|
||||||
w->Key("Dbit Offset");
|
w->Key("Dbit Offset");
|
||||||
w->Uint(dbitoffset);
|
w->Uint(dbitoffset);
|
||||||
|
w->Key("Dbit Reorder");
|
||||||
|
w->Uint(dbitreorder);
|
||||||
w->Key("Dbit Bitset");
|
w->Key("Dbit Bitset");
|
||||||
w->Uint64(dbitlist);
|
w->Uint64(dbitlist);
|
||||||
w->Key("Transceiver Mask");
|
w->Key("Transceiver Mask");
|
||||||
@ -766,6 +775,7 @@ void MasterAttributes::WriteCtbHDF5Attributes(H5::H5File *fd,
|
|||||||
MasterAttributes::WriteHDF5DigitalFlag(fd, group);
|
MasterAttributes::WriteHDF5DigitalFlag(fd, group);
|
||||||
MasterAttributes::WriteHDF5DigitalSamples(fd, group);
|
MasterAttributes::WriteHDF5DigitalSamples(fd, group);
|
||||||
MasterAttributes::WriteHDF5DbitOffset(fd, group);
|
MasterAttributes::WriteHDF5DbitOffset(fd, group);
|
||||||
|
MasterAttributes::WriteHDF5DbitReorder(fd, group);
|
||||||
MasterAttributes::WriteHDF5DbitList(fd, group);
|
MasterAttributes::WriteHDF5DbitList(fd, group);
|
||||||
MasterAttributes::WriteHDF5TransceiverMask(fd, group);
|
MasterAttributes::WriteHDF5TransceiverMask(fd, group);
|
||||||
MasterAttributes::WriteHDF5TransceiverFlag(fd, group);
|
MasterAttributes::WriteHDF5TransceiverFlag(fd, group);
|
||||||
@ -791,6 +801,8 @@ void MasterAttributes::GetXilinxCtbBinaryAttributes(
|
|||||||
w->Uint(digitalSamples);
|
w->Uint(digitalSamples);
|
||||||
w->Key("Dbit Offset");
|
w->Key("Dbit Offset");
|
||||||
w->Uint(dbitoffset);
|
w->Uint(dbitoffset);
|
||||||
|
w->Key("Dbit Reorder");
|
||||||
|
w->Uint(dbitreorder);
|
||||||
w->Key("Dbit Bitset");
|
w->Key("Dbit Bitset");
|
||||||
w->Uint64(dbitlist);
|
w->Uint64(dbitlist);
|
||||||
w->Key("Transceiver Mask");
|
w->Key("Transceiver Mask");
|
||||||
@ -812,6 +824,7 @@ void MasterAttributes::WriteXilinxCtbHDF5Attributes(H5::H5File *fd,
|
|||||||
MasterAttributes::WriteHDF5DigitalFlag(fd, group);
|
MasterAttributes::WriteHDF5DigitalFlag(fd, group);
|
||||||
MasterAttributes::WriteHDF5DigitalSamples(fd, group);
|
MasterAttributes::WriteHDF5DigitalSamples(fd, group);
|
||||||
MasterAttributes::WriteHDF5DbitOffset(fd, group);
|
MasterAttributes::WriteHDF5DbitOffset(fd, group);
|
||||||
|
MasterAttributes::WriteHDF5DbitReorder(fd, group);
|
||||||
MasterAttributes::WriteHDF5DbitList(fd, group);
|
MasterAttributes::WriteHDF5DbitList(fd, group);
|
||||||
MasterAttributes::WriteHDF5TransceiverMask(fd, group);
|
MasterAttributes::WriteHDF5TransceiverMask(fd, group);
|
||||||
MasterAttributes::WriteHDF5TransceiverFlag(fd, group);
|
MasterAttributes::WriteHDF5TransceiverFlag(fd, group);
|
||||||
|
@ -51,6 +51,7 @@ class MasterAttributes {
|
|||||||
uint32_t analogSamples{0};
|
uint32_t analogSamples{0};
|
||||||
uint32_t digital{0};
|
uint32_t digital{0};
|
||||||
uint32_t digitalSamples{0};
|
uint32_t digitalSamples{0};
|
||||||
|
uint32_t dbitreorder{1};
|
||||||
uint32_t dbitoffset{0};
|
uint32_t dbitoffset{0};
|
||||||
uint64_t dbitlist{0};
|
uint64_t dbitlist{0};
|
||||||
uint32_t transceiverMask{0};
|
uint32_t transceiverMask{0};
|
||||||
@ -104,6 +105,7 @@ class MasterAttributes {
|
|||||||
void WriteHDF5DigitalSamples(H5::H5File *fd, H5::Group *group);
|
void WriteHDF5DigitalSamples(H5::H5File *fd, H5::Group *group);
|
||||||
void WriteHDF5DbitOffset(H5::H5File *fd, H5::Group *group);
|
void WriteHDF5DbitOffset(H5::H5File *fd, H5::Group *group);
|
||||||
void WriteHDF5DbitList(H5::H5File *fd, H5::Group *group);
|
void WriteHDF5DbitList(H5::H5File *fd, H5::Group *group);
|
||||||
|
void WriteHDF5DbitReorder(H5::H5File *fd, H5::Group *group);
|
||||||
void WriteHDF5TransceiverMask(H5::H5File *fd, H5::Group *group);
|
void WriteHDF5TransceiverMask(H5::H5File *fd, H5::Group *group);
|
||||||
void WriteHDF5TransceiverFlag(H5::H5File *fd, H5::Group *group);
|
void WriteHDF5TransceiverFlag(H5::H5File *fd, H5::Group *group);
|
||||||
void WriteHDF5TransceiverSamples(H5::H5File *fd, H5::Group *group);
|
void WriteHDF5TransceiverSamples(H5::H5File *fd, H5::Group *group);
|
||||||
|
@ -19,8 +19,8 @@ namespace sls {
|
|||||||
// files
|
// files
|
||||||
|
|
||||||
// versions
|
// versions
|
||||||
#define HDF5_WRITER_VERSION (6.6) // 1 decimal places
|
#define HDF5_WRITER_VERSION (6.7) // 1 decimal places
|
||||||
#define BINARY_WRITER_VERSION (7.2) // 1 decimal places
|
#define BINARY_WRITER_VERSION (7.3) // 1 decimal places
|
||||||
|
|
||||||
#define MAX_FRAMES_PER_FILE 20000
|
#define MAX_FRAMES_PER_FILE 20000
|
||||||
#define SHORT_MAX_FRAMES_PER_FILE 100000
|
#define SHORT_MAX_FRAMES_PER_FILE 100000
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
target_sources(tests PRIVATE
|
target_sources(tests PRIVATE
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/test-GeneralData.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/test-GeneralData.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/test-CircularFifo.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/test-CircularFifo.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/test-ArrangeDataBasedOnBitList.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(tests PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../src>")
|
target_include_directories(tests PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../src>")
|
||||||
|
|
||||||
|
message(STATUS "Resolved path: ${CMAKE_CURRENT_SOURCE_DIR}/../src")
|
411
slsReceiverSoftware/tests/test-ArrangeDataBasedOnBitList.cpp
Normal file
411
slsReceiverSoftware/tests/test-ArrangeDataBasedOnBitList.cpp
Normal file
@ -0,0 +1,411 @@
|
|||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||||
|
// Copyright (C) 2025 Contributors to the SLS Detector Package
|
||||||
|
/************************************************
|
||||||
|
* @file test-ArrangeDataBasedOnBitList.cpp
|
||||||
|
* @short test case for DataProcessor rearrange functions,
|
||||||
|
***********************************************/
|
||||||
|
|
||||||
|
#include "DataProcessor.h"
|
||||||
|
#include "GeneralData.h"
|
||||||
|
#include "catch.hpp"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace sls {
|
||||||
|
|
||||||
|
// dummy GeneralData class for testing
|
||||||
|
class GeneralDataTest : public GeneralData {
|
||||||
|
|
||||||
|
public:
|
||||||
|
GeneralDataTest() { detType = slsDetectorDefs::CHIPTESTBOARD; }
|
||||||
|
|
||||||
|
int GetNumberOfAnalogDatabytes() { return nAnalogBytes; };
|
||||||
|
|
||||||
|
int GetNumberOfDigitalDatabytes() { return nDigitalBytes; };
|
||||||
|
|
||||||
|
int GetNumberOfTransceiverDatabytes() { return nTransceiverBytes; };
|
||||||
|
|
||||||
|
void SetNumberOfAnalogDatabytes(int value) { nAnalogBytes = value; }
|
||||||
|
|
||||||
|
void SetNumberOfDigitalDatabytes(int value) { nDigitalBytes = value; }
|
||||||
|
|
||||||
|
void SetNumberOfTransceiverDatabytes(int value) {
|
||||||
|
nTransceiverBytes = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetCtbDbitOffset(const int value) { ctbDbitOffset = value; }
|
||||||
|
|
||||||
|
void SetCtbDbitList(const std::vector<int> &value) { ctbDbitList = value; }
|
||||||
|
|
||||||
|
void SetCtbDbitReorder(const bool value) { ctbDbitReorder = value; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
int nAnalogBytes{};
|
||||||
|
int nDigitalBytes{};
|
||||||
|
int nTransceiverBytes{};
|
||||||
|
};
|
||||||
|
|
||||||
|
// dummy DataProcessor class for testing
|
||||||
|
class DataProcessorTest : public DataProcessor {
|
||||||
|
public:
|
||||||
|
DataProcessorTest() : DataProcessor(0){};
|
||||||
|
~DataProcessorTest(){};
|
||||||
|
void ArrangeDbitData(size_t &size, char *data) {
|
||||||
|
DataProcessor::ArrangeDbitData(size, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveTrailingBits(size_t &size, char *data) {
|
||||||
|
DataProcessor::RemoveTrailingBits(size, data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test fixture for Testing,
|
||||||
|
* num_analog_bytes = 1 byte has a value of 125
|
||||||
|
* num_transceiver_bytes = 2 both bytes have a value of 125
|
||||||
|
* num_digital_bytes is variable and is defined by number of samples
|
||||||
|
* default num sample is 5
|
||||||
|
* all bytes in digital data take a value of 255
|
||||||
|
*/
|
||||||
|
class DataProcessorTestFixture {
|
||||||
|
public:
|
||||||
|
DataProcessorTestFixture() {
|
||||||
|
// setup Test Fixture
|
||||||
|
dataprocessor = new DataProcessorTest;
|
||||||
|
generaldata = new GeneralDataTest;
|
||||||
|
|
||||||
|
generaldata->SetNumberOfAnalogDatabytes(num_analog_bytes);
|
||||||
|
generaldata->SetNumberOfTransceiverDatabytes(num_transceiver_bytes);
|
||||||
|
generaldata->SetNumberOfDigitalDatabytes(num_digital_bytes +
|
||||||
|
num_random_offset_bytes);
|
||||||
|
|
||||||
|
dataprocessor->SetGeneralData(generaldata);
|
||||||
|
}
|
||||||
|
|
||||||
|
~DataProcessorTestFixture() {
|
||||||
|
delete[] data;
|
||||||
|
delete dataprocessor;
|
||||||
|
delete generaldata;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t get_size() const {
|
||||||
|
return num_analog_bytes + num_digital_bytes + num_transceiver_bytes +
|
||||||
|
num_random_offset_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_num_samples(const size_t value) {
|
||||||
|
num_samples = value;
|
||||||
|
num_digital_bytes = num_samples * 8; // 64 (8 bytes) per sample
|
||||||
|
|
||||||
|
generaldata->SetNumberOfDigitalDatabytes(num_digital_bytes +
|
||||||
|
num_random_offset_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_random_offset_bytes(const size_t value) {
|
||||||
|
num_random_offset_bytes = value;
|
||||||
|
generaldata->SetNumberOfDigitalDatabytes(num_digital_bytes +
|
||||||
|
num_random_offset_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_data() {
|
||||||
|
delete[] data;
|
||||||
|
uint64_t max_bytes_per_bit =
|
||||||
|
num_samples % 8 == 0 ? num_samples / 8 : num_samples / 8 + 1;
|
||||||
|
uint64_t reserved_size =
|
||||||
|
get_size() - num_digital_bytes + max_bytes_per_bit * 64;
|
||||||
|
data = new char[reserved_size];
|
||||||
|
|
||||||
|
// set testing data
|
||||||
|
memset(data, dummy_value, num_analog_bytes); // set to dummy value
|
||||||
|
memset(data + num_analog_bytes, 0,
|
||||||
|
num_random_offset_bytes); // set to zero
|
||||||
|
memset(data + num_analog_bytes + num_random_offset_bytes, 0xFF,
|
||||||
|
num_digital_bytes); // all digital bits are one
|
||||||
|
memset(data + num_digital_bytes + num_analog_bytes +
|
||||||
|
num_random_offset_bytes,
|
||||||
|
dummy_value,
|
||||||
|
num_transceiver_bytes); // set to dummy value
|
||||||
|
}
|
||||||
|
|
||||||
|
DataProcessorTest *dataprocessor;
|
||||||
|
GeneralDataTest *generaldata;
|
||||||
|
const size_t num_analog_bytes = 1;
|
||||||
|
const size_t num_transceiver_bytes = 2;
|
||||||
|
const char dummy_value = static_cast<char>(125);
|
||||||
|
size_t num_digital_bytes = 40; // num_samples * 8 = 5 * 8 = 40
|
||||||
|
size_t num_random_offset_bytes = 0;
|
||||||
|
size_t num_samples = 5;
|
||||||
|
char *data = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(DataProcessorTestFixture, "Remove Trailing Bits",
|
||||||
|
"[.dataprocessor][.bitoffset]") {
|
||||||
|
|
||||||
|
const size_t num_random_offset_bytes = 3;
|
||||||
|
set_random_offset_bytes(num_random_offset_bytes);
|
||||||
|
set_data();
|
||||||
|
|
||||||
|
generaldata->SetCtbDbitOffset(num_random_offset_bytes);
|
||||||
|
|
||||||
|
size_t expected_size = get_size() - num_random_offset_bytes;
|
||||||
|
|
||||||
|
char *expected_data = new char[expected_size];
|
||||||
|
memset(expected_data, dummy_value, num_analog_bytes); // set to 125
|
||||||
|
memset(expected_data + num_analog_bytes, 0xFF,
|
||||||
|
num_digital_bytes); // set to 1
|
||||||
|
memset(expected_data + num_digital_bytes + num_analog_bytes, dummy_value,
|
||||||
|
num_transceiver_bytes); // set to 125
|
||||||
|
|
||||||
|
size_t size = get_size();
|
||||||
|
dataprocessor->RemoveTrailingBits(size, data);
|
||||||
|
|
||||||
|
CHECK(size == expected_size);
|
||||||
|
|
||||||
|
CHECK(memcmp(data, expected_data, expected_size) == 0);
|
||||||
|
|
||||||
|
delete[] expected_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parametric test tested with num_samples = 5, num_samples = 10, num_samples =
|
||||||
|
// 8
|
||||||
|
TEST_CASE_METHOD(DataProcessorTestFixture, "Reorder all",
|
||||||
|
"[.dataprocessor][.reorder]") {
|
||||||
|
// parameters: num_samples, expected_num_digital_bytes,
|
||||||
|
// expected_digital_part
|
||||||
|
auto parameters = GENERATE(
|
||||||
|
std::make_tuple(5, 64, std::vector<uint8_t>{0b00011111}),
|
||||||
|
std::make_tuple(10, 2 * 64, std::vector<uint8_t>{0xFF, 0b00000011}),
|
||||||
|
std::make_tuple(8, 64, std::vector<uint8_t>{0xFF}));
|
||||||
|
|
||||||
|
size_t num_samples, expected_num_digital_bytes;
|
||||||
|
std::vector<uint8_t> expected_digital_part;
|
||||||
|
std::tie(num_samples, expected_num_digital_bytes, expected_digital_part) =
|
||||||
|
parameters;
|
||||||
|
|
||||||
|
// set number of samples for test fixture -> create data
|
||||||
|
set_num_samples(num_samples);
|
||||||
|
set_data();
|
||||||
|
|
||||||
|
std::vector<int> bitlist(64);
|
||||||
|
std::iota(bitlist.begin(), bitlist.end(), 0);
|
||||||
|
generaldata->SetCtbDbitList(bitlist);
|
||||||
|
generaldata->SetCtbDbitReorder(true); // set reorder to true
|
||||||
|
|
||||||
|
const size_t expected_size =
|
||||||
|
num_analog_bytes + num_transceiver_bytes + expected_num_digital_bytes;
|
||||||
|
|
||||||
|
// create expected data
|
||||||
|
char *expected_data = new char[expected_size];
|
||||||
|
|
||||||
|
memset(expected_data, dummy_value, num_analog_bytes); // set to 125
|
||||||
|
for (size_t bit = 0; bit < 64; ++bit) {
|
||||||
|
memcpy(expected_data + num_analog_bytes +
|
||||||
|
expected_digital_part.size() * bit,
|
||||||
|
expected_digital_part.data(), expected_digital_part.size());
|
||||||
|
}
|
||||||
|
memset(expected_data + expected_num_digital_bytes + num_analog_bytes,
|
||||||
|
dummy_value,
|
||||||
|
num_transceiver_bytes); // set to 125
|
||||||
|
|
||||||
|
size_t size = get_size();
|
||||||
|
dataprocessor->ArrangeDbitData(size, data); // call reorder
|
||||||
|
|
||||||
|
CHECK(size == expected_size);
|
||||||
|
CHECK(memcmp(data, expected_data, expected_size) == 0);
|
||||||
|
|
||||||
|
delete[] expected_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(DataProcessorTestFixture,
|
||||||
|
"Reorder all and remove trailing bits",
|
||||||
|
"[.dataprocessor][.reorder]") {
|
||||||
|
|
||||||
|
// set number of samples for test fixture -> create data
|
||||||
|
const size_t num_random_offset_bytes = 3;
|
||||||
|
set_random_offset_bytes(num_random_offset_bytes);
|
||||||
|
set_data();
|
||||||
|
|
||||||
|
std::vector<int> bitlist(64);
|
||||||
|
std::iota(bitlist.begin(), bitlist.end(), 0);
|
||||||
|
generaldata->SetCtbDbitList(bitlist);
|
||||||
|
generaldata->SetCtbDbitOffset(num_random_offset_bytes);
|
||||||
|
generaldata->SetCtbDbitReorder(true); // set reorder to true
|
||||||
|
|
||||||
|
const size_t expected_num_digital_bytes = 64;
|
||||||
|
std::vector<uint8_t> expected_digital_part{0b00011111};
|
||||||
|
|
||||||
|
const size_t expected_size =
|
||||||
|
num_analog_bytes + num_transceiver_bytes + expected_num_digital_bytes;
|
||||||
|
|
||||||
|
// create expected data
|
||||||
|
char *expected_data = new char[expected_size];
|
||||||
|
|
||||||
|
memset(expected_data, dummy_value, num_analog_bytes); // set to 125
|
||||||
|
for (size_t bit = 0; bit < 64; ++bit) {
|
||||||
|
memcpy(expected_data + num_analog_bytes +
|
||||||
|
expected_digital_part.size() * bit,
|
||||||
|
expected_digital_part.data(), expected_digital_part.size());
|
||||||
|
}
|
||||||
|
memset(expected_data + expected_num_digital_bytes + num_analog_bytes,
|
||||||
|
dummy_value,
|
||||||
|
num_transceiver_bytes); // set to 125
|
||||||
|
|
||||||
|
size_t size = get_size();
|
||||||
|
dataprocessor->ArrangeDbitData(size, data); // call reorder
|
||||||
|
|
||||||
|
CHECK(size == expected_size);
|
||||||
|
CHECK(memcmp(data, expected_data, expected_size) == 0);
|
||||||
|
|
||||||
|
delete[] expected_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(DataProcessorTestFixture, "Arrange bitlist with reorder false",
|
||||||
|
"[.dataprocessor][.retrievebitlist]") {
|
||||||
|
// parameters: num_samples, bitlist, expected_num_digital_bytes,
|
||||||
|
// expected_digital_part
|
||||||
|
auto parameters = GENERATE(
|
||||||
|
std::make_tuple(5, std::vector<int>{1, 4, 5}, 5,
|
||||||
|
std::vector<uint8_t>{0b00000111}),
|
||||||
|
std::make_tuple(5, std::vector<int>{1, 5, 3, 7, 8, 50, 42, 60, 39}, 10,
|
||||||
|
std::vector<uint8_t>{0xFF, 0b00000001}),
|
||||||
|
std::make_tuple(5, std::vector<int>{1, 5, 3, 7, 8, 50, 42, 60}, 5,
|
||||||
|
std::vector<uint8_t>{0xFF}));
|
||||||
|
|
||||||
|
size_t num_samples, expected_num_digital_bytes;
|
||||||
|
std::vector<uint8_t> expected_digital_part;
|
||||||
|
std::vector<int> bitlist;
|
||||||
|
std::tie(num_samples, bitlist, expected_num_digital_bytes,
|
||||||
|
expected_digital_part) = parameters;
|
||||||
|
|
||||||
|
generaldata->SetCtbDbitList(bitlist);
|
||||||
|
|
||||||
|
generaldata->SetCtbDbitReorder(false);
|
||||||
|
|
||||||
|
set_num_samples(num_samples);
|
||||||
|
set_data();
|
||||||
|
|
||||||
|
size_t expected_size =
|
||||||
|
num_analog_bytes + num_transceiver_bytes + expected_num_digital_bytes;
|
||||||
|
|
||||||
|
// create expected data
|
||||||
|
char *expected_data = new char[expected_size];
|
||||||
|
|
||||||
|
memset(expected_data, dummy_value, num_analog_bytes);
|
||||||
|
|
||||||
|
for (size_t sample = 0; sample < num_samples; ++sample) {
|
||||||
|
memcpy(expected_data + num_analog_bytes +
|
||||||
|
expected_digital_part.size() * sample,
|
||||||
|
expected_digital_part.data(), expected_digital_part.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(expected_data + expected_num_digital_bytes + num_analog_bytes,
|
||||||
|
dummy_value, num_transceiver_bytes);
|
||||||
|
|
||||||
|
size_t size = get_size();
|
||||||
|
dataprocessor->ArrangeDbitData(size, data);
|
||||||
|
|
||||||
|
CHECK(size == expected_size);
|
||||||
|
|
||||||
|
CHECK(memcmp(data, expected_data, expected_size) == 0);
|
||||||
|
|
||||||
|
delete[] expected_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(DataProcessorTestFixture, "Arrange bitlist with reorder true",
|
||||||
|
"[.dataprocessor][.retrievebitlist]") {
|
||||||
|
// parameters: num_samples, bitlist, expected_num_digital_bytes,
|
||||||
|
// expected_digital_part
|
||||||
|
auto parameters = GENERATE(
|
||||||
|
std::make_tuple(5, std::vector<int>{1, 4, 5}, 3,
|
||||||
|
std::vector<uint8_t>{0b00011111}),
|
||||||
|
std::make_tuple(10, std::vector<int>{1, 4, 5}, 6,
|
||||||
|
std::vector<uint8_t>{0xFF, 0b00000011}),
|
||||||
|
std::make_tuple(8, std::vector<int>{1, 5, 3, 7, 8, 50, 42, 60, 39}, 9,
|
||||||
|
std::vector<uint8_t>{0xFF}));
|
||||||
|
|
||||||
|
size_t num_samples, expected_num_digital_bytes;
|
||||||
|
std::vector<uint8_t> expected_digital_part;
|
||||||
|
std::vector<int> bitlist;
|
||||||
|
std::tie(num_samples, bitlist, expected_num_digital_bytes,
|
||||||
|
expected_digital_part) = parameters;
|
||||||
|
|
||||||
|
generaldata->SetCtbDbitList(bitlist);
|
||||||
|
|
||||||
|
generaldata->SetCtbDbitReorder(true);
|
||||||
|
|
||||||
|
set_num_samples(num_samples);
|
||||||
|
set_data();
|
||||||
|
|
||||||
|
size_t expected_size =
|
||||||
|
num_analog_bytes + num_transceiver_bytes + expected_num_digital_bytes;
|
||||||
|
|
||||||
|
// create expected data
|
||||||
|
char *expected_data = new char[expected_size];
|
||||||
|
|
||||||
|
memset(expected_data, dummy_value, num_analog_bytes);
|
||||||
|
|
||||||
|
for (size_t sample = 0; sample < bitlist.size(); ++sample) {
|
||||||
|
memcpy(expected_data + num_analog_bytes +
|
||||||
|
expected_digital_part.size() * sample,
|
||||||
|
expected_digital_part.data(), expected_digital_part.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(expected_data + expected_num_digital_bytes + num_analog_bytes,
|
||||||
|
dummy_value, num_transceiver_bytes);
|
||||||
|
|
||||||
|
size_t size = get_size();
|
||||||
|
dataprocessor->ArrangeDbitData(size, data);
|
||||||
|
|
||||||
|
CHECK(size == expected_size);
|
||||||
|
|
||||||
|
CHECK(memcmp(data, expected_data, expected_size) == 0);
|
||||||
|
|
||||||
|
delete[] expected_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(DataProcessorTestFixture,
|
||||||
|
"Arrange bitlist and remove trailing bits",
|
||||||
|
"[.dataprocessor][.retrievebitlist]") {
|
||||||
|
|
||||||
|
size_t num_random_offset_bytes = 3;
|
||||||
|
std::vector<int> bitlist{1, 4, 5};
|
||||||
|
|
||||||
|
set_random_offset_bytes(num_random_offset_bytes);
|
||||||
|
set_data();
|
||||||
|
|
||||||
|
generaldata->SetCtbDbitList(bitlist);
|
||||||
|
|
||||||
|
generaldata->SetCtbDbitReorder(false);
|
||||||
|
|
||||||
|
generaldata->SetCtbDbitOffset(num_random_offset_bytes);
|
||||||
|
|
||||||
|
std::vector<uint8_t> expected_digital_part{0b00000111};
|
||||||
|
const size_t expected_num_digital_bytes = 5;
|
||||||
|
|
||||||
|
size_t expected_size =
|
||||||
|
num_analog_bytes + num_transceiver_bytes + expected_num_digital_bytes;
|
||||||
|
|
||||||
|
// create expected data
|
||||||
|
char *expected_data = new char[expected_size];
|
||||||
|
|
||||||
|
memset(expected_data, dummy_value, num_analog_bytes);
|
||||||
|
|
||||||
|
for (size_t sample = 0; sample < num_samples; ++sample) {
|
||||||
|
memcpy(expected_data + num_analog_bytes +
|
||||||
|
expected_digital_part.size() * sample,
|
||||||
|
expected_digital_part.data(), expected_digital_part.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(expected_data + expected_num_digital_bytes + num_analog_bytes,
|
||||||
|
dummy_value, num_transceiver_bytes);
|
||||||
|
|
||||||
|
size_t size = get_size();
|
||||||
|
dataprocessor->ArrangeDbitData(size, data);
|
||||||
|
|
||||||
|
CHECK(size == expected_size);
|
||||||
|
|
||||||
|
CHECK(memcmp(data, expected_data, expected_size) == 0);
|
||||||
|
|
||||||
|
delete[] expected_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sls
|
@ -88,6 +88,7 @@ message(STATUS "RAPID: ${SLS_INTERNAL_RAPIDJSON_DIR}")
|
|||||||
target_link_libraries(slsSupportObject
|
target_link_libraries(slsSupportObject
|
||||||
PUBLIC
|
PUBLIC
|
||||||
slsProjectOptions
|
slsProjectOptions
|
||||||
|
${STD_FS_LIB} # from helpers.cmake
|
||||||
|
|
||||||
PRIVATE
|
PRIVATE
|
||||||
slsProjectWarnings
|
slsProjectWarnings
|
||||||
|
@ -113,10 +113,12 @@ template <typename T, size_t Capacity> class StaticVector {
|
|||||||
// auto begin() noexcept -> decltype(data_.begin()) { return data_.begin();
|
// auto begin() noexcept -> decltype(data_.begin()) { return data_.begin();
|
||||||
// }
|
// }
|
||||||
const_iterator begin() const noexcept { return data_.begin(); }
|
const_iterator begin() const noexcept { return data_.begin(); }
|
||||||
iterator end() noexcept { return &data_[current_size]; }
|
iterator end() noexcept { return data_.begin() + current_size; }
|
||||||
const_iterator end() const noexcept { return &data_[current_size]; }
|
const_iterator end() const noexcept { return data_.begin() + current_size; }
|
||||||
const_iterator cbegin() const noexcept { return data_.cbegin(); }
|
const_iterator cbegin() const noexcept { return data_.cbegin(); }
|
||||||
const_iterator cend() const noexcept { return &data_[current_size]; }
|
const_iterator cend() const noexcept {
|
||||||
|
return data_.cbegin() + current_size;
|
||||||
|
}
|
||||||
|
|
||||||
void size_check(size_type s) const {
|
void size_check(size_type s) const {
|
||||||
if (s > Capacity) {
|
if (s > Capacity) {
|
||||||
|
@ -47,6 +47,8 @@ std::string ToString(const defs::polarity s);
|
|||||||
std::string ToString(const defs::timingInfoDecoder s);
|
std::string ToString(const defs::timingInfoDecoder s);
|
||||||
std::string ToString(const defs::collectionMode s);
|
std::string ToString(const defs::collectionMode s);
|
||||||
|
|
||||||
|
std::string ToString(bool value);
|
||||||
|
|
||||||
std::string ToString(const slsDetectorDefs::xy &coord);
|
std::string ToString(const slsDetectorDefs::xy &coord);
|
||||||
std::ostream &operator<<(std::ostream &os, const slsDetectorDefs::xy &coord);
|
std::ostream &operator<<(std::ostream &os, const slsDetectorDefs::xy &coord);
|
||||||
std::string ToString(const slsDetectorDefs::ROI &roi);
|
std::string ToString(const slsDetectorDefs::ROI &roi);
|
||||||
|
@ -11,7 +11,7 @@ class Version {
|
|||||||
private:
|
private:
|
||||||
std::string version_;
|
std::string version_;
|
||||||
std::string date_;
|
std::string date_;
|
||||||
const std::string defaultBranch_ = "developer";
|
inline static const std::string defaultVersion_[] = {"developer", "0.0.0"};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Version(const std::string &s);
|
explicit Version(const std::string &s);
|
||||||
|
@ -410,6 +410,8 @@ enum detFuncs {
|
|||||||
F_RECEIVER_SET_TRANSCEIVER_MASK,
|
F_RECEIVER_SET_TRANSCEIVER_MASK,
|
||||||
F_RECEIVER_SET_ROW,
|
F_RECEIVER_SET_ROW,
|
||||||
F_RECEIVER_SET_COLUMN,
|
F_RECEIVER_SET_COLUMN,
|
||||||
|
F_GET_RECEIVER_DBIT_REORDER,
|
||||||
|
F_SET_RECEIVER_DBIT_REORDER,
|
||||||
|
|
||||||
NUM_REC_FUNCTIONS
|
NUM_REC_FUNCTIONS
|
||||||
};
|
};
|
||||||
@ -816,7 +818,8 @@ const char* getFunctionNameFromEnum(enum detFuncs func) {
|
|||||||
case F_RECEIVER_SET_TRANSCEIVER_MASK: return "F_RECEIVER_SET_TRANSCEIVER_MASK";
|
case F_RECEIVER_SET_TRANSCEIVER_MASK: return "F_RECEIVER_SET_TRANSCEIVER_MASK";
|
||||||
case F_RECEIVER_SET_ROW: return "F_RECEIVER_SET_ROW";
|
case F_RECEIVER_SET_ROW: return "F_RECEIVER_SET_ROW";
|
||||||
case F_RECEIVER_SET_COLUMN: return "F_RECEIVER_SET_COLUMN";
|
case F_RECEIVER_SET_COLUMN: return "F_RECEIVER_SET_COLUMN";
|
||||||
|
case F_GET_RECEIVER_DBIT_REORDER: return "F_GET_RECEIVER_DBIT_REORDER";
|
||||||
|
case F_SET_RECEIVER_DBIT_REORDER: return "F_SET_RECEIVER_DBIT_REORDER";
|
||||||
|
|
||||||
case NUM_REC_FUNCTIONS: return "NUM_REC_FUNCTIONS";
|
case NUM_REC_FUNCTIONS: return "NUM_REC_FUNCTIONS";
|
||||||
default: return "Unknown Function";
|
default: return "Unknown Function";
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||||
/** API versions */
|
/** API versions */
|
||||||
#define APILIB "developer 0x241122"
|
#define APILIB "0.0.0 0x250523"
|
||||||
#define APIRECEIVER "developer 0x241122"
|
#define APIRECEIVER "0.0.0 0x250523"
|
||||||
#define APICTB "developer 0x250310"
|
#define APICTB "0.0.0 0x250523"
|
||||||
#define APIGOTTHARD2 "developer 0x250310"
|
#define APIGOTTHARD2 "0.0.0 0x250523"
|
||||||
#define APIMYTHEN3 "developer 0x250310"
|
#define APIMOENCH "0.0.0 0x250523"
|
||||||
#define APIMOENCH "developer 0x250310"
|
#define APIEIGER "0.0.0 0x250523"
|
||||||
#define APIEIGER "developer 0x250310"
|
#define APIXILINXCTB "0.0.0 0x250523"
|
||||||
#define APIXILINXCTB "developer 0x250311"
|
#define APIJUNGFRAU "0.0.0 0x250523"
|
||||||
#define APIJUNGFRAU "developer 0x250318"
|
#define APIMYTHEN3 "0.0.0 0x250523"
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
namespace sls {
|
namespace sls {
|
||||||
|
|
||||||
|
std::string ToString(bool value) { return value ? "1" : "0"; }
|
||||||
|
|
||||||
std::string ToString(const slsDetectorDefs::xy &coord) {
|
std::string ToString(const slsDetectorDefs::xy &coord) {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << '[' << coord.x << ", " << coord.y << ']';
|
oss << '[' << coord.x << ", " << coord.y << ']';
|
||||||
|
@ -21,7 +21,8 @@ Version::Version(const std::string &s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Version::hasSemanticVersioning() const {
|
bool Version::hasSemanticVersioning() const {
|
||||||
return version_ != defaultBranch_;
|
|
||||||
|
return (version_ != defaultVersion_[0]) && (version_ != defaultVersion_[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Version::getVersion() const { return version_; }
|
std::string Version::getVersion() const { return version_; }
|
||||||
|
@ -14,6 +14,7 @@ target_sources(tests PRIVATE
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/test-TypeTraits.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/test-TypeTraits.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/test-UdpRxSocket.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/test-UdpRxSocket.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/test-logger.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/test-logger.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/test-Version.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/test-ZmqSocket.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/test-ZmqSocket.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -8,10 +8,10 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace sls {
|
using sls::StaticVector;
|
||||||
|
|
||||||
TEST_CASE("StaticVector is a container") {
|
TEST_CASE("StaticVector is a container") {
|
||||||
REQUIRE(is_container<StaticVector<int, 7>>::value == true);
|
REQUIRE(sls::is_container<StaticVector<int, 7>>::value == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Comparing StaticVector containers") {
|
TEST_CASE("Comparing StaticVector containers") {
|
||||||
@ -90,10 +90,17 @@ TEST_CASE("Copy construct from array") {
|
|||||||
REQUIRE(fcc == arr);
|
REQUIRE(fcc == arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Construct from a smaller StaticVector") {
|
||||||
|
StaticVector<int, 3> sv{1, 2, 3};
|
||||||
|
StaticVector<int, 5> sv2{sv};
|
||||||
|
REQUIRE(sv == sv2);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("Free function and method gives the same iterators") {
|
TEST_CASE("Free function and method gives the same iterators") {
|
||||||
StaticVector<int, 3> fcc{1, 2, 3};
|
StaticVector<int, 3> fcc{1, 2, 3};
|
||||||
REQUIRE(std::begin(fcc) == fcc.begin());
|
REQUIRE(std::begin(fcc) == fcc.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
SCENARIO("StaticVectors can be sized and resized", "[support]") {
|
SCENARIO("StaticVectors can be sized and resized", "[support]") {
|
||||||
|
|
||||||
GIVEN("A default constructed container") {
|
GIVEN("A default constructed container") {
|
||||||
@ -246,23 +253,23 @@ SCENARIO("Sorting, removing and other manipulation of a container",
|
|||||||
REQUIRE(a[3] == 90);
|
REQUIRE(a[3] == 90);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// WHEN("Sorting is done using free function for begin and end") {
|
WHEN("Sorting is done using free function for begin and end") {
|
||||||
// std::sort(begin(a), end(a));
|
std::sort(std::begin(a), std::end(a));
|
||||||
// THEN("it also works") {
|
THEN("it also works") {
|
||||||
// REQUIRE(a[0] == 12);
|
REQUIRE(a[0] == 12);
|
||||||
// REQUIRE(a[1] == 12);
|
REQUIRE(a[1] == 12);
|
||||||
// REQUIRE(a[2] == 14);
|
REQUIRE(a[2] == 14);
|
||||||
// REQUIRE(a[3] == 90);
|
REQUIRE(a[3] == 90);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// WHEN("Erasing elements of a certain value") {
|
WHEN("Erasing elements of a certain value") {
|
||||||
// a.erase(std::remove(begin(a), end(a), 12));
|
a.erase(std::remove(std::begin(a), std::end(a), 12));
|
||||||
// THEN("all elements of that value are removed") {
|
THEN("all elements of that value are removed") {
|
||||||
// REQUIRE(a.size() == 2);
|
REQUIRE(a.size() == 2);
|
||||||
// REQUIRE(a[0] == 14);
|
REQUIRE(a[0] == 14);
|
||||||
// REQUIRE(a[1] == 90);
|
REQUIRE(a[1] == 90);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,5 +341,3 @@ TEST_CASE("StaticVector stream") {
|
|||||||
oss << vec;
|
oss << vec;
|
||||||
REQUIRE(oss.str() == "[33, 85667, 2]");
|
REQUIRE(oss.str() == "[33, 85667, 2]");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sls
|
|
||||||
|
@ -16,6 +16,16 @@ namespace sls {
|
|||||||
|
|
||||||
using namespace sls::time;
|
using namespace sls::time;
|
||||||
|
|
||||||
|
TEST_CASE("Convert bool to string", "[support]") {
|
||||||
|
REQUIRE(ToString(true) == "1");
|
||||||
|
REQUIRE(ToString(false) == "0");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Convert string to bool", "[support]") {
|
||||||
|
REQUIRE(StringTo<bool>("1") == true);
|
||||||
|
REQUIRE(StringTo<bool>("0") == false);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("Integer conversions", "[support]") {
|
TEST_CASE("Integer conversions", "[support]") {
|
||||||
REQUIRE(ToString(0) == "0");
|
REQUIRE(ToString(0) == "0");
|
||||||
REQUIRE(ToString(1) == "1");
|
REQUIRE(ToString(1) == "1");
|
||||||
|
19
slsSupportLib/tests/test-Version.cpp
Normal file
19
slsSupportLib/tests/test-Version.cpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||||
|
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||||
|
#include "catch.hpp"
|
||||||
|
#include "sls/Version.h"
|
||||||
|
|
||||||
|
namespace sls {
|
||||||
|
|
||||||
|
TEST_CASE("check if version is semantic", "[.version]") {
|
||||||
|
|
||||||
|
auto [version_string, has_semantic_version] =
|
||||||
|
GENERATE(std::make_tuple("developer 0x250512", false),
|
||||||
|
std::make_tuple("0.0.0 0x250512", false));
|
||||||
|
|
||||||
|
Version version(version_string);
|
||||||
|
|
||||||
|
CHECK(version.hasSemanticVersioning() == has_semantic_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sls
|
@ -60,3 +60,5 @@ include(Catch)
|
|||||||
catch_discover_tests(tests)
|
catch_discover_tests(tests)
|
||||||
|
|
||||||
configure_file(scripts/test_simulators.py ${CMAKE_BINARY_DIR}/bin/test_simulators.py COPYONLY)
|
configure_file(scripts/test_simulators.py ${CMAKE_BINARY_DIR}/bin/test_simulators.py COPYONLY)
|
||||||
|
configure_file(scripts/test_frame_synchronizer.py ${CMAKE_BINARY_DIR}/bin/test_frame_synchronizer.py COPYONLY)
|
||||||
|
configure_file(scripts/utils_for_test.py ${CMAKE_BINARY_DIR}/bin/utils_for_test.py COPYONLY)
|
||||||
|
141
tests/scripts/test_frame_synchronizer.py
Normal file
141
tests/scripts/test_frame_synchronizer.py
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||||
|
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||||
|
'''
|
||||||
|
This file is used to start up simulators, frame synchronizer, pull sockets, acquire, test and kill them finally.
|
||||||
|
'''
|
||||||
|
|
||||||
|
import sys, time
|
||||||
|
import traceback, json
|
||||||
|
|
||||||
|
from slsdet import Detector
|
||||||
|
from slsdet.defines import DEFAULT_TCP_RX_PORTNO
|
||||||
|
|
||||||
|
from utils_for_test import (
|
||||||
|
Log,
|
||||||
|
LogLevel,
|
||||||
|
RuntimeException,
|
||||||
|
checkIfProcessRunning,
|
||||||
|
killProcess,
|
||||||
|
cleanup,
|
||||||
|
cleanSharedmemory,
|
||||||
|
startProcessInBackground,
|
||||||
|
startProcessInBackgroundWithLogFile,
|
||||||
|
checkLogForErrors,
|
||||||
|
startDetectorVirtualServer,
|
||||||
|
loadConfig,
|
||||||
|
ParseArguments
|
||||||
|
)
|
||||||
|
|
||||||
|
LOG_PREFIX_FNAME = '/tmp/slsFrameSynchronizer_test'
|
||||||
|
MAIN_LOG_FNAME = LOG_PREFIX_FNAME + '_log.txt'
|
||||||
|
PULL_SOCKET_PREFIX_FNAME = LOG_PREFIX_FNAME + '_pull_socket_'
|
||||||
|
|
||||||
|
|
||||||
|
def startFrameSynchronizerPullSocket(name, fp):
|
||||||
|
fname = PULL_SOCKET_PREFIX_FNAME + name + '.txt'
|
||||||
|
cmd = ['python', '-u', 'frameSynchronizerPullSocket.py']
|
||||||
|
startProcessInBackgroundWithLogFile(cmd, fp, fname)
|
||||||
|
time.sleep(1)
|
||||||
|
checkLogForErrors(fp, fname)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def startFrameSynchronizer(num_mods, fp):
|
||||||
|
cmd = ['slsFrameSynchronizer', str(DEFAULT_TCP_RX_PORTNO), str(num_mods)]
|
||||||
|
# in 10.0.0
|
||||||
|
#cmd = ['slsFrameSynchronizer', '-p', str(DEFAULT_TCP_RX_PORTNO), '-n', str(num_mods)]
|
||||||
|
startProcessInBackground(cmd, fp)
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
|
||||||
|
def acquire(fp, det):
|
||||||
|
Log(LogLevel.INFO, 'Acquiring')
|
||||||
|
Log(LogLevel.INFO, 'Acquiring', fp)
|
||||||
|
det.acquire()
|
||||||
|
|
||||||
|
|
||||||
|
def testFramesCaught(name, det, num_frames):
|
||||||
|
fnum = det.rx_framescaught[0]
|
||||||
|
if fnum != num_frames:
|
||||||
|
raise RuntimeException(f"{name} caught only {fnum}. Expected {num_frames}")
|
||||||
|
|
||||||
|
Log(LogLevel.INFOGREEN, f'Frames caught test passed for {name}')
|
||||||
|
Log(LogLevel.INFOGREEN, f'Frames caught test passed for {name}', fp)
|
||||||
|
|
||||||
|
|
||||||
|
def testZmqHeadetTypeCount(name, det, num_mods, num_frames, fp):
|
||||||
|
|
||||||
|
Log(LogLevel.INFO, f"Testing Zmq Header type count for {name}")
|
||||||
|
Log(LogLevel.INFO, f"Testing Zmq Header type count for {name}", fp)
|
||||||
|
htype_counts = {
|
||||||
|
"header": 0,
|
||||||
|
"series_end": 0,
|
||||||
|
"module": 0
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
# get a count of each htype from file
|
||||||
|
pull_socket_fname = PULL_SOCKET_PREFIX_FNAME + name + '.txt'
|
||||||
|
with open(pull_socket_fname, 'r') as log_fp:
|
||||||
|
for line in log_fp:
|
||||||
|
line = line.strip()
|
||||||
|
if not line or not line.startswith('{'):
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
data = json.loads(line)
|
||||||
|
htype = data.get("htype")
|
||||||
|
if htype in htype_counts:
|
||||||
|
htype_counts[htype] += 1
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# test if file contents matches expected counts
|
||||||
|
num_ports_per_module = 1 if name == "gotthard2" else det.numinterfaces
|
||||||
|
total_num_frame_parts = num_ports_per_module * num_mods * num_frames
|
||||||
|
for htype, expected_count in [("header", num_mods), ("series_end", num_mods), ("module", total_num_frame_parts)]:
|
||||||
|
if htype_counts[htype] != expected_count:
|
||||||
|
msg = f"Expected {expected_count} '{htype}' entries, found {htype_counts[htype]}"
|
||||||
|
raise RuntimeException(msg)
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeException(f'Failed to get zmq header count type. Error:{str(e)}') from e
|
||||||
|
|
||||||
|
Log(LogLevel.INFOGREEN, f"Zmq Header type count test passed for {name}")
|
||||||
|
Log(LogLevel.INFOGREEN, f"Zmq Header type count test passed for {name}", fp)
|
||||||
|
|
||||||
|
|
||||||
|
def startTestsForAll(args, fp):
|
||||||
|
for server in args.servers:
|
||||||
|
try:
|
||||||
|
Log(LogLevel.INFOBLUE, f'Synchronizer Tests for {server}')
|
||||||
|
Log(LogLevel.INFOBLUE, f'Synchronizer Tests for {server}', fp)
|
||||||
|
cleanup(fp)
|
||||||
|
startDetectorVirtualServer(server, args.num_mods, fp)
|
||||||
|
startFrameSynchronizerPullSocket(server, fp)
|
||||||
|
startFrameSynchronizer(args.num_mods, fp)
|
||||||
|
d = loadConfig(name=server, rx_hostname=args.rx_hostname, settingsdir=args.settingspath, fp=fp, num_mods=args.num_mods, num_frames=args.num_frames)
|
||||||
|
acquire(fp, d)
|
||||||
|
testFramesCaught(server, d, args.num_frames)
|
||||||
|
testZmqHeadetTypeCount(server, d, args.num_mods, args.num_frames, fp)
|
||||||
|
Log(LogLevel.INFO, '\n')
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeException(f'Synchronizer Tests failed') from e
|
||||||
|
|
||||||
|
Log(LogLevel.INFOGREEN, 'Passed all synchronizer tests for all detectors \n' + str(args.servers))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
args = ParseArguments(description='Automated tests to test frame synchronizer', default_num_mods=2)
|
||||||
|
|
||||||
|
Log(LogLevel.INFOBLUE, '\nLog File: ' + MAIN_LOG_FNAME + '\n')
|
||||||
|
|
||||||
|
with open(MAIN_LOG_FNAME, 'w') as fp:
|
||||||
|
try:
|
||||||
|
startTestsForAll(args, fp)
|
||||||
|
cleanup(fp)
|
||||||
|
except Exception as e:
|
||||||
|
with open(MAIN_LOG_FNAME, 'a') as fp_error:
|
||||||
|
traceback.print_exc(file=fp_error)
|
||||||
|
cleanup(fp)
|
||||||
|
Log(LogLevel.ERROR, f'Tests Failed.')
|
||||||
|
|
||||||
|
|
@ -4,245 +4,86 @@
|
|||||||
This file is used to start up simulators, receivers and run all the tests on them and finally kill the simulators and receivers.
|
This file is used to start up simulators, receivers and run all the tests on them and finally kill the simulators and receivers.
|
||||||
'''
|
'''
|
||||||
import argparse
|
import argparse
|
||||||
import os, sys, subprocess, time, colorama, signal
|
import sys, subprocess, time, traceback
|
||||||
|
|
||||||
from colorama import Fore
|
from slsdet import Detector
|
||||||
from slsdet import Detector, detectorType, detectorSettings
|
from slsdet.defines import DEFAULT_TCP_RX_PORTNO
|
||||||
from slsdet.defines import DEFAULT_TCP_CNTRL_PORTNO, DEFAULT_TCP_RX_PORTNO, DEFAULT_UDP_DST_PORTNO
|
|
||||||
HALFMOD2_TCP_CNTRL_PORTNO=1955
|
|
||||||
HALFMOD2_TCP_RX_PORTNO=1957
|
|
||||||
|
|
||||||
colorama.init(autoreset=True)
|
from utils_for_test import (
|
||||||
|
Log,
|
||||||
class RuntimeException (Exception):
|
LogLevel,
|
||||||
def __init__ (self, message):
|
RuntimeException,
|
||||||
super().__init__(Fore.RED + message)
|
checkIfProcessRunning,
|
||||||
|
killProcess,
|
||||||
def Log(color, message):
|
cleanup,
|
||||||
print('\n' + color + message, flush=True)
|
cleanSharedmemory,
|
||||||
|
startProcessInBackground,
|
||||||
|
runProcessWithLogFile,
|
||||||
|
startDetectorVirtualServer,
|
||||||
|
loadConfig,
|
||||||
|
ParseArguments
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def checkIfProcessRunning(processName):
|
LOG_PREFIX_FNAME = '/tmp/slsDetectorPackage_virtual_test'
|
||||||
cmd = "ps -ef | grep " + processName
|
MAIN_LOG_FNAME = LOG_PREFIX_FNAME + '_log.txt'
|
||||||
print(cmd)
|
GENERAL_TESTS_LOG_FNAME = LOG_PREFIX_FNAME + '_results_general.txt'
|
||||||
res=subprocess.getoutput(cmd)
|
CMD_TEST_LOG_PREFIX_FNAME = LOG_PREFIX_FNAME + '_results_cmd_'
|
||||||
print(res)
|
|
||||||
# eg. of output
|
|
||||||
#l_user 250506 243295 0 14:38 pts/5 00:00:00 /bin/sh -c ps -ef | grep slsReceiver
|
|
||||||
#l_user 250508 250506 0 14:38 pts/5 00:00:00 grep slsReceiver
|
|
||||||
|
|
||||||
print('how many')
|
|
||||||
cmd = "ps -ef | grep " + processName + " | wc -l"
|
|
||||||
print(cmd)
|
|
||||||
res=subprocess.getoutput(cmd)
|
|
||||||
print(res)
|
|
||||||
|
|
||||||
if res == '2':
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def killProcess(name):
|
def startReceiver(num_mods, fp):
|
||||||
if checkIfProcessRunning(name):
|
if num_mods == 1:
|
||||||
Log(Fore.GREEN, 'killing ' + name)
|
cmd = ['slsReceiver']
|
||||||
p = subprocess.run(['killall', name])
|
|
||||||
if p.returncode != 0:
|
|
||||||
raise RuntimeException('killall failed for ' + name)
|
|
||||||
else:
|
else:
|
||||||
print('process not running : ' + name)
|
cmd = ['slsMultiReceiver', str(DEFAULT_TCP_RX_PORTNO), str(num_mods)]
|
||||||
|
# in 10.0.0
|
||||||
|
#cmd = ['slsMultiReceiver', '-p', str(DEFAULT_TCP_RX_PORTNO), '-n', str(num_mods)]
|
||||||
|
startProcessInBackground(cmd, fp)
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
def startGeneralTests(fp):
|
||||||
def killAllStaleProcesses():
|
fname = GENERAL_TESTS_LOG_FNAME
|
||||||
killProcess('eigerDetectorServer_virtual')
|
cmd = ['tests', '--abort', '-s']
|
||||||
killProcess('jungfrauDetectorServer_virtual')
|
|
||||||
killProcess('mythen3DetectorServer_virtual')
|
|
||||||
killProcess('gotthard2DetectorServer_virtual')
|
|
||||||
killProcess('ctbDetectorServer_virtual')
|
|
||||||
killProcess('moenchDetectorServer_virtual')
|
|
||||||
killProcess('xilinx_ctbDetectorServer_virtual')
|
|
||||||
killProcess('slsReceiver')
|
|
||||||
killProcess('slsMultiReceiver')
|
|
||||||
cleanSharedmemory()
|
|
||||||
|
|
||||||
def cleanup(name):
|
|
||||||
'''
|
|
||||||
kill both servers, receivers and clean shared memory
|
|
||||||
'''
|
|
||||||
Log(Fore.GREEN, 'Cleaning up...')
|
|
||||||
killProcess(name + 'DetectorServer_virtual')
|
|
||||||
killProcess('slsReceiver')
|
|
||||||
killProcess('slsMultiReceiver')
|
|
||||||
cleanSharedmemory()
|
|
||||||
|
|
||||||
def cleanSharedmemory():
|
|
||||||
Log(Fore.GREEN, 'Cleaning up shared memory...')
|
|
||||||
try:
|
try:
|
||||||
p = subprocess.run(['sls_detector_get', 'free'], stdout=fp, stderr=fp)
|
cleanup(fp)
|
||||||
except:
|
runProcessWithLogFile('General Tests', cmd, fp, fname)
|
||||||
Log(Fore.RED, 'Could not free shared memory')
|
except Exception as e:
|
||||||
raise
|
raise RuntimeException(f'General tests failed.') from e
|
||||||
|
|
||||||
def startProcessInBackground(name):
|
|
||||||
|
def startCmdTestsForAll(args, fp):
|
||||||
|
for server in args.servers:
|
||||||
try:
|
try:
|
||||||
# in background and dont print output
|
num_mods = 2 if server == 'eiger' else 1
|
||||||
p = subprocess.Popen(name.split(), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, restore_signals=False)
|
fname = CMD_TEST_LOG_PREFIX_FNAME + server + '.txt'
|
||||||
Log(Fore.GREEN, 'Starting up ' + name + ' ...')
|
cmd = ['tests', '--abort', '[.cmdcall]', '-s']
|
||||||
except:
|
|
||||||
Log(Fore.RED, 'Could not start ' + name)
|
|
||||||
raise
|
|
||||||
|
|
||||||
def startServer(name):
|
Log(LogLevel.INFOBLUE, f'Starting Cmd Tests for {server}')
|
||||||
|
cleanup(fp)
|
||||||
|
startDetectorVirtualServer(name=server, num_mods=num_mods, fp=fp)
|
||||||
|
startReceiver(num_mods, fp)
|
||||||
|
loadConfig(name=server, rx_hostname=args.rx_hostname, settingsdir=args.settingspath, fp=fp, num_mods=num_mods)
|
||||||
|
runProcessWithLogFile('Cmd Tests for ' + server, cmd, fp, fname)
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeException(f'Cmd Tests failed for {server}.') from e
|
||||||
|
|
||||||
startProcessInBackground(name + 'DetectorServer_virtual')
|
Log(LogLevel.INFOGREEN, 'Passed all tests for all detectors \n' + str(args.servers))
|
||||||
# second half
|
|
||||||
if name == 'eiger':
|
|
||||||
startProcessInBackground(name + 'DetectorServer_virtual -p' + str(HALFMOD2_TCP_CNTRL_PORTNO))
|
|
||||||
tStartup = 6
|
|
||||||
Log(Fore.WHITE, 'Takes ' + str(tStartup) + ' seconds... Please be patient')
|
|
||||||
time.sleep(tStartup)
|
|
||||||
|
|
||||||
def startReceiver(name):
|
|
||||||
startProcessInBackground('slsReceiver')
|
|
||||||
# second half
|
|
||||||
if name == 'eiger':
|
|
||||||
startProcessInBackground('slsReceiver -t' + str(HALFMOD2_TCP_RX_PORTNO))
|
|
||||||
time.sleep(2)
|
|
||||||
|
|
||||||
def loadConfig(name, rx_hostname, settingsdir):
|
if __name__ == '__main__':
|
||||||
Log(Fore.GREEN, 'Loading config')
|
args = ParseArguments('Automated tests with the virtual detector servers')
|
||||||
|
if args.num_mods > 1:
|
||||||
|
raise RuntimeException(f'Cannot support multiple modules at the moment (except Eiger).')
|
||||||
|
|
||||||
|
Log(LogLevel.INFOBLUE, '\nLog File: ' + MAIN_LOG_FNAME + '\n')
|
||||||
|
|
||||||
|
with open(MAIN_LOG_FNAME, 'w') as fp:
|
||||||
try:
|
try:
|
||||||
d = Detector()
|
startGeneralTests(fp)
|
||||||
if name == 'eiger':
|
startCmdTestsForAll(args, fp)
|
||||||
d.hostname = 'localhost:' + str(DEFAULT_TCP_CNTRL_PORTNO) + '+localhost:' + str(HALFMOD2_TCP_CNTRL_PORTNO)
|
cleanup(fp)
|
||||||
#d.udp_dstport = {2: 50003}
|
except Exception as e:
|
||||||
# will set up for every module
|
with open(MAIN_LOG_FNAME, 'a') as fp_error:
|
||||||
d.udp_dstport = DEFAULT_UDP_DST_PORTNO
|
traceback.print_exc(file=fp_error)
|
||||||
d.udp_dstport2 = DEFAULT_UDP_DST_PORTNO + 1
|
cleanup(fp)
|
||||||
d.rx_hostname = rx_hostname + ':' + str(DEFAULT_TCP_RX_PORTNO) + '+' + rx_hostname + ':' + str(HALFMOD2_TCP_RX_PORTNO)
|
Log(LogLevel.ERROR, f'Tests Failed.')
|
||||||
d.udp_dstip = 'auto'
|
|
||||||
d.trimen = [4500, 5400, 6400]
|
|
||||||
d.settingspath = settingsdir + '/eiger/'
|
|
||||||
d.setThresholdEnergy(4500, detectorSettings.STANDARD)
|
|
||||||
else:
|
|
||||||
d.hostname = 'localhost'
|
|
||||||
d.rx_hostname = rx_hostname
|
|
||||||
d.udp_dstip = 'auto'
|
|
||||||
d.udp_srcip = 'auto'
|
|
||||||
if d.type == detectorType.JUNGFRAU or d.type == detectorType.MOENCH or d.type == detectorType.XILINX_CHIPTESTBOARD:
|
|
||||||
d.powerchip = 1
|
|
||||||
if d.type == detectorType.XILINX_CHIPTESTBOARD:
|
|
||||||
d.configureTransceiver()
|
|
||||||
except:
|
|
||||||
Log(Fore.RED, 'Could not load config for ' + name)
|
|
||||||
raise
|
|
||||||
|
|
||||||
def startCmdTests(name, fp, fname):
|
|
||||||
Log(Fore.GREEN, 'Cmd Tests for ' + name)
|
|
||||||
cmd = 'tests --abort [.cmdcall] -s -o ' + fname
|
|
||||||
p = subprocess.run(cmd.split(), stdout=fp, stderr=fp, check=True, text=True)
|
|
||||||
p.check_returncode()
|
|
||||||
|
|
||||||
with open (fname, 'r') as f:
|
|
||||||
for line in f:
|
|
||||||
if "FAILED" in line:
|
|
||||||
msg = 'Cmd tests failed for ' + name + '!!!'
|
|
||||||
Log(Fore.RED, msg)
|
|
||||||
raise Exception(msg)
|
|
||||||
|
|
||||||
Log(Fore.GREEN, 'Cmd Tests successful for ' + name)
|
|
||||||
|
|
||||||
def startGeneralTests(fp, fname):
|
|
||||||
Log(Fore.GREEN, 'General Tests')
|
|
||||||
cmd = 'tests --abort -s -o ' + fname
|
|
||||||
p = subprocess.run(cmd.split(), stdout=fp, stderr=fp, check=True, text=True)
|
|
||||||
p.check_returncode()
|
|
||||||
|
|
||||||
with open (fname, 'r') as f:
|
|
||||||
for line in f:
|
|
||||||
if "FAILED" in line:
|
|
||||||
msg = 'General tests failed !!!'
|
|
||||||
Log(Fore.RED, msg)
|
|
||||||
raise Exception(msg)
|
|
||||||
|
|
||||||
Log(Fore.GREEN, 'General Tests successful')
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# parse cmd line for rx_hostname and settingspath using the argparse library
|
|
||||||
parser = argparse.ArgumentParser(description = 'automated tests with the virtual detector servers')
|
|
||||||
parser.add_argument('rx_hostname', help = 'hostname/ip of the current machine')
|
|
||||||
parser.add_argument('settingspath', help = 'Relative or absolut path to the settingspath')
|
|
||||||
parser.add_argument('-s', '--servers', help='Detector servers to run', nargs='*')
|
|
||||||
args = parser.parse_args()
|
|
||||||
if args.rx_hostname == 'localhost':
|
|
||||||
raise RuntimeException('Cannot use localhost for rx_hostname for the tests (fails for rx_arping for eg.)')
|
|
||||||
|
|
||||||
if args.servers is None:
|
|
||||||
servers = [
|
|
||||||
'eiger',
|
|
||||||
'jungfrau',
|
|
||||||
'mythen3',
|
|
||||||
'gotthard2',
|
|
||||||
'ctb',
|
|
||||||
'moench',
|
|
||||||
'xilinx_ctb'
|
|
||||||
]
|
|
||||||
else:
|
|
||||||
servers = args.servers
|
|
||||||
|
|
||||||
|
|
||||||
Log(Fore.WHITE, 'Arguments:\nrx_hostname: ' + args.rx_hostname + '\nsettingspath: \'' + args.settingspath + '\'')
|
|
||||||
|
|
||||||
|
|
||||||
# redirect to file
|
|
||||||
prefix_fname = '/tmp/slsDetectorPackage_virtual_test'
|
|
||||||
original_stdout = sys.stdout
|
|
||||||
original_stderr = sys.stderr
|
|
||||||
fname = prefix_fname + '_log.txt'
|
|
||||||
Log(Fore.BLUE, '\nLog File: ' + fname)
|
|
||||||
|
|
||||||
with open(fname, 'w') as fp:
|
|
||||||
|
|
||||||
# general tests
|
|
||||||
file_results = prefix_fname + '_results_general.txt'
|
|
||||||
Log(Fore.BLUE, 'General tests (results: ' + file_results + ')')
|
|
||||||
sys.stdout = fp
|
|
||||||
sys.stderr = fp
|
|
||||||
Log(Fore.BLUE, 'General tests (results: ' + file_results + ')')
|
|
||||||
startGeneralTests(fp, file_results)
|
|
||||||
|
|
||||||
killAllStaleProcesses()
|
|
||||||
|
|
||||||
for server in servers:
|
|
||||||
try:
|
|
||||||
# print to terminal for progress
|
|
||||||
sys.stdout = original_stdout
|
|
||||||
sys.stderr = original_stderr
|
|
||||||
file_results = prefix_fname + '_results_cmd_' + server + '.txt'
|
|
||||||
Log(Fore.BLUE, 'Cmd tests for ' + server + ' (results: ' + file_results + ')')
|
|
||||||
sys.stdout = fp
|
|
||||||
sys.stderr = fp
|
|
||||||
Log(Fore.BLUE, 'Cmd tests for ' + server + ' (results: ' + file_results + ')')
|
|
||||||
|
|
||||||
# cmd tests for det
|
|
||||||
cleanup(server)
|
|
||||||
startServer(server)
|
|
||||||
startReceiver(server)
|
|
||||||
loadConfig(server, args.rx_hostname, args.settingspath)
|
|
||||||
startCmdTests(server, fp, file_results)
|
|
||||||
cleanup(server)
|
|
||||||
except:
|
|
||||||
Log(Fore.RED, 'Exception caught. Cleaning up.')
|
|
||||||
cleanup(server)
|
|
||||||
sys.stdout = original_stdout
|
|
||||||
sys.stderr = original_stderr
|
|
||||||
Log(Fore.RED, 'Cmd tests failed for ' + server + '!!!')
|
|
||||||
raise
|
|
||||||
|
|
||||||
|
|
||||||
Log(Fore.GREEN, 'Passed all tests for virtual detectors \n' + str(servers))
|
|
||||||
|
|
||||||
# redirect to terminal
|
|
||||||
sys.stdout = original_stdout
|
|
||||||
sys.stderr = original_stderr
|
|
||||||
Log(Fore.GREEN, 'Passed all tests for virtual detectors \n' + str(servers) + '\nYayyyy! :) ')
|
|
||||||
|
259
tests/scripts/utils_for_test.py
Normal file
259
tests/scripts/utils_for_test.py
Normal file
@ -0,0 +1,259 @@
|
|||||||
|
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||||
|
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||||
|
'''
|
||||||
|
This file is used for common utils used for integration tests between simulators and receivers.
|
||||||
|
'''
|
||||||
|
|
||||||
|
import sys, subprocess, time, argparse
|
||||||
|
from enum import Enum
|
||||||
|
from colorama import Fore, Style, init
|
||||||
|
|
||||||
|
from slsdet import Detector, detectorSettings
|
||||||
|
from slsdet.defines import DEFAULT_TCP_RX_PORTNO, DEFAULT_UDP_DST_PORTNO
|
||||||
|
SERVER_START_PORTNO=1900
|
||||||
|
|
||||||
|
init(autoreset=True)
|
||||||
|
|
||||||
|
|
||||||
|
class LogLevel(Enum):
|
||||||
|
INFO = 0
|
||||||
|
INFORED = 1
|
||||||
|
INFOGREEN = 2
|
||||||
|
INFOBLUE = 3
|
||||||
|
WARNING = 4
|
||||||
|
ERROR = 5
|
||||||
|
DEBUG = 6
|
||||||
|
|
||||||
|
|
||||||
|
LOG_LABELS = {
|
||||||
|
LogLevel.WARNING: "WARNING: ",
|
||||||
|
LogLevel.ERROR: "ERROR: ",
|
||||||
|
LogLevel.DEBUG: "DEBUG: "
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LOG_COLORS = {
|
||||||
|
LogLevel.INFO: Fore.WHITE,
|
||||||
|
LogLevel.INFORED: Fore.RED,
|
||||||
|
LogLevel.INFOGREEN: Fore.GREEN,
|
||||||
|
LogLevel.INFOBLUE: Fore.BLUE,
|
||||||
|
LogLevel.WARNING: Fore.YELLOW,
|
||||||
|
LogLevel.ERROR: Fore.RED,
|
||||||
|
LogLevel.DEBUG: Fore.CYAN
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def Log(level: LogLevel, message: str, stream=sys.stdout):
|
||||||
|
color = LOG_COLORS.get(level, Fore.WHITE)
|
||||||
|
label = LOG_LABELS.get(level, "")
|
||||||
|
print(f"{color}{label}{message}{Style.RESET_ALL}", file=stream, flush=True)
|
||||||
|
|
||||||
|
|
||||||
|
class RuntimeException (Exception):
|
||||||
|
def __init__ (self, message):
|
||||||
|
Log(LogLevel.ERROR, message)
|
||||||
|
super().__init__(message)
|
||||||
|
|
||||||
|
|
||||||
|
def checkIfProcessRunning(processName):
|
||||||
|
cmd = f"pgrep -f {processName}"
|
||||||
|
res = subprocess.getoutput(cmd)
|
||||||
|
return res.strip().splitlines()
|
||||||
|
|
||||||
|
|
||||||
|
def killProcess(name, fp):
|
||||||
|
pids = checkIfProcessRunning(name)
|
||||||
|
if pids:
|
||||||
|
Log(LogLevel.INFO, f"Killing '{name}' processes with PIDs: {', '.join(pids)}", fp)
|
||||||
|
for pid in pids:
|
||||||
|
try:
|
||||||
|
p = subprocess.run(['kill', pid])
|
||||||
|
if p.returncode != 0 and bool(checkIfProcessRunning(name)):
|
||||||
|
raise RuntimeException(f"Could not kill {name} with pid {pid}")
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeException(f"Failed to kill process {name} pid:{pid}. Error: {str(e)}") from e
|
||||||
|
#else:
|
||||||
|
# Log(LogLevel.INFO, 'process not running : ' + name)
|
||||||
|
|
||||||
|
|
||||||
|
def cleanSharedmemory(fp):
|
||||||
|
Log(LogLevel.INFO, 'Cleaning up shared memory', fp)
|
||||||
|
try:
|
||||||
|
p = subprocess.run(['sls_detector_get', 'free'], stdout=fp, stderr=fp)
|
||||||
|
except:
|
||||||
|
raise RuntimeException('Could not free shared memory')
|
||||||
|
|
||||||
|
|
||||||
|
def cleanup(fp):
|
||||||
|
Log(LogLevel.INFO, 'Cleaning up')
|
||||||
|
Log(LogLevel.INFO, 'Cleaning up', fp)
|
||||||
|
killProcess('DetectorServer_virtual', fp)
|
||||||
|
killProcess('slsReceiver', fp)
|
||||||
|
killProcess('slsMultiReceiver', fp)
|
||||||
|
killProcess('slsFrameSynchronizer', fp)
|
||||||
|
killProcess('frameSynchronizerPullSocket', fp)
|
||||||
|
cleanSharedmemory(fp)
|
||||||
|
|
||||||
|
|
||||||
|
def startProcessInBackground(cmd, fp):
|
||||||
|
Log(LogLevel.INFO, 'Starting up ' + ' '.join(cmd))
|
||||||
|
Log(LogLevel.INFO, 'Starting up ' + ' '.join(cmd), fp)
|
||||||
|
try:
|
||||||
|
p = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, restore_signals=False)
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeException(f'Failed to start {cmd}:{str(e)}') from e
|
||||||
|
|
||||||
|
|
||||||
|
def startProcessInBackgroundWithLogFile(cmd, fp, log_file_name: str):
|
||||||
|
Log(LogLevel.INFOBLUE, 'Starting up ' + ' '.join(cmd) + '. Log: ' + log_file_name)
|
||||||
|
Log(LogLevel.INFOBLUE, 'Starting up ' + ' '.join(cmd) + '. Log: ' + log_file_name, fp)
|
||||||
|
try:
|
||||||
|
with open(log_file_name, 'w') as log_fp:
|
||||||
|
subprocess.Popen(cmd, stdout=log_fp, stderr=log_fp, text=True)
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeException(f'Failed to start {cmd}:{str(e)}') from e
|
||||||
|
|
||||||
|
|
||||||
|
def checkLogForErrors(fp, log_file_path: str):
|
||||||
|
try:
|
||||||
|
with open(log_file_path, 'r') as log_file:
|
||||||
|
for line in log_file:
|
||||||
|
if 'Error' in line:
|
||||||
|
Log(LogLevel.ERROR, f"Error found in log: {line.strip()}")
|
||||||
|
Log(LogLevel.ERROR, f"Error found in log: {line.strip()}", fp)
|
||||||
|
raise RuntimeException("Error found in log file")
|
||||||
|
except FileNotFoundError:
|
||||||
|
print(f"Log file not found: {log_file_path}")
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Exception while reading log: {e}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def runProcessWithLogFile(name, cmd, fp, log_file_name):
|
||||||
|
Log(LogLevel.INFOBLUE, 'Running ' + name + '. Log: ' + log_file_name)
|
||||||
|
Log(LogLevel.INFOBLUE, 'Running ' + name + '. Log: ' + log_file_name, fp)
|
||||||
|
Log(LogLevel.INFOBLUE, 'Cmd: ' + ' '.join(cmd), fp)
|
||||||
|
try:
|
||||||
|
with open(log_file_name, 'w') as log_fp:
|
||||||
|
subprocess.run(cmd, stdout=log_fp, stderr=log_fp, check=True, text=True)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
pass
|
||||||
|
except Exception as e:
|
||||||
|
Log(LogLevel.ERROR, f'Failed to run {name}:{str(e)}', fp)
|
||||||
|
raise RuntimeException(f'Failed to run {name}:{str(e)}')
|
||||||
|
|
||||||
|
with open (log_file_name, 'r') as f:
|
||||||
|
for line in f:
|
||||||
|
if "FAILED" in line:
|
||||||
|
raise RuntimeException(f'{line}')
|
||||||
|
|
||||||
|
Log(LogLevel.INFOGREEN, name + ' successful!\n')
|
||||||
|
Log(LogLevel.INFOGREEN, name + ' successful!\n', fp)
|
||||||
|
|
||||||
|
|
||||||
|
def startDetectorVirtualServer(name :str, num_mods, fp):
|
||||||
|
for i in range(num_mods):
|
||||||
|
port_no = SERVER_START_PORTNO + (i * 2)
|
||||||
|
cmd = [name + 'DetectorServer_virtual', '-p', str(port_no)]
|
||||||
|
startProcessInBackgroundWithLogFile(cmd, fp, "/tmp/virtual_det_" + name + str(i) + ".txt")
|
||||||
|
match name:
|
||||||
|
case 'jungfrau':
|
||||||
|
time.sleep(7)
|
||||||
|
case 'gotthard2':
|
||||||
|
time.sleep(5)
|
||||||
|
case _:
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
|
||||||
|
def connectToVirtualServers(name, num_mods):
|
||||||
|
try:
|
||||||
|
d = Detector()
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeException(f'Could not create Detector object for {name}. Error: {str(e)}') from e
|
||||||
|
|
||||||
|
counts_sec = 5
|
||||||
|
while (counts_sec != 0):
|
||||||
|
try:
|
||||||
|
d.virtual = [num_mods, SERVER_START_PORTNO]
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
# stop server still not up, wait a bit longer
|
||||||
|
if "Cannot connect to" in str(e):
|
||||||
|
Log(LogLevel.WARNING, f'Still waiting for {name} virtual server to be up...{counts_sec}s left')
|
||||||
|
time.sleep(1)
|
||||||
|
counts_sec -= 1
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
def loadConfig(name, rx_hostname, settingsdir, fp, num_mods = 1, num_frames = 1):
|
||||||
|
Log(LogLevel.INFO, 'Loading config')
|
||||||
|
Log(LogLevel.INFO, 'Loading config', fp)
|
||||||
|
try:
|
||||||
|
d = connectToVirtualServers(name, num_mods)
|
||||||
|
d.udp_dstport = DEFAULT_UDP_DST_PORTNO
|
||||||
|
if name == 'eiger':
|
||||||
|
d.udp_dstport2 = DEFAULT_UDP_DST_PORTNO + 1
|
||||||
|
|
||||||
|
d.rx_hostname = rx_hostname
|
||||||
|
d.udp_dstip = 'auto'
|
||||||
|
if name != "eiger":
|
||||||
|
d.udp_srcip = 'auto'
|
||||||
|
|
||||||
|
if name == "jungfrau" or name == "moench" or name == "xilinx_ctb":
|
||||||
|
d.powerchip = 1
|
||||||
|
|
||||||
|
if name == "xilinx_ctb":
|
||||||
|
d.configureTransceiver()
|
||||||
|
|
||||||
|
if name == "eiger":
|
||||||
|
d.trimen = [4500, 5400, 6400]
|
||||||
|
d.settingspath = settingsdir + '/eiger/'
|
||||||
|
d.setThresholdEnergy(4500, detectorSettings.STANDARD)
|
||||||
|
|
||||||
|
d.frames = num_frames
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeException(f'Could not load config for {name}. Error: {str(e)}') from e
|
||||||
|
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
def ParseArguments(description, default_num_mods=1):
|
||||||
|
parser = argparse.ArgumentParser(description)
|
||||||
|
|
||||||
|
parser.add_argument('rx_hostname', nargs='?', default='localhost',
|
||||||
|
help='Hostname/IP of the current machine')
|
||||||
|
parser.add_argument('settingspath', nargs='?', default='../../settingsdir',
|
||||||
|
help='Relative or absolute path to the settings directory')
|
||||||
|
parser.add_argument('-n', '--num-mods', nargs='?', default=default_num_mods, type=int,
|
||||||
|
help='Number of modules to test with')
|
||||||
|
parser.add_argument('-f', '--num-frames', nargs='?', default=1, type=int,
|
||||||
|
help='Number of frames to test with')
|
||||||
|
parser.add_argument('-s', '--servers', nargs='*',
|
||||||
|
help='Detector servers to run')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# Set default server list if not provided
|
||||||
|
if args.servers is None:
|
||||||
|
args.servers = [
|
||||||
|
'eiger',
|
||||||
|
'jungfrau',
|
||||||
|
'mythen3',
|
||||||
|
'gotthard2',
|
||||||
|
'ctb',
|
||||||
|
'moench',
|
||||||
|
'xilinx_ctb'
|
||||||
|
]
|
||||||
|
|
||||||
|
Log(LogLevel.INFO, 'Arguments:\n' +
|
||||||
|
'rx_hostname: ' + args.rx_hostname +
|
||||||
|
'\nsettingspath: \'' + args.settingspath +
|
||||||
|
'\nservers: \'' + ' '.join(args.servers) +
|
||||||
|
'\nnum_mods: \'' + str(args.num_mods) +
|
||||||
|
'\nnum_frames: \'' + str(args.num_frames) + '\'')
|
||||||
|
|
||||||
|
return args
|
81
updateAPIVersion.py
Normal file
81
updateAPIVersion.py
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||||
|
# Copyright (C) 2025 Contributors to the SLS Detector Package
|
||||||
|
"""
|
||||||
|
Script to update API VERSION file based on the version in VERSION file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import time
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
API_FILE = SCRIPT_DIR + "/slsSupportLib/include/sls/versionAPI.h"
|
||||||
|
|
||||||
|
VERSION_FILE = SCRIPT_DIR + "/VERSION"
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description = 'updates API version')
|
||||||
|
parser.add_argument('api_module_name', choices=["APILIB", "APIRECEIVER", "APICTB", "APIGOTTHARD2", "APIMOENCH", "APIEIGER", "APIXILINXCTB", "APIJUNGFRAU", "APIMYTHEN3"], help = 'module name to change api version options are: ["APILIB", "APIRECEIVER", "APICTB", "APIGOTTHARD2", "APIMOENCH", "APIEIGER", "APIXILINXCTB", "APIJUNGFRAU", "APIMYTHEN3"]')
|
||||||
|
parser.add_argument('api_dir', help = 'Relative or absolute path to the module code')
|
||||||
|
|
||||||
|
def update_api_file(new_api : str, api_module_name : str, api_file_name : str):
|
||||||
|
|
||||||
|
regex_pattern = re.compile(rf'#define\s+{api_module_name}\s+')
|
||||||
|
with open(api_file_name, "r") as api_file:
|
||||||
|
lines = api_file.readlines()
|
||||||
|
|
||||||
|
with open(api_file_name, "w") as api_file:
|
||||||
|
for line in lines:
|
||||||
|
if regex_pattern.match(line):
|
||||||
|
api_file.write(f'#define {api_module_name} "{new_api}"\n')
|
||||||
|
else:
|
||||||
|
api_file.write(line)
|
||||||
|
|
||||||
|
def get_latest_modification_date(directory : str):
|
||||||
|
latest_time = 0
|
||||||
|
latest_date = None
|
||||||
|
|
||||||
|
for root, dirs, files in os.walk(directory):
|
||||||
|
for file in files:
|
||||||
|
if file.endswith(".o"):
|
||||||
|
continue
|
||||||
|
full_path = os.path.join(root, file)
|
||||||
|
try:
|
||||||
|
mtime = os.path.getmtime(full_path)
|
||||||
|
if mtime > latest_time:
|
||||||
|
latest_time = mtime
|
||||||
|
except FileNotFoundError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
latest_date = datetime.fromtimestamp(latest_time).strftime("%y%m%d")
|
||||||
|
|
||||||
|
return latest_date
|
||||||
|
|
||||||
|
|
||||||
|
def update_api_version(api_module_name : str, api_dir : str):
|
||||||
|
api_date = get_latest_modification_date(api_dir)
|
||||||
|
api_date = "0x"+str(api_date)
|
||||||
|
|
||||||
|
with open(VERSION_FILE, "r") as version_file:
|
||||||
|
api_version = version_file.read().strip()
|
||||||
|
|
||||||
|
api_version = api_version + " " + api_date #not sure if we should give an argument option version_branch
|
||||||
|
|
||||||
|
update_api_file(api_version, api_module_name, API_FILE)
|
||||||
|
|
||||||
|
print(f"updated {api_module_name} api version to: {api_version}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
api_dir = SCRIPT_DIR + "/" + args.api_dir
|
||||||
|
|
||||||
|
|
||||||
|
update_api_version(args.api_module_name, api_dir)
|
||||||
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
|||||||
# SPDX-License-Identifier: LGPL-3.0-or-other
|
|
||||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
|
||||||
usage="\nUsage: updateAPIVersion.sh [API_NAME] [API_DIR] [API_BRANCH(opt)]."
|
|
||||||
|
|
||||||
if [ $# -lt 2 ]; then
|
|
||||||
echo -e "Requires atleast 2 arguments. $usage"
|
|
||||||
return [-1]
|
|
||||||
fi
|
|
||||||
|
|
||||||
API_NAME=$1
|
|
||||||
PACKAGE_DIR=$PWD
|
|
||||||
API_DIR=$PACKAGE_DIR/$2
|
|
||||||
API_FILE=$PACKAGE_DIR/slsSupportLib/include/sls/versionAPI.h
|
|
||||||
CURR_DIR=$PWD
|
|
||||||
|
|
||||||
if [ ! -d "$API_DIR" ]; then
|
|
||||||
echo "[API_DIR] does not exist. $usage"
|
|
||||||
return [-1]
|
|
||||||
fi
|
|
||||||
|
|
||||||
#go to directory
|
|
||||||
cd $API_DIR
|
|
||||||
|
|
||||||
#deleting line from file
|
|
||||||
NUM=$(sed -n '/'$API_NAME' /=' $API_FILE)
|
|
||||||
#echo $NUM
|
|
||||||
|
|
||||||
|
|
||||||
if [ "$NUM" -gt 0 ]; then
|
|
||||||
sed -i ${NUM}d $API_FILE
|
|
||||||
fi
|
|
||||||
|
|
||||||
#find new API date
|
|
||||||
API_DATE="find . -printf \"%T@ %CY-%Cm-%Cd\n\"| sort -nr | cut -d' ' -f2- | egrep -v '(\.)o' | head -n 1"
|
|
||||||
|
|
||||||
API_DATE=`eval $API_DATE`
|
|
||||||
|
|
||||||
API_DATE=$(sed "s/-//g" <<< $API_DATE | awk '{print $1;}' )
|
|
||||||
|
|
||||||
#extracting only date
|
|
||||||
API_DATE=${API_DATE:2:6}
|
|
||||||
|
|
||||||
#prefix of 0x
|
|
||||||
API_DATE=${API_DATE/#/0x}
|
|
||||||
echo "date="$API_DATE
|
|
||||||
|
|
||||||
|
|
||||||
# API_VAL concatenates branch and date
|
|
||||||
API_VAL=""
|
|
||||||
# API branch is defined (3rd argument)
|
|
||||||
if [ $# -eq 3 ]; then
|
|
||||||
API_BRANCH=$3
|
|
||||||
echo "branch="$API_BRANCH
|
|
||||||
API_VAL+="\"$API_BRANCH $API_DATE\""
|
|
||||||
else
|
|
||||||
# API branch not defined (default is developer)
|
|
||||||
echo "branch=developer"
|
|
||||||
API_VAL+="\"developer $API_DATE\""
|
|
||||||
fi
|
|
||||||
|
|
||||||
#copy it to versionAPI.h
|
|
||||||
echo "#define "$API_NAME $API_VAL >> $API_FILE
|
|
||||||
|
|
||||||
#go back to original directory
|
|
||||||
cd $CURR_DIR
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user