Compare commits

...

22 Commits

Author SHA1 Message Date
cb8403f1b0 zmq 2020-03-18 12:38:06 +01:00
b751238fc1 ZmqSocket 2020-03-18 12:12:01 +01:00
5479d3a198 fix 2020-03-18 11:11:00 +01:00
e1768905dd build interface 2020-03-18 11:06:37 +01:00
775d0842e9 build interface 2020-03-18 11:00:54 +01:00
e7e201bd2a export and include 2020-03-18 10:20:01 +01:00
ec9f8305e9 not export gui 2020-03-18 08:41:25 +01:00
3307bfab1b fix 2020-03-17 19:11:29 +01:00
ce2c62000d include cmake in build 2020-03-17 18:57:19 +01:00
cf817c4ec1 WIP 2020-03-17 18:29:51 +01:00
bd01a5f2d2 cmake pkg 2020-03-16 19:36:18 +01:00
b059ba7c90 Merge branch 'developer' of github.com:slsdetectorgroup/slsDetectorPackage into developer 2020-03-16 15:43:55 +01:00
89d70097f6 WIP 2020-03-16 15:43:46 +01:00
41d115a394 Merge branch 'developer' of github.com:slsdetectorgroup/slsDetectorPackage into developer 2020-03-13 19:36:38 +01:00
45c1d3a553 gotthard2: burst mode fix for all the registers 2020-03-13 19:36:23 +01:00
17227be4df gotthard2: burst mode fix 2020-03-13 17:39:16 +01:00
7f4f8e8f09 help bug emax 2020-03-13 09:56:11 +01:00
6809bd6567 removed header 2020-03-12 12:38:00 +01:00
711d40a56e added sendToReceiver 2020-03-12 11:45:12 +01:00
81911fae3c new version of send to detector 2020-03-11 19:18:26 +01:00
f940397e3a cleaning 2020-03-11 18:10:37 +01:00
dc53887a48 minor clean 2020-03-11 17:49:32 +01:00
35 changed files with 1178 additions and 914 deletions

View File

@ -203,11 +203,9 @@ if(SLS_BUILD_DOCS)
add_subdirectory(docs)
endif(SLS_BUILD_DOCS)
if(SLS_MASTER_PROJECT)
# Set install dir CMake packages
set(CMAKE_INSTALL_DIR ${CMAKE_INSTALL_DATADIR}/cmake/sls)
set(CMAKE_INSTALL_DIR "share/cmake/${PROJECT_NAME}")
# Set the list of exported targets
set(PROJECT_LIBRARIES slsSupportLib slsDetectorShared slsReceiverShared)
# Generate and install package config file and version

View File

@ -15,17 +15,20 @@ configure_package_config_file(
write_basic_package_version_file(
"${PROJECT_BINARY_DIR}/${PROJECT_NAME_LOWER}-config-version.cmake"
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion)
COMPATIBILITY SameMajorVersion
)
install(FILES
"${PROJECT_BINARY_DIR}/${PROJECT_NAME_LOWER}-config.cmake"
"${PROJECT_BINARY_DIR}/${PROJECT_NAME_LOWER}-config-version.cmake"
COMPONENT devel
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME_LOWER})
DESTINATION ${CMAKE_INSTALL_DIR}
)
if (PROJECT_LIBRARIES OR PROJECT_STATIC_LIBRARIES)
install(
EXPORT "${TARGETS_EXPORT_NAME}"
FILE ${PROJECT_NAME_LOWER}-targets.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME_LOWER})
DESTINATION ${CMAKE_INSTALL_DIR}
)
endif ()

View File

