Merge branch 'developer' into jf_h5reader

This commit is contained in:
2025-03-06 17:14:17 +01:00
56 changed files with 1870 additions and 1060 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1 @@
../slsDetectorServers/xilinx_ctbDetectorServer/bin/xilinx_ctbDetectorServer_developer

View File

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

View File

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

View File

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

View File

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

View File

@ -197,6 +197,8 @@ int isChipConfigured();
int powerChip(int on, char *mess);
int getPowerChip();
int configureChip(char *mess);
int readConfigFile(char *mess, char *fileName, char *fileType);
int resetChip(char *mess);
#endif
#if defined(JUNGFRAUD) || defined(MOENCHD) || defined(CHIPTESTBOARDD) || \
defined(MYTHEN3D) || defined(GOTTHARD2D)
@ -742,8 +744,7 @@ int softwareTrigger();
#if defined(EIGERD) || defined(JUNGFRAUD) || defined(MOENCHD)
int softwareTrigger(int block);
#endif
#if defined(EIGERD) || defined(MYTHEN3D) || defined(CHIPTESTBOARDD) || \
defined(XILINX_CHIPTESTBOARDD)
#if defined(EIGERD) || defined(MYTHEN3D) || defined(CHIPTESTBOARDD)
int startReadOut();
#endif
enum runStatus getRunStatus();

View File

@ -853,7 +853,7 @@ int loadPattern(char *message, enum TLogLevel printLevel,
}
}
// iocontrol
#if !defined(MYTHEN3D) && !defined(XILINX_CHIPTESTBOARDD) // TODO
#if !defined(MYTHEN3D)
if (ret == OK) {
ret = validate_writePatternIOControl(message, pat->ioctrl);
}
@ -914,7 +914,7 @@ int getPattern(char *message, patternParameters *pat) {
pat->word[i] = retval64;
}
// iocontrol
#if !defined(MYTHEN3D) && !defined(XILINX_CHIPTESTBOARDD) // TODO
#if !defined(MYTHEN3D)
if (ret == OK) {
validate_readPatternIOControl();
}
@ -1051,12 +1051,12 @@ int loadPatternFile(char *patFname, char *errMessage) {
}
// patioctrl
#if !defined(MYTHEN3D) && !defined(XILINX_CHIPTESTBOARDD) // TODO
#if !defined(MYTHEN3D) // TODO
if (!strncmp(line, "patioctrl", strlen("patioctrl"))) {
uint64_t arg = 0;
// cannot scan values
#ifdef VIRTUAL
#if defined(VIRTUAL) || defined(XILINX_CHIPTESTBOARDD)
if (sscanf(line, "%s 0x%lx", command, &arg) != 2) {
#else
if (sscanf(line, "%s 0x%llx", command, &arg) != 2) {

View File

@ -8467,8 +8467,7 @@ int get_bursts_left(int file_des) {
int start_readout(int file_des) {
ret = OK;
memset(mess, 0, sizeof(mess));
#if !defined(MYTHEN3D) && !defined(CHIPTESTBOARDD) && \
!defined(XILINX_CHIPTESTBOARDD)
#if !defined(MYTHEN3D) && !defined(CHIPTESTBOARDD)
functionNotImplemented();
#else
if (Server_VerifyLock() == OK) {
@ -9098,16 +9097,9 @@ int get_comp_disable_time(int file_des) {
functionNotImplemented();
#else
// get only
if (getChipVersion() != 11) {
ret = FAIL;
strcpy(mess,
"Cannot get comparator disable time. Only valid for chipv1.1\n");
LOG(logERROR, (mess));
} else {
retval = getComparatorDisableTime();
LOG(logDEBUG1,
("retval comp disable time %lld ns\n", (long long int)retval));
}
retval = getComparatorDisableTime();
LOG(logDEBUG1,
("retval comp disable time %lld ns\n", (long long int)retval));
#endif
return Server_SendResult(file_des, INT64, &retval, sizeof(retval));
}
@ -9125,23 +9117,16 @@ int set_comp_disable_time(int file_des) {
#else
// only set
if (Server_VerifyLock() == OK) {
if (getChipVersion() != 11) {
ret = FAIL;
strcpy(mess, "Cannot get comparator disable time. Only valid for "
"chipv1.1\n");
ret = setComparatorDisableTime(arg);
int64_t retval = getComparatorDisableTime();
LOG(logDEBUG1,
("retval get comp disable time %lld ns\n", (long long int)retval));
if (ret == FAIL) {
sprintf(mess,
"Could not set comp disable time. Set %lld ns, read "
"%lld ns.\n",
(long long int)arg, (long long int)retval);
LOG(logERROR, (mess));
} else {
ret = setComparatorDisableTime(arg);
int64_t retval = getComparatorDisableTime();
LOG(logDEBUG1, ("retval get comp disable time %lld ns\n",
(long long int)retval));
if (ret == FAIL) {
sprintf(mess,
"Could not set comp disable time. Set %lld ns, read "
"%lld ns.\n",
(long long int)arg, (long long int)retval);
LOG(logERROR, (mess));
}
}
}
#endif
@ -11144,6 +11129,12 @@ int set_timing_info_decoder(int file_des) {
modeNotImplemented("Timing info decoder index", (int)arg);
break;
}
if (ret == OK && isHardwareVersion_1_0()) {
ret = FAIL;
sprintf(mess, "Could not set timing info decoder. Not supported "
"for hardware version 1.0\n");
LOG(logERROR, (mess));
}
if (ret == OK) {
ret = setTimingInfoDecoder(arg);
if (ret == FAIL) {

View File

@ -40,3 +40,9 @@ set_target_properties(xilinx_ctbDetectorServer_virtual PROPERTIES
install(TARGETS xilinx_ctbDetectorServer_virtual
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
configure_file(chip_config_xilinx.txt ${CMAKE_BINARY_DIR}/bin/chip_config_xilinx.txt COPYONLY)
configure_file(reset_chip_xilinx.txt ${CMAKE_BINARY_DIR}/bin/reset_chip_xilinx.txt COPYONLY)
configure_file(enable_clock_pattern.pyat ${CMAKE_BINARY_DIR}/bin/enable_clock_pattern.pyat COPYONLY)
configure_file(readout_pattern.pyat ${CMAKE_BINARY_DIR}/bin/readout_pattern.pyat COPYONLY)

View File

@ -48,6 +48,10 @@ $(PROGS): $(OBJS)
mkdir -p $(DESTDIR)
$(CC) -o $@ $^ $(CFLAGS) $(LDLIBS)
mv $(PROGS) $(DESTDIR)
cp chip_config_xilinx.txt $(DESTDIR)
cp reset_chip_xilinx.txt $(DESTDIR)
cp enable_clock_pattern.pyat $(DESTDIR)
cp readout_pattern.pyat $(DESTDIR)
rm $(main_src)*.o $(md5_dir)*.o
clean:
rm -rf $(DESTDIR)/$(PROGS) *.o *.gdb $(main_src)*.o $(md5_dir)*.o

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,24 @@
# Prepare MH02 configuration
reg 0xB1B0 0x00000041
reg 0xB1B4 0x01200004
# configure Matterhorn SPI
setbit 0xB1B8 0
# wait till config is done
pollbit 0xB1B8 3 0
# reset transceiver
reg 0xB820 0x0
reg 0xB820 0x1
reg 0xB820 0x0
# set MSB LSB inversions and polarity for transceiver
reg 0xB820 0x61e0
# Enable MH02 PLL clock
pattern enable_clock_pattern.pyat
# start the flow
setbit 0xB004 0
clearbit 0xB004 0
sleep 1

View File

@ -0,0 +1,8 @@
patword 0x0000 0x0000000000000000
patword 0x0001 0x0000000000008000
patword 0x0002 0x0000000000008000
patword 0x0003 0x0000000000008000
patword 0x0004 0x0000000000008000
patword 0x0005 0x0000000000008000
patioctrl 0x01b3ffff
patlimits 0x0000 0x0005

View File

@ -0,0 +1,22 @@
patword 0x0000 0x0000000000008000
patword 0x0001 0x0000000000008000
patword 0x0002 0x0000000000008000
patword 0x0003 0x0000000000008000
patword 0x0004 0x0000000000008000
patword 0x0005 0x0000000000008000
patword 0x0006 0x0000000000008000
patword 0x0007 0x0000000000008000
patword 0x0008 0x0000000000008000
patword 0x0009 0x0000000000008000
patword 0x000a 0x0000000000008000
patword 0x000b 0x0000000000108000
patword 0x000c 0x0000000000108000
patword 0x000d 0x0000000000108000
patword 0x000e 0x0000000000108000
patword 0x000f 0x0000000000008000
patword 0x0010 0x0000000000008000
patword 0x0011 0x0000000000008000
patword 0x0012 0x0000000000008000
patword 0x0013 0x0000000000008000
patioctrl 0x01b3ffff
patlimits 0x0000 0x0013

View File

@ -0,0 +1,40 @@
# turn off clock
setbit 0xB1B0 16
setbit 0xB1B8 0
sleep 1
# reset Matterhorn periphery
setbit 0xB1B8 1
sleep 1
# turn on clock
clearbit 0xB1B0 16
setbit 0xB1B8 0
sleep 1
# reset rx transceiver datapath
setbit 0xB820 4
sleep 1
# reset 8b10b counters
setbit 0xB820 9
setbit 0xB820 10
setbit 0xB820 11
setbit 0xB820 12
sleep 1
clearbit 0xB820 9
clearbit 0xB820 10
# reset buffer fifos
reg 0x9024 0xFFFFFFFF
reg 0x9028 0xFFFFFFFF
reg 0x902C 0xFFFFFFFF
reg 0x9024 0x0
reg 0x9028 0x0
reg 0x902C 0x0
setbit 0xA000 18
# load default pattern
pattern readout_pattern.pyat

View File

@ -492,7 +492,16 @@ void setTransceiverAlignment(int align) {
#endif
int isTransceiverAligned() {
return (bus_r(TRANSCEIVERSTATUS) & RXBYTEISALIGNED_MSK);
int times = 0;
int retval = bus_r(TRANSCEIVERSTATUS2) & RXLOCKED_MSK;
while (retval) {
retval = bus_r(TRANSCEIVERSTATUS2) & RXLOCKED_MSK;
times++;
usleep(10);
if (times == 5)
return 1;
}
return retval;
}
int waitTransceiverAligned(char *mess) {
@ -511,7 +520,9 @@ int waitTransceiverAligned(char *mess) {
int times = 0;
while (transceiverWordAligned == 0) {
if (times++ > WAIT_TIME_OUT_0US_TIMES) {
sprintf(mess, "Transceiver alignment timed out\n");
sprintf(mess, "Transceiver alignment timed out. Check connection, "
"p-n inversions, LSB-MSB inversions, link error "
"counters and channel enable settings\n");
LOG(logERROR, (mess));
return FAIL;
}
@ -587,34 +598,197 @@ int getPowerChip() {
int configureChip(char *mess) {
LOG(logINFOBLUE, ("\tConfiguring chip\n"));
// enable correct endianness (Only for MH_PR_2)
// uint32_t addr = MATTERHORNSPIREG1;
// bus_w(addr, bus_r(addr) &~MATTERHORNSPI1_MSK);
// bus_w(addr, bus_r(addr) | ((0x40000 << MATTERHORNSPI1_OFST) &
// MATTERHORNSPI1_MSK));
// start configuration
uint32_t addr = MATTERHORNSPICTRL;
bus_w(addr, bus_r(addr) | CONFIGSTART_P_MSK);
bus_w(addr, bus_r(addr) & ~CONFIGSTART_P_MSK);
// wait until configuration is done
#ifndef VIRTUAL
int configDone = (bus_r(MATTERHORNSPICTRL) & BUSY_MSK);
int times = 0;
while (configDone == 0) {
if (times++ > WAIT_TIME_OUT_0US_TIMES) {
sprintf(mess, "Configuration of chip timed out\n");
LOG(logERROR, (mess));
return FAIL;
}
usleep(0);
configDone = (bus_r(MATTERHORNSPICTRL) & BUSY_MSK);
chipConfigured = 0;
if (readConfigFile(mess, CONFIG_CHIP_FILE, "chip config") == FAIL) {
return FAIL;
}
#endif
if (readConfigFile(mess, RESET_CHIP_FILE, "reset chip") == FAIL) {
return FAIL;
}
LOG(logINFOBLUE, ("Chip configured.\n"));
chipConfigured = 1;
LOG(logINFOBLUE, ("\tChip configured\n"));
return OK;
}
int readConfigFile(char *mess, char *fileName, char *fileType) {
const int fileNameSize = 128;
char fname[fileNameSize];
if (getAbsPath(fname, fileNameSize, fileName) == FAIL) {
sprintf(mess, "Could not get full path for %s file [%s].\n", fileType,
fname);
LOG(logERROR, (mess));
return FAIL;
}
if (access(fname, F_OK) != 0) {
sprintf(mess, "Could not find %s file [%s].\n", fileType, fname);
LOG(logERROR, (mess));
return FAIL;
}
FILE *fd = fopen(fname, "r");
if (fd == NULL) {
sprintf(mess, "Could not open on-board detector server %s file [%s].\n",
fileType, fname);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFOBLUE, ("Reading %s file %s\n", fileType, fname));
const size_t LZ = 256;
char line[LZ];
memset(line, 0, LZ);
char command[LZ];
// keep reading a line
while (fgets(line, LZ, fd)) {
// ignore comments
if (line[0] == '#') {
LOG(logDEBUG1, ("Ignoring Comment\n"));
continue;
}
// ignore empty lines
if (strlen(line) <= 1) {
LOG(logDEBUG1, ("Ignoring Empty line\n"));
continue;
}
// removing leading spaces
if (line[0] == ' ' || line[0] == '\t') {
int len = strlen(line);
// find first valid character
int i = 0;
for (i = 0; i < len; ++i) {
if (line[i] != ' ' && line[i] != '\t') {
break;
}
}
// ignore the line full of spaces (last char \n)
if (i >= len - 1) {
LOG(logDEBUG1, ("Ignoring line full of spaces\n"));
continue;
}
// copying only valid char
char temp[LZ];
memset(temp, 0, LZ);
memcpy(temp, line + i, strlen(line) - i);
memset(line, 0, LZ);
memcpy(line, temp, strlen(temp));
LOG(logDEBUG1, ("Removing leading spaces.\n"));
}
LOG(logDEBUG1, ("Command to process: (size:%d) %.*s\n", strlen(line),
strlen(line) - 1, line));
memset(command, 0, LZ);
// reg command
if (!strncmp(line, "reg", strlen("reg"))) {
uint32_t addr = 0;
uint32_t val = 0;
if (sscanf(line, "%s %x %x", command, &addr, &val) != 3) {
sprintf(mess, "Could not scan reg command. Line:[%s].\n", line);
LOG(logERROR, (mess));
return FAIL;
}
bus_w(addr, val);
LOG(logINFOBLUE, ("Wrote 0x%x to 0x%x\n", val, addr));
}
// setbit command
else if (!strncmp(line, "setbit", strlen("setbit"))) {
uint32_t addr = 0;
uint32_t bit = 0;
if (sscanf(line, "%s %x %d", command, &addr, &bit) != 3) {
sprintf(mess, "Could not scan setbit command. Line:[%s].\n",
line);
LOG(logERROR, (mess));
return FAIL;
}
bus_w(addr, bus_r(addr) | (1 << bit));
LOG(logINFOBLUE, ("Set bit %d in 0x%x\n", bit, addr));
}
// clearbit command
else if (!strncmp(line, "clearbit", strlen("clearbit"))) {
uint32_t addr = 0;
uint32_t bit = 0;
if (sscanf(line, "%s %x %d", command, &addr, &bit) != 3) {
sprintf(mess, "Could not scan clearbit command. Line:[%s].\n",
line);
LOG(logERROR, (mess));
return FAIL;
}
bus_w(addr, bus_r(addr) & ~(1 << bit));
LOG(logINFOBLUE, ("Cleared bit %d in 0x%x\n", bit, addr));
}
// pollbit command
else if (!strncmp(line, "pollbit", strlen("pollbit"))) {
uint32_t addr = 0;
uint32_t bit = 0;
uint32_t val = 0;
if (sscanf(line, "%s %x %d %d", command, &addr, &bit, &val) != 4) {
sprintf(mess, "Could not scan pollbit command. Line:[%s].\n",
line);
LOG(logERROR, (mess));
return FAIL;
}
#ifndef VIRTUAL
int times = 0;
while (((bus_r(addr) >> bit) & 0x1) != val) {
if (times++ > WAIT_TIME_OUT_0US_TIMES) {
sprintf(mess, "Polling bit %d in 0x%x timed out\n", bit,
addr);
LOG(logERROR, (mess));
return FAIL;
}
usleep(0);
}
#endif
LOG(logINFOBLUE, ("Polled bit %d in 0x%x\n", bit, addr));
}
// pattern command
else if (!strncmp(line, "pattern", strlen("pattern"))) {
// take a file name and call loadPatterFile
char patternFileName[LZ];
if (sscanf(line, "%s %s", command, patternFileName) != 2) {
sprintf(mess, "Could not scan pattern command. Line:[%s].\n",
line);
LOG(logERROR, (mess));
return FAIL;
}
if (loadPatternFile(patternFileName, mess) == FAIL) {
return FAIL;
}
LOG(logINFOBLUE, ("loaded pattern [%s].\n", patternFileName));
}
// sleep command
else if (!strncmp(line, "sleep", strlen("sleep"))) {
int time = 0;
if (sscanf(line, "%s %d", command, &time) != 2) {
sprintf(mess, "Could not scan sleep command. Line:[%s].\n",
line);
LOG(logERROR, (mess));
return FAIL;
}
usleep(time * 1000 * 1000);
LOG(logINFOBLUE, ("Slept for %d s\n", time));
}
// other commands
else {
sprintf(mess,
"Could not scan command from on-board server "
"%s file. Line:[%s].\n",
fileType, line);
break;
}
memset(line, 0, LZ);
}
fclose(fd);
LOG(logINFOBLUE, ("Successfully read %s file.\n", fileType));
return OK;
}
@ -1328,31 +1502,13 @@ int startStateMachine() {
return OK;
#endif
LOG(logINFOBLUE, ("Starting State Machine\n"));
// cleanFifos(); removing this for now as its done before readout pattern
LOG(logINFOBLUE, ("Starting readout\n"));
// start state machine
bus_w(FLOW_CONTROL_REG, bus_r(FLOW_CONTROL_REG) | START_F_MSK);
LOG(logINFORED, ("Waiting for exposing to be done\n"));
int exposingDone = (bus_r(FLOW_STATUS_REG) & RSM_BUSY_MSK);
while (exposingDone != 0) {
usleep(0);
exposingDone = (bus_r(FLOW_STATUS_REG) & RSM_BUSY_MSK);
}
LOG(logINFORED, ("Starting readout of chip to fifo\n"));
// MM:readout via pattern does not work right now due to firmware bug,
// readout via MatterhornCTRL for the moment
// bus_w(FLOW_CONTROL_REG, bus_r(FLOW_CONTROL_REG) | START_F_MSK);
bus_w(MATTERHORNSPICTRL, bus_r(MATTERHORNSPICTRL) | STARTREAD_P_MSK);
LOG(logINFORED, ("Waiting until k-words or end of acquisition\n"));
usleep(0);
int commaDet = (bus_r(TRANSCEIVERSTATUS) & RXCOMMADET_MSK);
while (commaDet == 0) {
usleep(0);
commaDet = (bus_r(TRANSCEIVERSTATUS) & RXCOMMADET_MSK);
}
LOG(logINFORED, ("Kwords or end of acquisition detected\n"));
return OK;
}
@ -1467,56 +1623,6 @@ int stopStateMachine() {
return OK;
}
int startReadOut() {
LOG(logINFOBLUE, ("Starting Readout\n"));
#ifdef VIRTUAL
// cannot set #frames and exptiem temporarily to 1 and 0,
// because have to set it back after readout (but this is non blocking)
return startStateMachine();
#endif
// check if data in fifo
int ret = FAIL;
if (transceiverEnable) {
if ((bus_r(X_FIFO_EMPTY_STATUS_REG) & X_FIFO_EMPTY_STATUS_MSK) !=
X_FIFO_EMPTY_STATUS_MSK) {
LOG(logINFO, ("Data in transceiver fifo\n"));
ret = OK;
}
}
if (analogEnable) {
if (bus_r(A_FIFO_EMPTY_STATUS_REG) != BIT32_MSK) {
LOG(logINFO, ("Data in analog fifo\n"));
ret = OK;
}
}
if (digitalEnable) {
if ((bus_r(D_FIFO_EMPTY_STATUS_REG) & D_FIFO_EMPTY_STATUS_MSK) !=
D_FIFO_EMPTY_STATUS_MSK) {
LOG(logINFO, ("Data in digital fifo\n"));
ret = OK;
}
}
// if no module, dont check fifo empty
if (checkModuleFlag && ret == FAIL) {
LOG(logERROR, ("No data in fifo\n"));
return FAIL;
}
LOG(logINFOBLUE, ("Streaming data from fifo\n"));
bus_w(FIFO_TO_GB_CONTROL_REG,
bus_r(FIFO_TO_GB_CONTROL_REG) | START_STREAMING_P_MSK);
// wait until streaming is done (not same as fifo empty)
int streamingBusy = (bus_r(STATUSREG1) & TRANSMISSIONBUSY_MSK);
while (streamingBusy != 0) {
usleep(0);
streamingBusy = (bus_r(STATUSREG1) & TRANSMISSIONBUSY_MSK);
}
LOG(logINFORED, ("Streaming done\n"));
return OK;
}
int softwareTrigger() {
#ifndef VIRTUAL
// ready for trigger
@ -1552,36 +1658,33 @@ enum runStatus getRunStatus() {
LOG(logINFOBLUE, ("Status: IDLE\n"));
return IDLE;
#endif
uint32_t retval = bus_r(FLOW_STATUS_REG);
LOG(logINFO, ("Flow Status Register: %08x\n", retval));
uint32_t retval = bus_r(STATUS_REG);
LOG(logINFO, ("Status Register: %08x\n", retval));
if (retval & RSM_TRG_WAIT_MSK) {
LOG(logINFOBLUE, ("Status: WAITING\n"));
return WAITING;
} else if (retval & RSM_BUSY_MSK) {
LOG(logINFOBLUE, ("Status: RUNNING (exposing)\n"));
return RUNNING;
} else if (bus_r(MATTERHORNSPICTRL) & READOUTFROMASIC_MSK) {
LOG(logINFOBLUE, ("Status: RUNNING (data from chip to fifo)\n"));
return RUNNING;
} else if (bus_r(STATUSREG1) & TRANSMISSIONBUSY_MSK) {
LOG(logINFOBLUE, ("Status: TRANSMITTING\n"));
return TRANSMITTING;
if (retval == 0x0) {
return IDLE;
}
LOG(logINFOBLUE, ("Status: IDLE\n"));
return IDLE;
// TODO: STOPPED, ERROR?
if (retval & RX_NOT_GOOD_MSK) {
LOG(logINFOBLUE, ("Status: ERROR\n"));
return ERROR;
}
if (retval & WAIT_FOR_TRIGGER_MSK) {
LOG(logINFOBLUE, ("Status: WAITING\n"));
return WAITING;
}
LOG(logINFOBLUE, ("Status: RUNNING\n"));
return RUNNING;
// TODO: STOPPED?
}
u_int32_t runBusy() {
#ifdef VIRTUAL
return ((sharedMemory_getStatus() == RUNNING) ? 1 : 0);
#endif
uint32_t exposingBusy = bus_r(FLOW_STATUS_REG) & RSM_BUSY_MSK;
uint32_t fillingFifoBusy = bus_r(MATTERHORNSPICTRL) & READOUTFROMASIC_MSK;
uint32_t streamingBusy = bus_r(STATUSREG1) & TRANSMISSIONBUSY_MSK;
return (exposingBusy || fillingFifoBusy || streamingBusy);
return (bus_r(STATUS_REG));
}
void waitForAcquisitionEnd() {

View File

@ -4,7 +4,7 @@
#include "RegisterDefs.h"
#include "sls/sls_detector_defs.h"
#define REQRD_FRMWRE_VRSN (0x230710)
#define REQRD_FRMWRE_VRSN (0x250203)
#define KERNEL_DATE_VRSN "Wed Nov 29 17:32:14 CET 2023"
#define LINKED_SERVER_NAME "xilinx_ctbDetectorServer"
@ -40,6 +40,9 @@
#define SLOWADC_DRIVER_FILE_NAME CURRENT_BOARD_LINKS_FOLDER "/ai%d"
#define TEMP_DRIVER_FILE_NAME DEVICE_TREE_DST "0/in_temp7_input"
#define CONFIG_CHIP_FILE "chip_config_xilinx.txt"
#define RESET_CHIP_FILE "reset_chip_xilinx.txt"
/** Default Parameters */
#define DEFAULT_NUM_FRAMES (1)
#define DEFAULT_NUM_CYCLES (1)

View File

@ -80,7 +80,7 @@ _sd() {
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 clearroi 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 exptimel 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 patternX 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 roi 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 clearroi 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 exptimel 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 roi 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 "
__acquire() {
FCN_RETURN=""
return 0
@ -1447,18 +1447,82 @@ return 0
}
__patloop() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "4" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__patloop0() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "4" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__patloop1() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "4" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__patloop2() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "4" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__patmask() {
@ -1472,18 +1536,70 @@ return 0
}
__patnloop() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__patnloop0() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__patnloop1() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__patnloop2() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__patsetbit() {
@ -1495,7 +1611,7 @@ fi
fi
return 0
}
__patternX() {
__pattern() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
@ -1522,18 +1638,70 @@ return 0
}
__patwait() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__patwait0() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__patwait1() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__patwait2() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__patwaittime() {

View File

@ -4,7 +4,7 @@
_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 clearroi 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 exptimel 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 patternX 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 roi 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 clearroi 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 exptimel 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 roi 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 "
__acquire() {
FCN_RETURN=""
return 0
@ -1371,18 +1371,82 @@ return 0
}
__patloop() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "4" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__patloop0() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "4" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__patloop1() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "4" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__patloop2() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "4" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__patmask() {
@ -1396,18 +1460,70 @@ return 0
}
__patnloop() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__patnloop0() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__patnloop1() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__patnloop2() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__patsetbit() {
@ -1419,7 +1535,7 @@ fi
fi
return 0
}
__patternX() {
__pattern() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
@ -1446,18 +1562,70 @@ return 0
}
__patwait() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__patwait0() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__patwait1() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__patwait2() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__patwaittime() {

View File

@ -468,7 +468,7 @@ subdeadtime:
function: setSubDeadTime
compdisabletime:
help: "[duration] [(optional unit) ns|us|ms|s]\n\t[Jungfrau] Time before end of exposure when comparator is disabled. It is only possible for chipv1.1."
help: "[duration] [(optional unit) ns|us|ms|s]\n\t[Jungfrau] Time before end of exposure when comparator is disabled."
inherit_actions: TIME_COMMAND
actions:
GET:
@ -1123,7 +1123,7 @@ temp_control:
input_types: [ bool ]
autocompdisable:
help: "[0, 1]\n\t[Jungfrau] Auto comparator disable mode. By default, the on-chip gain switching is active during the entire exposure.This mode disables the on - chip gain switching comparator automatically after 93.75% (only for chipv1.0) of exposure time (only for longer than 100us). It is possible to set the duration for chipv1.1 using compdisabletime command.\n\tDefault is 0 or this mode disabled(comparator enabled throughout). 1 enables mode. 0 disables mode. "
help: "[0, 1]\n\t[Jungfrau] Auto comparator disable mode. By default, the on-chip gain switching is active during the entire exposure.This mode disables the on - chip gain switching comparator automatically and the duration is set using compdisabletime command.\n\tDefault is 0 or this mode disabled(comparator enabled throughout). 1 enables mode. 0 disables mode. "
inherit_actions: INTEGER_COMMAND_VEC_ID
actions:
GET:
@ -1210,7 +1210,7 @@ polarity:
input_types: [ defs::polarity ]
timing_info_decoder:
help: "[swissfel|shine]\n\t[Jungfrau] Advanced Command and only for Swissfel and Shine. Sets the bunch id or timing info decoder. Default is swissfel."
help: "[swissfel|shine]\n\t[Jungfrau] Advanced Command and only for Swissfel and Shine. Sets the bunch id or timing info decoder. Default is swissfel. Only allowed for pcbv2.0."
inherit_actions: INTEGER_COMMAND_VEC_ID
actions:
GET:
@ -3467,7 +3467,7 @@ udp_dstlist:
output: [ ToString(args) ]
txdelay:
help: "[n_delay]\n\t[Eiger][Jungfrau][Moench][Mythen3] Set transmission delay for all modules in the detector using the step size provided.Sets up \n\t[Eiger] txdelay_left to (2 * mod_index * n_delay), \n\t[Eiger] txdelay_right to ((2 * mod_index + 1) * n_delay) and \n\t[Eiger] txdelay_frame to (2 *num_modules * n_delay)\n\t[Jungfrau][Moench][Mythen3] txdelay_frame to (num_modules * n_delay) for every module."
help: "[n_delay]\n\t[Eiger][Jungfrau][Moench][Mythen3] Set transmission delay for all modules in the detector using the step size provided.Sets up \n\t[Eiger] txdelay_left to (2 * mod_index * n_delay), \n\t[Eiger] txdelay_right to ((2 * mod_index + 1) * n_delay) and \n\t[Eiger] txdelay_frame to (2 * num_modules * n_delay)\n\t[Jungfrau][Moench][Mythen3] txdelay_frame to (num_modules * n_delay) for every module."
actions:
GET:
argc: 0
@ -3912,8 +3912,7 @@ diodelay:
cast_input: [ true, true ]
output: [ ToString(args) ]
# pattern is a keyword in yaml, so patternX is used to avoid it
patternX:
pattern:
help: "[fname]\n\t[Mythen3][Ctb][Xilinx Ctb] Loads ASCII pattern file directly to server (instead of executing line by line)"
command_name: "pattern"
actions:

View File

@ -164,6 +164,7 @@ i_d: im_d
i_io: im_io
#Pattern
patternX: pattern
#Moench
#Advanced

View File

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

View File

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

View File

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

View File

@ -543,7 +543,7 @@ class Caller {
{"patnloop1", &Caller::patnloop1},
{"patnloop2", &Caller::patnloop2},
{"patsetbit", &Caller::patsetbit},
{"patternX", &Caller::pattern},
{"pattern", &Caller::pattern},
{"patternstart", &Caller::patternstart},
{"patwait", &Caller::patwait},
{"patwait0", &Caller::patwait0},
@ -872,6 +872,7 @@ class Caller {
{"i_c", "im_c"},
{"i_d", "im_d"},
{"i_io", "im_io"},
{"patternX", "pattern"},
{"copydetectorserver", "updatedetectorserver"},
{"nframes", "framecounter"},
{"now", "runtime"},

View File

@ -198,7 +198,12 @@ std::string Caller::hostname(int action) {
os << "\n\tFrees shared memory and sets hostname (or IP address) of "
"all modules concatenated by +.\n\t Virtual servers can already "
"use the port in hostname separated by ':' and ports incremented "
"by 2 to accomodate the stop server as well."
"by 2 to accomodate the stop server as well. The row and column "
"values in the udp/zmq header are affected by the order in this "
"command and the detsize command. The modules are stacked row by "
"row until they reach the y-axis limit set by detsize (if "
"specified). Then, stacking continues in the next column and so "
"on. This only affects row and column in udp/zmq header."
<< '\n';
} else if (action == defs::GET_ACTION) {
if (!args.empty()) {

View File

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

View File

@ -488,7 +488,7 @@ class InferAction {
{"patnloop1", &InferAction::patnloop1},
{"patnloop2", &InferAction::patnloop2},
{"patsetbit", &InferAction::patsetbit},
{"patternX", &InferAction::pattern},
{"pattern", &InferAction::pattern},
{"patternstart", &InferAction::patternstart},
{"patwait", &InferAction::patwait},
{"patwait0", &InferAction::patwait0},

View File

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

View File

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

View File

@ -45,9 +45,8 @@ class Receiver : private virtual slsDetectorDefs {
* Call back arguments are:
* - startCallbackHeader metadata
*/
void registerCallBackStartAcquisition(int (*func)(const startCallbackHeader,
void *),
void *arg);
void registerCallBackStartAcquisition(
void (*func)(const startCallbackHeader, void *), void *arg);
/**
* Call back for acquisition finished

View File

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

View File

@ -34,9 +34,8 @@ class ClientInterface : private virtual slsDetectorDefs {
//***callback functions***
/** params: file path, file name, file index, image size */
void registerCallBackStartAcquisition(int (*func)(const startCallbackHeader,
void *),
void *arg);
void registerCallBackStartAcquisition(
void (*func)(const startCallbackHeader, void *), void *arg);
/** params: total frames caught */
void registerCallBackAcquisitionFinished(
@ -180,8 +179,8 @@ class ClientInterface : private virtual slsDetectorDefs {
//***callback parameters***
int (*startAcquisitionCallBack)(const startCallbackHeader,
void *) = nullptr;
void (*startAcquisitionCallBack)(const startCallbackHeader,
void *) = nullptr;
void *pStartAcquisition{nullptr};
void (*acquisitionFinishedCallBack)(const endCallbackHeader,
void *) = nullptr;
@ -194,6 +193,8 @@ class ClientInterface : private virtual slsDetectorDefs {
pid_t tcpThreadId{0};
std::vector<std::string> udpips =
std::vector<std::string>(MAX_NUMBER_OF_LISTENING_THREADS);
// necessary if Receiver objects using threads with callbacks
static std::mutex callbackMutex;
};
} // namespace sls

View File

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

View File

@ -1802,7 +1802,7 @@ void Implementation::setTransceiverEnableMask(uint32_t mask) {
* *
* ************************************************/
void Implementation::registerCallBackStartAcquisition(
int (*func)(const startCallbackHeader, void *), void *arg) {
void (*func)(const startCallbackHeader, void *), void *arg) {
startAcquisitionCallBack = func;
pStartAcquisition = arg;
}

View File

@ -265,9 +265,8 @@ class Implementation : private virtual slsDetectorDefs {
* *
* ************************************************/
/** params: file path, file name, file index, image size */
void registerCallBackStartAcquisition(int (*func)(const startCallbackHeader,
void *),
void *arg);
void registerCallBackStartAcquisition(
void (*func)(const startCallbackHeader, void *), void *arg);
/** params: total frames caught */
void registerCallBackAcquisitionFinished(
void (*func)(const endCallbackHeader, void *), void *arg);
@ -374,7 +373,8 @@ class Implementation : private virtual slsDetectorDefs {
int ctbDbitOffset{0};
// callbacks
int (*startAcquisitionCallBack)(const startCallbackHeader, void *){nullptr};
void (*startAcquisitionCallBack)(const startCallbackHeader,
void *){nullptr};
void *pStartAcquisition{nullptr};
void (*acquisitionFinishedCallBack)(const endCallbackHeader,
void *){nullptr};

View File

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

View File

@ -53,8 +53,8 @@ std::string getHelpMessage() {
* enabled) if registerCallBackRawDataReady or
* registerCallBackRawDataModifyReady registered, users get data
*/
int StartAcq(const slsDetectorDefs::startCallbackHeader callbackHeader,
void *objectPointer) {
void StartAcq(const slsDetectorDefs::startCallbackHeader callbackHeader,
void *objectPointer) {
LOG(sls::logINFOBLUE) << "#### Start Acquisition:"
<< "\n\t["
<< "\n\tUDP Port : "
@ -71,7 +71,6 @@ int StartAcq(const slsDetectorDefs::startCallbackHeader callbackHeader,
<< "\n\tAdditional Json Header : "
<< sls::ToString(callbackHeader.addJsonHeader)
<< "\n\t]";
return 0;
}
/** Acquisition Finished Call back */

View File

@ -134,7 +134,7 @@ std::string Receiver::getReceiverVersion() {
}
void Receiver::registerCallBackStartAcquisition(
int (*func)(const startCallbackHeader, void *), void *arg) {
void (*func)(const startCallbackHeader, void *), void *arg) {
tcpipInterface->registerCallBackStartAcquisition(func, arg);
}

View File

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

View File

@ -5,9 +5,9 @@
#define APIGOTTHARD2 "developer 0x241107"
#define APIMOENCH "developer 0x241107"
#define APIEIGER "developer 0x241107"
#define APIJUNGFRAU "developer 0x241120"
#define APILIB "developer 0x241122"
#define APIRECEIVER "developer 0x241122"
#define APIXILINXCTB "developer 0x250131"
#define APICTB "developer 0x250131"
#define APIMYTHEN3 "developer 0x250131"
#define APIXILINXCTB "developer 0x250213"
#define APIJUNGFRAU "developer 0x250224"
#define APIMYTHEN3 "developer 0x250304"