@ -5,18 +5,20 @@ mkdir $PREFIX/include
mkdir $PREFIX/include/slsDetectorPackage
#Shared and static libraries
cp build/bin/libSlsDetector.so $PREFIX/lib/.
cp build/bin/libSlsReceiver.so $PREFIX/lib/.
cp build/bin/libSlsSupport.so $PREFIX/lib/.
# cp build/bin/libSlsDetector.so $PREFIX/lib/.
# cp build/bin/libSlsReceiver.so $PREFIX/lib/.
# cp build/bin/libSlsSupport.so $PREFIX/lib/.
cp build/install/lib/* $PREFIX/lib/
#Binaries
cp build/bin/sls_detector_acquire $PREFIX/bin/.
cp build/bin/sls_detector_get $PREFIX/bin/.
cp build/bin/sls_detector_put $PREFIX/bin/.
cp build/bin/sls_detector_help $PREFIX/bin/.
cp build/bin/slsReceiver $PREFIX/bin/.
cp build/bin/slsMultiReceiver $PREFIX/bin/.
cp build/install/bin/sls_detector_acquire $PREFIX/bin/.
cp build/install/bin/sls_detector_get $PREFIX/bin/.
cp build/install/bin/sls_detector_put $PREFIX/bin/.
cp build/install/bin/sls_detector_help $PREFIX/bin/.
cp build/install/bin/slsReceiver $PREFIX/bin/.
cp build/install/bin/slsMultiReceiver $PREFIX/bin/.
#Which headers do we need for development??
cp build/install/include/* $PREFIX/include/slsDetectorPackage/
# cp include/some_lib.h $PREFIX/include/.
cp build/install/include/* $PREFIX/include/
cp -r build/install/share/ $PREFIX/share

View File

@ -7,7 +7,7 @@ source:
- path: ..
build:
number: 2
number: 0
binary_relocation: True
rpaths:
- lib/
@ -37,6 +37,7 @@ requirements:
host:
- libstdcxx-ng
- libgcc-ng
- zeromq
- xorg-libx11
- xorg-libice
- xorg-libxext
@ -46,6 +47,7 @@ requirements:
- xorg-libxfixes
run:
- zeromq
- libstdcxx-ng
- libgcc-ng

View File

@ -3,7 +3,7 @@ find_package(Sphinx)
if (DOXYGEN_FOUND AND SPHINX_FOUND)
message(${CMAKE_PROJECT_SORURCE_DIR}/slsDetectorSoftware/src)
# message(${CMAKE_PROJECT_SORURCE_DIR}/slsDetectorSoftware/src)
# Utility to generate command line documentation
add_executable(gendoc src/gendoc.cpp)
# This is a bit hacky, but better than exposing stuff?
@ -30,6 +30,7 @@ if (DOXYGEN_FOUND AND SPHINX_FOUND)
set(SPHINX_SOURCE_FILES
src/commandline.rst
src/container_utils.rst
src/consuming.rst
src/dependencies.rst
src/detector.rst
src/index.rst
@ -41,6 +42,7 @@ if (DOXYGEN_FOUND AND SPHINX_FOUND)
src/result.rst
src/type_traits.rst
src/ToString.rst
src/examples.rst
)

95
docs/src/consuming.rst Normal file
View File

@ -0,0 +1,95 @@
Consuming slsDetectorPackage
===============================
Depending on how you want to build your integration with
slsDetectorPackage there are a few different ways to
consume our package. The recommended way is to use one of the
CMake approaches.
CMake: slsDetectorPackage as submodule in your project
---------------------------------------
If you are using CMake to build your integration and want to build everything
in one go, we support adding slsDetectorPackage as a subfolder in your cmake project.
A minimal CMakeLists.txt could look like this:
.. code-block:: cmake
project(myDetectorIntegration)
cmake_minimum_required(VERSION 3.12)
add_subdirectory(slsDetectorPackage)
#Add your executable
add_executable(example main.cpp)
target_compile_features(example PRIVATE cxx_std_11)
#Link towards slsDetectorShared
target_link_libraries(example slsDetectorShared)
A fully working example can be found at:
https://github.com/slsdetectorgroup/cmake-subfolder-example
CMake: find_package(slsDetectorPackage)
------------------------------------------
If you have compiled and installed slsDetectorPackage we also support
find_package in CMake. If installed in a system wide location no path
should be needed, otherwise specify cmake prefix path.
.. code-block:: cmake
cmake_minimum_required(VERSION 3.12)
project(myintegration)
find_package(slsDetectorPackage 5.0 REQUIRED)
add_executable(example main.cpp)
target_link_libraries(example slsDetectorShared)
Then assuming the slsDetectorPackage is installed in /path/to/sls/install
you should be able to configure and build your project in this way.
.. code-block:: bash
cmake ../path/to/your/source -DCMAKE_PREFIX_PATH=/path/to/sls/install
make
A minimal example is available at: https://github.com/slsdetectorgroup/minimal-cmake
No tools minimal approach
-----------------------------
While not recommended it is still possible to specify the include and library paths
manually when invoking g++. This can sometimes be handy for a quick try.
.. code-block:: cpp
#include "Detector.h"
#include <iostream>
int main(){
sls::Detector det;
//Get all values and print them
std::cout << "Hostname: " << det.getHostname() << "\n";
std::cout << "Type: " << det.getDetectorType() << "\n";
std::cout << "Udp ip: " << det.getSourceUDPIP() << "\n";
//Get mac addr
const int module = 0;
auto mac = det.getSourceUDPMAC()[module];
std::cout << "Mac addr of module "<< module << " is " << mac.str() << '\n';
}
.. code-block:: bash
g++ -I/install/path/include/ -L/install/path/lib64/ myapp.cpp -lSlsDetector -lSlsSupport -Wl,-rpath=../install/path/lib64

View File

@ -13,7 +13,7 @@ To use the basic building blocks, meaning sls_detector_get/put and
the shared libraries these are needed:
* Linux, preferably recent kernel (currently no cross platform support)
* CMake > 3.9
* CMake > 3.12
* C++11 compatible compiler. (We test with gcc and clang)
* ZeroMQ version 4
@ -24,7 +24,7 @@ GUI
The GUI is currently using Qt4 but watch out for an upgrade to 5.
* Qt 4.8
* Qwt 6
* Qwt 6.1
-----------------------
Python bindings

115
docs/src/examples.rst Normal file
View File

@ -0,0 +1,115 @@
Examples
===========
Setup
------------
The examples here assume that you have compiled and installed slsDetectorPackage
to ~/sls/install and that the option for SLS_USE_SIMULATOR was enabled. This also builds
the virtual detector servers that we will be using for testing.
We also add ~/sls/detector/install/bin to the path for convenience.
Compile examples
-------------------
The source code of the examples is available at:
https://github.com/slsdetectorgroup/api-examples
.. code-block:: bash
git clone https://github.com/slsdetectorgroup/api-examples.git
mkdir build && cd build
cmake ../api-examples -DCMAKE_PREFIX_PATH=~/sls/detector/install
make
Below follows a short description of what is included in the examples.
Running a config file [e1]
-----------------------------
.. code-block:: cpp
#include "Detector.h"
...
sls::Detector det;
det.loadConfig("path/to/config/file.config");
To configure the connection between PC and detector the easiest
is to run a config file. For this example we first launch a virtual Jungfrau server and
then set up the detector.
**Launch a virtual detector server**
.. code-block:: bash
jungfrauDetectorServer_virtual
This launches a virtual Jungfrau detector server. As default is uses port 1952 and 1953
for communication over TCP. Most commands go on 1952 and only stop and status on 1953.
**Run example to configure**
.. code-block:: bash
./e1-config one_det_no_receiver.config
- 12:01:06.371 INFO: Shared memory deleted /slsDetectorPackage_multi_0_sls_0
- 12:01:06.371 INFO: Shared memory deleted /slsDetectorPackage_multi_0
- 12:01:06.372 INFO: Shared memory created /slsDetectorPackage_multi_0
- 12:01:06.376 INFO: Loading configuration file: one_det_no_receiver.config
- 12:01:06.376 INFO: Adding detector localhost
- 12:01:06.377 INFO: Shared memory created /slsDetectorPackage_multi_0_sls_0
- 12:01:06.377 INFO: Checking Detector Version Compatibility
- 12:01:06.378 INFO: Detector connecting - updating!
hostname [localhost]
Jungfrau detector with 1 modules configured
Using the return type sls::Result [e2]
-----------------------------------------
Since many our detectors have multiple modules we cannot return
a single value when reading from the Detector. Hostname, Ip and also
for example exposure time can differ between modules.
Therefore we return Result<T> which is a thin wrapper around
std::vector.
.. code-block:: cpp
sls::Result<int> res1{1, 1, 1};
std::cout << "res1: " << res1 << '\n';
res1.squash();
res1.squash(-1);
Setting exposure time [e3]
-----------------------------------------
For setting times, like exposure time, period, delay etc.
we use std::chrono::duration.
Example 3 shows how to set and read exposure time as well
as converting to floating point.
.. code-block:: cpp
#include "Detector.h"
#include <chrono>
...
std::chrono::microseconds t0{500};
det.setExptime(t0);

View File

@ -6,12 +6,18 @@
Welcome to slsDetectorPackage's documentation!
==============================================
.. note ::
This is the documentation for the latest development version of slsDetectorPackage
For documentation on current and previous releases visit the official page: https://www.psi.ch/en/detectors/documentation
.. toctree::
:maxdepth: 1
:caption: Installation:
installation
dependencies
consuming
.. toctree::
:caption: C++ API
@ -20,6 +26,7 @@ Welcome to slsDetectorPackage's documentation!
detector
result
receiver
examples
.. toctree::
:caption: Python API

View File

@ -2,4 +2,24 @@
Installation
==============================================
get the source etc.
Build from source using CMake
---------------------------------
.. note ::
The default branch of our git repository is developer. It contains the
latest development version. It is expected to compile and work but
features might be added or tweaked. In some cases the API might also change
without being communicated. If absolute stability of the API is needed please
use one of the release versions.
.. code-block:: bash
git clone https://github.com/slsdetectorgroup/slsDetectorPackage.git
mkdir build && cd build
cmake ../slsDetectorPackage -DCMAKE_INSTALL_PREFIX=/your/install/path
make -j12
make install

View File

@ -1,9 +1,9 @@
Detector
=====================================================
.. py:currentmodule:: sls_detector
.. py:currentmodule:: slsdet
.. autoclass:: ExperimentalDetector
.. autoclass:: Detector
:members:
:undoc-members:
:show-inheritance:

View File

@ -45,7 +45,7 @@ ext_modules = [
# get_pybind_include(),
# get_pybind_include(user=True),
os.path.join('../libs/pybind11/include'),
os.path.join(get_conda_path(), 'include/slsDetectorPackage'),
os.path.join(get_conda_path(), 'include'),
],
libraries=['SlsDetector', 'SlsReceiver', 'zmq'],

View File

@ -103,10 +103,10 @@ set_target_properties(slsDetectorGui PROPERTIES
)
install(TARGETS slsDetectorGui
EXPORT "${TARGETS_EXPORT_NAME}"
# EXPORT "${TARGETS_EXPORT_NAME}"
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
# LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
# ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
# PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)

View File

@ -1,5 +1,5 @@
#include "SlsQt2DPlot.h"
#include "ansi.h"
// #include "ansi.h"
#include <qlist.h>
#include <qprinter.h>

View File

@ -47,9 +47,10 @@ int injectedChannelsIncrement = 0;
int vetoReference[NCHIP][NCHAN];
uint8_t adcConfiguration[NCHIP][NADC];
int burstMode = BURST_INTERNAL;
int64_t numTriggers = 1;
int64_t numBursts = 1;
int64_t burstPeriodNs = 0;
int64_t numTriggersReg = 1;
int64_t delayReg = 0;
int64_t numBurstsReg = 1;
int64_t burstPeriodReg = 0;
int detPos[2] = {};
int isInitCheckDone() {
@ -354,9 +355,10 @@ void setupDetector() {
injectedChannelsOffset = 0;
injectedChannelsIncrement = 0;
burstMode = BURST_INTERNAL;
numTriggers = 1;
numBursts = 1;
burstPeriodNs = 0;
numTriggersReg = 1;
delayReg = 0;
numBurstsReg = 1;
burstPeriodReg = 0;
{
int i, j;
for (i = 0; i < NUM_CLOCKS; ++i) {
@ -736,32 +738,31 @@ int setDynamicRange(int dr){
/* parameters - timer */
void setNumFrames(int64_t val) {
if (val > 0) {
LOG(logINFO, ("Setting number of frames %lld [local]\n", val));
// continuous mode
if (burstMode == BURST_OFF) {
setNumFramesCont(val);
setNumFramesBurst(1);
LOG(logINFO, ("Setting number of frames %lld [Continuous mode]\n", val));
set64BitReg(val, SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
} else {
setNumFramesBurst(val);
setNumFramesCont(1);
LOG(logINFO, ("Setting number of frames %d [Burst mode]\n", (int)val));
bus_w(ASIC_INT_FRAMES_REG, bus_r(ASIC_INT_FRAMES_REG) &~ ASIC_INT_FRAMES_MSK);
bus_w(ASIC_INT_FRAMES_REG, bus_r(ASIC_INT_FRAMES_REG) | (((int)val << ASIC_INT_FRAMES_OFST) & ASIC_INT_FRAMES_MSK));
}
}
}
int64_t getNumFrames() {
if (burstMode == BURST_OFF) {
return getNumFramesCont();
return get64BitReg(SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
} else {
return getNumFramesBurst();
return ((bus_r(ASIC_INT_FRAMES_REG) & ASIC_INT_FRAMES_MSK) >> ASIC_INT_FRAMES_OFST);
}
}
void setNumTriggers(int64_t val) {
if (val > 0) {
LOG(logINFO, ("Setting number of triggers %lld\n", val));
numTriggers = val;
if (burstMode != BURST_OFF && getTiming() == AUTO_TIMING) {
LOG(logINFO, ("\tBurst and Auto mode: not writing #triggers to register\n"));
if (getTiming() == AUTO_TIMING) {
LOG(logINFO, ("\tNot trigger mode: not writing to register\n"));
numTriggersReg = val;
} else {
set64BitReg(val, SET_CYCLES_LSB_REG, SET_CYCLES_MSB_REG);
}
@ -769,8 +770,8 @@ void setNumTriggers(int64_t val) {
}
int64_t getNumTriggers() {
if (burstMode != BURST_OFF && getTiming() == AUTO_TIMING) {
return numTriggers;
if (getTiming() == AUTO_TIMING) {
return numTriggersReg;
}
return get64BitReg(SET_CYCLES_LSB_REG, SET_CYCLES_MSB_REG);
}
@ -778,20 +779,20 @@ int64_t getNumTriggers() {
void setNumBursts(int64_t val) {
if (val > 0) {
LOG(logINFO, ("Setting number of bursts %lld\n", val));
numBursts = val;
if (burstMode != BURST_OFF && getTiming() == AUTO_TIMING) {
set64BitReg(val, SET_CYCLES_LSB_REG, SET_CYCLES_MSB_REG);
set64BitReg(val, SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
} else {
LOG(logINFO, ("\tNot (Burst and Auto mode): not writing #bursts to register\n"));
LOG(logINFO, ("\tNot (Burst and Auto mode): not writing to register\n"));
numBurstsReg = val;
}
}
}
int64_t getNumBursts() {
if (burstMode != BURST_OFF && getTiming() == AUTO_TIMING) {
return get64BitReg(SET_CYCLES_LSB_REG, SET_CYCLES_MSB_REG);
return get64BitReg(SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
}
return numBursts;
return numBurstsReg;
}
int setExpTime(int64_t val) {
@ -799,17 +800,21 @@ int setExpTime(int64_t val) {
LOG(logERROR, ("Invalid exptime: %lld ns\n", val));
return FAIL;
}
LOG(logINFO, ("Setting exptime %lld ns [local]\n", val));
// continuous mode
if (burstMode == BURST_OFF) {
return setExptimeCont(val);
} else {
return setExptimeBurst(val);
}
LOG(logINFO, ("Setting exptime %lld ns\n", val));
val *= (1E-9 * systemFrequency);
set64BitReg(val, ASIC_INT_EXPTIME_LSB_REG, ASIC_INT_EXPTIME_MSB_REG);
// validate for tolerance
int64_t retval = getExpTime();
val /= (1E-9 * systemFrequency);
if (val != retval) {
return FAIL;
}
return OK;
}
int64_t getExpTime() {
return getExptimeBoth();
return get64BitReg(ASIC_INT_EXPTIME_LSB_REG, ASIC_INT_EXPTIME_MSB_REG) / (1E-9 * systemFrequency);
}
int setPeriod(int64_t val) {
@ -817,110 +822,31 @@ int setPeriod(int64_t val) {
LOG(logERROR, ("Invalid period: %lld ns\n", val));
return FAIL;
}
LOG(logINFO, ("Setting period %lld ns [local]\n", val));
// continuous mode
val *= (1E-9 * systemFrequency);
if (burstMode == BURST_OFF) {
setPeriodBurst(0);
return setPeriodCont(val);
LOG(logINFO, ("Setting period %lld ns [Continuous mode]\n", val));
set64BitReg(val, SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
} else {
//setPeriodCont(0);
return setPeriodBurst(val);
LOG(logINFO, ("Setting period %lld ns [Burst mode]\n", val));
set64BitReg(val, ASIC_INT_PERIOD_LSB_REG, ASIC_INT_PERIOD_MSB_REG);
}
// validate for tolerance
int64_t retval = getPeriod();
val /= (1E-9 * systemFrequency);
if (val != retval) {
return FAIL;
}
return OK;
}
int64_t getPeriod() {
if (burstMode == BURST_OFF) {
return getPeriodCont();
return get64BitReg(SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG)/ (1E-9 * systemFrequency);
} else {
return getPeriodBurst();
return get64BitReg(ASIC_INT_PERIOD_LSB_REG, ASIC_INT_PERIOD_MSB_REG)/ (1E-9 * systemFrequency);
}
}
void setNumFramesBurst(int64_t val) {
LOG(logINFO, ("Setting number of frames %d [Burst mode]\n", (int)val));
bus_w(ASIC_INT_FRAMES_REG, bus_r(ASIC_INT_FRAMES_REG) &~ ASIC_INT_FRAMES_MSK);
bus_w(ASIC_INT_FRAMES_REG, bus_r(ASIC_INT_FRAMES_REG) | (((int)val << ASIC_INT_FRAMES_OFST) & ASIC_INT_FRAMES_MSK));
}
int64_t getNumFramesBurst() {
return ((bus_r(ASIC_INT_FRAMES_REG) & ASIC_INT_FRAMES_MSK) >> ASIC_INT_FRAMES_OFST);
}
void setNumFramesCont(int64_t val) {
LOG(logINFO, ("Setting number of frames %lld [Continuous mode]\n", val));
set64BitReg(val, SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
}
int64_t getNumFramesCont() {
return get64BitReg(SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
}
int setExptimeBurst(int64_t val) {
LOG(logINFO, ("Setting exptime %lld ns [Burst mode]\n", val));
return setExptimeBoth(val);
}
int setExptimeCont(int64_t val) {
LOG(logINFO, ("Setting exptime %lld ns [Continuous mode]\n", val));
return setExptimeBoth(val);
}
int setExptimeBoth(int64_t val) {
val *= (1E-9 * systemFrequency);
set64BitReg(val, ASIC_INT_EXPTIME_LSB_REG, ASIC_INT_EXPTIME_MSB_REG);
// validate for tolerance
int64_t retval = getExptimeBoth();
val /= (1E-9 * systemFrequency);
if (val != retval) {
return FAIL;
}
return OK;
}
int64_t getExptimeBoth() {
return get64BitReg(ASIC_INT_EXPTIME_LSB_REG, ASIC_INT_EXPTIME_MSB_REG) / (1E-9 * systemFrequency);
}
int setPeriodBurst(int64_t val) {
LOG(logINFO, ("Setting period %lld ns [Burst mode]\n", val));
val *= (1E-9 * systemFrequency);
set64BitReg(val, ASIC_INT_PERIOD_LSB_REG, ASIC_INT_PERIOD_MSB_REG);
// validate for tolerance
int64_t retval = getPeriodBurst();
val /= (1E-9 * systemFrequency);
if (val != retval) {
return FAIL;
}
return OK;
}
int64_t getPeriodBurst() {
LOG(logDEBUG, ("Getting period [Burst mode]\n"));
return get64BitReg(ASIC_INT_PERIOD_LSB_REG, ASIC_INT_PERIOD_MSB_REG)/ (1E-9 * systemFrequency);
}
int setPeriodCont(int64_t val) {
LOG(logINFO, ("Setting period %lld ns [Continuous mode]\n", val));
val *= (1E-9 * systemFrequency);
set64BitReg(val, SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
// validate for tolerance
int64_t retval = getPeriodCont();
val /= (1E-9 * systemFrequency);
if (val != retval) {
return FAIL;
}
return OK;
}
int64_t getPeriodCont() {
LOG(logDEBUG, ("Getting period [Continuous mode]\n"));
return get64BitReg(SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG)/ (1E-9 * systemFrequency);
}
int setDelayAfterTrigger(int64_t val) {
if (val < 0) {
LOG(logERROR, ("Invalid delay after trigger: %lld ns\n", val));
@ -928,8 +854,12 @@ int setDelayAfterTrigger(int64_t val) {
}
LOG(logINFO, ("Setting delay after trigger %lld ns\n", val));
val *= (1E-9 * systemFrequency);
set64BitReg(val, SET_TRIGGER_DELAY_LSB_REG, SET_TRIGGER_DELAY_MSB_REG);
if (getTiming() == AUTO_TIMING) {
LOG(logINFO, ("\tNot trigger mode: not writing to register\n"));
delayReg = val;
} else {
set64BitReg(val, SET_TRIGGER_DELAY_LSB_REG, SET_TRIGGER_DELAY_MSB_REG);
}
// validate for tolerance
int64_t retval = getDelayAfterTrigger();
val /= (1E-9 * systemFrequency);
@ -940,6 +870,9 @@ int setDelayAfterTrigger(int64_t val) {
}
int64_t getDelayAfterTrigger() {
if (getTiming() == AUTO_TIMING) {
return delayReg / (1E-9 * systemFrequency);
}
return get64BitReg(SET_TRIGGER_DELAY_LSB_REG, SET_TRIGGER_DELAY_MSB_REG) / (1E-9 * systemFrequency);
}
@ -949,12 +882,12 @@ int setBurstPeriod(int64_t val) {
return FAIL;
}
LOG(logINFO, ("Setting burst period %lld ns\n", val));
burstPeriodNs = val;
val *= (1E-9 * systemFrequency);
if (burstMode != BURST_OFF) {
if (burstMode != BURST_OFF && getTiming() == AUTO_TIMING) {
set64BitReg(val, SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
} else {
LOG(logINFO, ("\t(Continuous mode): not writing burst period to register\n"));
LOG(logINFO, ("\tNot (Burst and Auto mode): not writing to register\n"));
burstPeriodReg = val;
}
// validate for tolerance
@ -967,10 +900,10 @@ int setBurstPeriod(int64_t val) {
}
int64_t getBurstPeriod() {
if (burstMode != BURST_OFF) {
if (burstMode != BURST_OFF && getTiming() == AUTO_TIMING) {
return get64BitReg(SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG) / (1E-9 * systemFrequency);
}
return burstPeriodNs;
return burstPeriodReg / (1E-9 * systemFrequency);
}
int64_t getNumFramesLeft() {
@ -1185,6 +1118,18 @@ int setHighVoltage(int val){
/* parameters - timing */
void setTiming( enum timingMode arg){
// update
// trigger
if (getTiming() == TRIGGER_EXPOSURE) {
numTriggersReg = get64BitReg(SET_CYCLES_LSB_REG, SET_CYCLES_MSB_REG);
delayReg = get64BitReg(SET_TRIGGER_DELAY_LSB_REG, SET_TRIGGER_DELAY_MSB_REG);
}
// auto and burst
else if (burstMode != BURST_OFF) {
numBurstsReg = get64BitReg(SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
burstPeriodReg = get64BitReg(SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
}
switch(arg){
case AUTO_TIMING:
LOG(logINFO, ("Set Timing: Auto\n"));
@ -1198,9 +1143,32 @@ void setTiming( enum timingMode arg){
LOG(logERROR, ("Unknown timing mode %d\n", arg));
}
LOG(logINFO, ("\tUpdating trigger/burst and delay/burst period registers\n"))
setNumTriggers(numTriggers);
setNumBursts(numBursts);
LOG(logINFO, ("\tUpdating registers\n"))
// trigger
if (getTiming() == TRIGGER_EXPOSURE) {
set64BitReg(numTriggersReg, SET_CYCLES_LSB_REG, SET_CYCLES_MSB_REG);
set64BitReg(delayReg, SET_TRIGGER_DELAY_LSB_REG, SET_TRIGGER_DELAY_MSB_REG);
LOG(logINFO, ("\tTriggers reg: %lld, Delay reg: %lldns\n", getNumTriggers(), getDelayAfterTrigger()));
// burst
if (burstMode != BURST_OFF) {
LOG(logINFO, ("\tFrame reg: 1, Period reg: 0\n"))
set64BitReg(1, SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
set64BitReg(0, SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
}
}
// auto
else {
LOG(logINFO, ("\tTrigger reg: 1, Delay reg: 0\n"))
set64BitReg(1, SET_CYCLES_LSB_REG, SET_CYCLES_MSB_REG);
set64BitReg(0, SET_TRIGGER_DELAY_LSB_REG, SET_TRIGGER_DELAY_MSB_REG);
// burst
if (burstMode != BURST_OFF) {
set64BitReg(numBurstsReg, SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
set64BitReg(burstPeriodReg, SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
LOG(logINFO, ("\tFrames reg (bursts): %lld, Period reg(burst period): %lldns\n", getNumBursts(), getBurstPeriod()));
}
}
LOG(logINFO, ("\tDone Updating registers\n"))
}
enum timingMode getTiming() {
@ -1875,23 +1843,62 @@ int setBurstModeinFPGA(enum burstMode value) {
int setBurstMode(enum burstMode burst) {
LOG(logINFO, ("Setting burst mode to %s\n", burst == BURST_OFF ? "off" : (burst == BURST_INTERNAL ? "internal" : "external")));
// remember the number of frames and period (before changing burst mode)
int64_t frames = getNumFrames();
int64_t period = getPeriod();
// update
int64_t framesReg = 0;
int64_t periodReg = 0;
// burst
if (burstMode != BURST_OFF) {
framesReg = ((bus_r(ASIC_INT_FRAMES_REG) & ASIC_INT_FRAMES_MSK) >> ASIC_INT_FRAMES_OFST);
periodReg = get64BitReg(ASIC_INT_PERIOD_LSB_REG, ASIC_INT_PERIOD_MSB_REG);
// auto
if (getTiming() == AUTO_TIMING) {
numBurstsReg = get64BitReg(SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
burstPeriodReg = get64BitReg(SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
}
}
// continuous
else {
framesReg = get64BitReg(SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
periodReg = get64BitReg(SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
}
if (setBurstModeinFPGA(burst) == FAIL) {
return FAIL;
}
LOG(logINFO, ("\tUpdating trigger/burst and burst period registers\n"))
setNumTriggers(numTriggers);
setNumBursts(numBursts);
setBurstPeriod(burstPeriodNs);
LOG(logINFO, ("\tUpdating registers\n"));
// continuous
if (burstMode == BURST_OFF) {
set64BitReg(framesReg, SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
set64BitReg(periodReg, SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
LOG(logINFO, ("\tFrames reg: %lld, Period reg: %lldns\n", getNumFrames(), getPeriod()));
// set number of frames and period again (set registers according to timing mode)
LOG(logINFO, ("\tUpdating #frames and period registers\n"));
setNumFrames(frames);
setPeriod(period);
LOG(logINFO, ("\tInt. Frame reg: 1, Int. Period reg: 0\n"))
bus_w(ASIC_INT_FRAMES_REG, bus_r(ASIC_INT_FRAMES_REG) &~ ASIC_INT_FRAMES_MSK);
bus_w(ASIC_INT_FRAMES_REG, bus_r(ASIC_INT_FRAMES_REG) | ((1 << ASIC_INT_FRAMES_OFST) & ASIC_INT_FRAMES_MSK));
set64BitReg(0, ASIC_INT_PERIOD_LSB_REG, ASIC_INT_PERIOD_MSB_REG);
}
// burst
else {
bus_w(ASIC_INT_FRAMES_REG, bus_r(ASIC_INT_FRAMES_REG) &~ ASIC_INT_FRAMES_MSK);
bus_w(ASIC_INT_FRAMES_REG, bus_r(ASIC_INT_FRAMES_REG) | (((int)framesReg << ASIC_INT_FRAMES_OFST) & ASIC_INT_FRAMES_MSK));
set64BitReg(periodReg, ASIC_INT_PERIOD_LSB_REG, ASIC_INT_PERIOD_MSB_REG);
LOG(logINFO, ("\tInt. Frames reg: %lld, Int. Period reg: %lldns\n", getNumFrames(), getPeriod()));
// trigger
if (getTiming() == TRIGGER_EXPOSURE) {
LOG(logINFO, ("\tFrame reg: 1, Period reg: 0\n"))
set64BitReg(1, SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
set64BitReg(0, SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
}
//auto
else {
set64BitReg(numBurstsReg, SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
set64BitReg(burstPeriodReg, SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
LOG(logINFO, ("\tFrames reg (bursts): %lld, Period reg(burst period): %lldns\n", getNumBursts(), getBurstPeriod()));
}
}
LOG(logINFO, ("\tDone Updating registers\n"))
LOG(logINFO, ("\tSetting %s Mode in Chip\n", burstMode == BURST_OFF ? "Continuous" : "Burst"));
int value = burstMode ? ASIC_GLOBAL_BURST_VALUE : ASIC_GLOBAL_CONT_VALUE;

View File

@ -14,15 +14,12 @@ add_executable(jungfrauDetectorServer_virtual
../slsDetectorServer/src/communication_funcs_UDP.c
)
include_directories(
target_include_directories(jungfrauDetectorServer_virtual
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
../slsDetectorServer/include
../../slsSupportLib/include
)
target_include_directories(jungfrauDetectorServer_virtual
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
)
target_compile_definitions(jungfrauDetectorServer_virtual
PUBLIC JUNGFRAUD VIRTUAL STOP_SERVER
)
@ -36,5 +33,6 @@ set_target_properties(jungfrauDetectorServer_virtual PROPERTIES
)
install(TARGETS jungfrauDetectorServer_virtual
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
EXPORT "${TARGETS_EXPORT_NAME}"
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

View File

@ -202,19 +202,6 @@ void setNumBursts(int64_t val);
int64_t getNumBursts();
int setBurstPeriod(int64_t val);
int64_t getBurstPeriod();
void setNumFramesBurst(int64_t val);
int64_t getNumFramesBurst();
void setNumFramesCont(int64_t val);
int64_t getNumFramesCont();
int setExptimeBurst(int64_t val);
int setExptimeCont(int64_t val);
int setExptimeBoth(int64_t val);
int64_t getExptimeBoth();
int setPeriodBurst(int64_t val);
int64_t getPeriodBurst();
int setPeriodCont(int64_t val);
int64_t getPeriodCont();
#endif
#ifdef EIGERD
int setSubExpTime(int64_t val);

View File

@ -15,7 +15,6 @@ add_library(slsDetectorShared SHARED
${HEADERS}
)
# Do we have link time optimization?
check_ipo_supported(RESULT LTO_AVAILABLE)
if(LTO_AVAILABLE)
@ -28,15 +27,18 @@ target_include_directories(slsDetectorShared PUBLIC
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
)
target_link_libraries(slsDetectorShared PUBLIC
slsProjectOptions
slsProjectWarnings
target_link_libraries(slsDetectorShared
PUBLIC
slsSupportLib
${ZeroMQ_LIBRARIES}
pthread
rt
slsProjectOptions
PRIVATE
slsProjectWarnings
${ZeroMQ_LIBRARIES}
)
set(PUBLICHEADERS
include/slsDetectorUsers.h
include/detectorData.h
@ -69,7 +71,7 @@ foreach(val RANGE ${len2})
target_link_libraries(${val1}
slsDetectorShared
pthread
${ZeroMQ_LIBRARIES}
zmq
rt
)
set_target_properties(${val1} PROPERTIES

View File

@ -1,15 +1,17 @@
#pragma once
#include "Result.h"
#include "network_utils.h"
#include "sls_detector_defs.h"
#include <chrono>
#include <memory>
#include <vector>
class DetectorImpl;
class detectorData;
namespace sls {
using ns = std::chrono::nanoseconds;
class DetectorImpl;
class MacAddr;
class IpAddr;

View File

@ -1782,7 +1782,7 @@ std::string CmdProxy::MinMaxEnergyThreshold(int action) {
os << "[n_value]\n\t[Moench] Minimum energy threshold (soft "
"setting) for processor."
<< '\n';
} else if (cmd == "emin") {
} else if (cmd == "emax") {
os << "[n_value]\n\t[Moench] Maximum energy threshold (soft "
"setting) for processor."
<< '\n';

View File

@ -7,6 +7,7 @@
#include "DetectorImpl.h"
#include "Module.h"
#include "sls_detector_defs.h"
#include "versionAPI.h"
#include <fstream>
@ -97,11 +98,11 @@ void Detector::setVirtualDetectorServers(int numServers, int startingPort) {
int Detector::getShmId() const { return pimpl->getMultiId(); }
std::string Detector::getPackageVersion() const {
return pimpl->getPackageVersion();
return GITBRANCH;
}
int64_t Detector::getClientVersion() const {
return pimpl->getClientSoftwareVersion();
return APILIB;
}
Result<int64_t> Detector::getFirmwareVersion(Positions pos) const {

View File

@ -26,7 +26,7 @@
#include <future>
#include <vector>
using namespace sls;
namespace sls{
DetectorImpl::DetectorImpl(int multi_id, bool verify, bool update)
: multiId(multi_id), multi_shm(multi_id, -1) {
@ -49,10 +49,6 @@ void DetectorImpl::setAcquiringFlag(bool flag) {
int DetectorImpl::getMultiId() const { return multiId; }
std::string DetectorImpl::getPackageVersion() const { return GITBRANCH; }
int64_t DetectorImpl::getClientSoftwareVersion() const { return APILIB; }
void DetectorImpl::freeSharedMemory(int multiId, int detPos) {
// single
if (detPos >= 0) {
@ -160,7 +156,6 @@ void DetectorImpl::initializeDetectorStructure() {
multi_shm()->numberOfChannels.x = 0;
multi_shm()->numberOfChannels.y = 0;
multi_shm()->acquiringFlag = false;
multi_shm()->receiver_upstream = false;
multi_shm()->initialChecks = true;
}
@ -822,46 +817,6 @@ bool DetectorImpl::enableDataStreamingToClient(int enable) {
return client_downstream;
}
void DetectorImpl::savePattern(const std::string &fname) {
// std::ofstream outfile;
// outfile.open(fname.c_str(), std::ios_base::out);
// if (!outfile.is_open()) {
// throw RuntimeError("Could not create file to save pattern");
// }
// // get pattern limits
// auto r = Parallel(&Module::setPatternLoopAddresses, {}, -1, -1, -1)
// .tsquash("Inconsistent pattern limits");
// // pattern words
// for (int i = r[0]; i <= r[1]; ++i) {
// std::ostringstream os;
// os << "patword 0x" << std::hex << i;
// std::string cmd = os.str();
// multiSlsDetectorClient(cmd, GET_ACTION, this, outfile);
// }
// // rest of pattern file
// const std::vector<std::string> commands{
// "patioctrl",
// "patclkctrl",
// "patlimits",
// "patloop0",
// "patnloop0",
// "patloop1",
// "patnloop1",
// "patloop2",
// "patnloop2",
// "patwait0",
// "patwaittime0",
// "patwait1",
// "patwaittime1",
// "patwait2",
// "patwaittime2",
// "patmask",
// "patsetbit",
// };
// for (const auto &cmd : commands)
// multiSlsDetectorClient(cmd, GET_ACTION, this, outfile);
}
void DetectorImpl::registerAcquisitionFinishedCallback(void (*func)(double, int,
void *),
void *pArg) {
@ -1199,3 +1154,5 @@ std::vector<char> DetectorImpl::readProgrammingFile(const std::string &fname) {
LOG(logINFO) << "Read file into memory";
return buffer;
}
}//namespace sls

View File

@ -5,10 +5,6 @@
#include "logger.h"
#include "sls_detector_defs.h"
namespace sls{
class Module;
}
class ZmqSocket;
class detectorData;
@ -25,6 +21,11 @@ class detectorData;
#include <future>
#include <numeric>
namespace sls{
class Module;
/**
* @short structure allocated in shared memory to store detector settings
* for IPC and cache
@ -64,9 +65,6 @@ struct sharedMultiSlsDetector {
/** flag for acquiring */
bool acquiringFlag;
/** data streaming (up stream) enable in receiver */
bool receiver_upstream;
/** initial checks */
bool initialChecks;
};
@ -202,10 +200,6 @@ class DetectorImpl : public virtual slsDetectorDefs {
/** return multi detector shared memory ID */
int getMultiId() const;
std::string getPackageVersion() const;
int64_t getClientSoftwareVersion() const;
/** Free specific shared memory from the command line without creating object */
static void freeSharedMemory(int multiId, int detPos = -1);
@ -255,8 +249,6 @@ class DetectorImpl : public virtual slsDetectorDefs {
*/
bool enableDataStreamingToClient(int enable = -1);
void savePattern(const std::string &fname);
/**
* register callback for accessing acquisition final data
* @param func function to be called at the end of the acquisition.
@ -393,14 +385,6 @@ class DetectorImpl : public virtual slsDetectorDefs {
*/
int kbhit();
/**
* Convert a double holding time in seconds to an int64_t with nano seconds
* Used for conversion when sending time to detector
* @param t time in seconds
* @returns time in nano seconds
*/
int64_t secondsToNanoSeconds(double t);
/** Multi detector Id */
const int multiId{0};
@ -448,3 +432,5 @@ class DetectorImpl : public virtual slsDetectorDefs {
void (*dataReady)(detectorData *, uint64_t, uint32_t, void *){nullptr};
void *pCallbackArg{nullptr};
};
}//namespace sls

View File

@ -164,6 +164,29 @@ void Module::sendToDetector(int fnum) {
sendToDetector(fnum, nullptr, 0, nullptr, 0);
}
template <typename Ret>
Ret Module::sendToDetector(int fnum){
LOG(logDEBUG1) << "Sending: ["
<< getFunctionNameFromEnum(static_cast<slsDetectorDefs::detFuncs>(fnum))
<< ", nullptr, 0, " << typeid(Ret).name() << ", " << sizeof(Ret) << "]";
Ret retval{};
sendToDetector(fnum, nullptr, 0, &retval, sizeof(retval));
LOG(logDEBUG1) << "Got back: " << retval;
return retval;
}
template <typename Ret, typename Arg>
Ret Module::sendToDetector(int fnum, const Arg &args){
LOG(logDEBUG1) << "Sending: ["
<< getFunctionNameFromEnum(static_cast<slsDetectorDefs::detFuncs>(fnum))
<< ", " << args << ", " << sizeof(args) << ", " << typeid(Ret).name() << ", " << sizeof(Ret) << "]";
Ret retval{};
sendToDetector(fnum, &args, sizeof(args), &retval, sizeof(retval));
LOG(logDEBUG1) << "Got back: " << retval;
return retval;
}
void Module::sendToDetectorStop(int fnum, const void *args,
size_t args_size, void *retval,
size_t retval_size) {
@ -265,14 +288,58 @@ void Module::sendToReceiver(int fnum, std::nullptr_t, Ret &retval) const {
sendToReceiver(fnum, nullptr, 0, &retval, sizeof(retval));
}
void Module::sendToReceiver(int fnum) {
sendToReceiver(fnum, nullptr, 0, nullptr, 0);
template <typename Ret>
Ret Module::sendToReceiver(int fnum){
LOG(logDEBUG1) << "Sending: ["
<< getFunctionNameFromEnum(static_cast<slsDetectorDefs::detFuncs>(fnum))
<< ", nullptr, 0, " << typeid(Ret).name() << ", " << sizeof(Ret) << "]";
Ret retval{};
sendToReceiver(fnum, nullptr, 0, &retval, sizeof(retval));
LOG(logDEBUG1) << "Got back: " << retval;
return retval;
}
void Module::sendToReceiver(int fnum) const {
sendToReceiver(fnum, nullptr, 0, nullptr, 0);
template <typename Ret>
Ret Module::sendToReceiver(int fnum) const{
LOG(logDEBUG1) << "Sending: ["
<< getFunctionNameFromEnum(static_cast<slsDetectorDefs::detFuncs>(fnum))
<< ", nullptr, 0, " << typeid(Ret).name() << ", " << sizeof(Ret) << "]";
Ret retval{};
sendToReceiver(fnum, nullptr, 0, &retval, sizeof(retval));
LOG(logDEBUG1) << "Got back: " << retval;
return retval;
}
template <typename Ret, typename Arg>
Ret Module::sendToReceiver(int fnum, const Arg &args){
LOG(logDEBUG1) << "Sending: ["
<< getFunctionNameFromEnum(static_cast<slsDetectorDefs::detFuncs>(fnum))
<< ", " << args << ", " << sizeof(args) << ", " << typeid(Ret).name() << ", " << sizeof(Ret) << "]";
Ret retval{};
sendToReceiver(fnum, &args, sizeof(args), &retval, sizeof(retval));
LOG(logDEBUG1) << "Got back: " << retval;
return retval;
}
template <typename Ret, typename Arg>
Ret Module::sendToReceiver(int fnum, const Arg &args) const{
LOG(logDEBUG1) << "Sending: ["
<< getFunctionNameFromEnum(static_cast<slsDetectorDefs::detFuncs>(fnum))
<< ", " << args << ", " << sizeof(args) << ", " << typeid(Ret).name() << ", " << sizeof(Ret) << "]";
Ret retval{};
sendToReceiver(fnum, &args, sizeof(args), &retval, sizeof(retval));
LOG(logDEBUG1) << "Got back: " << retval;
return retval;
}
// void Module::sendToReceiver(int fnum) {
// sendToReceiver(fnum, nullptr, 0, nullptr, 0);
// }
// void Module::sendToReceiver(int fnum) const {
// sendToReceiver(fnum, nullptr, 0, nullptr, 0);
// }
void Module::freeSharedMemory() {
if (shm.IsExisting()) {
shm.RemoveSharedMemory();
@ -1277,10 +1344,7 @@ void Module::setNumberOfDigitalSamples(int value) {
}
int64_t Module::getExptime() {
int64_t retval = -1;
sendToDetector(F_GET_EXPTIME, nullptr, retval);
LOG(logDEBUG1) << "exptime :" << retval << "ns";
return retval;
return sendToDetector<int64_t>(F_GET_EXPTIME);
}
void Module::setExptime(int64_t value) {
@ -1303,10 +1367,7 @@ void Module::setExptime(int64_t value) {
}
int64_t Module::getPeriod() {
int64_t retval = -1;
sendToDetector(F_GET_PERIOD, nullptr, retval);
LOG(logDEBUG1) << "period :" << retval << "ns";
return retval;
return sendToDetector<int64_t>(F_GET_PERIOD);
}
void Module::setPeriod(int64_t value) {
@ -1319,10 +1380,7 @@ void Module::setPeriod(int64_t value) {
}
int64_t Module::getDelayAfterTrigger() {
int64_t retval = -1;
sendToDetector(F_GET_DELAY_AFTER_TRIGGER, nullptr, retval);
LOG(logDEBUG1) << "delay after trigger :" << retval << "ns";
return retval;
return sendToDetector<int64_t>(F_GET_DELAY_AFTER_TRIGGER);
}
void Module::setDelayAfterTrigger(int64_t value) {
@ -1331,10 +1389,7 @@ void Module::setDelayAfterTrigger(int64_t value) {
}
int64_t Module::getBurstPeriod() {
int64_t retval = -1;
sendToDetector(F_GET_BURST_PERIOD, nullptr, retval);
LOG(logDEBUG1) << "burst period :" << retval << "ns";
return retval;
return sendToDetector<int64_t>(F_GET_BURST_PERIOD);
}
void Module::setBurstPeriod(int64_t value) {
@ -1343,10 +1398,7 @@ void Module::setBurstPeriod(int64_t value) {
}
int64_t Module::getSubExptime() {
int64_t retval = -1;
sendToDetector(F_GET_SUB_EXPTIME, nullptr, retval);
LOG(logDEBUG1) << "sub exptime :" << retval << "ns";
return retval;
return sendToDetector<int64_t>(F_GET_SUB_EXPTIME);
}
void Module::setSubExptime(int64_t value) {
@ -1369,10 +1421,7 @@ void Module::setSubExptime(int64_t value) {
}
int64_t Module::getSubDeadTime() {
int64_t retval = -1;
sendToDetector(F_GET_SUB_DEADTIME, nullptr, retval);
LOG(logDEBUG1) << "sub deadtime :" << retval << "ns";
return retval;
return sendToDetector<int64_t>(F_GET_SUB_DEADTIME);
}
void Module::setSubDeadTime(int64_t value) {
@ -1623,31 +1672,17 @@ void Module::setInterruptSubframe(const bool enable) {
}
bool Module::getInterruptSubframe() {
int retval = -1;
LOG(logDEBUG1) << "Getting Interrupt subframe";
sendToDetector(F_GET_INTERRUPT_SUBFRAME, nullptr, retval);
LOG(logDEBUG1) << "Interrupt subframe: " << retval;
auto retval = sendToDetector<int>(F_GET_INTERRUPT_SUBFRAME);
return static_cast<bool>(retval);
}
uint32_t Module::writeRegister(uint32_t addr, uint32_t val) {
uint32_t args[]{addr, val};
uint32_t retval = -1;
LOG(logDEBUG1) << "Writing to reg 0x" << std::hex << addr << "data: 0x"
<< std::hex << val << std::dec;
sendToDetector(F_WRITE_REGISTER, args, retval);
LOG(logDEBUG1) << "Reg 0x" << std::hex << addr << ": 0x" << std::hex
<< retval << std::dec;
return retval;
return sendToDetector<uint32_t>(F_WRITE_REGISTER, args);
}
uint32_t Module::readRegister(uint32_t addr) {
uint32_t retval = -1;
LOG(logDEBUG1) << "Reading reg 0x" << std::hex << addr << std::dec;
sendToDetector(F_READ_REGISTER, addr, retval);
LOG(logDEBUG1) << "Reg 0x" << std::hex << addr << ": 0x" << std::hex
<< retval << std::dec;
return retval;
return sendToDetector<uint32_t>(F_READ_REGISTER, addr);
}
uint32_t Module::setBit(uint32_t addr, int n) {
@ -2032,12 +2067,8 @@ void Module::setClientStreamingPort(int port) { shm()->zmqport = port; }
int Module::getClientStreamingPort() { return shm()->zmqport; }
void Module::setReceiverStreamingPort(int port) {
int fnum = F_SET_RECEIVER_STREAMING_PORT;
int retval = -1;
LOG(logDEBUG1) << "Sending receiver streaming port to receiver: "
<< port;
if (shm()->useReceiverFlag) {
sendToReceiver(fnum, port, retval);
auto retval = sendToReceiver<int>(F_SET_RECEIVER_STREAMING_PORT, port);
LOG(logDEBUG1) << "Receiver streaming port: " << retval;
shm()->rxZmqport = retval;
} else {
@ -2278,14 +2309,7 @@ int64_t Module::getReceiverUDPSocketBufferSize() {
}
int64_t Module::getReceiverRealUDPSocketBufferSize() const {
int64_t retval = -1;
LOG(logDEBUG1) << "Getting real UDP Socket Buffer size from receiver";
if (shm()->useReceiverFlag) {
sendToReceiver(F_RECEIVER_REAL_UDP_SOCK_BUF_SIZE, nullptr, retval);
LOG(logDEBUG1)
<< "Real Receiver UDP Socket Buffer size: " << retval;
}
return retval;
return sendToReceiver<int64_t>(F_RECEIVER_REAL_UDP_SOCK_BUF_SIZE);
}
void Module::executeFirmwareTest() {
@ -3136,7 +3160,7 @@ sls::IpAddr Module::getReceiverLastClientIP() const {
void Module::exitReceiver() {
LOG(logDEBUG1) << "Sending exit command to receiver server";
if (shm()->useReceiverFlag) {
sendToReceiver(F_EXIT_RECEIVER);
sendToReceiver(F_EXIT_RECEIVER, nullptr, nullptr);
}
}
@ -3431,7 +3455,7 @@ int64_t Module::incrementFileIndex() {
void Module::startReceiver() {
LOG(logDEBUG1) << "Starting Receiver";
if (shm()->useReceiverFlag) {
sendToReceiver(F_START_RECEIVER);
sendToReceiver(F_START_RECEIVER, nullptr, nullptr);
}
}
@ -3635,7 +3659,7 @@ bool Module::setReceiverSilentMode(int value) {
void Module::restreamStopFromReceiver() {
LOG(logDEBUG1) << "Restream stop dummy from Receiver via zmq";
if (shm()->useReceiverFlag) {
sendToReceiver(F_RESTREAM_STOP_FROM_RECEIVER);
sendToReceiver(F_RESTREAM_STOP_FROM_RECEIVER, nullptr, nullptr);
}
}

View File

@ -1915,6 +1915,12 @@ class Module : public virtual slsDetectorDefs {
void sendToDetector(int fnum, std::nullptr_t, Ret &retval);
void sendToDetector(int fnum);
template <typename Ret>
Ret sendToDetector(int fnum);
template <typename Ret, typename Arg>
Ret sendToDetector(int fnum, const Arg &args);
/**
* Send function parameters to detector (stop server)
* @param fnum function enum
@ -1983,9 +1989,17 @@ class Module : public virtual slsDetectorDefs {
template <typename Ret>
void sendToReceiver(int fnum, std::nullptr_t, Ret &retval) const;
void sendToReceiver(int fnum);
template <typename Ret>
Ret sendToReceiver(int fnum);
void sendToReceiver(int fnum) const;
template <typename Ret>
Ret sendToReceiver(int fnum) const;
template <typename Ret, typename Arg>
Ret sendToReceiver(int fnum, const Arg &args);
template <typename Ret, typename Arg>
Ret sendToReceiver(int fnum, const Arg &args) const;
/**
* Get Detector Type from Shared Memory (opening shm without verifying size)

View File

@ -8,7 +8,6 @@
*@short functions basic implemenation of shared memory
*/
#include "ansi.h"
#include "logger.h"
#include "sls_detector_exceptions.h"
@ -18,7 +17,7 @@
#include <fcntl.h> // O_CREAT, O_TRUNC..
#include <iostream>
#include <sstream>
#include <stdio.h> // printf
// #include <stdio.h> // printf
#include <sys/mman.h> // shared memory
#include <sys/stat.h> // fstat
#include <unistd.h>

View File

@ -9,7 +9,6 @@
*/
#include "ansi.h"
#include "logger.h"
#include <string>

View File

@ -15,6 +15,7 @@
#include <fstream>
#include <iostream>
#include <sys/stat.h> // stat
#include <unistd.h>
/** cosntructor & destructor */

View File

@ -6,6 +6,7 @@ set(SOURCES
src/ServerSocket.cpp
src/ServerInterface.cpp
src/network_utils.cpp
src/ZmqSocket.cpp
)
set(HEADERS
@ -20,7 +21,6 @@ set(PUBLICHEADERS
include/file_utils.h
include/container_utils.h
include/string_utils.h
include/genericSocket.h
include/logger.h
include/ClientSocket.h
include/DataSocket.h
@ -44,22 +44,36 @@ if(result)
endif()
target_include_directories(slsSupportLib PUBLIC
${ZeroMQ_INCLUDE_DIRS}
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
)
target_include_directories(slsSupportLib PRIVATE
${ZeroMQ_INCLUDE_DIRS}
)
set_target_properties(slsSupportLib PROPERTIES
LIBRARY_OUTPUT_NAME SlsSupport
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
PUBLIC_HEADER "${PUBLICHEADERS}"
)
message(${ZeroMQ_LIBRARIES})
target_link_libraries(slsSupportLib
PUBLIC
slsProjectOptions
# ${ZeroMQ_LIBRARIES}
zmq
PRIVATE
slsProjectWarnings
${ZeroMQ_LIBRARIES}
rapidjson)
PUBLIC
rapidjson
)
if (SLS_USE_TESTS)
add_subdirectory(tests)

View File

@ -9,7 +9,6 @@ this might be deprecated in the future
*/
// #include "genericSocket.h"
#include "network_utils.h"
#include "sls_detector_exceptions.h"
#include <cstdint>

View File

@ -7,20 +7,8 @@
*@short functions to open/close zmq sockets
*/
#include "ansi.h"
#include "sls_detector_exceptions.h"
#include <arpa/inet.h> //inet_ntoa
#include <errno.h>
#include <iostream>
#include <netdb.h> //gethostbyname()
#include <rapidjson/document.h> //json header in zmq stream
#include <string.h>
#include <unistd.h> //usleep in some machines
#include <vector>
#include <zmq.h>
using namespace rapidjson;
#define MAX_STR_LENGTH 1000
@ -28,404 +16,161 @@ using namespace rapidjson;
#define ROIVERBOSITY
class zmq_msg_t;
class ZmqSocket {
public:
public:
// Socket Options for optimization
// ZMQ_LINGER default is already -1 means no messages discarded. use this
// options if optimizing required ZMQ_SNDHWM default is 0 means no limit. use
// this to optimize if optimizing required
// eg. int value = -1;
// if (zmq_setsockopt(socketDescriptor, ZMQ_LINGER, &value,sizeof(value))) {
// Close();
/**
* Constructor for a client
* Creates socket, context and connects to server
* @param hostname hostname or ip of server
* @param portnumber port number
*/
ZmqSocket(const char *const hostname_or_ip, const uint32_t portnumber);
//Socket Options for optimization
//ZMQ_LINGER default is already -1 means no messages discarded. use this options if optimizing required
//ZMQ_SNDHWM default is 0 means no limit. use this to optimize if optimizing required
// eg. int value = -1;
// if (zmq_setsockopt(socketDescriptor, ZMQ_LINGER, &value,sizeof(value))) {
// Close();
/**
* Constructor for a client
* Creates socket, context and connects to server
* @param hostname hostname or ip of server
* @param portnumber port number
*/
ZmqSocket (const char* const hostname_or_ip, const uint32_t portnumber):
portno (portnumber)
// headerMessage(0)
{
char ip[MAX_STR_LENGTH] = "";
memset(ip, 0, MAX_STR_LENGTH);
/**
* Constructor for a server
* Creates socket, context and connects to server
* @param hostname hostname or ip of server
* @param portnumber port number
* @param ethip is the ip of the ethernet interface to stream zmq from
*/
ZmqSocket(const uint32_t portnumber, const char *ethip);
// convert hostname to ip (not required, but a test that returns if failed)
struct addrinfo *result;
if ((ConvertHostnameToInternetAddress(hostname_or_ip, &result)) ||
(ConvertInternetAddresstoIpString(result, ip, MAX_STR_LENGTH)))
throw sls::ZmqSocketError("Could convert IP to string");
/**
* Destructor
*/
~ZmqSocket() = default;
// construct address
sprintf (sockfd.serverAddress, "tcp://%s:%d", ip, portno);
#ifdef VERBOSE
cprintf(BLUE,"address:%s\n",sockfd.serverAddress);
#endif
/**
* Returns Port Number
* @returns Port Number
*/
uint32_t GetPortNumber() { return portno; }
// create context
sockfd.contextDescriptor = zmq_ctx_new();
if (sockfd.contextDescriptor == 0)
throw sls::ZmqSocketError("Could not create contextDescriptor");
/**
* Returns Server Address
* @returns Server Address
*/
char *GetZmqServerAddress() { return sockfd.serverAddress; }
// create publisher
sockfd.socketDescriptor = zmq_socket (sockfd.contextDescriptor, ZMQ_SUB);
if (sockfd.socketDescriptor == 0) {
PrintError ();
Close ();
throw sls::ZmqSocketError("Could not create socket");
}
/**
* Returns Socket Descriptor
* @reutns Socket descriptor
*/
//Socket Options provided above
// an empty string implies receiving any messages
if ( zmq_setsockopt(sockfd.socketDescriptor, ZMQ_SUBSCRIBE, "", 0)) {
PrintError ();
Close();
throw sls::ZmqSocketError("Could set socket opt");
}
//ZMQ_LINGER default is already -1 means no messages discarded. use this options if optimizing required
//ZMQ_SNDHWM default is 0 means no limit. use this to optimize if optimizing required
// eg. int value = -1;
int value = 0;
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_LINGER, &value,sizeof(value))) {
PrintError ();
Close();
throw sls::ZmqSocketError("Could not set ZMQ_LINGER");
}
};
void *GetsocketDescriptor() { return sockfd.socketDescriptor; }
/**
* Constructor for a server
* Creates socket, context and connects to server
* @param hostname hostname or ip of server
* @param portnumber port number
* @param ethip is the ip of the ethernet interface to stream zmq from
*/
ZmqSocket (const uint32_t portnumber, const char *ethip):
/**
* Connect client socket to server socket
* @returns 1 for fail, 0 for success
*/
int Connect();
portno (portnumber)
// headerMessage(0)
{
sockfd.server = true;
/**
* Unbinds the Socket
*/
void Disconnect() { sockfd.Disconnect(); };
// create context
sockfd.contextDescriptor = zmq_ctx_new();
if (sockfd.contextDescriptor == 0)
throw sls::ZmqSocketError("Could not create contextDescriptor");
// create publisher
sockfd.socketDescriptor = zmq_socket (sockfd.contextDescriptor, ZMQ_PUB);
if (sockfd.socketDescriptor == 0) {
PrintError ();
Close ();
throw sls::ZmqSocketError("Could not create socket");
}
/**
* Close Socket and destroy Context
*/
void Close() { sockfd.Close(); };
//Socket Options provided above
/**
* Convert Hostname to Internet address info structure
* One must use freeaddrinfo(res) after using it
* @param hostname hostname
* @param res address of pointer to address info structure
* @return 1 for fail, 0 for success
*/
// Do not make this static (for multi threading environment)
int ConvertHostnameToInternetAddress(const char *const hostname,
struct addrinfo **res);
// construct addresss
sprintf (sockfd.serverAddress,"tcp://%s:%d", ethip, portno);
#ifdef VERBOSE
cprintf(BLUE,"address:%s\n",sockfd.serverAddress);
#endif
// bind address
if (zmq_bind (sockfd.socketDescriptor, sockfd.serverAddress) < 0) {
PrintError ();
Close ();
throw sls::ZmqSocketError("Could not bind socket");
}
/**
* Convert Internet Address structure pointer to ip string (char*)
* Clears the internet address structure as well
* @param res pointer to internet address structure
* @param ip pointer to char array to store result in
* @param ipsize size available in ip buffer
* @return 1 for fail, 0 for success
*/
// Do not make this static (for multi threading environment)
int ConvertInternetAddresstoIpString(struct addrinfo *res, char *ip,
const int ipsize);
//sleep for a few milliseconds to allow a slow-joiner
usleep(200* 1000);
};
/**
* Send Message Header
* @param index self index for debugging
* @param dummy true if a dummy message for end of acquisition
* @param jsonversion json version
* @param dynamicrange dynamic range
* @param fileIndex file or acquisition index
* @param ndetx number of detectors in x axis
* @param ndety number of detectors in y axis
* @param npixelsx number of pixels/channels in x axis for this zmq socket
* @param npixelsy number of pixels/channels in y axis for this zmq socket
* @param imageSize number of bytes for an image in this socket
* @param frameNumber current frame number
* @param expLength exposure length or subframe index if eiger
* @param packetNumber number of packets caught for this frame
* @param bunchId bunch id
* @param timestamp time stamp
* @param modId module Id
* @param row row index in complete detector
* @param column column index in complete detector
* @param reserved reserved
* @param debug debug
* @param roundRNumber not used yet
* @param detType detector enum
* @param version detector header version
* @param gapPixelsEnable gap pixels enable (exception: if gap pixels enable
* for 4 bit mode, data is not yet gap pixel enabled in receiver)
* @param flippedDataX if it is flipped across x axis
* @param quadEnable if quad is enabled
* @param additionalJsonHeader additional json header
* @returns 0 if error, else 1
*/
int SendHeaderData(
int index, bool dummy, uint32_t jsonversion, uint32_t dynamicrange = 0,
uint64_t fileIndex = 0, uint32_t ndetx = 0, uint32_t ndety = 0,
uint32_t npixelsx = 0, uint32_t npixelsy = 0, uint32_t imageSize = 0,
uint64_t acqIndex = 0, uint64_t fIndex = 0, const char *fname = nullptr,
uint64_t frameNumber = 0, uint32_t expLength = 0,
uint32_t packetNumber = 0, uint64_t bunchId = 0, uint64_t timestamp = 0,
uint16_t modId = 0, uint16_t row = 0, uint16_t column = 0,
uint16_t reserved = 0, uint32_t debug = 0, uint16_t roundRNumber = 0,
uint8_t detType = 0, uint8_t version = 0, int gapPixelsEnable = 0,
int flippedDataX = 0, uint32_t quadEnable = 0,
std::string *additionalJsonHeader = 0);
/**
* Destructor
*/
~ZmqSocket () {
//mySocketDescriptor destructor also gets called
};
/**
* Send Message Body
* @param buf message
* @param length length of message
* @returns 0 if error, else 1
*/
int SendData(char *buf, int length);
/**
* Returns Port Number
* @returns Port Number
*/
uint32_t GetPortNumber () { return portno; };
/**
* Returns Server Address
* @returns Server Address
*/
char* GetZmqServerAddress () { return sockfd.serverAddress; };
/**
* Returns Socket Descriptor
* @reutns Socket descriptor
*/
void* GetsocketDescriptor () { return sockfd.socketDescriptor; };
/**
* Connect client socket to server socket
* @returns 1 for fail, 0 for success
*/
int Connect() {
if (zmq_connect(sockfd.socketDescriptor, sockfd.serverAddress) < 0) {
PrintError ();
return 1;
}
return 0;
}
/**
* Unbinds the Socket
*/
void Disconnect () {sockfd.Disconnect();};
/**
* Close Socket and destroy Context
*/
void Close () { sockfd.Close(); };
/**
* Convert Hostname to Internet address info structure
* One must use freeaddrinfo(res) after using it
* @param hostname hostname
* @param res address of pointer to address info structure
* @return 1 for fail, 0 for success
*/
// Do not make this static (for multi threading environment)
int ConvertHostnameToInternetAddress (const char* const hostname, struct addrinfo **res) {
// criteria in selecting socket address structures returned by res
struct addrinfo hints;
memset (&hints, 0, sizeof (hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
// get host info into res
int errcode = getaddrinfo (hostname, NULL, &hints, res);
if (errcode != 0) {
LOG(logERROR) << "Error: Could not convert hostname " << hostname << " to internet address (zmq):"
<< gai_strerror(errcode);
} else {
if (*res == NULL) {
LOG(logERROR) << "Could not convert hostname " << hostname << " to internet address (zmq): "
"gettaddrinfo returned null";
} else{
return 0;
}
}
LOG(logERROR) << "Could not convert hostname to internet address";
return 1;
};
/**
* Convert Internet Address structure pointer to ip string (char*)
* Clears the internet address structure as well
* @param res pointer to internet address structure
* @param ip pointer to char array to store result in
* @param ipsize size available in ip buffer
* @return 1 for fail, 0 for success
*/
// Do not make this static (for multi threading environment)
int ConvertInternetAddresstoIpString (struct addrinfo *res, char* ip, const int ipsize) {
if (inet_ntop (res->ai_family, &((struct sockaddr_in *) res->ai_addr)->sin_addr, ip, ipsize) != NULL) {
freeaddrinfo(res);
return 0;
}
LOG(logERROR) << "Could not convert internet address to ip string";
return 1;
}
/**
* Send Message Header
* @param index self index for debugging
* @param dummy true if a dummy message for end of acquisition
* @param jsonversion json version
* @param dynamicrange dynamic range
* @param fileIndex file or acquisition index
* @param ndetx number of detectors in x axis
* @param ndety number of detectors in y axis
* @param npixelsx number of pixels/channels in x axis for this zmq socket
* @param npixelsy number of pixels/channels in y axis for this zmq socket
* @param imageSize number of bytes for an image in this socket
* @param frameNumber current frame number
* @param expLength exposure length or subframe index if eiger
* @param packetNumber number of packets caught for this frame
* @param bunchId bunch id
* @param timestamp time stamp
* @param modId module Id
* @param row row index in complete detector
* @param column column index in complete detector
* @param reserved reserved
* @param debug debug
* @param roundRNumber not used yet
* @param detType detector enum
* @param version detector header version
* @param gapPixelsEnable gap pixels enable (exception: if gap pixels enable for 4 bit mode, data is not yet gap pixel enabled in receiver)
* @param flippedDataX if it is flipped across x axis
* @param quadEnable if quad is enabled
* @param additionalJsonHeader additional json header
* @returns 0 if error, else 1
*/
int SendHeaderData ( int index, bool dummy, uint32_t jsonversion, uint32_t dynamicrange = 0, uint64_t fileIndex = 0,
uint32_t ndetx = 0, uint32_t ndety = 0, uint32_t npixelsx = 0, uint32_t npixelsy = 0, uint32_t imageSize = 0,
uint64_t acqIndex = 0, uint64_t fIndex = 0, const char* fname = NULL,
uint64_t frameNumber = 0, uint32_t expLength = 0, uint32_t packetNumber = 0,
uint64_t bunchId = 0, uint64_t timestamp = 0,
uint16_t modId = 0, uint16_t row = 0, uint16_t column = 0, uint16_t reserved = 0,
uint32_t debug = 0, uint16_t roundRNumber = 0,
uint8_t detType = 0, uint8_t version = 0, int gapPixelsEnable = 0, int flippedDataX = 0,
uint32_t quadEnable = 0,
std::string* additionalJsonHeader = 0) {
/** Json Header Format */
const char jsonHeaderFormat[] =
"{"
"\"jsonversion\":%u, "
"\"bitmode\":%u, "
"\"fileIndex\":%lu, "
"\"detshape\":[%u, %u], "
"\"shape\":[%u, %u], "
"\"size\":%u, "
"\"acqIndex\":%lu, "
"\"fIndex\":%lu, "
"\"fname\":\"%s\", "
"\"data\": %d, "
"\"frameNumber\":%lu, "
"\"expLength\":%u, "
"\"packetNumber\":%u, "
"\"bunchId\":%lu, "
"\"timestamp\":%lu, "
"\"modId\":%u, "
"\"row\":%u, "
"\"column\":%u, "
"\"reserved\":%u, "
"\"debug\":%u, "
"\"roundRNumber\":%u, "
"\"detType\":%u, "
"\"version\":%u, "
//additional stuff
"\"gappixels\":%u, "
"\"flippedDataX\":%u, "
"\"quad\":%u"
;//"}\n";
char buf[MAX_STR_LENGTH] = "";
sprintf(buf, jsonHeaderFormat,
jsonversion, dynamicrange, fileIndex, ndetx, ndety, npixelsx, npixelsy, imageSize,
acqIndex, fIndex, (fname == NULL)? "":fname, dummy?0:1,
frameNumber, expLength, packetNumber, bunchId, timestamp,
modId, row, column, reserved, debug, roundRNumber,
detType, version,
//additional stuff
gapPixelsEnable,
flippedDataX,
quadEnable
);
if (additionalJsonHeader && !((*additionalJsonHeader).empty())) {
strcat(buf, ", ");
strcat(buf, (*additionalJsonHeader).c_str());
}
strcat(buf, "}\n");
int length = strlen(buf);
#ifdef VERBOSE
//if(!index)
cprintf(BLUE,"%d : Streamer: buf: %s\n", index, buf);
#endif
if(zmq_send (sockfd.socketDescriptor, buf, length, dummy?0:ZMQ_SNDMORE) < 0) {
PrintError ();
return 0;
}
#ifdef VERBOSE
cprintf(GREEN,"[%u] send header data\n",portno);
#endif
return 1;
};
/**
* Send Message Body
* @param buf message
* @param length length of message
* @returns 0 if error, else 1
*/
int SendData (char* buf, int length) {
if(zmq_send (sockfd.socketDescriptor, buf, length, 0) < 0) {
PrintError ();
return 0;
}
#ifdef VERBOSE
cprintf(GREEN,"[%u] send data\n",portno);
#endif
return 1;
};
/**
* Receive Message
* @param index self index for debugging
* @param message message
* @returns length of message, -1 if error
*/
int ReceiveMessage(const int index, zmq_msg_t& message) {
int length = zmq_msg_recv (&message, sockfd.socketDescriptor, 0);
if (length == -1) {
PrintError ();
LOG(logERROR) << "Could not read header for socket " << index;
}
#ifdef VERBOSE
else
cprintf( RED,"Message %d Length: %d Header:%s \n", index, length, (char*) zmq_msg_data (&message) );
#endif
return length;
};
/**
* Receive Header (Important to close message after parsing header)
* @param index self index for debugging
* @param document parsed document reference
* @param version version that has to match, -1 to not care
* @returns 0 if error or end of acquisition, else 1 (call CloseHeaderMessage after parsing header)
*/
int ReceiveHeader(const int index, Document& document, uint32_t version)
{
std::vector<char>buffer(MAX_STR_LENGTH);
int len = zmq_recv(sockfd.socketDescriptor, buffer.data(), buffer.size(),0);
if ( len > 0 ) {
bool dummy = false;
#ifdef ZMQ_DETAIL
cprintf( BLUE,"Header %d [%d] Length: %d Header:%s \n", index, portno, len, buffer.data());
#endif
if ( ParseHeader (index, len, buffer.data(), document, dummy, version)) {
#ifdef ZMQ_DETAIL
cprintf( RED,"Parsed Header %d [%d] Length: %d Header:%s \n", index, portno, len, buffer.data() );
#endif
if (dummy) {
#ifdef ZMQ_DETAIL
cprintf(RED,"%d [%d] Received end of acquisition\n", index, portno );
#endif
return 0;
}
#ifdef ZMQ_DETAIL
cprintf(GREEN,"%d [%d] data\n",index, portno );
#endif
return 1;
}
}
return 0;
};
/**
* Receive Header (Important to close message after parsing header)
* @param index self index for debugging
* @param document parsed document reference
* @param version version that has to match, -1 to not care
* @returns 0 if error or end of acquisition, else 1 (call
* CloseHeaderMessage after parsing header)
*/
int ReceiveHeader(const int index, rapidjson::Document &document, uint32_t version);
/**
* Close Header Message. Call this function if ReceiveHeader returned 1
@ -445,183 +190,60 @@ public:
* @param version version that has to match, -1 to not care
* @returns true if successful else false
*/
int ParseHeader(const int index, int length, char* buff,
Document& document, bool& dummy, uint32_t version)
{
if ( document.Parse( buff, length).HasParseError() ) {
LOG(logERROR) << index << " Could not parse. len:" << length << ": Message:" << buff;
fflush ( stdout );
// char* buf = (char*) zmq_msg_data (&message);
for ( int i= 0; i < length; ++i ) {
cprintf(RED,"%02x ",buff[i]);
}
printf("\n");
fflush( stdout );
return 0;
}
int ParseHeader(const int index, int length, char *buff, rapidjson::Document &document,
bool &dummy, uint32_t version);
if (document["jsonversion"].GetUint() != version) {
LOG(logERROR) << "version mismatch. required " << version << ", got " << document["jsonversion"].GetUint();
return 0;
}
/**
* Receive Data
* @param index self index for debugging
* @param buf buffer to copy image data to
* @param size size of image
* @returns length of data received
*/
int ReceiveData(const int index, char *buf, const int size);
dummy = false;
int temp = document["data"].GetUint();
dummy = temp ? false : true;
/**
* Print error
*/
void PrintError();
return 1;
private:
/**
* Receive Message
* @param index self index for debugging
* @param message message
* @returns length of message, -1 if error
*/
int ReceiveMessage(const int index, zmq_msg_t &message);
/**
* Class to close socket descriptors automatically
* upon encountering exceptions in the ZmqSocket constructor
*/
class mySocketDescriptors {
public:
/** Constructor */
mySocketDescriptors();
/** Destructor */
~mySocketDescriptors();
/** Unbinds the Socket */
void Disconnect();
/** Close Socket and destroy Context */
void Close();
/** true if server, else false */
bool server;
/** Server Address */
char serverAddress[1000];
/** Context Descriptor */
void *contextDescriptor;
/** Socket Descriptor */
void *socketDescriptor;
};
private:
/** Port Number */
uint32_t portno;
/**
* Receive Data
* @param index self index for debugging
* @param buf buffer to copy image data to
* @param size size of image
* @returns length of data received
*/
int ReceiveData(const int index, char* buf, const int size)
{
zmq_msg_t message;
zmq_msg_init (&message);
int length = ReceiveMessage(index, message);
//actual data
if (length == size) {
#ifdef VERBOSE
cprintf(BLUE,"%d actual data\n", index);
#endif
memcpy(buf, (char*)zmq_msg_data(&message), size);
}
//incorrect size (smaller)
else if (length < size){
#ifdef ROIVERBOSITY
cprintf(RED,"Error: Received smaller packet size %d for socket %d\n", length, index);
#endif
memcpy(buf, (char*)zmq_msg_data(&message), length);
memset(buf+length,0xFF,size-length);
}
//incorrect size (larger)
else {
LOG(logERROR) << "Received weird packet size " << length << " for socket " << index;
memset(buf,0xFF,size);
}
zmq_msg_close(&message);
return length;
};
/**
* Print error
*/
void PrintError () {
switch (errno) {
case EINVAL:
LOG(logERROR) << "The socket type/option or value/endpoint supplied is invalid (zmq)";
break;
case EAGAIN:
LOG(logERROR) << "Non-blocking mode was requested and the message cannot be sent/available at the moment (zmq)";
break;
case ENOTSUP:
LOG(logERROR) << "The zmq_send()/zmq_msg_recv() operation is not supported by this socket type (zmq)";
break;
case EFSM:
LOG(logERROR) << "The zmq_send()/zmq_msg_recv() unavailable now as socket in inappropriate state (eg. ZMQ_REP). Look up messaging patterns (zmq)";
break;
case EFAULT:
LOG(logERROR) << "The provided context/message is invalid (zmq)";
break;
case EMFILE:
LOG(logERROR) << "The limit on the total number of open ØMQ sockets has been reached (zmq)";
break;
case EPROTONOSUPPORT:
LOG(logERROR) << "The requested transport protocol is not supported (zmq)";
break;
case ENOCOMPATPROTO:
LOG(logERROR) << "The requested transport protocol is not compatible with the socket type (zmq)";
break;
case EADDRINUSE:
LOG(logERROR) << "The requested address is already in use (zmq)";
break;
case EADDRNOTAVAIL:
LOG(logERROR) << "The requested address was not local (zmq)";
break;
case ENODEV:
LOG(logERROR) << "The requested address specifies a nonexistent interface (zmq)";
break;
case ETERM:
LOG(logERROR) << "The ØMQ context associated with the specified socket was terminated (zmq)";
break;
case ENOTSOCK:
LOG(logERROR) << "The provided socket was invalid (zmq)";
break;
case EINTR:
LOG(logERROR) << "The operation was interrupted by delivery of a signal (zmq)";
break;
case EMTHREAD:
LOG(logERROR) << "No I/O thread is available to accomplish the task (zmq)";
break;
default:
LOG(logERROR) << "Unknown socket error (zmq)";
break;
}
};
private:
/**
* Class to close socket descriptors automatically
* upon encountering exceptions in the ZmqSocket constructor
*/
class mySocketDescriptors {
public:
/** Constructor */
mySocketDescriptors():
server(false),
contextDescriptor(0),
socketDescriptor(0) {};
/** Destructor */
~mySocketDescriptors() {
Disconnect();
Close();
}
/** Unbinds the Socket */
void Disconnect () {
if (server)
zmq_unbind (socketDescriptor, serverAddress);
else
zmq_disconnect (socketDescriptor, serverAddress);
};
/** Close Socket and destroy Context */
void Close () {
if (socketDescriptor != NULL) {
zmq_close (socketDescriptor);
socketDescriptor = NULL;
}
if (contextDescriptor != NULL) {
zmq_ctx_destroy (contextDescriptor);
contextDescriptor = NULL;
}
};
/** true if server, else false */
bool server;
/** Server Address */
char serverAddress[1000];
/** Context Descriptor */
void* contextDescriptor;
/** Socket Descriptor */
void* socketDescriptor;
};
private:
/** Port Number */
uint32_t portno;
/** Socket descriptor */
mySocketDescriptors sockfd;
/** Socket descriptor */
mySocketDescriptors sockfd;
};

View File

@ -14,8 +14,6 @@
#define __cplusplus
#endif
#include "ansi.h"
#ifdef __cplusplus
//C++ includes
#include "sls_detector_exceptions.h"

View File

@ -5,8 +5,8 @@
#define APIGUI 0x200227
#define APICTB 0x200310
#define APIGOTTHARD 0x200310
#define APIGOTTHARD2 0x200310
#define APIJUNGFRAU 0x200310
#define APIMYTHEN3 0x200310
#define APIMOENCH 0x200310
#define APIEIGER 0x200310
#define APIGOTTHARD2 0x200313

View File

@ -0,0 +1,410 @@
#include "ZmqSocket.h"
#include <zmq.h>
#include <vector>
#include <arpa/inet.h> //inet_ntoa
#include <errno.h>
#include <iostream>
#include <netdb.h> //gethostbyname()
#include <string.h>
#include <unistd.h> //usleep in some machines
using namespace rapidjson;
ZmqSocket::ZmqSocket(const char *const hostname_or_ip,
const uint32_t portnumber)
: portno(portnumber)
// headerMessage(0)
{
char ip[MAX_STR_LENGTH] = "";
memset(ip, 0, MAX_STR_LENGTH);
// convert hostname to ip (not required, but a test that returns if failed)
struct addrinfo *result;
if ((ConvertHostnameToInternetAddress(hostname_or_ip, &result)) ||
(ConvertInternetAddresstoIpString(result, ip, MAX_STR_LENGTH)))
throw sls::ZmqSocketError("Could convert IP to string");
// construct address
sprintf(sockfd.serverAddress, "tcp://%s:%d", ip, portno);
#ifdef VERBOSE
cprintf(BLUE, "address:%s\n", sockfd.serverAddress);
#endif
// create context
sockfd.contextDescriptor = zmq_ctx_new();
if (sockfd.contextDescriptor == 0)
throw sls::ZmqSocketError("Could not create contextDescriptor");
// create publisher
sockfd.socketDescriptor = zmq_socket(sockfd.contextDescriptor, ZMQ_SUB);
if (sockfd.socketDescriptor == 0) {
PrintError();
Close();
throw sls::ZmqSocketError("Could not create socket");
}
// Socket Options provided above
// an empty string implies receiving any messages
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_SUBSCRIBE, "", 0)) {
PrintError();
Close();
throw sls::ZmqSocketError("Could set socket opt");
}
// ZMQ_LINGER default is already -1 means no messages discarded. use this
// options if optimizing required ZMQ_SNDHWM default is 0 means no limit.
// use this to optimize if optimizing required eg. int value = -1;
int value = 0;
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_LINGER, &value,
sizeof(value))) {
PrintError();
Close();
throw sls::ZmqSocketError("Could not set ZMQ_LINGER");
}
}
ZmqSocket::ZmqSocket(const uint32_t portnumber, const char *ethip)
:
portno(portnumber)
// headerMessage(0)
{
sockfd.server = true;
// create context
sockfd.contextDescriptor = zmq_ctx_new();
if (sockfd.contextDescriptor == 0)
throw sls::ZmqSocketError("Could not create contextDescriptor");
// create publisher
sockfd.socketDescriptor = zmq_socket(sockfd.contextDescriptor, ZMQ_PUB);
if (sockfd.socketDescriptor == 0) {
PrintError();
Close();
throw sls::ZmqSocketError("Could not create socket");
}
// Socket Options provided above
// construct addresss
sprintf(sockfd.serverAddress, "tcp://%s:%d", ethip, portno);
#ifdef VERBOSE
cprintf(BLUE, "address:%s\n", sockfd.serverAddress);
#endif
// bind address
if (zmq_bind(sockfd.socketDescriptor, sockfd.serverAddress) < 0) {
PrintError();
Close();
throw sls::ZmqSocketError("Could not bind socket");
}
// sleep for a few milliseconds to allow a slow-joiner
usleep(200 * 1000);
};
int ZmqSocket::Connect() {
if (zmq_connect(sockfd.socketDescriptor, sockfd.serverAddress) < 0) {
PrintError();
return 1;
}
return 0;
}
int ZmqSocket::ConvertHostnameToInternetAddress(const char *const hostname,
struct addrinfo **res) {
// criteria in selecting socket address structures returned by res
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
// get host info into res
int errcode = getaddrinfo(hostname, NULL, &hints, res);
if (errcode != 0) {
LOG(logERROR) << "Error: Could not convert hostname " << hostname
<< " to internet address (zmq):" << gai_strerror(errcode);
} else {
if (*res == NULL) {
LOG(logERROR) << "Could not convert hostname " << hostname
<< " to internet address (zmq): "
"gettaddrinfo returned null";
} else {
return 0;
}
}
LOG(logERROR) << "Could not convert hostname to internet address";
return 1;
};
int ZmqSocket::ConvertInternetAddresstoIpString(struct addrinfo *res, char *ip,
const int ipsize) {
if (inet_ntop(res->ai_family,
&((struct sockaddr_in *)res->ai_addr)->sin_addr, ip,
ipsize) != NULL) {
freeaddrinfo(res);
return 0;
}
LOG(logERROR) << "Could not convert internet address to ip string";
return 1;
}
void ZmqSocket::PrintError() {
switch (errno) {
case EINVAL:
LOG(logERROR) << "The socket type/option or value/endpoint supplied is "
"invalid (zmq)";
break;
case EAGAIN:
LOG(logERROR) << "Non-blocking mode was requested and the message "
"cannot be sent/available at the moment (zmq)";
break;
case ENOTSUP:
LOG(logERROR) << "The zmq_send()/zmq_msg_recv() operation is not "
"supported by this socket type (zmq)";
break;
case EFSM:
LOG(logERROR) << "The zmq_send()/zmq_msg_recv() unavailable now as "
"socket in inappropriate state (eg. ZMQ_REP). Look up "
"messaging patterns (zmq)";
break;
case EFAULT:
LOG(logERROR) << "The provided context/message is invalid (zmq)";
break;
case EMFILE:
LOG(logERROR) << "The limit on the total number of open ØMQ sockets "
"has been reached (zmq)";
break;
case EPROTONOSUPPORT:
LOG(logERROR)
<< "The requested transport protocol is not supported (zmq)";
break;
case ENOCOMPATPROTO:
LOG(logERROR) << "The requested transport protocol is not compatible "
"with the socket type (zmq)";
break;
case EADDRINUSE:
LOG(logERROR) << "The requested address is already in use (zmq)";
break;
case EADDRNOTAVAIL:
LOG(logERROR) << "The requested address was not local (zmq)";
break;
case ENODEV:
LOG(logERROR)
<< "The requested address specifies a nonexistent interface (zmq)";
break;
case ETERM:
LOG(logERROR) << "The ØMQ context associated with the specified socket "
"was terminated (zmq)";
break;
case ENOTSOCK:
LOG(logERROR) << "The provided socket was invalid (zmq)";
break;
case EINTR:
LOG(logERROR)
<< "The operation was interrupted by delivery of a signal (zmq)";
break;
case EMTHREAD:
LOG(logERROR)
<< "No I/O thread is available to accomplish the task (zmq)";
break;
default:
LOG(logERROR) << "Unknown socket error (zmq)";
break;
}
}
int ZmqSocket::ReceiveData(const int index, char *buf, const int size) {
zmq_msg_t message;
zmq_msg_init(&message);
int length = ReceiveMessage(index, message);
if (length == size) {
memcpy(buf, (char *)zmq_msg_data(&message), size);
} else if (length < size) {
memcpy(buf, (char *)zmq_msg_data(&message), length);
memset(buf + length, 0xFF, size - length);
} else {
LOG(logERROR) << "Received weird packet size " << length
<< " for socket " << index;
memset(buf, 0xFF, size);
}
zmq_msg_close(&message);
return length;
}
int ZmqSocket::ParseHeader(const int index, int length, char *buff,
Document &document, bool &dummy, uint32_t version) {
if (document.Parse(buff, length).HasParseError()) {
LOG(logERROR) << index << " Could not parse. len:" << length
<< ": Message:" << buff;
fflush(stdout);
// char* buf = (char*) zmq_msg_data (&message);
for (int i = 0; i < length; ++i) {
cprintf(RED, "%02x ", buff[i]);
}
printf("\n");
fflush(stdout);
return 0;
}
if (document["jsonversion"].GetUint() != version) {
LOG(logERROR) << "version mismatch. required " << version << ", got "
<< document["jsonversion"].GetUint();
return 0;
}
dummy = false;
int temp = document["data"].GetUint();
dummy = temp ? false : true;
return 1;
}
int ZmqSocket::ReceiveHeader(const int index, Document &document,
uint32_t version) {
std::vector<char> buffer(MAX_STR_LENGTH);
int len =
zmq_recv(sockfd.socketDescriptor, buffer.data(), buffer.size(), 0);
if (len > 0) {
bool dummy = false;
#ifdef ZMQ_DETAIL
cprintf(BLUE, "Header %d [%d] Length: %d Header:%s \n", index, portno,
len, buffer.data());
#endif
if (ParseHeader(index, len, buffer.data(), document, dummy, version)) {
#ifdef ZMQ_DETAIL
cprintf(RED, "Parsed Header %d [%d] Length: %d Header:%s \n", index,
portno, len, buffer.data());
#endif
if (dummy) {
#ifdef ZMQ_DETAIL
cprintf(RED, "%d [%d] Received end of acquisition\n", index,
portno);
#endif
return 0;
}
#ifdef ZMQ_DETAIL
cprintf(GREEN, "%d [%d] data\n", index, portno);
#endif
return 1;
}
}
return 0;
};
int ZmqSocket::ReceiveMessage(const int index, zmq_msg_t &message) {
int length = zmq_msg_recv(&message, sockfd.socketDescriptor, 0);
if (length == -1) {
PrintError();
LOG(logERROR) << "Could not read header for socket " << index;
}
return length;
}
int ZmqSocket::SendData(char *buf, int length) {
if (zmq_send(sockfd.socketDescriptor, buf, length, 0) < 0) {
PrintError();
return 0;
}
return 1;
}
int ZmqSocket::SendHeaderData(
int index, bool dummy, uint32_t jsonversion, uint32_t dynamicrange,
uint64_t fileIndex, uint32_t ndetx, uint32_t ndety, uint32_t npixelsx,
uint32_t npixelsy, uint32_t imageSize, uint64_t acqIndex, uint64_t fIndex,
const char *fname, uint64_t frameNumber, uint32_t expLength,
uint32_t packetNumber, uint64_t bunchId, uint64_t timestamp, uint16_t modId,
uint16_t row, uint16_t column, uint16_t reserved, uint32_t debug,
uint16_t roundRNumber, uint8_t detType, uint8_t version,
int gapPixelsEnable, int flippedDataX, uint32_t quadEnable,
std::string *additionalJsonHeader) {
/** Json Header Format */
const char jsonHeaderFormat[] = "{"
"\"jsonversion\":%u, "
"\"bitmode\":%u, "
"\"fileIndex\":%lu, "
"\"detshape\":[%u, %u], "
"\"shape\":[%u, %u], "
"\"size\":%u, "
"\"acqIndex\":%lu, "
"\"fIndex\":%lu, "
"\"fname\":\"%s\", "
"\"data\": %d, "
"\"frameNumber\":%lu, "
"\"expLength\":%u, "
"\"packetNumber\":%u, "
"\"bunchId\":%lu, "
"\"timestamp\":%lu, "
"\"modId\":%u, "
"\"row\":%u, "
"\"column\":%u, "
"\"reserved\":%u, "
"\"debug\":%u, "
"\"roundRNumber\":%u, "
"\"detType\":%u, "
"\"version\":%u, "
// additional stuff
"\"gappixels\":%u, "
"\"flippedDataX\":%u, "
"\"quad\":%u"
; //"}\n";
char buf[MAX_STR_LENGTH] = "";
sprintf(buf, jsonHeaderFormat, jsonversion, dynamicrange, fileIndex, ndetx,
ndety, npixelsx, npixelsy, imageSize, acqIndex, fIndex,
(fname == NULL) ? "" : fname, dummy ? 0 : 1,
frameNumber, expLength, packetNumber, bunchId, timestamp, modId,
row, column, reserved, debug, roundRNumber, detType, version,
// additional stuff
gapPixelsEnable, flippedDataX, quadEnable);
if (additionalJsonHeader && !((*additionalJsonHeader).empty())) {
strcat(buf, ", ");
strcat(buf, (*additionalJsonHeader).c_str());
}
strcat(buf, "}\n");
int length = strlen(buf);
#ifdef VERBOSE
// if(!index)
cprintf(BLUE, "%d : Streamer: buf: %s\n", index, buf);
#endif
if (zmq_send(sockfd.socketDescriptor, buf, length,
dummy ? 0 : ZMQ_SNDMORE) < 0) {
PrintError();
return 0;
}
#ifdef VERBOSE
cprintf(GREEN, "[%u] send header data\n", portno);
#endif
return 1;
}
//Nested class to do RAII handling of socket descriptors
ZmqSocket::mySocketDescriptors::mySocketDescriptors()
: server(false), contextDescriptor(0), socketDescriptor(0){};
ZmqSocket::mySocketDescriptors::~mySocketDescriptors() {
Disconnect();
Close();
}
void ZmqSocket::mySocketDescriptors::Disconnect() {
if (server)
zmq_unbind(socketDescriptor, serverAddress);
else
zmq_disconnect(socketDescriptor, serverAddress);
};
void ZmqSocket::mySocketDescriptors::Close() {
if (socketDescriptor != NULL) {
zmq_close(socketDescriptor);
socketDescriptor = NULL;
}
if (contextDescriptor != NULL) {
zmq_ctx_destroy(contextDescriptor);
contextDescriptor = NULL;
}
};