merge fix

This commit is contained in:
maliakal_d 2021-09-28 16:09:51 +02:00
commit 0b45fdfed8
76 changed files with 2791 additions and 1041 deletions

View File

@ -96,6 +96,20 @@ target_compile_options(slsProjectWarnings INTERFACE
) )
#Settings for C code
add_library(slsProjectCSettings INTERFACE)
target_compile_features(slsProjectCSettings INTERFACE c_std_99)
target_compile_options(slsProjectCSettings INTERFACE
-Wall
-Wextra
-Wno-unused-parameter
-Wdouble-promotion
-Wformat=2
-Wredundant-decls
-Wdouble-promotion
-Werror=return-type
)
#Testing for minimum version for compilers #Testing for minimum version for compilers
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")

View File

@ -1,7 +1,7 @@
SLS Detector Package 5.2.0 released on 28.07.2021 (Minor Release) SLS Detector Package 6.0.0 released on xx.10.2021 (Major Release)
=================================================================== ===================================================================
This document describes the differences between 5.2.0 and 5.1.0 releases. This document describes the differences between 6.0.0 and 5.2.0 releases.
@ -83,16 +83,71 @@ virtual server plots increasing values for every packet.. not every pixel
3. Firmware Requirements 3. Firmware Requirements
======================== ========================
Gotthard2: 0x210201 ??? Eiger
=====
Compatible version : 08.09.2020 (v27)
Jungfrau
========
Compatible version : 31.08.2021 (v1.2, PCB v1.0)
: 10.09.2021 (v2.2, PCB v2.0)
Gotthard
========
Compatible version : 08.02.2018 (50um and 25um Master)
: 09.02.2018 (25 um Slave)
Mythen3
=======
Compatible version : 10.09.2021 (development)
Gotthard2
=========
Compatible version : 27.05.2021 (v1.0)
Moench
======
Compatible version : 05.10.2020 (v1.0)
Ctb
===
Compatible version : 05.10.2020 (v1.0)
Detector Upgrade
================
The following can be upgraded remotely:
Eiger via bit files
Jungfrau via command <.pof>
Mythen3 via command <.rbf>
Gotthard2 via command <.rbf>
Moench via command <.pof>
Ctb via command <.pof>
The following cannot be upgraded remotely:
Gotthard
Instructions available at
https://slsdetectorgroup.github.io/devdoc/firmware.html
and
https://slsdetectorgroup.github.io/devdoc/serverupgrade.html
Other detectors no updates from 5.1.0
5. Known Issues 5. Known Issues
=============== ===============
No updates from 5.1.0 Receiver
--------
1. It does not handle readnrows or partial readout. Only the summary
is adjusted to print in red. However, it will still write complete
images with missing data padded. Roi will be implemented in future
that can be complimented with this feature to remove the additional
data in files.
2. Round robin is not implemented in receiver side, ie. one cannot configure
more than 1 receiver at a time. This will/might be done in the future.

View File

@ -154,6 +154,8 @@ Upgrade (from v5.0.0)
Check :ref:`firmware troubleshooting <blackfin firmware troubleshooting>` if you run into issues while programming firmware. Check :ref:`firmware troubleshooting <blackfin firmware troubleshooting>` if you run into issues while programming firmware.
Always ensure that the client and server software are of the same release.
#. Program from console #. Program from console
.. code-block:: bash .. code-block:: bash
@ -222,6 +224,8 @@ Download
Upgrade (from v5.0.0) Upgrade (from v5.0.0)
^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
Always ensure that the client and server software are of the same release.
#. Program from console #. Program from console
.. code-block:: bash .. code-block:: bash
@ -251,6 +255,8 @@ Download
Upgrade (from v5.0.0) Upgrade (from v5.0.0)
^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
Always ensure that the client and server software are of the same release.
#. Program from console #. Program from console
.. code-block:: bash .. code-block:: bash
@ -278,6 +284,8 @@ Upgrade (from v5.0.0)
Check :ref:`firmware troubleshooting <blackfin firmware troubleshooting>` if you run into issues while programming firmware. Check :ref:`firmware troubleshooting <blackfin firmware troubleshooting>` if you run into issues while programming firmware.
Always ensure that the client and server software are of the same release.
#. Program from console #. Program from console
.. code-block:: bash .. code-block:: bash
@ -304,6 +312,8 @@ Upgrade (from v5.0.0)
Check :ref:`firmware troubleshooting <blackfin firmware troubleshooting>` if you run into issues while programming firmware. Check :ref:`firmware troubleshooting <blackfin firmware troubleshooting>` if you run into issues while programming firmware.
Always ensure that the client and server software are of the same release.
#. Program from console #. Program from console
.. code-block:: bash .. code-block:: bash
@ -344,26 +354,43 @@ Firmware Troubleshooting with blackfin
5. If one can't list it, read the next section to try to get the blackfin to list it. 5. If one can't list it, read the next section to try to get the blackfin to list it.
How to get back mtd3 drive remotely How to get back mtd3 drive remotely (copying new kernel)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This might take a few reruns (maybe even 10) until the mtd drive is accessed by the blackfin upon linux startup.
.. code-block:: bash .. code-block:: bash
# step 1: connect to the board # step 1: get the kernel image (uImage.lzma) from slsdetectorgroup
# and copy it to pc's tftp folder
# step 2: connect to the board
telnet bchipxxx telnet bchipxxx
# step 2: check if mtd3 drive listed #step 3: go to directory for space
more /proc/mtd cd /var/tmp/
# step 3: tell fpga not to touch flash and reboot # step 3: copy kernel to board
echo 9 > /sys/class/gpio/export; tftp pcxxx -r uImage.lzma -g
echo out > /sys/class/gpio/gpio9/direction;
echo 0 > /sys/class/gpio/gpio9/value; # step 4: verify kernel copied properly
ls -lrt
# step 5: erase flash
flash_eraseall /dev/mtd1
# step 6: copy new image to kernel drive
cat uImage.lzma > /dev/mtd1
# step 7:
sync
# step 8:
reboot reboot
# step 4: repeat steps 1 - 3 until you see the mtd3 drive # step 9: verification
telnet bchipxxx
uname -a # verify kernel date
more /proc/mtd # verify mtd3 is listed
Last Resort using USB Blaster Last Resort using USB Blaster
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -41,42 +41,55 @@ Automatic start
One can start the on-board detector server automatically upon powering on the board. One can start the on-board detector server automatically upon powering on the board.
First create a soft link to the binary on board. #. Create a soft link to the binary on board
.. code-block:: bash :
.. code-block:: bash
ln -sf someDetectorServervx.x.x someDetectorServer ln -sf someDetectorServervx.x.x someDetectorServer
Then, do the following depending on the detector type.
Eiger
.. code-block:: bash #. Do the following depending on the detector type :
Eiger
.. code-block:: bash
# create script in rc5.d on the board
vi /etc/rc5.d/S50board_com.sh
# enter the following (edit server name)
#! /bin/sh
/home/root/executables/eigerDetectorServer &> /dev/null &
exit 0
Jungfrau | Moench | CTB | Gotthard I
.. code-block:: bash
# Edit inittab on board
vi /etc/inittab
# enter the following line
ttyS0::respawn:/./xxxDetectorServer
Gotthard II | Mythen III
.. code-block:: bash
# create script in init.d on board
vi /etc/init.d/S99detServer.sh
# enter the following (edit server name)
#! /bin/sh
cd /root >> /dev/null
/root/xxxDetectorServer >> /dev/null &
#. Sync, reboot and verify
:
.. code-block:: bash
# create script in rc5.d on the board sync
vi /etc/rc5.d/S50board_com.sh reboot
# enter the following (edit server name) # verify
#! /bin/sh ps -ef | grep xxxDetectorServer
/home/root/executables/eigerDetectorServer &> /dev/null &
exit 0
Jungfrau | Moench | CTB | Gotthard I
.. code-block:: bash
# Edit inittab on board
vi /etc/inittab
# enter the following line
ttyS0::respawn:/./jungfrauDetectorServer
Gotthard II | Mythen III
.. code-block:: bash
# create script in init.d on the board
vi /etc/init.d/S99detServer.sh
# enter the following (edit server name)
#! /bin/sh
cd /root >> /dev/null
/root/mythen3DetectorServer >> /dev/null &

View File

@ -1,17 +1,5 @@
add_library(slsProjectCSettings INTERFACE)
target_compile_features(slsProjectCSettings INTERFACE c_std_99)
target_compile_options(slsProjectCSettings INTERFACE
-Wall
-Wextra
-Wno-unused-parameter #Needs to be slowly mitigated
-Wdouble-promotion
-Wformat=2
-Wredundant-decls
# -Wconversion
-Wdouble-promotion
-Werror=return-type
)
# Install fake the library # Install fake the library
install(TARGETS slsProjectCSettings install(TARGETS slsProjectCSettings

View File

@ -18,6 +18,7 @@ add_executable(ctbDetectorServer_virtual
../slsDetectorServer/src/programFpgaBlackfin.c ../slsDetectorServer/src/programFpgaBlackfin.c
../slsDetectorServer/src/sharedMemory.c ../slsDetectorServer/src/sharedMemory.c
../slsDetectorServer/src/loadPattern.c ../slsDetectorServer/src/loadPattern.c
../../slsSupportLib/src/md5.c
) )
include_directories( include_directories(

View File

@ -3,6 +3,7 @@ main_inc = ../slsDetectorServer/include/
main_src = ../slsDetectorServer/src/ main_src = ../slsDetectorServer/src/
support_lib = ../../slsSupportLib/include/ support_lib = ../../slsSupportLib/include/
det_lib = ../../slsDetectorSoftware/include/sls/ det_lib = ../../slsDetectorSoftware/include/sls/
md5_dir = ../../slsSupportLib/src/
CROSS = bfin-uclinux- CROSS = bfin-uclinux-
CC = $(CROSS)gcc CC = $(CROSS)gcc
@ -13,7 +14,7 @@ DESTDIR ?= bin
INSTMODE = 0777 INSTMODE = 0777
SRCS = slsDetectorFunctionList.c SRCS = slsDetectorFunctionList.c
SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)blackfin.c $(main_src)common.c $(main_src)commonServerFunctions.c $(main_src)communication_funcs_UDP.c $(main_src)UDPPacketHeaderGenerator.c $(main_src)AD7689.c $(main_src)AD9257.c $(main_src)ALTERA_PLL.c $(main_src)I2C.c $(main_src)INA226.c $(main_src)LTC2620.c $(main_src)MAX1932.c $(main_src)programFpgaBlackfin.c $(main_src)/sharedMemory.c $(main_src)/loadPattern.c SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)blackfin.c $(main_src)common.c $(main_src)commonServerFunctions.c $(main_src)communication_funcs_UDP.c $(main_src)UDPPacketHeaderGenerator.c $(main_src)AD7689.c $(main_src)AD9257.c $(main_src)ALTERA_PLL.c $(main_src)I2C.c $(main_src)INA226.c $(main_src)LTC2620.c $(main_src)MAX1932.c $(main_src)programFpgaBlackfin.c $(main_src)/sharedMemory.c $(main_src)/loadPattern.c $(md5_dir)md5.c
OBJS = $(SRCS:.c=.o) OBJS = $(SRCS:.c=.o)
@ -34,10 +35,10 @@ $(PROGS): $(OBJS)
$(CC) -o $@ $^ $(CFLAGS) $(LDLIBS) $(CC) -o $@ $^ $(CFLAGS) $(LDLIBS)
mv $(PROGS) $(DESTDIR) mv $(PROGS) $(DESTDIR)
rm *.gdb rm *.gdb
rm $(main_src)*.o rm $(main_src)*.o $(md5_dir)*.o
clean: clean:
rm -rf $(DESTDIR)/$(PROGS) *.o *.gdb $(main_src)*.o rm -rf $(DESTDIR)/$(PROGS) *.o *.gdb $(main_src)*.o $(md5_dir)*.o

View File

@ -6,6 +6,7 @@ set(src
../slsDetectorServer/src/communication_funcs_UDP.c ../slsDetectorServer/src/communication_funcs_UDP.c
../slsDetectorServer/src/common.c ../slsDetectorServer/src/common.c
../slsDetectorServer/src/sharedMemory.c ../slsDetectorServer/src/sharedMemory.c
../../slsSupportLib/src/md5.c
) )
include_directories( include_directories(

View File

@ -2,18 +2,19 @@ current_dir = $(shell pwd)
main_inc = ../slsDetectorServer/include/ main_inc = ../slsDetectorServer/include/
main_src = ../slsDetectorServer/src/ main_src = ../slsDetectorServer/src/
support_lib = ../../slsSupportLib/include/ support_lib = ../../slsSupportLib/include/
md5_dir = ../../slsSupportLib/src/
BLACKFIN_CC = bfin-uclinux-gcc BLACKFIN_CC = bfin-uclinux-gcc
CROSS = powerpc-4xx-softfloat- CROSS = powerpc-4xx-softfloat-
CC = $(CROSS)gcc CC = $(CROSS)gcc
CFLAGS += -Wall -std=gnu99 -DEIGERD -DSTOP_SERVER -I$(main_inc) -I$(support_lib) -I$(current_dir) #-DDEBUG1 #-DVERBOSEI #-DVERBOSE CFLAGS += -Wall -std=gnu99 -DEIGERD -DSTOP_SERVER -I$(main_inc) -I$(support_lib) -I$(current_dir) #-DDEBUG1 #-DVERBOSEI #-DVERBOSE
LDLIBS += -lm -lrt -pthread LDLIBS += -lm -lrt -pthread
PROGS = eigerDetectorServer PROGS = eigerDetectorServer
DESTDIR = bin DESTDIR = bin
INSTMODE = 0777 INSTMODE = 0777
SRCS = slsDetectorFunctionList.c HardwareIO.c LocalLinkInterface.c FebInterface.c FebControl.c Beb.c SRCS = slsDetectorFunctionList.c HardwareIO.c LocalLinkInterface.c FebInterface.c FebControl.c Beb.c
SRCS += $(main_src)communication_funcs.c $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs_UDP.c $(main_src)common.c $(main_src)/sharedMemory.c SRCS += $(main_src)communication_funcs.c $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs_UDP.c $(main_src)common.c $(main_src)/sharedMemory.c $(md5_dir)md5.c
OBJS = $(SRCS:.c=.o) OBJS = $(SRCS:.c=.o)
@ -40,9 +41,9 @@ $(PROGS): $(OBJS)
hv9m_blackfin_server:9mhvserial_bf.c hv9m_blackfin_server:9mhvserial_bf.c
$(BLACKFIN_CC) -o hv9m_blackfin_server 9mhvserial_bf.c -Wall #-DVERBOSE $(BLACKFIN_CC) -o hv9m_blackfin_server 9mhvserial_bf.c -Wall #-DVERBOSE
mv hv9m_blackfin_server $(DESTDIR) mv hv9m_blackfin_server $(DESTDIR)
rm hv9m_blackfin_server.gdb $(main_server)*.o rm hv9m_blackfin_server.gdb $(main_src)*.o $(md5_dir)*.o
clean: clean:
rm -rf $(DESTDIR)/$(PROGS) *.o $(DESTDIR)/hv9m_blackfin_server $(main_server)*.o rm -rf $(DESTDIR)/$(PROGS) *.o $(DESTDIR)/hv9m_blackfin_server $(main_src)*.o $(md5_dir)*.o

View File

@ -12,6 +12,7 @@ add_executable(gotthard2DetectorServer_virtual
../slsDetectorServer/src/ASIC_Driver.c ../slsDetectorServer/src/ASIC_Driver.c
../slsDetectorServer/src/programFpgaNios.c ../slsDetectorServer/src/programFpgaNios.c
../slsDetectorServer/src/sharedMemory.c ../slsDetectorServer/src/sharedMemory.c
../../slsSupportLib/src/md5.c
) )
include_directories( include_directories(

View File

@ -2,17 +2,18 @@ current_dir = $(shell pwd)
main_inc = ../slsDetectorServer/include/ main_inc = ../slsDetectorServer/include/
main_src = ../slsDetectorServer/src/ main_src = ../slsDetectorServer/src/
support_lib = ../../slsSupportLib/include/ support_lib = ../../slsSupportLib/include/
md5_dir = ../../slsSupportLib/src/
CROSS = nios2-buildroot-linux-gnu- CROSS = nios2-buildroot-linux-gnu-
CC = $(CROSS)gcc CC = $(CROSS)gcc
CFLAGS += -Wall -std=gnu99 -DGOTTHARD2D -DSTOP_SERVER -I$(main_inc) -I$(support_lib) -I$(current_dir) #-DDEBUG1 #-DVERBOSEI #-DVERBOSE CFLAGS += -Wall -std=gnu99 -DGOTTHARD2D -DSTOP_SERVER -I$(main_inc) -I$(support_lib) -I$(current_dir) #-DDEBUG1 #-DVERBOSEI #-DVERBOSE
LDLIBS += -lm -lrt -pthread LDLIBS += -lm -lrt -pthread
PROGS = gotthard2DetectorServer PROGS = gotthard2DetectorServer
DESTDIR ?= bin DESTDIR ?= bin
INSTMODE = 0777 INSTMODE = 0777
SRCS = slsDetectorFunctionList.c SRCS = slsDetectorFunctionList.c
SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)nios.c $(main_src)common.c $(main_src)DAC6571.c $(main_src)LTC2620_Driver.c $(main_src)ALTERA_PLL_CYCLONE10.c $(main_src)ASIC_Driver.c $(main_src)/programFpgaNios.c $(main_src)/sharedMemory.c SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)nios.c $(main_src)common.c $(main_src)DAC6571.c $(main_src)LTC2620_Driver.c $(main_src)ALTERA_PLL_CYCLONE10.c $(main_src)ASIC_Driver.c $(main_src)/programFpgaNios.c $(main_src)/sharedMemory.c $(md5_dir)md5.c
OBJS = $(SRCS:.c=.o) OBJS = $(SRCS:.c=.o)
@ -34,10 +35,10 @@ $(PROGS): $(OBJS)
mv $(PROGS) $(DESTDIR) mv $(PROGS) $(DESTDIR)
cp config_gotthard2.txt $(DESTDIR) cp config_gotthard2.txt $(DESTDIR)
cp detid_gotthard2.txt $(DESTDIR) cp detid_gotthard2.txt $(DESTDIR)
rm $(main_src)*.o rm $(main_src)*.o $(md5_dir)*.o
clean: clean:
rm -rf $(DESTDIR)/$(PROGS) *.o *.gdb $(main_src)*.o rm -rf $(DESTDIR)/$(PROGS) *.o *.gdb $(main_src)*.o $(md5_dir)*.o

View File

@ -149,6 +149,10 @@
#define ASIC_CONFIG_CURRENT_SRC_EN_MSK (0x00000001 << ASIC_CONFIG_CURRENT_SRC_EN_OFST) #define ASIC_CONFIG_CURRENT_SRC_EN_MSK (0x00000001 << ASIC_CONFIG_CURRENT_SRC_EN_OFST)
#define ASIC_CONFIG_RST_DAC_OFST (15) #define ASIC_CONFIG_RST_DAC_OFST (15)
#define ASIC_CONFIG_RST_DAC_MSK (0x00000001 << ASIC_CONFIG_RST_DAC_OFST) #define ASIC_CONFIG_RST_DAC_MSK (0x00000001 << ASIC_CONFIG_RST_DAC_OFST)
#define ASIC_CONFIG_DOUT_RDY_SRC_OFST (16)
#define ASIC_CONFIG_DOUT_RDY_SRC_MSK (0x0000000F << ASIC_CONFIG_DOUT_RDY_SRC_OFST)
#define ASIC_CONFIG_DOUT_RDY_DLY_OFST (20)
#define ASIC_CONFIG_DOUT_RDY_DLY_MSK (0x000000FF << ASIC_CONFIG_DOUT_RDY_DLY_OFST)
#define ASIC_CONFIG_DONE_OFST (31) #define ASIC_CONFIG_DONE_OFST (31)
#define ASIC_CONFIG_DONE_MSK (0x00000001 << ASIC_CONFIG_DONE_OFST) #define ASIC_CONFIG_DONE_MSK (0x00000001 << ASIC_CONFIG_DONE_OFST)

View File

@ -472,6 +472,11 @@ void setupDetector() {
// power on chip // power on chip
powerChip(1); powerChip(1);
setASICDefaults();
setPhase(READOUT_C1, DEFAULT_CLK1_PHASE_DEG, 1);
setDBITPipeline(DEFAULT_DBIT_PIPELINE);
// also sets default dac and on chip dac values // also sets default dac and on chip dac values
if (readConfigFile() == FAIL) { if (readConfigFile() == FAIL) {
return; return;
@ -503,6 +508,24 @@ void setupDetector() {
setVetoAlgorithm(DEFAULT_ALGORITHM, ETHERNET_10GB); setVetoAlgorithm(DEFAULT_ALGORITHM, ETHERNET_10GB);
} }
void setASICDefaults() {
uint32_t addr = ASIC_CONFIG_REG;
// dout ready source
bus_w(addr, bus_r(addr) & ~ASIC_CONFIG_DOUT_RDY_SRC_MSK);
bus_w(addr, bus_r(addr) | ((DEFAULT_ASIC_DOUT_RDY_SRC
<< ASIC_CONFIG_DOUT_RDY_SRC_OFST) &
ASIC_CONFIG_DOUT_RDY_SRC_MSK));
// dout ready delay
bus_w(addr, bus_r(addr) & ~ASIC_CONFIG_DOUT_RDY_DLY_MSK);
bus_w(addr, bus_r(addr) | ((DEFAULT_ASIC_DOUT_RDY_DLY
<< ASIC_CONFIG_DOUT_RDY_DLY_OFST) &
ASIC_CONFIG_DOUT_RDY_DLY_MSK));
// config done
bus_w(addr, bus_r(addr) | ASIC_CONFIG_DONE_MSK);
LOG(logINFO, ("Setting ASIC Defaults (0x%x)\n", bus_r(addr)));
}
int resetToDefaultDacs(int hardReset) { int resetToDefaultDacs(int hardReset) {
// reset defaults to hardcoded defaults // reset defaults to hardcoded defaults
if (hardReset) { if (hardReset) {

View File

@ -52,8 +52,8 @@
#define DEFAULT_TIMING_SOURCE (TIMING_INTERNAL) #define DEFAULT_TIMING_SOURCE (TIMING_INTERNAL)
#define DEFAULT_ALGORITHM (ALG_HITS) #define DEFAULT_ALGORITHM (ALG_HITS)
#define DEFAULT_READOUT_C0 (6) //(144444448) // rdo_clk, 144 MHz #define DEFAULT_READOUT_C0 (8) //(108333336) // rdo_clk, 144 MHz
#define DEFAULT_READOUT_C1 (6) //(144444448) // rdo_x2_clk, 144 MHz #define DEFAULT_READOUT_C1 (8) //(108333336) // rdo_x2_clk, 144 MHz
#define DEFAULT_SYSTEM_C0 (5) //(144444448) // run_clk, 144 MHz #define DEFAULT_SYSTEM_C0 (5) //(144444448) // run_clk, 144 MHz
#define DEFAULT_SYSTEM_C1 (10) //(72222224) // chip_clk, 72 MHz #define DEFAULT_SYSTEM_C1 (10) //(72222224) // chip_clk, 72 MHz
#define DEFAULT_SYSTEM_C2 (5) //(144444448) // sync_clk, 144 MHz #define DEFAULT_SYSTEM_C2 (5) //(144444448) // sync_clk, 144 MHz
@ -65,6 +65,11 @@
#define READOUT_PLL_VCO_FREQ_HZ (866666688) // 866 MHz #define READOUT_PLL_VCO_FREQ_HZ (866666688) // 866 MHz
#define SYSTEM_PLL_VCO_FREQ_HZ (722222224) // 722 MHz #define SYSTEM_PLL_VCO_FREQ_HZ (722222224) // 722 MHz
#define DEFAULT_CLK1_PHASE_DEG (270)
#define DEFAULT_DBIT_PIPELINE (1)
#define DEFAULT_ASIC_DOUT_RDY_SRC (0x5)
#define DEFAULT_ASIC_DOUT_RDY_DLY (0x3)
#define VETO_DATA_SIZE (160) #define VETO_DATA_SIZE (160)
typedef struct { typedef struct {
uint64_t frameNumber; uint64_t frameNumber;

View File

@ -11,6 +11,7 @@ add_executable(gotthardDetectorServer_virtual
../slsDetectorServer/src/commonServerFunctions.c ../slsDetectorServer/src/commonServerFunctions.c
../slsDetectorServer/src/communication_funcs_UDP.c ../slsDetectorServer/src/communication_funcs_UDP.c
../slsDetectorServer/src/sharedMemory.c ../slsDetectorServer/src/sharedMemory.c
../../slsSupportLib/src/md5.c
) )
include_directories( include_directories(

View File

@ -2,17 +2,18 @@ current_dir = $(shell pwd)
main_inc = ../slsDetectorServer/include/ main_inc = ../slsDetectorServer/include/
main_src = ../slsDetectorServer/src/ main_src = ../slsDetectorServer/src/
support_lib = ../../slsSupportLib/include/ support_lib = ../../slsSupportLib/include/
md5_dir = ../../slsSupportLib/src/
CROSS = bfin-uclinux- CROSS = bfin-uclinux-
CC = $(CROSS)gcc CC = $(CROSS)gcc
CFLAGS += -Wall -std=gnu99 -DGOTTHARDD -DSTOP_SERVER -I$(main_inc) -I$(support_lib) -I$(current_dir)#-DVERBOSEI #-DVERBOSE CFLAGS += -Wall -std=gnu99 -DGOTTHARDD -DSTOP_SERVER -I$(main_inc) -I$(support_lib) -I$(current_dir) #-DVERBOSEI #-DVERBOSE
LDLIBS += -lm -lrt -pthread LDLIBS += -lm -lrt -pthread
PROGS = gotthardDetectorServer PROGS = gotthardDetectorServer
DESTDIR ?= bin DESTDIR ?= bin
INSTMODE = 0777 INSTMODE = 0777
SRCS = slsDetectorFunctionList.c SRCS = slsDetectorFunctionList.c
SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)blackfin.c $(main_src)AD9252.c $(main_src)AD9257.c $(main_src)LTC2620.c $(main_src)common.c $(main_src)commonServerFunctions.c $(main_src)/sharedMemory.c SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)blackfin.c $(main_src)AD9252.c $(main_src)AD9257.c $(main_src)LTC2620.c $(main_src)common.c $(main_src)commonServerFunctions.c $(main_src)/sharedMemory.c $(md5_dir)md5.c
OBJS = $(SRCS:.c=.o) OBJS = $(SRCS:.c=.o)
all: clean $(PROGS) all: clean $(PROGS)
@ -33,10 +34,10 @@ $(PROGS): $(OBJS)
mv $(PROGS) $(DESTDIR) mv $(PROGS) $(DESTDIR)
cp config_gotthard.txt $(DESTDIR) cp config_gotthard.txt $(DESTDIR)
rm *.gdb rm *.gdb
rm $(main_src)*.o rm $(main_src)*.o $(md5_dir)*.o
clean: clean:
rm -rf $(DESTDIR)/$(PROGS) *.o *.gdb $(main_src)*.o rm -rf $(DESTDIR)/$(PROGS) *.o *.gdb $(main_src)*.o $(md5_dir)*.o

View File

@ -13,6 +13,7 @@ add_executable(jungfrauDetectorServer_virtual
../slsDetectorServer/src/programFpgaBlackfin.c ../slsDetectorServer/src/programFpgaBlackfin.c
../slsDetectorServer/src/communication_funcs_UDP.c ../slsDetectorServer/src/communication_funcs_UDP.c
../slsDetectorServer/src/sharedMemory.c ../slsDetectorServer/src/sharedMemory.c
../../slsSupportLib/src/md5.c
) )
target_include_directories(jungfrauDetectorServer_virtual target_include_directories(jungfrauDetectorServer_virtual

View File

@ -2,17 +2,18 @@ current_dir = $(shell pwd)
main_inc = ../slsDetectorServer/include/ main_inc = ../slsDetectorServer/include/
main_src = ../slsDetectorServer/src/ main_src = ../slsDetectorServer/src/
support_lib = ../../slsSupportLib/include/ support_lib = ../../slsSupportLib/include/
md5_dir = ../../slsSupportLib/src/
CROSS = bfin-uclinux- CROSS = bfin-uclinux-
CC = $(CROSS)gcc CC = $(CROSS)gcc
CFLAGS += -Wall -std=gnu99 -DJUNGFRAUD -DSTOP_SERVER -I$(main_inc) -I$(support_lib) -I$(current_dir)#-DVERBOSEI #-DVERBOSE CFLAGS += -Wall -std=gnu99 -DJUNGFRAUD -DSTOP_SERVER -I$(main_inc) -I$(support_lib) -I$(current_dir) #-DVERBOSEI #-DVERBOSE
LDLIBS += -lm -lrt -pthread LDLIBS += -lm -lrt -pthread
PROGS = jungfrauDetectorServer PROGS = jungfrauDetectorServer
DESTDIR ?= bin DESTDIR ?= bin
INSTMODE = 0777 INSTMODE = 0777
SRCS = slsDetectorFunctionList.c SRCS = slsDetectorFunctionList.c
SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)blackfin.c $(main_src)common.c $(main_src)commonServerFunctions.c $(main_src)AD9257.c $(main_src)ALTERA_PLL.c $(main_src)LTC2620.c $(main_src)MAX1932.c $(main_src)programFpgaBlackfin.c $(main_src)/sharedMemory.c SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)blackfin.c $(main_src)common.c $(main_src)commonServerFunctions.c $(main_src)AD9257.c $(main_src)ALTERA_PLL.c $(main_src)LTC2620.c $(main_src)MAX1932.c $(main_src)programFpgaBlackfin.c $(main_src)/sharedMemory.c $(md5_dir)md5.c
OBJS = $(SRCS:.c=.o) OBJS = $(SRCS:.c=.o)
@ -34,10 +35,10 @@ $(PROGS): $(OBJS)
mv $(PROGS) $(DESTDIR) mv $(PROGS) $(DESTDIR)
cp config_jungfrau.txt $(DESTDIR) cp config_jungfrau.txt $(DESTDIR)
rm *.gdb rm *.gdb
rm $(main_src)*.o rm $(main_src)*.o $(md5_dir)*.o
clean: clean:
rm -rf $(DESTDIR)/$(PROGS) *.o *.gdb $(main_src)*.o rm -rf $(DESTDIR)/$(PROGS) *.o *.gdb $(main_src)*.o $(md5_dir)*.o

View File

@ -343,6 +343,8 @@
#define DAQ_FIX_GAIN_STG_2_VAL ((0x3 << DAQ_FIX_GAIN_OFST) & DAQ_FIX_GAIN_MSK) #define DAQ_FIX_GAIN_STG_2_VAL ((0x3 << DAQ_FIX_GAIN_OFST) & DAQ_FIX_GAIN_MSK)
#define DAQ_CMP_RST_OFST (4) #define DAQ_CMP_RST_OFST (4)
#define DAQ_CMP_RST_MSK (0x00000001 << DAQ_CMP_RST_OFST) #define DAQ_CMP_RST_MSK (0x00000001 << DAQ_CMP_RST_OFST)
#define DAQ_CHIP11_VRSN_OFST (7)
#define DAQ_CHIP11_VRSN_MSK (0x00000001 << DAQ_CHIP11_VRSN_OFST)
#define DAQ_STRG_CELL_SLCT_OFST (8) #define DAQ_STRG_CELL_SLCT_OFST (8)
#define DAQ_STRG_CELL_SLCT_MSK (0x0000000F << DAQ_STRG_CELL_SLCT_OFST) #define DAQ_STRG_CELL_SLCT_MSK (0x0000000F << DAQ_STRG_CELL_SLCT_OFST)
#define DAQ_FRCE_SWTCH_GAIN_OFST (12) #define DAQ_FRCE_SWTCH_GAIN_OFST (12)

View File

@ -49,7 +49,6 @@ int defaultDacValue_G0[] = SPECIAL_DEFAULT_DYNAMIC_GAIN_VALS;
int defaultDacValue_HG0[] = SPECIAL_DEFAULT_DYNAMICHG0_GAIN_VALS; int defaultDacValue_HG0[] = SPECIAL_DEFAULT_DYNAMICHG0_GAIN_VALS;
int32_t clkPhase[NUM_CLOCKS] = {}; int32_t clkPhase[NUM_CLOCKS] = {};
int detPos[4] = {}; int detPos[4] = {};
int chipVersion = 10; // (1.0)
int chipConfigured = 0; int chipConfigured = 0;
int isInitCheckDone() { return initCheckDone; } int isInitCheckDone() { return initCheckDone; }
@ -299,7 +298,24 @@ int isHardwareVersion2() {
: 0); : 0);
} }
int getChipVersion() { return chipVersion; } int getChipVersion() {
// chip v1.1
if (bus_r(DAQ_REG | DAQ_CHIP11_VRSN_MSK)) {
return 11;
}
// chip v1.0
return 10;
}
void setChipVersion(int version) {
LOG(logINFO,
("Setting chip version to %0.1f in FPGA\n", (double)version / 10.0));
if (version == 11) {
bus_w(DAQ_REG, bus_r(DAQ_REG) | DAQ_CHIP11_VRSN_MSK);
} else {
bus_w(DAQ_REG, bus_r(DAQ_REG) & ~DAQ_CHIP11_VRSN_MSK);
}
}
u_int32_t getDetectorNumber() { u_int32_t getDetectorNumber() {
#ifdef VIRTUAL #ifdef VIRTUAL
@ -397,11 +413,6 @@ void setupDetector() {
setupUDPCommParameters(); setupUDPCommParameters();
#endif #endif
// get chip version
if (readConfigFile() == FAIL) {
return;
}
ALTERA_PLL_ResetPLL(); ALTERA_PLL_ResetPLL();
resetCore(); resetCore();
resetPeripheral(); resetPeripheral();
@ -436,9 +447,16 @@ void setupDetector() {
PLL_CNTRL_WR_PRMTR_MSK, PLL_CNTRL_PLL_RST_MSK, PLL_CNTRL_ADDR_MSK, PLL_CNTRL_WR_PRMTR_MSK, PLL_CNTRL_PLL_RST_MSK, PLL_CNTRL_ADDR_MSK,
PLL_CNTRL_ADDR_OFST, PLL_CNTRL_DBIT_WR_PRMTR_MSK, DBIT_CLK_INDEX); PLL_CNTRL_ADDR_OFST, PLL_CNTRL_DBIT_WR_PRMTR_MSK, DBIT_CLK_INDEX);
bus_w(DAQ_REG, 0x0); /* Only once at server startup */ /* Only once at server startup */
bus_w(DAQ_REG, 0x0);
LOG(logINFOBLUE, ("Setting Default parameters\n")); LOG(logINFOBLUE, ("Setting Default parameters\n"));
// get chip version
if (readConfigFile() == FAIL) {
return;
}
setClockDivider(RUN_CLK, HALF_SPEED); setClockDivider(RUN_CLK, HALF_SPEED);
cleanFifos(); cleanFifos();
resetCore(); resetCore();
@ -713,17 +731,14 @@ int readConfigFile() {
version, line); version, line);
break; break;
} }
// validations
chipVersion = version;
LOG(logINFOBLUE, ("Chip Version: v%.01f\n", chipVersion / 10.0));
// version 1.1 and HW 1.0 (version reg value = 2) is incompatible // version 1.1 and HW 1.0 (version reg value = 2) is incompatible
if (chipVersion == 11 && isHardwareVersion2()) { if (version == 11 && isHardwareVersion2()) {
strcpy(initErrorMessage, strcpy(initErrorMessage,
"Chip version 1.1 (from on-board config file) is incompatible with old board (v1.0). Please update board or correct on-board config file.\n"); "Chip version 1.1 (from on-board config file) is incompatible with old board (v1.0). Please update board or correct on-board config file.\n");
break; break;
} }
setChipVersion(version);
} }
memset(line, 0, LZ); memset(line, 0, LZ);
@ -1735,11 +1750,13 @@ int isChipConfigured() {
void configureChip() { void configureChip() {
// only for chipv1.1 // only for chipv1.1
if (chipVersion == 11) { if (getChipVersion() == 11) {
LOG(logINFOBLUE, ("Configuring chip\n")); LOG(logINFOBLUE, ("Configuring chip\n"));
// write same register values back to configure chip // write same register values back to configure chip
uint32_t val = bus_r(CONFIG_V11_REG); bus_w(CONFIG_V11_REG, bus_r(CONFIG_V11_REG));
bus_w(CONFIG_V11_REG, val); // default values for current source
bus_w(CRRNT_SRC_COL_LSB_REG, BIT32_MASK);
bus_w(CRRNT_SRC_COL_MSB_REG, BIT32_MASK);
chipConfigured = 1; chipConfigured = 1;
} }
} }
@ -1821,7 +1838,11 @@ int setClockDivider(enum CLKINDEX ind, int val) {
} }
LOG(logINFO, ("Setting Full Speed (40 MHz):\n")); LOG(logINFO, ("Setting Full Speed (40 MHz):\n"));
adcOfst = ADC_OFST_FULL_SPEED_VAL; adcOfst = ADC_OFST_FULL_SPEED_VAL;
sampleAdcSpeed = SAMPLE_ADC_FULL_SPEED; if (getChipVersion() == 10) {
sampleAdcSpeed = SAMPLE_ADC_FULL_SPEED_CHIP10;
} else {
sampleAdcSpeed = SAMPLE_ADC_FULL_SPEED;
}
adcPhase = ADC_PHASE_FULL_SPEED; adcPhase = ADC_PHASE_FULL_SPEED;
dbitPhase = DBIT_PHASE_FULL_SPEED; dbitPhase = DBIT_PHASE_FULL_SPEED;
config = CONFIG_FULL_SPEED_40MHZ_VAL; config = CONFIG_FULL_SPEED_40MHZ_VAL;
@ -1829,27 +1850,43 @@ int setClockDivider(enum CLKINDEX ind, int val) {
case HALF_SPEED: case HALF_SPEED:
LOG(logINFO, ("Setting Half Speed (20 MHz):\n")); LOG(logINFO, ("Setting Half Speed (20 MHz):\n"));
adcOfst = isHardwareVersion2() ? ADC_OFST_HALF_SPEED_BOARD2_VAL if (isHardwareVersion2()) {
: ADC_OFST_HALF_SPEED_VAL; adcOfst = ADC_OFST_HALF_SPEED_BOARD2_VAL;
sampleAdcSpeed = isHardwareVersion2() ? SAMPLE_ADC_HALF_SPEED_BOARD2 sampleAdcSpeed = SAMPLE_ADC_HALF_SPEED_BOARD2;
: SAMPLE_ADC_HALF_SPEED; adcPhase = ADC_PHASE_HALF_SPEED_BOARD2;
adcPhase = isHardwareVersion2() ? ADC_PHASE_HALF_SPEED_BOARD2 dbitPhase = DBIT_PHASE_HALF_SPEED_BOARD2;
: ADC_PHASE_HALF_SPEED; } else if (getChipVersion() == 10) {
dbitPhase = isHardwareVersion2() ? DBIT_PHASE_HALF_SPEED_BOARD2 adcOfst = ADC_OFST_HALF_SPEED_VAL;
: DBIT_PHASE_HALF_SPEED; sampleAdcSpeed = SAMPLE_ADC_HALF_SPEED_CHIP10;
adcPhase = ADC_PHASE_HALF_SPEED;
dbitPhase = DBIT_PHASE_HALF_SPEED;
} else {
adcOfst = ADC_OFST_HALF_SPEED_VAL;
sampleAdcSpeed = SAMPLE_ADC_HALF_SPEED;
adcPhase = ADC_PHASE_HALF_SPEED;
dbitPhase = DBIT_PHASE_HALF_SPEED;
}
config = CONFIG_HALF_SPEED_20MHZ_VAL; config = CONFIG_HALF_SPEED_20MHZ_VAL;
break; break;
case QUARTER_SPEED: case QUARTER_SPEED:
LOG(logINFO, ("Setting Half Speed (10 MHz):\n")); LOG(logINFO, ("Setting Half Speed (10 MHz):\n"));
adcOfst = isHardwareVersion2() ? ADC_OFST_QUARTER_SPEED_BOARD2_VAL if (isHardwareVersion2()) {
: ADC_OFST_QUARTER_SPEED_VAL; adcOfst = ADC_OFST_QUARTER_SPEED_BOARD2_VAL;
sampleAdcSpeed = isHardwareVersion2() ? SAMPLE_ADC_QUARTER_SPEED_BOARD2 sampleAdcSpeed = SAMPLE_ADC_QUARTER_SPEED_BOARD2;
: SAMPLE_ADC_QUARTER_SPEED; adcPhase = ADC_PHASE_QUARTER_SPEED_BOARD2;
adcPhase = isHardwareVersion2() ? ADC_PHASE_QUARTER_SPEED_BOARD2 dbitPhase = DBIT_PHASE_QUARTER_SPEED_BOARD2;
: ADC_PHASE_QUARTER_SPEED; } else if (getChipVersion() == 10) {
dbitPhase = isHardwareVersion2() ? DBIT_PHASE_QUARTER_SPEED_BOARD2 adcOfst = ADC_OFST_QUARTER_SPEED_VAL;
: DBIT_PHASE_QUARTER_SPEED; sampleAdcSpeed = SAMPLE_ADC_QUARTER_SPEED_CHIP10;
adcPhase = ADC_PHASE_QUARTER_SPEED;
dbitPhase = DBIT_PHASE_QUARTER_SPEED;
} else {
adcOfst = ADC_OFST_QUARTER_SPEED_VAL;
sampleAdcSpeed = SAMPLE_ADC_QUARTER_SPEED;
adcPhase = ADC_PHASE_QUARTER_SPEED;
dbitPhase = DBIT_PHASE_QUARTER_SPEED;
}
config = CONFIG_QUARTER_SPEED_10MHZ_VAL; config = CONFIG_QUARTER_SPEED_10MHZ_VAL;
break; break;
@ -2170,7 +2207,7 @@ void disableCurrentSource() {
} }
void enableCurrentSource(int fix, uint64_t select, int normal) { void enableCurrentSource(int fix, uint64_t select, int normal) {
if (chipVersion == 11) { if (getChipVersion() == 11) {
LOG(logINFO, ("Enabling current source [fix:%d, select:%lld]\n", fix, LOG(logINFO, ("Enabling current source [fix:%d, select:%lld]\n", fix,
(long long int)select)); (long long int)select));
} else { } else {
@ -2186,7 +2223,7 @@ void enableCurrentSource(int fix, uint64_t select, int normal) {
} else { } else {
bus_w(DAQ_REG, bus_r(DAQ_REG) & ~DAQ_CRRNT_SRC_CLMN_FIX_MSK); bus_w(DAQ_REG, bus_r(DAQ_REG) & ~DAQ_CRRNT_SRC_CLMN_FIX_MSK);
} }
if (chipVersion == 10) { if (getChipVersion() == 10) {
// select // select
bus_w(DAQ_REG, bus_r(DAQ_REG) & ~DAQ_CRRNT_SRC_CLMN_SLCT_MSK); bus_w(DAQ_REG, bus_r(DAQ_REG) & ~DAQ_CRRNT_SRC_CLMN_SLCT_MSK);
bus_w(DAQ_REG, bus_w(DAQ_REG,
@ -2240,7 +2277,7 @@ int getNormalCurrentSource() {
} }
uint64_t getSelectCurrentSource() { uint64_t getSelectCurrentSource() {
if (chipVersion == 10) { if (getChipVersion() == 10) {
return ((bus_r(DAQ_REG) & DAQ_CRRNT_SRC_CLMN_SLCT_MSK) >> return ((bus_r(DAQ_REG) & DAQ_CRRNT_SRC_CLMN_SLCT_MSK) >>
DAQ_CRRNT_SRC_CLMN_SLCT_OFST); DAQ_CRRNT_SRC_CLMN_SLCT_OFST);
} else { } else {

View File

@ -3,8 +3,8 @@
#include "sls/sls_detector_defs.h" #include "sls/sls_detector_defs.h"
#define MIN_REQRD_VRSN_T_RD_API 0x171220 #define MIN_REQRD_VRSN_T_RD_API 0x171220
#define REQRD_FRMWRE_VRSN_BOARD2 0x210621 // 1.0 pcb (version = 010) #define REQRD_FRMWRE_VRSN_BOARD2 0x210831 // 1.0 pcb (version = 010)
#define REQRD_FRMWRE_VRSN 0x210622 // 2.0 pcb (version = 011) #define REQRD_FRMWRE_VRSN 0x210910 // 2.0 pcb (version = 011)
#define CTRL_SRVR_INIT_TIME_US (300 * 1000) #define CTRL_SRVR_INIT_TIME_US (300 * 1000)
@ -67,9 +67,9 @@ enum DACINDEX {
#define NSPECIALDACS (3) #define NSPECIALDACS (3)
#define SPECIALDACINDEX {J_VREF_PRECH, J_VREF_DS, J_VREF_COMP}; #define SPECIALDACINDEX {J_VREF_PRECH, J_VREF_DS, J_VREF_COMP};
#define SPECIAL_DEFAULT_DYNAMIC_GAIN_VALS \ #define SPECIAL_DEFAULT_DYNAMIC_GAIN_VALS \
{ 1000, 500, 400 } { 1450, 480, 420 }
#define SPECIAL_DEFAULT_DYNAMICHG0_GAIN_VALS \ #define SPECIAL_DEFAULT_DYNAMICHG0_GAIN_VALS \
{ 1500, 550, 450 } { 1450, 480, 420 }
enum NETWORKINDEX { TXN_FRAME, FLOWCTRL_10G }; enum NETWORKINDEX { TXN_FRAME, FLOWCTRL_10G };
enum CLKINDEX { RUN_CLK, ADC_CLK, DBIT_CLK, NUM_CLOCKS }; enum CLKINDEX { RUN_CLK, ADC_CLK, DBIT_CLK, NUM_CLOCKS };
@ -141,16 +141,28 @@ enum CLKINDEX { RUN_CLK, ADC_CLK, DBIT_CLK, NUM_CLOCKS };
#define ADC_PORT_INVERT_VAL (0x5A5A5A5A) #define ADC_PORT_INVERT_VAL (0x5A5A5A5A)
#define ADC_PORT_INVERT_BOARD2_VAL (0x453b2a9c) #define ADC_PORT_INVERT_BOARD2_VAL (0x453b2a9c)
// 2.0 pcb // 2.0 pcb (chipv1.1)
#define SAMPLE_ADC_FULL_SPEED \ #define SAMPLE_ADC_FULL_SPEED \
(SAMPLE_ADC_SAMPLE_0_VAL + SAMPLE_ADC_DECMT_FACTOR_0_VAL + \ (SAMPLE_ADC_SAMPLE_0_VAL + SAMPLE_ADC_DECMT_FACTOR_0_VAL + \
SAMPLE_DGTL_SAMPLE_1_VAL + SAMPLE_DECMT_FACTOR_FULL_VAL) // 0x100 SAMPLE_DGTL_SAMPLE_0_VAL + SAMPLE_DECMT_FACTOR_FULL_VAL) // 0x0000
#define SAMPLE_ADC_HALF_SPEED \ #define SAMPLE_ADC_HALF_SPEED \
(SAMPLE_ADC_SAMPLE_0_VAL + SAMPLE_ADC_DECMT_FACTOR_1_VAL + \ (SAMPLE_ADC_SAMPLE_0_VAL + SAMPLE_ADC_DECMT_FACTOR_1_VAL + \
SAMPLE_DGTL_SAMPLE_3_VAL + SAMPLE_DECMT_FACTOR_HALF_VAL) // 0x1310 SAMPLE_DGTL_SAMPLE_1_VAL + SAMPLE_DECMT_FACTOR_HALF_VAL) // 0x1110
#define SAMPLE_ADC_QUARTER_SPEED \ #define SAMPLE_ADC_QUARTER_SPEED \
(SAMPLE_ADC_SAMPLE_0_VAL + SAMPLE_ADC_DECMT_FACTOR_3_VAL + \
SAMPLE_DGTL_SAMPLE_2_VAL + SAMPLE_DECMT_FACTOR_QUARTER_VAL) // 0x2230
// 2.0 pcb (chipv1.0)
#define SAMPLE_ADC_FULL_SPEED_CHIP10 \
(SAMPLE_ADC_SAMPLE_0_VAL + SAMPLE_ADC_DECMT_FACTOR_0_VAL + \
SAMPLE_DGTL_SAMPLE_1_VAL + SAMPLE_DECMT_FACTOR_FULL_VAL) // 0x0100
#define SAMPLE_ADC_HALF_SPEED_CHIP10 \
(SAMPLE_ADC_SAMPLE_0_VAL + SAMPLE_ADC_DECMT_FACTOR_1_VAL + \
SAMPLE_DGTL_SAMPLE_3_VAL + SAMPLE_DECMT_FACTOR_HALF_VAL) // 0x1310
#define SAMPLE_ADC_QUARTER_SPEED_CHIP10 \
(SAMPLE_ADC_SAMPLE_0_VAL + SAMPLE_ADC_DECMT_FACTOR_3_VAL + \ (SAMPLE_ADC_SAMPLE_0_VAL + SAMPLE_ADC_DECMT_FACTOR_3_VAL + \
SAMPLE_DGTL_SAMPLE_6_VAL + SAMPLE_DECMT_FACTOR_QUARTER_VAL) // 0x2630 SAMPLE_DGTL_SAMPLE_6_VAL + SAMPLE_DECMT_FACTOR_QUARTER_VAL) // 0x2630
// 1.0 pcb (2 resistor network) // 1.0 pcb (2 resistor network)
#define SAMPLE_ADC_HALF_SPEED_BOARD2 \ #define SAMPLE_ADC_HALF_SPEED_BOARD2 \
(SAMPLE_ADC_SAMPLE_0_VAL + SAMPLE_ADC_DECMT_FACTOR_0_VAL + \ (SAMPLE_ADC_SAMPLE_0_VAL + SAMPLE_ADC_DECMT_FACTOR_0_VAL + \
@ -159,13 +171,13 @@ enum CLKINDEX { RUN_CLK, ADC_CLK, DBIT_CLK, NUM_CLOCKS };
(SAMPLE_ADC_SAMPLE_0_VAL + SAMPLE_ADC_DECMT_FACTOR_1_VAL + \ (SAMPLE_ADC_SAMPLE_0_VAL + SAMPLE_ADC_DECMT_FACTOR_1_VAL + \
SAMPLE_DGTL_SAMPLE_6_VAL + SAMPLE_DECMT_FACTOR_QUARTER_VAL) // 0x2610 SAMPLE_DGTL_SAMPLE_6_VAL + SAMPLE_DECMT_FACTOR_QUARTER_VAL) // 0x2610
#define ADC_PHASE_FULL_SPEED (150) // 2.0 pcb #define ADC_PHASE_FULL_SPEED (175) // 2.0 pcb
#define ADC_PHASE_HALF_SPEED (200) // 2.0 pcb #define ADC_PHASE_HALF_SPEED (175) // 2.0 pcb
#define ADC_PHASE_QUARTER_SPEED (200) // 2.0 pcb #define ADC_PHASE_QUARTER_SPEED (175) // 2.0 pcb
#define ADC_PHASE_HALF_SPEED_BOARD2 (110) // 1.0 pcb (2 resistor network) #define ADC_PHASE_HALF_SPEED_BOARD2 (110) // 1.0 pcb (2 resistor network)
#define ADC_PHASE_QUARTER_SPEED_BOARD2 (220) // 1.0 pcb (2 resistor network) #define ADC_PHASE_QUARTER_SPEED_BOARD2 (220) // 1.0 pcb (2 resistor network)
#define DBIT_PHASE_FULL_SPEED (85) // 2.0 pcb #define DBIT_PHASE_FULL_SPEED (100) // 2.0 pcb
#define DBIT_PHASE_HALF_SPEED (150) // 2.0 pcb #define DBIT_PHASE_HALF_SPEED (150) // 2.0 pcb
#define DBIT_PHASE_QUARTER_SPEED (150) // 2.0 pcb #define DBIT_PHASE_QUARTER_SPEED (150) // 2.0 pcb
#define DBIT_PHASE_HALF_SPEED_BOARD2 (150) // 1.0 pcb (2 resistor network) #define DBIT_PHASE_HALF_SPEED_BOARD2 (150) // 1.0 pcb (2 resistor network)

View File

@ -15,6 +15,7 @@ add_executable(moenchDetectorServer_virtual
../slsDetectorServer/src/programFpgaBlackfin.c ../slsDetectorServer/src/programFpgaBlackfin.c
../slsDetectorServer/src/loadPattern.c ../slsDetectorServer/src/loadPattern.c
../slsDetectorServer/src/sharedMemory.c ../slsDetectorServer/src/sharedMemory.c
../../slsSupportLib/src/md5.c
) )
include_directories( include_directories(

View File

@ -3,17 +3,18 @@ main_inc = ../slsDetectorServer/include/
main_src = ../slsDetectorServer/src/ main_src = ../slsDetectorServer/src/
support_lib = ../../slsSupportLib/include/ support_lib = ../../slsSupportLib/include/
det_lib = ../../slsDetectorSoftware/include/sls/ det_lib = ../../slsDetectorSoftware/include/sls/
md5_dir = ../../slsSupportLib/src/
CROSS = bfin-uclinux- CROSS = bfin-uclinux-
CC = $(CROSS)gcc CC = $(CROSS)gcc
CFLAGS += -Wall -std=gnu99 -DMOENCHD -DSTOP_SERVER -I$(main_inc) -I$(support_lib) -I$(det_lib) -I$(current_dir)#-DVERBOSEI #-DVERBOSE CFLAGS += -Wall -std=gnu99 -DMOENCHD -DSTOP_SERVER -I$(main_inc) -I$(support_lib) -I$(det_lib) -I$(current_dir) #-DVERBOSEI #-DVERBOSE
LDLIBS += -lm -lrt -pthread LDLIBS += -lm -lrt -pthread
PROGS = moenchDetectorServer PROGS = moenchDetectorServer
DESTDIR ?= bin DESTDIR ?= bin
INSTMODE = 0777 INSTMODE = 0777
SRCS = slsDetectorFunctionList.c SRCS = slsDetectorFunctionList.c
SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)blackfin.c $(main_src)common.c $(main_src)commonServerFunctions.c $(main_src)communication_funcs_UDP.c $(main_src)UDPPacketHeaderGenerator.c $(main_src)AD9257.c $(main_src)ALTERA_PLL.c $(main_src)LTC2620.c $(main_src)MAX1932.c $(main_src)programFpgaBlackfin.c $(main_src)loadPattern.c $(main_src)/sharedMemory.c SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)blackfin.c $(main_src)common.c $(main_src)commonServerFunctions.c $(main_src)communication_funcs_UDP.c $(main_src)UDPPacketHeaderGenerator.c $(main_src)AD9257.c $(main_src)ALTERA_PLL.c $(main_src)LTC2620.c $(main_src)MAX1932.c $(main_src)programFpgaBlackfin.c $(main_src)loadPattern.c $(main_src)/sharedMemory.c $(md5_dir)md5.c
OBJS = $(SRCS:.c=.o) OBJS = $(SRCS:.c=.o)
@ -36,10 +37,10 @@ $(PROGS): $(OBJS)
cp DefaultPattern_moench.txt $(DESTDIR) cp DefaultPattern_moench.txt $(DESTDIR)
rm *.gdb rm *.gdb
rm $(main_src)*.o rm $(main_src)*.o
rm *.o rm *.o $(md5_dir)*.o
clean: clean:
rm -rf $(DESTDIR)/$(PROGS) *.o *.gdb $(main_src)*.o rm -rf $(DESTDIR)/$(PROGS) *.o *.gdb $(main_src)*.o $(md5_dir)*.o

View File

@ -13,6 +13,7 @@ add_executable(mythen3DetectorServer_virtual
../slsDetectorServer/src/programFpgaNios.c ../slsDetectorServer/src/programFpgaNios.c
../slsDetectorServer/src/loadPattern.c ../slsDetectorServer/src/loadPattern.c
../slsDetectorServer/src/sharedMemory.c ../slsDetectorServer/src/sharedMemory.c
../../slsSupportLib/src/md5.c
) )
include_directories( include_directories(

View File

@ -3,17 +3,18 @@ main_inc = ../slsDetectorServer/include/
main_src = ../slsDetectorServer/src/ main_src = ../slsDetectorServer/src/
support_lib = ../../slsSupportLib/include/ support_lib = ../../slsSupportLib/include/
det_lib = ../../slsDetectorSoftware/include/sls/ det_lib = ../../slsDetectorSoftware/include/sls/
md5_dir = ../../slsSupportLib/src/
CROSS = nios2-buildroot-linux-gnu- CROSS = nios2-buildroot-linux-gnu-
CC = $(CROSS)gcc CC = $(CROSS)gcc
CFLAGS += -Wall -std=gnu99 -DMYTHEN3D -DSTOP_SERVER -I$(main_inc) -I$(support_lib) -I$(det_lib) -I$(current_dir) #-DDEBUG1 #-DVERBOSEI #-DVERBOSE CFLAGS += -Wall -std=gnu99 -DMYTHEN3D -DSTOP_SERVER -I$(main_inc) -I$(support_lib) -I$(det_lib) -I$(current_dir) #-DDEBUG1 #-DVERBOSEI #-DVERBOSE
LDLIBS += -lm -lrt -pthread LDLIBS += -lm -lrt -pthread
PROGS = mythen3DetectorServer PROGS = mythen3DetectorServer
DESTDIR ?= bin DESTDIR ?= bin
INSTMODE = 0777 INSTMODE = 0777
SRCS = slsDetectorFunctionList.c SRCS = slsDetectorFunctionList.c
SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)nios.c $(main_src)DAC6571.c $(main_src)common.c $(main_src)LTC2620_Driver.c $(main_src)ALTERA_PLL_CYCLONE10.c $(main_src)/programFpgaNios.c $(main_src)/sharedMemory.c $(main_src)/loadPattern.c mythen3.c SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)nios.c $(main_src)DAC6571.c $(main_src)common.c $(main_src)LTC2620_Driver.c $(main_src)ALTERA_PLL_CYCLONE10.c $(main_src)/programFpgaNios.c $(main_src)/sharedMemory.c $(main_src)/loadPattern.c mythen3.c $(md5_dir)md5.c
OBJS = $(SRCS:.c=.o) OBJS = $(SRCS:.c=.o)
@ -35,10 +36,10 @@ $(PROGS): $(OBJS)
mv $(PROGS) $(DESTDIR) mv $(PROGS) $(DESTDIR)
cp DefaultPattern_mythen3.txt $(DESTDIR) cp DefaultPattern_mythen3.txt $(DESTDIR)
cp detid_mythen3.txt $(DESTDIR) cp detid_mythen3.txt $(DESTDIR)
rm $(main_src)*.o rm $(main_src)*.o $(md5_dir)*.o
clean: clean:
rm -rf $(DESTDIR)/$(PROGS) *.o *.gdb $(main_src)*.o rm -rf $(DESTDIR)/$(PROGS) *.o *.gdb $(main_src)*.o $(md5_dir)*.o

View File

@ -113,6 +113,12 @@
#define SYSTEM_STATUS_SLV_BRD_DTCT_MSK (0x00000001 << SYSTEM_STATUS_SLV_BRD_DTCT_OFST) #define SYSTEM_STATUS_SLV_BRD_DTCT_MSK (0x00000001 << SYSTEM_STATUS_SLV_BRD_DTCT_OFST)
#define MOD_ID_REG (0x0B * REG_OFFSET + BASE_CONTROL)
#define MOD_ID_OFST (0)
#define MOD_ID_MSK (0x0000FFFF << MOD_ID_OFST)
/* Config RW regiseter */ /* Config RW regiseter */
#define CONFIG_REG (0x20 * REG_OFFSET + BASE_CONTROL) #define CONFIG_REG (0x20 * REG_OFFSET + BASE_CONTROL)

View File

@ -283,7 +283,14 @@ u_int32_t getDetectorNumber() {
int getModuleId(int *ret, char *mess) { int getModuleId(int *ret, char *mess) {
return getModuleIdInFile(ret, mess, ID_FILE); return ((bus_r(MOD_ID_REG) & ~MOD_ID_MSK) >> MOD_ID_OFST);
}
void setModuleId(int modid) {
LOG(logINFOBLUE, ("Setting module id in fpga: %d\n", modid))
bus_w(MOD_ID_REG, bus_r(MOD_ID_REG) & ~MOD_ID_MSK);
bus_w(MOD_ID_REG,
bus_r(MOD_ID_REG) | ((modid << MOD_ID_OFST) & MOD_ID_MSK));
} }
u_int64_t getDetectorMAC() { u_int64_t getDetectorMAC() {
@ -445,12 +452,11 @@ void setupDetector() {
setADIFDefaults(); setADIFDefaults();
// set module id in register // set module id in register
getModuleIdInFile(&initError, initErrorMessage, ID_FILE); int modid = getModuleIdInFile(&initError, initErrorMessage, ID_FILE);
if (initError == FAIL) { if (initError == FAIL) {
return; return;
} }
// until firmware is done setModuleId(modid);
// setModuleId(modid);
// set trigger flow for m3 (for all timing modes) // set trigger flow for m3 (for all timing modes)
bus_w(FLOW_TRIGGER_REG, bus_r(FLOW_TRIGGER_REG) | FLOW_TRIGGER_MSK); bus_w(FLOW_TRIGGER_REG, bus_r(FLOW_TRIGGER_REG) | FLOW_TRIGGER_MSK);

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "sls/sls_detector_defs.h" #include "sls/sls_detector_defs.h"
#define REQRD_FRMWRE_VRSN (0x210201) #define REQRD_FRMWRE_VRSN (0x210910)
#define KERNEL_DATE_VRSN "Wed May 20 13:58:38 CEST 2020" #define KERNEL_DATE_VRSN "Wed May 20 13:58:38 CEST 2020"
#define ID_FILE "detid_mythen3.txt" #define ID_FILE "detid_mythen3.txt"

View File

@ -1,7 +1,9 @@
#pragma once #pragma once
#include "sls/md5.h"
#include <stdint.h> // int64_t #include <stdint.h> // int64_t
#include <stdio.h> #include <stdio.h>
#include <sys/types.h>
#include <time.h> #include <time.h>
enum numberMode { DEC, HEX }; enum numberMode { DEC, HEX };
@ -30,4 +32,10 @@ void validate64(int *ret, char *mess, int64_t arg, int64_t retval,
char *modename, enum numberMode nummode); char *modename, enum numberMode nummode);
int getModuleIdInFile(int *ret, char *mess, char *fileName); int getModuleIdInFile(int *ret, char *mess, char *fileName);
int setModuleIdInFile(char *mess, int arg, char *fileName); int setModuleIdInFile(char *mess, int arg, char *fileName);
int verifyChecksumFromBuffer(char *mess, char *clientChecksum, char *buffer,
ssize_t bytes);
int verifyChecksumFromFile(char *mess, char *clientChecksum, char *fname);
int verifyChecksumFromFlash(char *mess, char *clientChecksum, char *fname,
ssize_t fsize);
int verifyChecksum(char *mess, char *clientChecksum, MD5_CTX *c, char *msg);

View File

@ -2,54 +2,29 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <sys/types.h>
#define TEMP_PROG_FILE_NAME "/var/tmp/tmp.rawbin"
/**
* Define GPIO pins if not defined
*/
void defineGPIOpins(); void defineGPIOpins();
/**
* Notify FPGA to not touch flash
*/
void FPGAdontTouchFlash(); void FPGAdontTouchFlash();
/**
* Notify FPGA to program from flash
*/
void FPGATouchFlash(); void FPGATouchFlash();
/**
* Reset FPGA
*/
void resetFPGA(); void resetFPGA();
int deleteOldFile(char *mess);
/** /**
* Erasing flash * deletes old file
* verify memory available to copy
* open file to copy
*/ */
void eraseFlash(); int preparetoCopyFPGAProgram(FILE **fd, uint64_t fsize, char *mess);
int copyToFlash(ssize_t fsize, char *clientChecksum, char *mess);
/** int getDrive(char *mess);
* Open the drive to copy program and /** Notify fpga not to touch flash, open src and flash drive to write */
* notify FPGA not to touch the program int openFileForFlash(FILE **flashfd, FILE **srcfd, char *mess);
* @param filefp pointer to flash int eraseFlash(char *mess);
* @return 0 for success, 1 for fail (cannot open file for writing program) /* write from tmp file to flash */
int writeToFlash(ssize_t fsize, FILE *flashfd, FILE *srcfd, char *mess);
/** Notify fpga to pick up firmware from flash and wait for status confirmation
*/ */
int startWritingFPGAprogram(FILE **filefp); int waitForFPGAtoTouchFlash(char *mess);
/**
* When done writing the program, close file pointer and
* notify FPGA to pick up the program from flash
* @param filefp pointer to flash
* @return 0 for success, 1 for fail (time taken for fpga to touch flash
* exceeded)
*/
int stopWritingFPGAprogram(FILE *filefp);
/**
* Write FPGA Program to flash
* @param fpgasrc source program
* @param fsize size of program
* @param filefp pointer to flash
* @return 0 for success, 1 for fail (cannot write)
*/
int writeFPGAProgram(char *fpgasrc, uint64_t fsize, FILE *filefp);

View File

@ -11,29 +11,8 @@ void NotifyServerStartSuccess();
/** reset fpga and controller(only implemented for >= v1.1 boards) */ /** reset fpga and controller(only implemented for >= v1.1 boards) */
void rebootControllerAndFPGA(); void rebootControllerAndFPGA();
/** finds the right mtd drive int eraseAndWriteToFlash(char *mess, char *checksum, char *fpgasrc, uint64_t fsize);
* @param mess error message int getDrive(char *mess);
* @returns ok or fail int openFileForFlash(FILE **flashfd, char *mess);
*/ int eraseFlash(char *mess);
int findFlash(char *mess); int writeToFlash(ssize_t fsize, FILE *flashfd, char *buffer, char *mess);
/** erase flash */
void eraseFlash();
/** erase and write flash
* @param mess error message
* @param fpgasrc program source
* @param fsize file size
* @returns ok or fail
*/
int eraseAndWriteToFlash(char *mess, char *fpgasrc, uint64_t fsize);
/**
* Write FPGA Program to flash
* @param mess error message
* @param fpgasrc source program
* @param fsize size of program
* @param filefp pointer to flash
* @return ok or fail
*/
int writeFPGAProgram(char *mess, char *fpgasrc, uint64_t fsize, FILE *filefp);

View File

@ -89,6 +89,7 @@ u_int16_t getHardwareSerialNumber();
#ifdef JUNGFRAUD #ifdef JUNGFRAUD
int isHardwareVersion2(); int isHardwareVersion2();
int getChipVersion(); int getChipVersion();
void setChipVersion(int version);
#endif #endif
#ifndef EIGERD #ifndef EIGERD
u_int32_t getDetectorNumber(); u_int32_t getDetectorNumber();
@ -96,7 +97,7 @@ u_int32_t getDetectorNumber();
#if defined(GOTTHARD2D) || defined(EIGERD) || defined(MYTHEN3D) #if defined(GOTTHARD2D) || defined(EIGERD) || defined(MYTHEN3D)
int getModuleId(int *ret, char *mess); int getModuleId(int *ret, char *mess);
#endif #endif
#ifdef GOTTHARD2D #if defined(GOTTHARD2D) || defined(MYTHEN3D)
void setModuleId(int modid); void setModuleId(int modid);
#endif #endif
u_int64_t getDetectorMAC(); u_int64_t getDetectorMAC();
@ -127,8 +128,10 @@ int resetToDefaultDacs(int hardReset);
int getDefaultDac(enum DACINDEX index, enum detectorSettings sett, int *retval); int getDefaultDac(enum DACINDEX index, enum detectorSettings sett, int *retval);
int setDefaultDac(enum DACINDEX index, enum detectorSettings sett, int value); int setDefaultDac(enum DACINDEX index, enum detectorSettings sett, int value);
#endif #endif
#ifdef MYTHEN3D #if defined(MYTHEN3D) || defined(GOTTHARD2D)
void setASICDefaults(); void setASICDefaults();
#endif
#ifdef MYTHEN3D
void setADIFDefaults(); void setADIFDefaults();
#endif #endif
#if defined(GOTTHARD2D) || defined(EIGERD) || defined(JUNGFRAUD) #if defined(GOTTHARD2D) || defined(EIGERD) || defined(JUNGFRAUD)

View File

@ -271,6 +271,6 @@ int get_module_id(int);
int get_dest_udp_list(int); int get_dest_udp_list(int);
int set_dest_udp_list(int); int set_dest_udp_list(int);
int get_num_dest_list(int); int get_num_dest_list(int);
int set_num_dest_list(int); int clear_all_udp_dst(int);
int get_udp_first_dest(int); int get_udp_first_dest(int);
int set_udp_first_dest(int); int set_udp_first_dest(int);

View File

@ -7,6 +7,7 @@
#include <string.h> #include <string.h>
#include <unistd.h> // readlink #include <unistd.h> // readlink
int ConvertToDifferentRange(int inputMin, int inputMax, int outputMin, int ConvertToDifferentRange(int inputMin, int inputMax, int outputMin,
int outputMax, int inputValue, int *outputValue) { int outputMax, int inputValue, int *outputValue) {
LOG(logDEBUG1, (" Input Value: %d (Input:(%d - %d), Output:(%d - %d))\n", LOG(logDEBUG1, (" Input Value: %d (Input:(%d - %d), Output:(%d - %d))\n",
@ -178,3 +179,147 @@ int setModuleIdInFile(char *mess, int arg, char *fileName) {
} }
return OK; return OK;
} }
int verifyChecksumFromBuffer(char *mess, char *clientChecksum, char *buffer,
ssize_t bytes) {
LOG(logINFO, ("\tVerifying Checksum...\n"));
MD5_CTX c;
if (!MD5_Init_SLS(&c)) {
strcpy(mess, "Unable to calculate checksum (MD5_Init_SLS)\n");
LOG(logERROR, (mess));
return FAIL;
}
if (!MD5_Update_SLS(&c, buffer, bytes)) {
strcpy(mess, "Unable to calculate checksum (MD5_Update_SLS)\n");
LOG(logERROR, (mess));
return FAIL;
}
return verifyChecksum(mess, clientChecksum, &c, "copied program");
}
int verifyChecksumFromFile(char *mess, char *clientChecksum, char *fname) {
LOG(logINFO, ("\tVerifying Checksum...\n"));
FILE *fp = fopen(fname, "r");
if (fp == NULL) {
sprintf(mess, "Unable to open %s in read mode to get checksum\n",
fname);
LOG(logERROR, (mess));
return FAIL;
}
MD5_CTX c;
if (!MD5_Init_SLS(&c)) {
fclose(fp);
strcpy(mess, "Unable to calculate checksum (MD5_Init_SLS)\n");
LOG(logERROR, (mess));
return FAIL;
}
const int readUnitSize = 128;
char buf[readUnitSize];
ssize_t bytes = fread(buf, 1, readUnitSize, fp);
ssize_t totalBytesRead = bytes;
while (bytes > 0) {
if (!MD5_Update_SLS(&c, buf, bytes)) {
fclose(fp);
strcpy(mess, "Unable to calculate checksum (MD5_Update_SLS)\n");
LOG(logERROR, (mess));
return FAIL;
}
bytes = fread(buf, 1, readUnitSize, fp);
totalBytesRead += bytes;
}
LOG(logINFO, ("\tRead %lu bytes to calculate checksum\n", totalBytesRead));
fclose(fp);
return verifyChecksum(mess, clientChecksum, &c, "copied program");
}
int verifyChecksumFromFlash(char *mess, char *clientChecksum, char *fname,
ssize_t fsize) {
LOG(logINFO, ("\tVerifying FlashChecksum...\n"));
FILE *fp = fopen(fname, "r");
if (fp == NULL) {
sprintf(mess, "Unable to open %s in read mode to get checksum\n",
fname);
LOG(logERROR, (mess));
return FAIL;
}
MD5_CTX c;
if (!MD5_Init_SLS(&c)) {
fclose(fp);
strcpy(mess, "Unable to calculate checksum (MD5_Init_SLS)\n");
LOG(logERROR, (mess));
return FAIL;
}
const int readUnitSize = 128;
char buf[readUnitSize];
ssize_t bytes = fread(buf, 1, readUnitSize, fp);
ssize_t totalBytesRead = bytes;
int oldProgress = 0;
while (bytes > 0) {
int progress = (int)(((double)(totalBytesRead) / fsize) * 100);
if (oldProgress != progress) {
printf("%d%%\r", progress);
fflush(stdout);
oldProgress = progress;
}
if (!MD5_Update_SLS(&c, buf, bytes)) {
fclose(fp);
strcpy(mess, "Unable to calculate checksum (MD5_Update_SLS)\n");
LOG(logERROR, (mess));
return FAIL;
}
// read only until a particular size (drive)
if (fsize != 0 && totalBytesRead >= fsize) {
LOG(logINFO, ("\tReached %lu bytes. Not reading more\n", totalBytesRead));
break;
}
bytes = fread(buf, 1, readUnitSize, fp);
totalBytesRead += bytes;
}
LOG(logINFO, ("\tRead %lu bytes to calculate checksum\n", totalBytesRead));
fclose(fp);
int ret = verifyChecksum(mess, clientChecksum, &c, "flash");
if (ret == OK) {
LOG(logINFO, ("Checksum in Flash verified\n"));
}
return ret;
}
int verifyChecksum(char *mess, char *clientChecksum, MD5_CTX *c, char *msg) {
unsigned char out[MD5_DIGEST_LENGTH];
if (!MD5_Final_SLS(out, c)) {
strcpy(mess, "Unable to calculate checksum (MD5_Final_SLS)\n");
LOG(logERROR, (mess));
return FAIL;
}
char checksum[512];
memset(checksum, 0, 512);
for (int i = 0; i != MD5_DIGEST_LENGTH; ++i) {
char part[16];
memset(part, 0, 16);
sprintf(part, "%02x", out[i]);
strcat(checksum, part);
}
LOG(logDEBUG1,
("\nC checksum: %s\nS checksum: %s\n", clientChecksum, checksum));
// compare checksum
if (strcmp(clientChecksum, checksum)) {
sprintf(mess,
"Checksum of %s does not match. Client "
"checksum:%s, copied checksum:%s\n",
msg, clientChecksum, checksum);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tChecksum verified\n"));
return OK;
}

View File

@ -1,19 +1,31 @@
#include "programFpgaBlackfin.h" #include "programFpgaBlackfin.h"
#include "clogger.h" #include "clogger.h"
#include "common.h"
#include "sls/ansi.h" #include "sls/ansi.h"
#include "slsDetectorServer_defs.h" #include "slsDetectorServer_defs.h"
#include <string.h> #include <string.h>
#include <unistd.h> // usleep #include <unistd.h> // usleep
#include <sys/sysinfo.h>
/* global variables */ /* global variables */
#define MTDSIZE 10 // clang-format off
#define MAX_TIME_FPGA_TOUCH_FLASH_US (10 * 1000 * 1000) // 10s #define MAX_TIME_FPGA_TOUCH_FLASH_US (10 * 1000 * 1000) // 10s
#define CMD_GET_FLASH "awk \'$4== \"\\\"bitfile(spi)\\\"\" {print $1}\' /proc/mtd"
#define CMD_FPGA_PICKED_STATUS "cat /sys/class/gpio/gpio7/value"
#define FLASH_BUFFER_MEMORY_SIZE (128 * 1024) // 500 KB
// clang-format on
#define FLASH_DRIVE_NAME_SIZE 16
char flashDriveName[FLASH_DRIVE_NAME_SIZE] = {0};
int gpioDefined = 0; int gpioDefined = 0;
char mtdvalue[MTDSIZE] = {0};
extern int executeCommand(char *command, char *result, enum TLogLevel level);
void defineGPIOpins() { void defineGPIOpins() {
#ifdef VIRTUAL
return;
#endif
if (!gpioDefined) { if (!gpioDefined) {
// define the gpio pins // define the gpio pins
system("echo 7 > /sys/class/gpio/export"); system("echo 7 > /sys/class/gpio/export");
@ -28,35 +40,125 @@ void defineGPIOpins() {
} }
void FPGAdontTouchFlash() { void FPGAdontTouchFlash() {
#ifdef VIRTUAL
return;
#endif
// tell FPGA to not touch flash // tell FPGA to not touch flash
system("echo 0 > /sys/class/gpio/gpio9/value"); system("echo 0 > /sys/class/gpio/gpio9/value");
// usleep(100*1000); // usleep(100*1000);
} }
void FPGATouchFlash() { void FPGATouchFlash() {
#ifdef VIRTUAL
return;
#endif
// tell FPGA to touch flash to program itself // tell FPGA to touch flash to program itself
system("echo 1 > /sys/class/gpio/gpio9/value"); system("echo 1 > /sys/class/gpio/gpio9/value");
} }
void resetFPGA() { void resetFPGA() {
LOG(logINFOBLUE, ("Reseting FPGA\n")); LOG(logINFOBLUE, ("Reseting FPGA\n"));
#ifdef VIRTUAL
return;
#endif
FPGAdontTouchFlash(); FPGAdontTouchFlash();
FPGATouchFlash(); FPGATouchFlash();
usleep(CTRL_SRVR_INIT_TIME_US); usleep(CTRL_SRVR_INIT_TIME_US);
} }
void eraseFlash() { int deleteOldFile(char *mess) {
LOG(logDEBUG1, ("Erasing Flash\n")); char cmd[MAX_STR_LENGTH] = {0};
char command[255]; char retvals[MAX_STR_LENGTH] = {0};
memset(command, 0, 255); sprintf(cmd, "rm -fr %s", TEMP_PROG_FILE_NAME);
sprintf(command, "flash_eraseall %s", mtdvalue); if (FAIL == executeCommand(cmd, retvals, logDEBUG1)) {
system(command); strcpy(mess,
LOG(logINFO, ("Flash erased\n")); "Could not program fpga. (could not delete old file: ");
strncat(mess, retvals, sizeof(mess) - strlen(mess) - 1);
strcat(mess, "\n");
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tDeleted old programming file (%s)\n", TEMP_PROG_FILE_NAME));
return OK;
} }
int startWritingFPGAprogram(FILE **filefp) { int preparetoCopyFPGAProgram(FILE **fd, uint64_t fsize, char *mess) {
LOG(logDEBUG1, ("Start Writing of FPGA program\n"));
if (deleteOldFile(mess) == FAIL) {
return FAIL;
}
// check available memory to copy program
{
struct sysinfo info;
sysinfo(&info);
if (fsize >= info.freeram) {
sprintf(mess,
"Could not program fpga. Not enough memory to copy "
"program. [File size:%ldMB, free RAM: %ldMB]\n",
(long int)(fsize / (1024 * 1024)),
(long int)(info.freeram / (1024 * 1024)));
LOG(logERROR, (mess));
return FAIL;
}
}
// open file to copy program
*fd = fopen(TEMP_PROG_FILE_NAME, "w");
if (*fd == NULL) {
sprintf(mess, "Unable to open %s in write mode\n", TEMP_PROG_FILE_NAME);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tGoing to copy program to %s\n", TEMP_PROG_FILE_NAME));
return OK;
}
int copyToFlash(ssize_t fsize, char *clientChecksum, char *mess) {
if (getDrive(mess) == FAIL) {
return FAIL;
}
FILE *flashfd = NULL;
FILE *srcfd = NULL;
if (openFileForFlash(&flashfd, &srcfd, mess) == FAIL) {
return FAIL;
}
if (eraseFlash(mess) == FAIL) {
fclose(flashfd);
fclose(srcfd);
return FAIL;
}
if (writeToFlash(fsize, flashfd, srcfd, mess) == FAIL) {
return FAIL;
}
if (deleteOldFile(mess) == FAIL) {
return FAIL;
}
/* ignoring this until a consistent way to read from bfin flash
if (verifyChecksumFromFlash(mess, clientChecksum, flashDriveName, fsize) ==
FAIL) {
return FAIL;
}
*/
if (waitForFPGAtoTouchFlash(mess) == FAIL) {
return FAIL;
}
return OK;
}
int getDrive(char *mess) {
#ifdef VIRTUAL
strcpy(flashDriveName, "/tmp/SLS_mtd3");
return OK;
#endif
LOG(logDEBUG1, ("Finding flash drive...\n"));
// getting the drive // getting the drive
// root:/> cat /proc/mtd // root:/> cat /proc/mtd
// dev: size erasesize name // dev: size erasesize name
@ -64,86 +166,189 @@ int startWritingFPGAprogram(FILE **filefp) {
// mtd1: 00100000 00020000 "linux kernel(nor)" // mtd1: 00100000 00020000 "linux kernel(nor)"
// mtd2: 002c0000 00020000 "file system(nor)" // mtd2: 002c0000 00020000 "file system(nor)"
// mtd3: 01000000 00010000 "bitfile(spi)" // mtd3: 01000000 00010000 "bitfile(spi)"
char output[255];
memset(output, 0, 255); char cmd[MAX_STR_LENGTH] = {0};
FILE *fp = popen( char retvals[MAX_STR_LENGTH] = {0};
"awk \'$4== \"\\\"bitfile(spi)\\\"\" {print $1}\' /proc/mtd", "r"); strcpy(cmd, CMD_GET_FLASH);
if (fp == NULL) { if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
LOG(logERROR, ("popen returned NULL. Need that to get mtd drive.\n")); strcpy(mess, "Could not program fpga. (could not get flash drive: ");
return 1; strncat(mess, retvals, sizeof(mess) - strlen(mess) - 1);
strcat(mess, "\n");
LOG(logERROR, (mess));
return FAIL;
} }
if (fgets(output, sizeof(output), fp) == NULL) {
LOG(logERROR, ("fgets returned NULL. Need that to get mtd drive.\n")); char *pch = strtok(retvals, ":");
return 1;
}
pclose(fp);
memset(mtdvalue, 0, MTDSIZE);
strcpy(mtdvalue, "/dev/");
char *pch = strtok(output, ":");
if (pch == NULL) { if (pch == NULL) {
LOG(logERROR, ("Could not get mtd value\n")); strcpy(mess, "Could not get mtd drive to flash (strtok fail).\n");
return 1; LOG(logERROR, (mess));
return FAIL;
} }
strcat(mtdvalue, pch);
LOG(logINFO, ("Flash drive found: %s\n", mtdvalue));
FPGAdontTouchFlash(); memset(flashDriveName, 0, sizeof(flashDriveName));
strcpy(flashDriveName, "/dev/");
// writing the program to flash strcat(flashDriveName, pch);
*filefp = fopen(mtdvalue, "w"); LOG(logINFO, ("\tFlash drive found: %s\n", flashDriveName));
if (*filefp == NULL) { return OK;
LOG(logERROR, ("Unable to open %s in write mode\n", mtdvalue));
return 1;
}
LOG(logINFO, ("Flash ready for writing\n"));
return 0;
} }
int stopWritingFPGAprogram(FILE *filefp) { int openFileForFlash(FILE **flashfd, FILE **srcfd, char *mess) {
LOG(logDEBUG1, ("Stopping of writing FPGA program\n")); FPGAdontTouchFlash();
if (filefp != NULL) { // open src file
fclose(filefp); *srcfd = fopen(TEMP_PROG_FILE_NAME, "r");
if (*srcfd == NULL) {
sprintf(mess,
"Could not flash. Unable to open temp program file %s in read "
"mode\n",
TEMP_PROG_FILE_NAME);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logDEBUG1, ("Temp file ready for reading\n"));
// open flash drive for writing
*flashfd = fopen(flashDriveName, "w");
if (*flashfd == NULL) {
fclose(*srcfd);
sprintf(mess, "Unable to open flash drive %s in write mode\n",
flashDriveName);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tFlash ready for writing\n"));
return OK;
}
int eraseFlash(char *mess) {
LOG(logINFO, ("\tErasing Flash...\n"));
#ifdef VIRTUAL
return OK;
#endif
char cmd[MAX_STR_LENGTH] = {0};
char retvals[MAX_STR_LENGTH] = {0};
sprintf(cmd, "flash_eraseall %s", flashDriveName);
if (FAIL == executeCommand(cmd, retvals, logDEBUG1)) {
strcpy(mess, "Could not program fpga. (could not erase flash: ");
strncat(mess, retvals, sizeof(mess) - strlen(mess) - 1);
strcat(mess, "\n");
LOG(logERROR, (mess));
return FAIL;
} }
// touch and program LOG(logINFO, ("\tFlash erased\n"));
return OK;
}
int writeToFlash(ssize_t fsize, FILE *flashfd, FILE *srcfd, char *mess) {
LOG(logDEBUG1, ("writing to flash\n"));
char* buffer = malloc(FLASH_BUFFER_MEMORY_SIZE);
if (buffer == NULL) {
fclose(flashfd);
fclose(srcfd);
strcpy(mess, "Could not program fpga. Memory allocation to write to "
"flash failed.\n");
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tWriting to Flash...\n"));
int oldProgress = 0;
ssize_t totalBytes = 0;
ssize_t bytes = fread((void*)buffer, sizeof(char), FLASH_BUFFER_MEMORY_SIZE, srcfd);
while (bytes > 0) {
ssize_t bytesWritten =
fwrite((void*)buffer, sizeof(char), bytes, flashfd);
totalBytes += bytesWritten;
if (bytesWritten != bytes) {
free(buffer);
fclose(flashfd);
fclose(srcfd);
sprintf(mess,
"Could not write to flash (bytes written:%ld, expected: "
"%ld, total written:%ld)\n",
(long int)bytesWritten, (long int)bytes,
(long int)totalBytes);
LOG(logERROR, (mess));
return FAIL;
}
// print progress
if (fsize > 0) {
int progress = (int)(((double)(totalBytes) / fsize) * 100);
if (oldProgress != progress) {
printf("%d%%\r", progress);
fflush(stdout);
oldProgress = progress;
}
} else printf(".");
bytes = fread((void*)buffer, sizeof(char), FLASH_BUFFER_MEMORY_SIZE, srcfd);
}
if (fsize <= 0) {
printf("\n");
}
free(buffer);
fclose(flashfd);
fclose(srcfd);
LOG(logINFO, ("\tWrote %ld bytes to flash\n", totalBytes));
if (totalBytes != fsize) {
sprintf(mess, "Could not program fpga. Incorrect bytes written to flash %lu [expected: %lu]\n", totalBytes, fsize);
LOG(logERROR, (mess));
return FAIL;
}
return OK;
}
int waitForFPGAtoTouchFlash(char* mess) {
// touch and program
FPGATouchFlash(); FPGATouchFlash();
LOG(logINFO, ("Waiting for FPGA to program from flash\n")); #ifdef VIRTUAL
// waiting for success or done return OK;
char output[255]; #endif
int res = 0; LOG(logINFO, ("\tWaiting for FPGA to program from flash\n"));
int timeSpent = 0; int timeSpent = 0;
while (res == 0) {
int result = 0;
while (result == 0) {
// time taken for fpga to pick up from flash // time taken for fpga to pick up from flash
usleep(1000); usleep(1000);
timeSpent += 1000; timeSpent += 1000;
if (timeSpent >= MAX_TIME_FPGA_TOUCH_FLASH_US) { if (timeSpent >= MAX_TIME_FPGA_TOUCH_FLASH_US) {
return 1; sprintf(mess, "Could not program fpga. (exceeded max time allowed: %ds)\n",
MAX_TIME_FPGA_TOUCH_FLASH_US/(1000 * 1000));
LOG(logERROR, (mess));
return FAIL;
} }
FILE *sysFile = popen("cat /sys/class/gpio/gpio7/value", "r");
fgets(output, sizeof(output), sysFile);
pclose(sysFile);
sscanf(output, "%d", &res);
LOG(logDEBUG1, ("gpi07 returned %d\n", res));
}
LOG(logINFO, ("FPGA has picked up the program from flash\n"));
return 0;
}
int writeFPGAProgram(char *fpgasrc, uint64_t fsize, FILE *filefp) { // read gpio status
LOG(logDEBUG1, char retvals[MAX_STR_LENGTH] = {0};
("Writing of FPGA Program\n" if (FAIL == executeCommand(CMD_FPGA_PICKED_STATUS, retvals, logDEBUG1)) {
"\taddress of fpgasrc:%p\n" strcpy(mess,
"\tfsize:%llu\n\tpointer:%p\n", "Could not program fpga. (could not read gpio status: ");
(void *)fpgasrc, (long long unsigned int)fsize, (void *)filefp)); strncat(mess, retvals, sizeof(mess) - strlen(mess) - 1);
strcat(mess, "\n");
LOG(logERROR, (mess));
return FAIL;
}
if (fwrite((void *)fpgasrc, sizeof(char), fsize, filefp) != fsize) { // convert to int
LOG(logERROR, ("Could not write FPGA source to flash (size:%llu)\n", if (sscanf(retvals, "%d\n", &result) != 1) {
(long long unsigned int)fsize)); sprintf(mess, "Could not program fpga. (could not scan int for gpio status: [%s])\n",
return 1; retvals);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logDEBUG1, ("gpi07 returned %d\n", result));
} }
LOG(logDEBUG1, ("program written to flash\n")); LOG(logINFO, ("\tFPGA has picked up the program from flash\n"));
return 0; return OK;
} }

View File

@ -1,5 +1,6 @@
#include "programFpgaNios.h" #include "programFpgaNios.h"
#include "clogger.h" #include "clogger.h"
#include "common.h"
#include "sls/ansi.h" #include "sls/ansi.h"
#include "slsDetectorServer_defs.h" #include "slsDetectorServer_defs.h"
@ -7,10 +8,15 @@
#include <unistd.h> // usleep #include <unistd.h> // usleep
/* global variables */ /* global variables */
#define MTDSIZE 10
char mtdvalue[MTDSIZE] = {0}; #define CMD_GET_FLASH "awk \'$5== \"Application\" {print $1}\' /proc/mtd"
#define FLASH_DRIVE_NAME_SIZE 16
char flashDriveName[FLASH_DRIVE_NAME_SIZE] = {0};
#define MICROCONTROLLER_FILE "/dev/ttyAL0" #define MICROCONTROLLER_FILE "/dev/ttyAL0"
extern int executeCommand(char *command, char *result, enum TLogLevel level);
void NotifyServerStartSuccess() { void NotifyServerStartSuccess() {
LOG(logINFOBLUE, ("Server started successfully\n")); LOG(logINFOBLUE, ("Server started successfully\n"));
char command[255]; char command[255];
@ -27,7 +33,44 @@ void rebootControllerAndFPGA() {
system(command); system(command);
} }
int findFlash(char *mess) { int eraseAndWriteToFlash(char *mess, char *checksum, char *fpgasrc,
uint64_t fsize) {
if (verifyChecksumFromBuffer(mess, checksum, fpgasrc, fsize) == FAIL) {
return FAIL;
}
if (getDrive(mess) == FAIL) {
return FAIL;
}
FILE *flashfd = NULL;
if (openFileForFlash(&flashfd, mess) == FAIL) {
return FAIL;
}
if (eraseFlash(mess) == FAIL) {
fclose(flashfd);
return FAIL;
}
if (writeToFlash(fsize, flashfd, fpgasrc, mess) == FAIL) {
return FAIL;
}
/* ignoring this until a consistent way to read from nios flash
if (verifyChecksumFromFlash(mess, checksum, flashDriveName, fsize) ==
FAIL) {
return FAIL;
}
*/
return OK;
}
int getDrive(char *mess) {
#ifdef VIRTUAL
strcpy(flashDriveName, "/tmp/SLS_mtd3");
return OK;
#endif
LOG(logDEBUG1, ("Finding flash drive...\n")); LOG(logDEBUG1, ("Finding flash drive...\n"));
// getting the drive // getting the drive
// # cat /proc/mtd // # cat /proc/mtd
@ -38,82 +81,78 @@ int findFlash(char *mess) {
// mtd3: 00800000 00010000 "qspi Linux Kernel with initramfs Backup" // mtd3: 00800000 00010000 "qspi Linux Kernel with initramfs Backup"
// mtd4: 02500000 00010000 "qspi ubi filesystem" // mtd4: 02500000 00010000 "qspi ubi filesystem"
// mtd5: 04000000 00010000 "qspi Complete Flash" // mtd5: 04000000 00010000 "qspi Complete Flash"
char output[255];
memset(output, 0, 255); char cmd[MAX_STR_LENGTH] = {0};
FILE *fp = popen("awk \'$5== \"Application\" {print $1}\' /proc/mtd", "r"); char retvals[MAX_STR_LENGTH] = {0};
if (fp == NULL) { strcpy(cmd, CMD_GET_FLASH);
strcpy(mess, "popen returned NULL. Need that to get mtd drive.\n"); if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
strcpy(mess, "Could not program fpga. (could not get flash drive: ");
strncat(mess, retvals, sizeof(mess) - strlen(mess) - 1);
strcat(mess, "\n");
LOG(logERROR, (mess)); LOG(logERROR, (mess));
return FAIL; return FAIL;
} }
if (fgets(output, sizeof(output), fp) == NULL) {
strcpy(mess, "fgets returned NULL. Need that to get mtd drive.\n"); char *pch = strtok(retvals, ":");
LOG(logERROR, (mess));
return FAIL;
}
pclose(fp);
memset(mtdvalue, 0, MTDSIZE);
strcpy(mtdvalue, "/dev/");
char *pch = strtok(output, ":");
if (pch == NULL) { if (pch == NULL) {
strcpy(mess, "Could not get mtd value\n"); strcpy(mess, "Could not get mtd drive to flash (strtok fail).\n");
LOG(logERROR, (mess)); LOG(logERROR, (mess));
return FAIL; return FAIL;
} }
strcat(mtdvalue, pch);
LOG(logINFO, ("\tFlash drive found: %s\n", mtdvalue)); memset(flashDriveName, 0, sizeof(flashDriveName));
strcpy(flashDriveName, "/dev/");
strcat(flashDriveName, pch);
LOG(logINFO, ("\tFlash drive found: %s\n", flashDriveName));
return OK; return OK;
} }
void eraseFlash() { int openFileForFlash(FILE **flashfd, char *mess) {
LOG(logDEBUG1, ("Erasing Flash...\n")); *flashfd = fopen(flashDriveName, "w");
char command[255]; if (*flashfd == NULL) {
memset(command, 0, 255); sprintf(mess, "Unable to open flash drive %s in write mode\n",
sprintf(command, "flash_erase %s 0 0", mtdvalue); flashDriveName);
system(command);
LOG(logINFO, ("\tFlash erased\n"));
}
int eraseAndWriteToFlash(char *mess, char *fpgasrc, uint64_t fsize) {
if (findFlash(mess) == FAIL) {
return FAIL;
}
eraseFlash();
// open file pointer to flash
FILE *filefp = fopen(mtdvalue, "w");
if (filefp == NULL) {
sprintf(mess, "Unable to open %s in write mode\n", mtdvalue);
LOG(logERROR, (mess)); LOG(logERROR, (mess));
return FAIL; return FAIL;
} }
LOG(logINFO, ("\tFlash ready for writing\n")); LOG(logINFO, ("\tFlash ready for writing\n"));
// write to flash
if (writeFPGAProgram(mess, fpgasrc, fsize, filefp) == FAIL) {
fclose(filefp);
return FAIL;
}
fclose(filefp);
return OK; return OK;
} }
int writeFPGAProgram(char *mess, char *fpgasrc, uint64_t fsize, FILE *filefp) { int eraseFlash(char *mess) {
LOG(logDEBUG1, ("Writing to flash...\n" LOG(logINFO, ("\tErasing Flash...\n"));
"\taddress of fpgasrc:%p\n"
"\tfsize:%lu\n\tpointer:%p\n",
(void *)fpgasrc, fsize, (void *)filefp));
uint64_t retval = fwrite((void *)fpgasrc, sizeof(char), fsize, filefp); #ifdef VIRTUAL
if (retval != fsize) { return OK;
sprintf( #endif
mess, char cmd[MAX_STR_LENGTH] = {0};
"Could not write FPGA source to flash (size:%llu), write %llu\n", char retvals[MAX_STR_LENGTH] = {0};
(long long unsigned int)fsize, (long long unsigned int)retval); sprintf(cmd, "flash_erase %s 0 0", flashDriveName);
if (FAIL == executeCommand(cmd, retvals, logDEBUG1)) {
strcpy(mess, "Could not program fpga. (could not erase flash: ");
strncat(mess, retvals, sizeof(mess) - strlen(mess) - 1);
strcat(mess, "\n");
LOG(logERROR, (mess)); LOG(logERROR, (mess));
return FAIL; return FAIL;
} }
LOG(logINFO, ("\tProgram written to flash\n"));
LOG(logINFO, ("\tFlash erased\n"));
return OK;
}
int writeToFlash(ssize_t fsize, FILE *flashfd, char *buffer, char *mess) {
LOG(logINFO, ("\tWriting to Flash...\n"));
ssize_t bytesWritten = fwrite((void *)buffer, sizeof(char), fsize, flashfd);
if (bytesWritten != fsize) {
fclose(flashfd);
sprintf(
mess,
"Could not program fpga. Incorrect bytes written to flash %lu [expected: %lu]\n",
(long int)bytesWritten, (long int)fsize);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tWritten to Flash\n"));
return OK; return OK;
} }

View File

@ -14,6 +14,7 @@
#include <pthread.h> #include <pthread.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <sys/sysinfo.h>
// defined in the detector specific Makefile // defined in the detector specific Makefile
#ifdef GOTTHARDD #ifdef GOTTHARDD
@ -407,7 +408,7 @@ void function_table() {
flist[F_GET_DEST_UDP_LIST] = &get_dest_udp_list; flist[F_GET_DEST_UDP_LIST] = &get_dest_udp_list;
flist[F_SET_DEST_UDP_LIST] = &set_dest_udp_list; flist[F_SET_DEST_UDP_LIST] = &set_dest_udp_list;
flist[F_GET_NUM_DEST_UDP] = &get_num_dest_list; flist[F_GET_NUM_DEST_UDP] = &get_num_dest_list;
flist[F_SET_NUM_DEST_UDP] = &set_num_dest_list; flist[F_CLEAR_ALL_UDP_DEST] = &clear_all_udp_dst;
flist[F_GET_UDP_FIRST_DEST] = &get_udp_first_dest; flist[F_GET_UDP_FIRST_DEST] = &get_udp_first_dest;
flist[F_SET_UDP_FIRST_DEST] = &set_udp_first_dest; flist[F_SET_UDP_FIRST_DEST] = &set_udp_first_dest;
@ -444,11 +445,13 @@ int executeCommand(char *command, char *result, enum TLogLevel level) {
memset(temp, 0, tempsize); memset(temp, 0, tempsize);
memset(result, 0, MAX_STR_LENGTH); memset(result, 0, MAX_STR_LENGTH);
LOG(level, ("Executing command:\n[%s]\n", command)); // copy command
strcat(command, " 2>&1"); char cmd[MAX_STR_LENGTH]= {0};
sprintf(cmd, "%s 2>&1", command);
LOG(level, ("Executing command:\n[%s]\n", cmd));
fflush(stdout); fflush(stdout);
FILE *sysFile = popen(command, "r"); FILE *sysFile = popen(cmd, "r");
while (fgets(temp, tempsize, sysFile) != NULL) { while (fgets(temp, tempsize, sysFile) != NULL) {
// size left excludes terminating character // size left excludes terminating character
size_t sizeleft = MAX_STR_LENGTH - strlen(result) - 1; size_t sizeleft = MAX_STR_LENGTH - strlen(result) - 1;
@ -460,16 +463,19 @@ int executeCommand(char *command, char *result, enum TLogLevel level) {
strncat(result, temp, tempsize); strncat(result, temp, tempsize);
memset(temp, 0, tempsize); memset(temp, 0, tempsize);
} }
int sucess = pclose(sysFile); result[MAX_STR_LENGTH - 1] = '\0';
int success = pclose(sysFile);
if (strlen(result)) { if (strlen(result)) {
if (sucess) { if (success) {
sucess = FAIL; success = FAIL;
LOG(logERROR, ("%s\n", result)); LOG(logERROR, ("%s\n", result));
} else { } else {
LOG(level, ("Result:\n[%s]\n", result)); LOG(level, ("Result:\n[%s]\n", result));
} }
} else {
LOG(level, ("No result\n"));
} }
return sucess; return success;
} }
int M_nofunc(int file_des) { int M_nofunc(int file_des) {
@ -1497,7 +1503,7 @@ int set_module(int file_des) {
ret = OK; ret = OK;
memset(mess, 0, sizeof(mess)); memset(mess, 0, sizeof(mess));
#if defined(CHIPTESTBOARDD) || defined(MOENCHD) || defined(GOTTHARD2D) #if !(defined(MYTHEN3D) || defined(EIGERD))
functionNotImplemented(); functionNotImplemented();
#else #else
@ -1518,7 +1524,6 @@ int set_module(int file_des) {
} else } else
module.dacs = myDac; module.dacs = myDac;
#if defined(EIGERD) || defined(MYTHEN3D)
// allocate chans // allocate chans
if (ret == OK) { if (ret == OK) {
myChan = malloc(getTotalNumberOfChannels() * sizeof(int)); myChan = malloc(getTotalNumberOfChannels() * sizeof(int));
@ -1529,7 +1534,6 @@ int set_module(int file_des) {
} else } else
module.chanregs = myChan; module.chanregs = myChan;
} }
#endif
// receive arguments // receive arguments
if (ret == OK) { if (ret == OK) {
module.nchip = getNumberOfChips(); module.nchip = getNumberOfChips();
@ -1567,6 +1571,7 @@ int set_module(int file_des) {
// setsettings // setsettings
#ifndef MYTHEN3D #ifndef MYTHEN3D
// m3 uses reg for chip (not settings)
validate_settings((enum detectorSettings)(module.reg)); validate_settings((enum detectorSettings)(module.reg));
#endif #endif
ret = setModule(module, mess); ret = setModule(module, mess);
@ -3674,19 +3679,25 @@ int program_fpga(int file_des) {
n = receiveData(file_des, mess, MAX_STR_LENGTH, OTHER); n = receiveData(file_des, mess, MAX_STR_LENGTH, OTHER);
functionNotImplemented(); functionNotImplemented();
#else #else
#ifndef VIRTUAL
// only set // only set
if (Server_VerifyLock() == OK) { if (Server_VerifyLock() == OK) {
LOG(logINFOBLUE, ("Programming FPGA...\n")); LOG(logINFOBLUE, ("Programming FPGA...\n"));
#if defined(MYTHEN3D) || defined(GOTTHARD2D)
uint64_t filesize = 0;
// filesize // filesize
uint64_t filesize = 0;
if (receiveData(file_des, &filesize, sizeof(filesize), INT64) < 0) if (receiveData(file_des, &filesize, sizeof(filesize), INT64) < 0)
return printSocketReadError(); return printSocketReadError();
LOG(logDEBUG1, ("Total program size is: %llx\n", LOG(logDEBUG1, ("Program size is: %lld\n", (long long int)filesize));
(long long unsigned int)filesize));
// checksum
char checksum[MAX_STR_LENGTH];
memset(checksum, 0, MAX_STR_LENGTH);
if (receiveData(file_des, checksum, MAX_STR_LENGTH, OTHER) < 0)
return printSocketReadError();
LOG(logDEBUG1, ("checksum is: %s\n\n", checksum));
#if defined(MYTHEN3D) || defined(GOTTHARD2D)
if (filesize > NIOS_MAX_APP_IMAGE_SIZE) { if (filesize > NIOS_MAX_APP_IMAGE_SIZE) {
ret = FAIL; ret = FAIL;
sprintf(mess, sprintf(mess,
@ -3701,119 +3712,108 @@ int program_fpga(int file_des) {
// receive program // receive program
if (ret == OK) { if (ret == OK) {
char *fpgasrc = malloc(filesize); char *fpgasrc = malloc(filesize);
if (receiveData(file_des, fpgasrc, filesize, OTHER) < 0) if (receiveData(file_des, fpgasrc, filesize, OTHER) < 0) {
free(fpgasrc);
return printSocketReadError(); return printSocketReadError();
}
ret = eraseAndWriteToFlash(mess, fpgasrc, filesize); ret = eraseAndWriteToFlash(mess, checksum, fpgasrc, filesize);
Server_SendResult(file_des, INT32, NULL, 0); Server_SendResult(file_des, INT32, NULL, 0);
// free resources
free(fpgasrc); free(fpgasrc);
} }
if (ret == FAIL) {
LOG(logERROR, ("Program FPGA FAIL!\n"));
return FAIL;
}
#else // jungfrau, ctb, moench #else // jungfrau, ctb, moench
uint64_t filesize = 0;
uint64_t totalsize = 0;
uint64_t unitprogramsize = 0;
char *fpgasrc = NULL;
FILE *fp = NULL;
// filesize // open file and allocate memory for part program
if (receiveData(file_des, &filesize, sizeof(filesize), INT32) < 0) FILE *fd = NULL;
return printSocketReadError(); ret = preparetoCopyFPGAProgram(&fd, filesize, mess);
totalsize = filesize; char *src = NULL;
LOG(logDEBUG1, ("Total program size is: %lld\n", if (ret == OK) {
(long long unsigned int)totalsize)); src = malloc(MAX_FPGAPROGRAMSIZE);
if (src == NULL) {
// opening file pointer to flash and telling FPGA to not touch flash fclose(fd);
if (startWritingFPGAprogram(&fp) != OK) { struct sysinfo info;
ret = FAIL; sysinfo(&info);
sprintf(mess, "Could not write to flash. Error at startup.\n"); sprintf(mess, "Could not allocate memory to get fpga program. Free space: %d MB\n", (int)(info.freeram/ (1024 * 1024)));
LOG(logERROR, (mess)); LOG(logERROR, (mess));
ret = FAIL;
}
} }
Server_SendResult(file_des, INT32, NULL, 0); Server_SendResult(file_des, INT32, NULL, 0);
if (ret == FAIL) {
// erasing flash LOG(logERROR, ("Program FPGA FAIL1!\n"));
if (ret != FAIL) { return FAIL;
eraseFlash();
fpgasrc = malloc(MAX_FPGAPROGRAMSIZE);
} }
// writing to flash part by part // copying program part by part
int clientSocketCrash = 0; uint64_t totalsize = filesize;
while (ret != FAIL && filesize) { while (ret == OK && filesize) {
uint64_t unitprogramsize = MAX_FPGAPROGRAMSIZE; // 2mb
unitprogramsize = MAX_FPGAPROGRAMSIZE; // 2mb if (unitprogramsize > filesize) // less than 2mb
if (unitprogramsize > filesize) // less than 2mb
unitprogramsize = filesize; unitprogramsize = filesize;
LOG(logDEBUG1, ("unit size to receive is:%lld\nfilesize:%lld\n", LOG(logDEBUG1, ("unit size to receive is:%lld [filesize:%lld]\n",
(long long unsigned int)unitprogramsize, (long long unsigned int)unitprogramsize,
(long long unsigned int)filesize)); (long long unsigned int)filesize));
// receive part of program // receive part of program
if (receiveData(file_des, fpgasrc, unitprogramsize, OTHER) < 0) { if (receiveData(file_des, src, unitprogramsize, OTHER) < 0) {
printSocketReadError(); printSocketReadError();
clientSocketCrash = 1; break;
}
if (unitprogramsize - filesize == 0) {
// src[unitprogramsize] = '\0';
filesize -= unitprogramsize;
// unitprogramsize++;
} else
filesize -= unitprogramsize;
// copy program
if (fwrite((void *)src, sizeof(char), unitprogramsize, fd) !=
unitprogramsize) {
ret = FAIL; ret = FAIL;
} sprintf(mess, "Could not copy program to /var/tmp (size:%ld)\n",
// client has not crashed yet, so write to flash and send ret (long int)unitprogramsize);
else {
if (!(unitprogramsize - filesize)) {
fpgasrc[unitprogramsize] = '\0';
filesize -= unitprogramsize;
unitprogramsize++;
} else
filesize -= unitprogramsize;
// write part to flash
ret = writeFPGAProgram(fpgasrc, unitprogramsize, fp);
Server_SendResult(file_des, INT32, NULL, 0);
if (ret == FAIL) {
strcpy(mess, "Could not write to flash. Breaking out of "
"program receiving. Try to flash again "
"without rebooting.\n");
LOG(logERROR, (mess));
} else {
// print progress
LOG(logINFO,
("Writing to Flash:%d%%\r",
(int)(((double)(totalsize - filesize) / totalsize) *
100)));
fflush(stdout);
}
}
}
if (ret == OK) {
LOG(logINFO, ("Done copying program\n"));
// closing file pointer to flash and informing FPGA
ret = stopWritingFPGAprogram(fp);
if (ret == FAIL) {
strcpy(mess, "Failed to program fpga. FPGA is taking too long "
"to pick up program from flash! Try to flash "
"again without rebooting!\n");
LOG(logERROR, (mess)); LOG(logERROR, (mess));
} }
Server_SendResult(file_des, INT32, NULL, 0);
if (ret == FAIL) {
break;
}
// print progress
LOG(logINFO,
("\t%d%%\r",
(int)(((double)(totalsize - filesize) / totalsize) * 100)));
fflush(stdout);
}
free(src);
fclose(fd);
// checksum of copied program
if (ret == OK) {
ret =
verifyChecksumFromFile(mess, checksum, TEMP_PROG_FILE_NAME);
}
Server_SendResult(file_des, INT32, NULL, 0);
if (ret == FAIL) {
LOG(logERROR, ("Program FPGA FAIL!\n"));
return FAIL;
} }
// free resources // copy to flash
free(fpgasrc); ret = copyToFlash(totalsize, checksum, mess);
if (fp != NULL) Server_SendResult(file_des, INT32, NULL, 0);
fclose(fp); if (ret == FAIL) {
LOG(logERROR, ("Program FPGA FAIL!\n"));
// send final ret (if no client crash) return FAIL;
if (clientSocketCrash == 0) {
Server_SendResult(file_des, INT32, NULL, 0);
} }
#endif // end of Blackfin programming #endif // end of Blackfin programming
if (ret == FAIL) { LOG(logINFOGREEN, ("Programming FPGA completed successfully\n"));
LOG(logERROR, ("Program FPGA FAIL!\n"));
} else {
LOG(logINFOGREEN, ("Programming FPGA completed successfully\n"));
}
} }
#endif
#endif #endif
return ret; return ret;
} }
@ -4322,11 +4322,19 @@ int reboot_controller(int file_des) {
Server_SendResult(file_des, INT32, NULL, 0); Server_SendResult(file_des, INT32, NULL, 0);
return GOODBYE; return GOODBYE;
} }
#ifdef VIRTUAL
ret = GOODBYE;
#else
ret = REBOOT; ret = REBOOT;
#endif
#elif EIGERD #elif EIGERD
functionNotImplemented(); functionNotImplemented();
#else
#ifdef VIRTUAL
ret = GOODBYE;
#else #else
ret = REBOOT; ret = REBOOT;
#endif
#endif #endif
Server_SendResult(file_des, INT32, NULL, 0); Server_SendResult(file_des, INT32, NULL, 0);
return ret; return ret;
@ -4783,7 +4791,7 @@ int set_read_n_rows(int file_des) {
LOG(logERROR, (mess)); LOG(logERROR, (mess));
} else } else
#elif JUNGFRAUD #elif JUNGFRAUD
if ((check_detector_idle("set nmber of rows") == OK) && (arg % READ_N_ROWS_MULTIPLE != 0)) { if ((check_detector_idle("set number of rows") == OK) && (arg % READ_N_ROWS_MULTIPLE != 0)) {
ret = FAIL; ret = FAIL;
sprintf(mess, sprintf(mess,
"Could not set number of rows. %d must be a multiple " "Could not set number of rows. %d must be a multiple "
@ -8849,8 +8857,7 @@ int set_flip_rows(int file_des) {
#else #else
// only set // only set
if (Server_VerifyLock() == OK) { if (Server_VerifyLock() == OK) {
if ((check_detector_idle("set flip rows") == OK) && (arg != 0 && arg != 1)) {
if (arg != 0 && arg != 1) {
ret = FAIL; ret = FAIL;
sprintf(mess, sprintf(mess,
"Could not set flip rows. Invalid argument %d.\n", "Could not set flip rows. Invalid argument %d.\n",
@ -9191,7 +9198,32 @@ int set_dest_udp_list(int file_des) {
} }
} }
} }
configure_mac(); // find number of destinations
int numdest = 0;
for (int i = MAX_UDP_DESTINATION; i >= 0; --i) {
if (udpDetails[i].dstip != 0) {
numdest = i + 1;
break;
}
}
// atleast 1 destination
if (numdest == 0) {
numdest = 1;
}
// set number of destinations
#if defined(JUNGFRAUD) || defined(EIGERD)
if (setNumberofDestinations(numdest) == FAIL) {
ret = FAIL;
strcpy(mess, "Could not set number of udp destinations.\n");
LOG(logERROR, (mess));
} else
#endif
{
numUdpDestinations = numdest;
LOG(logINFOBLUE, ("Number of UDP Destinations: %d\n",
numUdpDestinations));
configure_mac();
}
} }
} }
} }
@ -9203,10 +9235,13 @@ int get_num_dest_list(int file_des) {
ret = OK; ret = OK;
memset(mess, 0, sizeof(mess)); memset(mess, 0, sizeof(mess));
int retval = -1; int retval = -1;
#if !defined(JUNGFRAUD) && !defined(EIGERD) #if !defined(JUNGFRAUD) && !defined(EIGERD)
functionNotImplemented(); functionNotImplemented();
#else #else
retval = numUdpDestinations; retval = numUdpDestinations;
LOG(logDEBUG1, ("numUdpDestinations retval: 0x%x\n", retval));
int retval1 = 0; int retval1 = 0;
if (getNumberofDestinations(&retval1) == FAIL || retval1 != retval) { if (getNumberofDestinations(&retval1) == FAIL || retval1 != retval) {
ret = FAIL; ret = FAIL;
@ -9216,42 +9251,23 @@ int get_num_dest_list(int file_des) {
LOG(logERROR, (mess)); LOG(logERROR, (mess));
} }
#endif #endif
LOG(logDEBUG1, ("numUdpDestinations retval: 0x%x\n", retval));
return Server_SendResult(file_des, INT32, &retval, sizeof(retval)); return Server_SendResult(file_des, INT32, &retval, sizeof(retval));
} }
int set_num_dest_list(int file_des) { int clear_all_udp_dst(int file_des) {
ret = OK; ret = OK;
memset(mess, 0, sizeof(mess)); memset(mess, 0, sizeof(mess));
int arg = -1;
if (receiveData(file_des, &arg, sizeof(arg), INT32) < 0) LOG(logINFO, ("Clearing all udp destinations\n"));
return printSocketReadError(); if (Server_VerifyLock() == OK) {
LOG(logDEBUG1, ("Setting number of udp destinations to %d\n", arg)); if (check_detector_idle("clear all udp destinations") == OK) {
memset(udpDetails, 0, sizeof(udpDetails));
#if !defined(JUNGFRAUD) && !defined(EIGERD) // minimum 1 destination in fpga
functionNotImplemented(); numUdpDestinations = 1;
#else configure_mac();
if (arg < 1 || arg > MAX_UDP_DESTINATION) {
ret = FAIL;
sprintf(mess,
"Could not set number of udp destinations. Options: 1-%d\n",
MAX_UDP_DESTINATION);
LOG(logERROR, (mess));
} else {
if (check_detector_idle("set number of udp destinations") == OK) {
if (setNumberofDestinations(arg) == FAIL) {
ret = FAIL;
strcpy(mess,
"Could not set number of udp destinations.\n");
LOG(logERROR, (mess));
} else {
numUdpDestinations = arg;
configure_mac();
}
} }
} }
#endif
return Server_SendResult(file_des, INT32, NULL, 0); return Server_SendResult(file_des, INT32, NULL, 0);
} }
@ -9288,19 +9304,22 @@ int set_udp_first_dest(int file_des) {
#ifndef JUNGFRAUD #ifndef JUNGFRAUD
functionNotImplemented(); functionNotImplemented();
#else #else
if (arg < 0 || arg >= numUdpDestinations) { // only set
ret = FAIL; if (Server_VerifyLock() == OK) {
sprintf(mess, "Could not set first destination. Options: 0-%d\n", if (arg < 0 || arg >= numUdpDestinations) {
numUdpDestinations - 1); ret = FAIL;
LOG(logERROR, (mess)); sprintf(mess, "Could not set first destination. Options: 0-%d\n",
} else { numUdpDestinations - 1);
if (check_detector_idle("set first udp destination") == OK) { LOG(logERROR, (mess));
setFirstUDPDestination(arg); } else {
int retval = getFirstUDPDestination(); if (check_detector_idle("set first udp destination") == OK) {
validate(&ret, mess, arg, retval, "set udp first destination", DEC); setFirstUDPDestination(arg);
if (ret == OK) { int retval = getFirstUDPDestination();
firstUDPDestination = arg; validate(&ret, mess, arg, retval, "set udp first destination", DEC);
//configure_mac(); if (ret == OK) {
firstUDPDestination = arg;
//configure_mac();
}
} }
} }
} }

View File

@ -19,7 +19,7 @@ class IpAddr;
// Free function to avoid dependence on class // Free function to avoid dependence on class
// and avoid the option to free another objects // and avoid the option to free another objects
// shm by mistake // shm by mistake
void freeSharedMemory(int multiId, int detPos = -1); void freeSharedMemory(int detectorIndex, int moduleIndex = -1);
/** /**
* \class Detector * \class Detector
@ -671,8 +671,7 @@ class Detector {
/** [Jungfrau][Eiger] */ /** [Jungfrau][Eiger] */
Result<int> getNumberofUDPDestinations(Positions pos = {}) const; Result<int> getNumberofUDPDestinations(Positions pos = {}) const;
/**[Jungfrau][Eiger] Options 1-32 */ void clearUDPDestinations(Positions pos = {});
void setNumberofUDPDestinations(const int value, Positions pos = {});
/** [Jungfrau] */ /** [Jungfrau] */
Result<int> getFirstUDPDestination(Positions pos = {}) const; Result<int> getFirstUDPDestination(Positions pos = {}) const;

View File

@ -67,7 +67,7 @@ int main(int argc, char *argv[]) {
sls::Detector det(parser.multi_id()); sls::Detector det(parser.multi_id());
sls::CmdProxy proxy(&det); sls::CmdProxy proxy(&det);
proxy.Call(parser.command(), parser.arguments(), parser.detector_id(), proxy.Call(parser.command(), parser.arguments(), parser.detector_id(),
action); action, std::cout, parser.receiver_id());
} catch (const sls::RuntimeError &e) { } catch (const sls::RuntimeError &e) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }

View File

@ -29,10 +29,11 @@ std::ostream &operator<<(std::ostream &os,
void CmdProxy::Call(const std::string &command, void CmdProxy::Call(const std::string &command,
const std::vector<std::string> &arguments, int detector_id, const std::vector<std::string> &arguments, int detector_id,
int action, std::ostream &os) { int action, std::ostream &os, int receiver_id) {
cmd = command; cmd = command;
args = arguments; args = arguments;
det_id = detector_id; det_id = detector_id;
rx_id = receiver_id;
std::string temp; std::string temp;
while (temp != cmd) { while (temp != cmd) {
@ -1381,16 +1382,13 @@ IpAddr CmdProxy::getIpFromAuto() {
UdpDestination CmdProxy::getUdpEntry() { UdpDestination CmdProxy::getUdpEntry() {
UdpDestination udpDestination{}; UdpDestination udpDestination{};
bool hasEntry = false; udpDestination.entry = rx_id;
for (auto it : args) { for (auto it : args) {
size_t pos = it.find('='); size_t pos = it.find('=');
std::string key = it.substr(0, pos); std::string key = it.substr(0, pos);
std::string value = it.substr(pos + 1); std::string value = it.substr(pos + 1);
if (key == "entry") { if (key == "ip") {
udpDestination.entry = StringTo<int>(value);
hasEntry = true;
} else if (key == "ip") {
if (value == "auto") { if (value == "auto") {
auto val = getIpFromAuto(); auto val = getIpFromAuto();
LOG(logINFO) << "Setting udp_dstip of detector " << det_id LOG(logINFO) << "Setting udp_dstip of detector " << det_id
@ -1418,9 +1416,6 @@ UdpDestination CmdProxy::getUdpEntry() {
udpDestination.port2 = StringTo<uint32_t>(value); udpDestination.port2 = StringTo<uint32_t>(value);
} }
} }
if (!hasEntry) {
throw sls::RuntimeError("Found no entry argument.");
}
return udpDestination; return udpDestination;
} }
@ -1437,16 +1432,29 @@ std::string CmdProxy::UDPDestinationList(int action) {
"set to ip of rx_hostname." "set to ip of rx_hostname."
<< '\n'; << '\n';
} else if (action == defs::GET_ACTION) { } else if (action == defs::GET_ACTION) {
if (args.size() != 1) { if (!args.empty()) {
WrongNumberOfParameters(1); WrongNumberOfParameters(0);
} }
auto t = det->getDestinationUDPList(StringTo<int>(args[0]), if (det_id == -1) {
std::vector<int>{det_id}); throw sls::RuntimeError("udp_dstlist must be at module level.");
}
if (rx_id < 0 || rx_id >= MAX_UDP_DESTINATION) {
throw sls::RuntimeError(
"Invalid receiver index to get round robin entry.");
}
auto t = det->getDestinationUDPList(rx_id, std::vector<int>{det_id});
os << OutString(t) << '\n'; os << OutString(t) << '\n';
} else if (action == defs::PUT_ACTION) { } else if (action == defs::PUT_ACTION) {
if (args.empty()) { if (args.empty()) {
WrongNumberOfParameters(1); WrongNumberOfParameters(1);
} }
if (det_id == -1) {
throw sls::RuntimeError("udp_dstlist must be at module level.");
}
if (rx_id < 0 || rx_id >= MAX_UDP_DESTINATION) {
throw sls::RuntimeError(
"Invalid receiver index to set round robin entry.");
}
auto t = getUdpEntry(); auto t = getUdpEntry();
det->setDestinationUDPList(t, det_id); det->setDestinationUDPList(t, det_id);
os << ToString(args) << std::endl; os << ToString(args) << std::endl;

View File

@ -529,7 +529,8 @@ class CmdProxy {
void Call(const std::string &command, void Call(const std::string &command,
const std::vector<std::string> &arguments, int detector_id = -1, const std::vector<std::string> &arguments, int detector_id = -1,
int action = -1, std::ostream &os = std::cout); int action = -1, std::ostream &os = std::cout,
int receiver_id = -1);
bool ReplaceIfDepreciated(std::string &command); bool ReplaceIfDepreciated(std::string &command);
size_t GetFunctionMapSize() const noexcept { return functions.size(); }; size_t GetFunctionMapSize() const noexcept { return functions.size(); };
@ -541,6 +542,7 @@ class CmdProxy {
std::string cmd; std::string cmd;
std::vector<std::string> args; std::vector<std::string> args;
int det_id{-1}; int det_id{-1};
int rx_id{-1};
template <typename V> std::string OutStringHex(const V &value) { template <typename V> std::string OutStringHex(const V &value) {
if (value.equal()) if (value.equal())
@ -859,6 +861,7 @@ class CmdProxy {
{"selinterface", &CmdProxy::selinterface}, {"selinterface", &CmdProxy::selinterface},
{"udp_dstlist", &CmdProxy::UDPDestinationList}, {"udp_dstlist", &CmdProxy::UDPDestinationList},
{"udp_numdst", &CmdProxy::udp_numdst}, {"udp_numdst", &CmdProxy::udp_numdst},
{"udp_cleardst", &CmdProxy::udp_cleardst},
{"udp_firstdst", &CmdProxy::udp_firstdst}, {"udp_firstdst", &CmdProxy::udp_firstdst},
{"udp_srcip", &CmdProxy::udp_srcip}, {"udp_srcip", &CmdProxy::udp_srcip},
{"udp_srcip2", &CmdProxy::udp_srcip2}, {"udp_srcip2", &CmdProxy::udp_srcip2},
@ -1535,11 +1538,13 @@ class CmdProxy {
"[0, 1]\n\t[Jungfrau] The udp interface to stream data from detector. " "[0, 1]\n\t[Jungfrau] The udp interface to stream data from detector. "
"Effective only when number of interfaces is 1. Default: 0 (outer)"); "Effective only when number of interfaces is 1. Default: 0 (outer)");
INTEGER_COMMAND_VEC_ID(udp_numdst, getNumberofUDPDestinations, GET_COMMAND(udp_numdst, getNumberofUDPDestinations,
setNumberofUDPDestinations, StringTo<int>, "\n\t[Jungfrau][Eiger] One can enter upto 32 "
"[1 - 32]\n\t[Jungfrau][Eiger] One can set upto 32 "
"destinations that the detector will stream images " "destinations that the detector will stream images "
"out in a round robin fashion. Default: 1"); "out in a round robin fashion. This is get only command. Default: 1");
EXECUTE_SET_COMMAND(udp_cleardst, clearUDPDestinations,
"\n\tClears udp destination details on the detector.");
INTEGER_COMMAND_VEC_ID( INTEGER_COMMAND_VEC_ID(
udp_firstdst, getFirstUDPDestination, setFirstUDPDestination, udp_firstdst, getFirstUDPDestination, setFirstUDPDestination,

View File

@ -17,29 +17,29 @@
namespace sls { namespace sls {
void freeSharedMemory(int multiId, int detPos) { void freeSharedMemory(int detectorIndex, int moduleIndex) {
// single // single module
if (detPos >= 0) { if (moduleIndex >= 0) {
SharedMemory<sharedSlsDetector> temp_shm(multiId, detPos); SharedMemory<sharedModule> moduleShm(detectorIndex, moduleIndex);
if (temp_shm.IsExisting()) { if (moduleShm.IsExisting()) {
temp_shm.RemoveSharedMemory(); moduleShm.RemoveSharedMemory();
} }
return; return;
} }
// multi - get number of detectors from shm // detector - multi module - get number of detectors from shm
SharedMemory<sharedMultiSlsDetector> multiShm(multiId, -1); SharedMemory<sharedDetector> detectorShm(detectorIndex, -1);
int numDetectors = 0; int numDetectors = 0;
if (multiShm.IsExisting()) { if (detectorShm.IsExisting()) {
multiShm.OpenSharedMemory(); detectorShm.OpenSharedMemory();
numDetectors = multiShm()->numberOfDetectors; numDetectors = detectorShm()->numberOfModules;
multiShm.RemoveSharedMemory(); detectorShm.RemoveSharedMemory();
} }
for (int i = 0; i < numDetectors; ++i) { for (int i = 0; i < numDetectors; ++i) {
SharedMemory<sharedSlsDetector> shm(multiId, i); SharedMemory<sharedModule> moduleShm(detectorIndex, i);
shm.RemoveSharedMemory(); moduleShm.RemoveSharedMemory();
} }
} }
@ -101,7 +101,7 @@ void Detector::setVirtualDetectorServers(int numServers, int startingPort) {
pimpl->setVirtualDetectorServers(numServers, startingPort); pimpl->setVirtualDetectorServers(numServers, startingPort);
} }
int Detector::getShmId() const { return pimpl->getMultiId(); } int Detector::getShmId() const { return pimpl->getDetectorIndex(); }
std::string Detector::getPackageVersion() const { return GITBRANCH; } std::string Detector::getPackageVersion() const { return GITBRANCH; }
@ -136,7 +136,7 @@ int Detector::size() const { return pimpl->size(); }
bool Detector::empty() const { return pimpl->size() == 0; } bool Detector::empty() const { return pimpl->size() == 0; }
defs::xy Detector::getModuleGeometry() const { defs::xy Detector::getModuleGeometry() const {
return pimpl->getNumberOfDetectors(); return pimpl->getNumberOfModules();
} }
Result<defs::xy> Detector::getModuleSize(Positions pos) const { Result<defs::xy> Detector::getModuleSize(Positions pos) const {
@ -256,7 +256,7 @@ void Detector::setSettingsPath(const std::string &value, Positions pos) {
} }
void Detector::loadTrimbits(const std::string &fname, Positions pos) { void Detector::loadTrimbits(const std::string &fname, Positions pos) {
pimpl->Parallel(&Module::loadSettingsFile, pos, fname); pimpl->Parallel(&Module::loadTrimbits, pos, fname);
} }
Result<int> Detector::getAllTrimbits(Positions pos) const { Result<int> Detector::getAllTrimbits(Positions pos) const {
@ -921,8 +921,8 @@ Result<int> Detector::getNumberofUDPDestinations(Positions pos) const {
return pimpl->Parallel(&Module::getNumberofUDPDestinations, pos); return pimpl->Parallel(&Module::getNumberofUDPDestinations, pos);
} }
void Detector::setNumberofUDPDestinations(const int value, Positions pos) { void Detector::clearUDPDestinations(Positions pos) {
pimpl->Parallel(&Module::setNumberofUDPDestinations, pos, value); pimpl->Parallel(&Module::clearUDPDestinations, pos);
} }
Result<int> Detector::getFirstUDPDestination(Positions pos) const { Result<int> Detector::getFirstUDPDestination(Positions pos) const {

View File

@ -28,14 +28,14 @@
namespace sls { namespace sls {
DetectorImpl::DetectorImpl(int multi_id, bool verify, bool update) DetectorImpl::DetectorImpl(int detector_index, bool verify, bool update)
: multiId(multi_id), multi_shm(multi_id, -1) { : detectorIndex(detector_index), shm(detector_index, -1) {
setupMultiDetector(verify, update); setupDetector(verify, update);
} }
DetectorImpl::~DetectorImpl() = default; DetectorImpl::~DetectorImpl() = default;
void DetectorImpl::setupMultiDetector(bool verify, bool update) { void DetectorImpl::setupDetector(bool verify, bool update) {
initSharedMemory(verify); initSharedMemory(verify);
initializeMembers(verify); initializeMembers(verify);
if (update) { if (update) {
@ -43,104 +43,100 @@ void DetectorImpl::setupMultiDetector(bool verify, bool update) {
} }
} }
void DetectorImpl::setAcquiringFlag(bool flag) { void DetectorImpl::setAcquiringFlag(bool flag) { shm()->acquiringFlag = flag; }
multi_shm()->acquiringFlag = flag;
}
int DetectorImpl::getMultiId() const { return multiId; } int DetectorImpl::getDetectorIndex() const { return detectorIndex; }
void DetectorImpl::freeSharedMemory(int multiId, int detPos) { void DetectorImpl::freeSharedMemory(int detectorIndex, int detPos) {
// single // single
if (detPos >= 0) { if (detPos >= 0) {
SharedMemory<sharedSlsDetector> temp_shm(multiId, detPos); SharedMemory<sharedModule> moduleShm(detectorIndex, detPos);
if (temp_shm.IsExisting()) { if (moduleShm.IsExisting()) {
temp_shm.RemoveSharedMemory(); moduleShm.RemoveSharedMemory();
} }
return; return;
} }
// multi - get number of detectors from shm // multi - get number of modules from shm
SharedMemory<sharedMultiSlsDetector> multiShm(multiId, -1); SharedMemory<sharedDetector> detectorShm(detectorIndex, -1);
int numDetectors = 0; int numModules = 0;
if (multiShm.IsExisting()) { if (detectorShm.IsExisting()) {
multiShm.OpenSharedMemory(); detectorShm.OpenSharedMemory();
numDetectors = multiShm()->numberOfDetectors; numModules = detectorShm()->numberOfModules;
multiShm.RemoveSharedMemory(); detectorShm.RemoveSharedMemory();
} }
for (int i = 0; i < numDetectors; ++i) { for (int i = 0; i < numModules; ++i) {
SharedMemory<sharedSlsDetector> shm(multiId, i); SharedMemory<sharedModule> moduleShm(detectorIndex, i);
shm.RemoveSharedMemory(); moduleShm.RemoveSharedMemory();
} }
} }
void DetectorImpl::freeSharedMemory() { void DetectorImpl::freeSharedMemory() {
zmqSocket.clear(); zmqSocket.clear();
for (auto &d : detectors) { for (auto &module : modules) {
d->freeSharedMemory(); module->freeSharedMemory();
} }
detectors.clear(); modules.clear();
// clear multi detector shm // clear detector shm
multi_shm.RemoveSharedMemory(); shm.RemoveSharedMemory();
client_downstream = false; client_downstream = false;
} }
std::string DetectorImpl::getUserDetails() { std::string DetectorImpl::getUserDetails() {
if (detectors.empty()) { if (modules.empty()) {
return std::string("none"); return std::string("none");
} }
std::ostringstream sstream; std::ostringstream sstream;
sstream << "\nHostname: "; sstream << "\nHostname: ";
for (auto &d : detectors) { for (auto &module : modules) {
sstream << (d->isFixedPatternSharedMemoryCompatible() ? d->getHostname() sstream << (module->isFixedPatternSharedMemoryCompatible()
: "Unknown") ? module->getHostname()
: "Unknown")
<< "+"; << "+";
} }
sstream << "\nType: "; sstream << "\nType: ";
// get type from multi shm // get type from detector version shm
if (multi_shm()->shmversion >= MULTI_SHMAPIVERSION) { if (shm()->shmversion >= DETECTOR_SHMAPIVERSION) {
sstream << ToString(multi_shm()->multiDetectorType); sstream << ToString(shm()->detType);
} }
// get type from slsdet shm // get type from module shm
else { else {
for (auto &d : detectors) { for (auto &module : modules) {
sstream << (d->isFixedPatternSharedMemoryCompatible() sstream << (module->isFixedPatternSharedMemoryCompatible()
? ToString(d->getDetectorType()) ? ToString(module->getDetectorType())
: "Unknown") : "Unknown")
<< "+"; << "+";
} }
} }
sstream << "\nPID: " << multi_shm()->lastPID sstream << "\nPID: " << shm()->lastPID << "\nUser: " << shm()->lastUser
<< "\nUser: " << multi_shm()->lastUser << "\nDate: " << shm()->lastDate << std::endl;
<< "\nDate: " << multi_shm()->lastDate << std::endl;
return sstream.str(); return sstream.str();
} }
bool DetectorImpl::getInitialChecks() const { bool DetectorImpl::getInitialChecks() const { return shm()->initialChecks; }
return multi_shm()->initialChecks;
}
void DetectorImpl::setInitialChecks(const bool value) { void DetectorImpl::setInitialChecks(const bool value) {
multi_shm()->initialChecks = value; shm()->initialChecks = value;
} }
void DetectorImpl::initSharedMemory(bool verify) { void DetectorImpl::initSharedMemory(bool verify) {
if (!multi_shm.IsExisting()) { if (!shm.IsExisting()) {
multi_shm.CreateSharedMemory(); shm.CreateSharedMemory();
initializeDetectorStructure(); initializeDetectorStructure();
} else { } else {
multi_shm.OpenSharedMemory(); shm.OpenSharedMemory();
if (verify && multi_shm()->shmversion != MULTI_SHMVERSION) { if (verify && shm()->shmversion != DETECTOR_SHMVERSION) {
LOG(logERROR) << "Multi shared memory (" << multiId LOG(logERROR) << "Detector shared memory (" << detectorIndex
<< ") version mismatch " << ") version mismatch "
"(expected 0x" "(expected 0x"
<< std::hex << MULTI_SHMVERSION << " but got 0x" << std::hex << DETECTOR_SHMVERSION << " but got 0x"
<< multi_shm()->shmversion << std::dec << shm()->shmversion << std::dec
<< ". Clear Shared memory to continue."; << ". Clear Shared memory to continue.";
throw SharedMemoryError("Shared memory version mismatch!"); throw SharedMemoryError("Shared memory version mismatch!");
} }
@ -148,18 +144,18 @@ void DetectorImpl::initSharedMemory(bool verify) {
} }
void DetectorImpl::initializeDetectorStructure() { void DetectorImpl::initializeDetectorStructure() {
multi_shm()->shmversion = MULTI_SHMVERSION; shm()->shmversion = DETECTOR_SHMVERSION;
multi_shm()->numberOfDetectors = 0; shm()->numberOfModules = 0;
multi_shm()->multiDetectorType = GENERIC; shm()->detType = GENERIC;
multi_shm()->numberOfDetector.x = 0; shm()->numberOfModule.x = 0;
multi_shm()->numberOfDetector.y = 0; shm()->numberOfModule.y = 0;
multi_shm()->numberOfChannels.x = 0; shm()->numberOfChannels.x = 0;
multi_shm()->numberOfChannels.y = 0; shm()->numberOfChannels.y = 0;
multi_shm()->acquiringFlag = false; shm()->acquiringFlag = false;
multi_shm()->initialChecks = true; shm()->initialChecks = true;
multi_shm()->gapPixels = false; shm()->gapPixels = false;
// zmqlib default // zmqlib default
multi_shm()->zmqHwm = -1; shm()->zmqHwm = -1;
} }
void DetectorImpl::initializeMembers(bool verify) { void DetectorImpl::initializeMembers(bool verify) {
@ -167,38 +163,39 @@ void DetectorImpl::initializeMembers(bool verify) {
zmqSocket.clear(); zmqSocket.clear();
// get objects from single det shared memory (open) // get objects from single det shared memory (open)
for (int i = 0; i < multi_shm()->numberOfDetectors; i++) { for (int i = 0; i < shm()->numberOfModules; i++) {
try { try {
detectors.push_back(sls::make_unique<Module>(multiId, i, verify)); modules.push_back(
sls::make_unique<Module>(detectorIndex, i, verify));
} catch (...) { } catch (...) {
detectors.clear(); modules.clear();
throw; throw;
} }
} }
} }
void DetectorImpl::updateUserdetails() { void DetectorImpl::updateUserdetails() {
multi_shm()->lastPID = getpid(); shm()->lastPID = getpid();
memset(multi_shm()->lastUser, 0, sizeof(multi_shm()->lastUser)); memset(shm()->lastUser, 0, sizeof(shm()->lastUser));
memset(multi_shm()->lastDate, 0, sizeof(multi_shm()->lastDate)); memset(shm()->lastDate, 0, sizeof(shm()->lastDate));
try { try {
sls::strcpy_safe(multi_shm()->lastUser, exec("whoami").c_str()); sls::strcpy_safe(shm()->lastUser, exec("whoami").c_str());
sls::strcpy_safe(multi_shm()->lastDate, exec("date").c_str()); sls::strcpy_safe(shm()->lastDate, exec("date").c_str());
} catch (...) { } catch (...) {
sls::strcpy_safe(multi_shm()->lastUser, "errorreading"); sls::strcpy_safe(shm()->lastUser, "errorreading");
sls::strcpy_safe(multi_shm()->lastDate, "errorreading"); sls::strcpy_safe(shm()->lastDate, "errorreading");
} }
} }
bool DetectorImpl::isAcquireReady() { bool DetectorImpl::isAcquireReady() {
if (multi_shm()->acquiringFlag) { if (shm()->acquiringFlag) {
LOG(logWARNING) LOG(logWARNING)
<< "Acquire has already started. " << "Acquire has already started. "
"If previous acquisition terminated unexpectedly, " "If previous acquisition terminated unexpectedly, "
"reset busy flag to restart.(sls_detector_put clearbusy)"; "reset busy flag to restart.(sls_detector_put clearbusy)";
return false; return false;
} }
multi_shm()->acquiringFlag = true; shm()->acquiringFlag = true;
return true; return true;
} }
@ -233,22 +230,22 @@ void DetectorImpl::setVirtualDetectorServers(const int numdet, const int port) {
void DetectorImpl::setHostname(const std::vector<std::string> &name) { void DetectorImpl::setHostname(const std::vector<std::string> &name) {
// this check is there only to allow the previous detsizechan command // this check is there only to allow the previous detsizechan command
if (multi_shm()->numberOfDetectors != 0) { if (shm()->numberOfModules != 0) {
LOG(logWARNING) << "There are already detector(s) in shared memory." LOG(logWARNING) << "There are already module(s) in shared memory."
"Freeing Shared memory now."; "Freeing Shared memory now.";
bool initialChecks = multi_shm()->initialChecks; bool initialChecks = shm()->initialChecks;
freeSharedMemory(); freeSharedMemory();
setupMultiDetector(); setupDetector();
multi_shm()->initialChecks = initialChecks; shm()->initialChecks = initialChecks;
} }
for (const auto &hostname : name) { for (const auto &hostname : name) {
addSlsDetector(hostname); addModule(hostname);
} }
updateDetectorSize(); updateDetectorSize();
} }
void DetectorImpl::addSlsDetector(const std::string &hostname) { void DetectorImpl::addModule(const std::string &hostname) {
LOG(logINFO) << "Adding detector " << hostname; LOG(logINFO) << "Adding module " << hostname;
int port = DEFAULT_PORTNO; int port = DEFAULT_PORTNO;
std::string host = hostname; std::string host = hostname;
@ -259,11 +256,11 @@ void DetectorImpl::addSlsDetector(const std::string &hostname) {
} }
if (host != "localhost") { if (host != "localhost") {
for (auto &d : detectors) { for (auto &module : modules) {
if (d->getHostname() == host) { if (module->getHostname() == host) {
LOG(logWARNING) LOG(logWARNING)
<< "Detector " << host << "Module " << host << "already part of the Detector!"
<< "already part of the multiDetector!" << std::endl << std::endl
<< "Remove it before adding it back in a new position!"; << "Remove it before adding it back in a new position!";
return; return;
} }
@ -272,33 +269,33 @@ void DetectorImpl::addSlsDetector(const std::string &hostname) {
// get type by connecting // get type by connecting
detectorType type = Module::getTypeFromDetector(host, port); detectorType type = Module::getTypeFromDetector(host, port);
auto pos = detectors.size(); auto pos = modules.size();
detectors.emplace_back(sls::make_unique<Module>(type, multiId, pos, false)); modules.emplace_back(
multi_shm()->numberOfDetectors = detectors.size(); sls::make_unique<Module>(type, detectorIndex, pos, false));
detectors[pos]->setControlPort(port); shm()->numberOfModules = modules.size();
detectors[pos]->setStopPort(port + 1); modules[pos]->setControlPort(port);
detectors[pos]->setHostname(host, multi_shm()->initialChecks); modules[pos]->setStopPort(port + 1);
// detector type updated by now modules[pos]->setHostname(host, shm()->initialChecks);
multi_shm()->multiDetectorType = // module type updated by now
Parallel(&Module::getDetectorType, {}) shm()->detType = Parallel(&Module::getDetectorType, {})
.tsquash("Inconsistent detector types."); .tsquash("Inconsistent detector types.");
// for moench and ctb // for moench and ctb
detectors[pos]->updateNumberOfChannels(); modules[pos]->updateNumberOfChannels();
} }
void DetectorImpl::updateDetectorSize() { void DetectorImpl::updateDetectorSize() {
LOG(logDEBUG) << "Updating Multi-Detector Size: " << size(); LOG(logDEBUG) << "Updating Detector Size: " << size();
const slsDetectorDefs::xy det_size = detectors[0]->getNumberOfChannels(); const slsDetectorDefs::xy det_size = modules[0]->getNumberOfChannels();
if (det_size.x == 0 || det_size.y == 0) { if (det_size.x == 0 || det_size.y == 0) {
throw sls::RuntimeError("Module size for x or y dimensions is 0. Unable to proceed in updating detector size. "); throw sls::RuntimeError("Module size for x or y dimensions is 0. Unable to proceed in updating detector size. ");
} }
int maxx = multi_shm()->numberOfChannels.x; int maxx = shm()->numberOfChannels.x;
int maxy = multi_shm()->numberOfChannels.y; int maxy = shm()->numberOfChannels.y;
int ndetx = 0, ndety = 0; int ndetx = 0, ndety = 0;
// 1d, add detectors along x axis // 1d, add modules along x axis
if (det_size.y == 1) { if (det_size.y == 1) {
if (maxx == 0) { if (maxx == 0) {
maxx = det_size.x * size(); maxx = det_size.x * size();
@ -309,7 +306,7 @@ void DetectorImpl::updateDetectorSize() {
++ndety; ++ndety;
} }
} }
// 2d, add detectors along y axis (due to eiger top/bottom) // 2d, add modules along y axis (due to eiger top/bottom)
else { else {
if (maxy == 0) { if (maxy == 0) {
maxy = det_size.y * size(); maxy = det_size.y * size();
@ -321,33 +318,33 @@ void DetectorImpl::updateDetectorSize() {
} }
} }
multi_shm()->numberOfDetector.x = ndetx; shm()->numberOfModule.x = ndetx;
multi_shm()->numberOfDetector.y = ndety; shm()->numberOfModule.y = ndety;
multi_shm()->numberOfChannels.x = det_size.x * ndetx; shm()->numberOfChannels.x = det_size.x * ndetx;
multi_shm()->numberOfChannels.y = det_size.y * ndety; shm()->numberOfChannels.y = det_size.y * ndety;
LOG(logDEBUG) << "\n\tNumber of Detectors in X direction:" LOG(logDEBUG) << "\n\tNumber of Modules in X direction:"
<< multi_shm()->numberOfDetector.x << shm()->numberOfModule.x
<< "\n\tNumber of Detectors in Y direction:" << "\n\tNumber of Modules in Y direction:"
<< multi_shm()->numberOfDetector.y << shm()->numberOfModule.y
<< "\n\tNumber of Channels in X direction:" << "\n\tNumber of Channels in X direction:"
<< multi_shm()->numberOfChannels.x << shm()->numberOfChannels.x
<< "\n\tNumber of Channels in Y direction:" << "\n\tNumber of Channels in Y direction:"
<< multi_shm()->numberOfChannels.y; << shm()->numberOfChannels.y;
for (auto &d : detectors) { for (auto &module : modules) {
d->updateNumberOfDetector(multi_shm()->numberOfDetector); module->updateNumberOfModule(shm()->numberOfModule);
} }
} }
int DetectorImpl::size() const { return detectors.size(); } int DetectorImpl::size() const { return modules.size(); }
slsDetectorDefs::xy DetectorImpl::getNumberOfDetectors() const { slsDetectorDefs::xy DetectorImpl::getNumberOfModules() const {
return multi_shm()->numberOfDetector; return shm()->numberOfModule;
} }
slsDetectorDefs::xy DetectorImpl::getNumberOfChannels() const { slsDetectorDefs::xy DetectorImpl::getNumberOfChannels() const {
return multi_shm()->numberOfChannels; return shm()->numberOfChannels;
} }
void DetectorImpl::setNumberOfChannels(const slsDetectorDefs::xy c) { void DetectorImpl::setNumberOfChannels(const slsDetectorDefs::xy c) {
@ -355,33 +352,31 @@ void DetectorImpl::setNumberOfChannels(const slsDetectorDefs::xy c) {
throw RuntimeError( throw RuntimeError(
"Set the number of channels before setting hostname."); "Set the number of channels before setting hostname.");
} }
multi_shm()->numberOfChannels = c; shm()->numberOfChannels = c;
} }
bool DetectorImpl::getGapPixelsinCallback() const { bool DetectorImpl::getGapPixelsinCallback() const { return shm()->gapPixels; }
return multi_shm()->gapPixels;
}
void DetectorImpl::setGapPixelsinCallback(const bool enable) { void DetectorImpl::setGapPixelsinCallback(const bool enable) {
if (enable) { if (enable) {
switch (multi_shm()->multiDetectorType) { switch (shm()->detType) {
case JUNGFRAU: case JUNGFRAU:
break; break;
case EIGER: case EIGER:
if (size() && detectors[0]->getQuad()) { if (size() && modules[0]->getQuad()) {
break; break;
} }
if (multi_shm()->numberOfDetector.y % 2 != 0) { if (shm()->numberOfModule.y % 2 != 0) {
throw RuntimeError("Gap pixels can only be used " throw RuntimeError("Gap pixels can only be used "
"for full modules."); "for full modules.");
} }
break; break;
default: default:
throw RuntimeError("Gap Pixels is not implemented for " + throw RuntimeError("Gap Pixels is not implemented for " +
ToString(multi_shm()->multiDetectorType)); ToString(shm()->detType));
} }
} }
multi_shm()->gapPixels = enable; shm()->gapPixels = enable;
} }
int DetectorImpl::destroyReceivingDataSockets() { int DetectorImpl::destroyReceivingDataSockets() {
@ -400,33 +395,33 @@ int DetectorImpl::createReceivingDataSockets() {
} }
LOG(logINFO) << "Going to create data sockets"; LOG(logINFO) << "Going to create data sockets";
size_t numSockets = detectors.size(); size_t numSockets = modules.size();
size_t numSocketsPerDetector = 1; size_t numSocketsPerModule = 1;
if (multi_shm()->multiDetectorType == EIGER) { if (shm()->detType == EIGER) {
numSocketsPerDetector = 2; numSocketsPerModule = 2;
} }
// gotthard2 second interface is only for veto debugging // gotthard2 second interface is only for veto debugging
else if (multi_shm()->multiDetectorType != GOTTHARD2) { else if (shm()->detType != GOTTHARD2) {
if (Parallel(&Module::getNumberofUDPInterfacesFromShm, {}).squash() == if (Parallel(&Module::getNumberofUDPInterfacesFromShm, {}).squash() ==
2) { 2) {
numSocketsPerDetector = 2; numSocketsPerModule = 2;
} }
} }
numSockets *= numSocketsPerDetector; numSockets *= numSocketsPerModule;
for (size_t iSocket = 0; iSocket < numSockets; ++iSocket) { for (size_t iSocket = 0; iSocket < numSockets; ++iSocket) {
uint32_t portnum = (detectors[iSocket / numSocketsPerDetector] uint32_t portnum =
->getClientStreamingPort()); (modules[iSocket / numSocketsPerModule]->getClientStreamingPort());
portnum += (iSocket % numSocketsPerDetector); portnum += (iSocket % numSocketsPerModule);
try { try {
zmqSocket.push_back(sls::make_unique<ZmqSocket>( zmqSocket.push_back(sls::make_unique<ZmqSocket>(
detectors[iSocket / numSocketsPerDetector] modules[iSocket / numSocketsPerModule]
->getClientStreamingIP() ->getClientStreamingIP()
.str() .str()
.c_str(), .c_str(),
portnum)); portnum));
// set high water mark // set high water mark
int hwm = multi_shm()->zmqHwm; int hwm = shm()->zmqHwm;
if (hwm >= 0) { if (hwm >= 0) {
zmqSocket[iSocket]->SetReceiveHighWaterMark(hwm); zmqSocket[iSocket]->SetReceiveHighWaterMark(hwm);
if (zmqSocket[iSocket]->GetReceiveHighWaterMark() != hwm) { if (zmqSocket[iSocket]->GetReceiveHighWaterMark() != hwm) {
@ -451,7 +446,7 @@ int DetectorImpl::createReceivingDataSockets() {
void DetectorImpl::readFrameFromReceiver() { void DetectorImpl::readFrameFromReceiver() {
bool gapPixels = multi_shm()->gapPixels; bool gapPixels = shm()->gapPixels;
LOG(logDEBUG) << "Gap pixels: " << gapPixels; LOG(logDEBUG) << "Gap pixels: " << gapPixels;
int nX = 0; int nX = 0;
int nY = 0; int nY = 0;
@ -461,7 +456,7 @@ void DetectorImpl::readFrameFromReceiver() {
bool eiger = false; bool eiger = false;
bool numInterfaces = 1; bool numInterfaces = 1;
// gotthard2 second interface is veto debugging // gotthard2 second interface is veto debugging
if (multi_shm()->multiDetectorType != GOTTHARD2) { if (shm()->detType != GOTTHARD2) {
numInterfaces = Parallel(&Module::getNumberofUDPInterfacesFromShm, {}) numInterfaces = Parallel(&Module::getNumberofUDPInterfacesFromShm, {})
.squash(); // cannot pick up from zmq .squash(); // cannot pick up from zmq
} }
@ -540,7 +535,7 @@ void DetectorImpl::readFrameFromReceiver() {
// shape // shape
nPixelsX = zHeader.npixelsx; nPixelsX = zHeader.npixelsx;
nPixelsY = zHeader.npixelsy; nPixelsY = zHeader.npixelsy;
// detector shape // module shape
nX = zHeader.ndetx; nX = zHeader.ndetx;
nY = zHeader.ndety; nY = zHeader.ndety;
nY *= numInterfaces; nY *= numInterfaces;
@ -603,7 +598,7 @@ void DetectorImpl::readFrameFromReceiver() {
uint32_t yoffset = coordY * nPixelsY; uint32_t yoffset = coordY * nPixelsY;
uint32_t singledetrowoffset = nPixelsX * bytesPerPixel; uint32_t singledetrowoffset = nPixelsX * bytesPerPixel;
uint32_t rowoffset = nX * singledetrowoffset; uint32_t rowoffset = nX * singledetrowoffset;
if (multi_shm()->multiDetectorType == CHIPTESTBOARD) { if (shm()->detType == CHIPTESTBOARD) {
singledetrowoffset = size; singledetrowoffset = size;
} }
LOG(logDEBUG1) LOG(logDEBUG1)
@ -765,7 +760,7 @@ int DetectorImpl::InsertGapPixels(char *image, char *&gpImage, bool quadEnable,
// eiger requires inter chip gap pixels are halved // eiger requires inter chip gap pixels are halved
// jungfrau prefers same inter chip gap pixels as the boundary pixels // jungfrau prefers same inter chip gap pixels as the boundary pixels
int divisionValue = 2; int divisionValue = 2;
slsDetectorDefs::detectorType detType = multi_shm()->multiDetectorType; slsDetectorDefs::detectorType detType = shm()->detType;
if (detType == JUNGFRAU) { if (detType == JUNGFRAU) {
divisionValue = 1; divisionValue = 1;
} }
@ -1001,7 +996,7 @@ void DetectorImpl::setDataStreamingToClient(bool enable) {
int DetectorImpl::getClientStreamingHwm() const { int DetectorImpl::getClientStreamingHwm() const {
// disabled // disabled
if (!client_downstream) { if (!client_downstream) {
return multi_shm()->zmqHwm; return shm()->zmqHwm;
} }
// enabled // enabled
sls::Result<int> result; sls::Result<int> result;
@ -1019,7 +1014,7 @@ void DetectorImpl::setClientStreamingHwm(const int limit) {
"Cannot set hwm to less than -1 (-1 is lib default)."); "Cannot set hwm to less than -1 (-1 is lib default).");
} }
// update shm // update shm
multi_shm()->zmqHwm = limit; shm()->zmqHwm = limit;
// streaming enabled // streaming enabled
if (client_downstream) { if (client_downstream) {
@ -1028,7 +1023,7 @@ void DetectorImpl::setClientStreamingHwm(const int limit) {
for (auto &it : zmqSocket) { for (auto &it : zmqSocket) {
it->SetReceiveHighWaterMark(limit); it->SetReceiveHighWaterMark(limit);
if (it->GetReceiveHighWaterMark() != limit) { if (it->GetReceiveHighWaterMark() != limit) {
multi_shm()->zmqHwm = -1; shm()->zmqHwm = -1;
throw sls::ZmqSocketError("Could not set zmq rcv hwm to " + throw sls::ZmqSocketError("Could not set zmq rcv hwm to " +
std::to_string(limit)); std::to_string(limit));
} }
@ -1096,13 +1091,13 @@ int DetectorImpl::acquire() {
// start and read all // start and read all
try { try {
if(detector_type == defs::MYTHEN3 && detectors.size() > 1){ if (detector_type == defs::MYTHEN3 && modules.size() > 1) {
//Multi module mythen //Multi module mythen
std::vector<int> master; std::vector<int> master;
std::vector<int> slaves; std::vector<int> slaves;
auto is_master = Parallel(&Module::isMaster, {}); auto is_master = Parallel(&Module::isMaster, {});
slaves.reserve(detectors.size()-1); //check this one!! slaves.reserve(modules.size() - 1); // check this one!!
for (size_t i = 0; i<detectors.size(); ++i){ for (size_t i = 0; i < modules.size(); ++i) {
if(is_master[i]) if(is_master[i])
master.push_back(i); master.push_back(i);
else else
@ -1110,11 +1105,11 @@ int DetectorImpl::acquire() {
} }
Parallel(&Module::startAcquisition, slaves); Parallel(&Module::startAcquisition, slaves);
Parallel(&Module::startAndReadAll, master); Parallel(&Module::startAndReadAll, master);
}else{ } else {
//Normal acquire //Normal acquire
Parallel(&Module::startAndReadAll, {}); Parallel(&Module::startAndReadAll, {});
} }
} catch (...) { } catch (...) {
if (receiver) if (receiver)
Parallel(&Module::stopReceiver, {}); Parallel(&Module::stopReceiver, {});
@ -1243,7 +1238,7 @@ int DetectorImpl::kbhit() {
std::vector<char> DetectorImpl::readProgrammingFile(const std::string &fname) { std::vector<char> DetectorImpl::readProgrammingFile(const std::string &fname) {
// validate type of file // validate type of file
bool isPof = false; bool isPof = false;
switch (multi_shm()->multiDetectorType) { switch (shm()->detType) {
case JUNGFRAU: case JUNGFRAU:
case CHIPTESTBOARD: case CHIPTESTBOARD:
case MOENCH: case MOENCH:
@ -1266,7 +1261,6 @@ std::vector<char> DetectorImpl::readProgrammingFile(const std::string &fname) {
<< "Updating Firmware. This can take awhile. Please be patient..."; << "Updating Firmware. This can take awhile. Please be patient...";
LOG(logDEBUG1) << "Programming FPGA with file name:" << fname; LOG(logDEBUG1) << "Programming FPGA with file name:" << fname;
size_t filesize = 0;
// check if it exists // check if it exists
struct stat st; struct stat st;
if (stat(fname.c_str(), &st) != 0) { if (stat(fname.c_str(), &st) != 0) {
@ -1281,6 +1275,16 @@ std::vector<char> DetectorImpl::readProgrammingFile(const std::string &fname) {
fname); fname);
} }
// get srcSize to print progress
if (fseek(src, 0, SEEK_END) != 0) {
throw RuntimeError("Program FPGA: Seek error in src file");
}
size_t srcSize = ftell(src);
if (srcSize <= 0) {
throw RuntimeError("Program FPGA: Could not get length of source file");
}
rewind(src);
// create temp destination file // create temp destination file
char destfname[] = "/tmp/SLS_DET_MCB.XXXXXX"; char destfname[] = "/tmp/SLS_DET_MCB.XXXXXX";
int dst = mkstemp(destfname); // create temporary file and open it in r/w int dst = mkstemp(destfname); // create temporary file and open it in r/w
@ -1294,6 +1298,7 @@ std::vector<char> DetectorImpl::readProgrammingFile(const std::string &fname) {
// convert src to dst rawbin // convert src to dst rawbin
LOG(logDEBUG1) << "Converting " << fname << " to " << destfname; LOG(logDEBUG1) << "Converting " << fname << " to " << destfname;
LOG(logINFO) << "Converting program to rawbin";
{ {
constexpr int pofNumHeaderBytes = 0x11C; constexpr int pofNumHeaderBytes = 0x11C;
constexpr int pofFooterOfst = 0x1000000; constexpr int pofFooterOfst = 0x1000000;
@ -1312,7 +1317,15 @@ std::vector<char> DetectorImpl::readProgrammingFile(const std::string &fname) {
} }
} }
// Swap bits from source and write to dest // Swap bits from source and write to dest
int oldProgress = 0;
while (!feof(src)) { while (!feof(src)) {
// print progress
int progress = (int)(((double)(dstFilePos) / srcSize) * 100);
if (oldProgress != progress) {
printf("%d%%\r", progress);
fflush(stdout);
oldProgress = progress;
}
// pof: exit early to discard footer // pof: exit early to discard footer
if (isPof && dstFilePos >= pofFooterOfst) { if (isPof && dstFilePos >= pofFooterOfst) {
break; break;
@ -1342,9 +1355,10 @@ std::vector<char> DetectorImpl::readProgrammingFile(const std::string &fname) {
if (close(dst) != 0) { if (close(dst) != 0) {
throw RuntimeError("Program FPGA: Could not close destination file"); throw RuntimeError("Program FPGA: Could not close destination file");
} }
LOG(logDEBUG1) << "File has been converted to " << destfname; LOG(logINFOBLUE) << "File has been converted to " << destfname;
// loading dst file to memory // loading dst file to memory
// FILE *fp = fopen("/tmp/SLS_DET_MCB.tzgmUT", "r");
FILE *fp = fopen(destfname, "r"); FILE *fp = fopen(destfname, "r");
if (fp == nullptr) { if (fp == nullptr) {
throw RuntimeError("Program FPGA: Could not open rawbin file"); throw RuntimeError("Program FPGA: Could not open rawbin file");
@ -1352,7 +1366,7 @@ std::vector<char> DetectorImpl::readProgrammingFile(const std::string &fname) {
if (fseek(fp, 0, SEEK_END) != 0) { if (fseek(fp, 0, SEEK_END) != 0) {
throw RuntimeError("Program FPGA: Seek error in rawbin file"); throw RuntimeError("Program FPGA: Seek error in rawbin file");
} }
filesize = ftell(fp); size_t filesize = ftell(fp);
if (filesize <= 0) { if (filesize <= 0) {
throw RuntimeError("Program FPGA: Could not get length of rawbin file"); throw RuntimeError("Program FPGA: Could not get length of rawbin file");
} }
@ -1367,9 +1381,10 @@ std::vector<char> DetectorImpl::readProgrammingFile(const std::string &fname) {
throw RuntimeError( throw RuntimeError(
"Program FPGA: Could not close destination file after converting"); "Program FPGA: Could not close destination file after converting");
} }
unlink(destfname); // delete temporary file
//unlink(destfname); // delete temporary file
LOG(logDEBUG1) << "Successfully loaded the rawbin file to program memory"; LOG(logDEBUG1) << "Successfully loaded the rawbin file to program memory";
LOG(logINFO) << "Read file into memory"; LOG(logDEBUG1) << "Read file into memory";
return buffer; return buffer;
} }

View File

@ -15,8 +15,8 @@ class detectorData;
#include <thread> #include <thread>
#include <vector> #include <vector>
#define MULTI_SHMAPIVERSION 0x190809 #define DETECTOR_SHMAPIVERSION 0x190809
#define MULTI_SHMVERSION 0x201007 #define DETECTOR_SHMVERSION 0x201007
#define SHORT_STRING_LENGTH 50 #define SHORT_STRING_LENGTH 50
#include <future> #include <future>
@ -30,7 +30,7 @@ class Module;
* @short structure allocated in shared memory to store detector settings * @short structure allocated in shared memory to store detector settings
* for IPC and cache * for IPC and cache
*/ */
struct sharedMultiSlsDetector { struct sharedDetector {
/* FIXED PATTERN FOR STATIC FUNCTIONS. DO NOT CHANGE, ONLY APPEND /* FIXED PATTERN FOR STATIC FUNCTIONS. DO NOT CHANGE, ONLY APPEND
* ------*/ * ------*/
@ -47,14 +47,14 @@ struct sharedMultiSlsDetector {
/** last time stamp when accessing the shared memory */ /** last time stamp when accessing the shared memory */
char lastDate[SHORT_STRING_LENGTH]; char lastDate[SHORT_STRING_LENGTH];
int numberOfDetectors; int numberOfModules;
slsDetectorDefs::detectorType multiDetectorType; slsDetectorDefs::detectorType detType;
/** END OF FIXED PATTERN /** END OF FIXED PATTERN
* -----------------------------------------------*/ * -----------------------------------------------*/
/** Number of detectors operated at once */ /** Number of modules operated at once */
slsDetectorDefs::xy numberOfDetector; slsDetectorDefs::xy numberOfModule;
/** max number of channels for complete detector*/ /** max number of channels for complete detector*/
slsDetectorDefs::xy numberOfChannels; slsDetectorDefs::xy numberOfChannels;
@ -69,13 +69,11 @@ struct sharedMultiSlsDetector {
class DetectorImpl : public virtual slsDetectorDefs { class DetectorImpl : public virtual slsDetectorDefs {
public: public:
/** /**
* Constructor
* @param multi_id multi detector id
* @param verify true to verify if shared memory version matches existing * @param verify true to verify if shared memory version matches existing
* one * one
* @param update true to update last user pid, date etc * @param update true to update last user pid, date etc
*/ */
explicit DetectorImpl(int multi_id = 0, bool verify = true, explicit DetectorImpl(int detector_index = 0, bool verify = true,
bool update = true); bool update = true);
/** /**
@ -89,20 +87,20 @@ class DetectorImpl : public virtual slsDetectorDefs {
std::vector<int> positions, std::vector<int> positions,
typename NonDeduced<CT>::type... Args) { typename NonDeduced<CT>::type... Args) {
if (detectors.empty()) if (modules.empty())
throw sls::RuntimeError("No detectors added"); throw sls::RuntimeError("No modules added");
if (positions.empty() || if (positions.empty() ||
(positions.size() == 1 && positions[0] == -1)) { (positions.size() == 1 && positions[0] == -1)) {
positions.resize(detectors.size()); positions.resize(modules.size());
std::iota(begin(positions), end(positions), 0); std::iota(begin(positions), end(positions), 0);
} }
std::vector<std::future<RT>> futures; std::vector<std::future<RT>> futures;
futures.reserve(positions.size()); futures.reserve(positions.size());
for (size_t i : positions) { for (size_t i : positions) {
if (i >= detectors.size()) if (i >= modules.size())
throw sls::RuntimeError("Detector out of range"); throw sls::RuntimeError("Module out of range");
futures.push_back(std::async(std::launch::async, somefunc, futures.push_back(std::async(std::launch::async, somefunc,
detectors[i].get(), Args...)); modules[i].get(), Args...));
} }
sls::Result<RT> result; sls::Result<RT> result;
result.reserve(positions.size()); result.reserve(positions.size());
@ -117,20 +115,20 @@ class DetectorImpl : public virtual slsDetectorDefs {
std::vector<int> positions, std::vector<int> positions,
typename NonDeduced<CT>::type... Args) const { typename NonDeduced<CT>::type... Args) const {
if (detectors.empty()) if (modules.empty())
throw sls::RuntimeError("No detectors added"); throw sls::RuntimeError("No modules added");
if (positions.empty() || if (positions.empty() ||
(positions.size() == 1 && positions[0] == -1)) { (positions.size() == 1 && positions[0] == -1)) {
positions.resize(detectors.size()); positions.resize(modules.size());
std::iota(begin(positions), end(positions), 0); std::iota(begin(positions), end(positions), 0);
} }
std::vector<std::future<RT>> futures; std::vector<std::future<RT>> futures;
futures.reserve(positions.size()); futures.reserve(positions.size());
for (size_t i : positions) { for (size_t i : positions) {
if (i >= detectors.size()) if (i >= modules.size())
throw sls::RuntimeError("Detector out of range"); throw sls::RuntimeError("Module out of range");
futures.push_back(std::async(std::launch::async, somefunc, futures.push_back(std::async(std::launch::async, somefunc,
detectors[i].get(), Args...)); modules[i].get(), Args...));
} }
sls::Result<RT> result; sls::Result<RT> result;
result.reserve(positions.size()); result.reserve(positions.size());
@ -145,20 +143,20 @@ class DetectorImpl : public virtual slsDetectorDefs {
std::vector<int> positions, std::vector<int> positions,
typename NonDeduced<CT>::type... Args) { typename NonDeduced<CT>::type... Args) {
if (detectors.empty()) if (modules.empty())
throw sls::RuntimeError("No detectors added"); throw sls::RuntimeError("No modules added");
if (positions.empty() || if (positions.empty() ||
(positions.size() == 1 && positions[0] == -1)) { (positions.size() == 1 && positions[0] == -1)) {
positions.resize(detectors.size()); positions.resize(modules.size());
std::iota(begin(positions), end(positions), 0); std::iota(begin(positions), end(positions), 0);
} }
std::vector<std::future<void>> futures; std::vector<std::future<void>> futures;
futures.reserve(positions.size()); futures.reserve(positions.size());
for (size_t i : positions) { for (size_t i : positions) {
if (i >= detectors.size()) if (i >= modules.size())
throw sls::RuntimeError("Detector out of range"); throw sls::RuntimeError("Module out of range");
futures.push_back(std::async(std::launch::async, somefunc, futures.push_back(std::async(std::launch::async, somefunc,
detectors[i].get(), Args...)); modules[i].get(), Args...));
} }
for (auto &i : futures) { for (auto &i : futures) {
i.get(); i.get();
@ -170,20 +168,20 @@ class DetectorImpl : public virtual slsDetectorDefs {
std::vector<int> positions, std::vector<int> positions,
typename NonDeduced<CT>::type... Args) const { typename NonDeduced<CT>::type... Args) const {
if (detectors.empty()) if (modules.empty())
throw sls::RuntimeError("No detectors added"); throw sls::RuntimeError("No modules added");
if (positions.empty() || if (positions.empty() ||
(positions.size() == 1 && positions[0] == -1)) { (positions.size() == 1 && positions[0] == -1)) {
positions.resize(detectors.size()); positions.resize(modules.size());
std::iota(begin(positions), end(positions), 0); std::iota(begin(positions), end(positions), 0);
} }
std::vector<std::future<void>> futures; std::vector<std::future<void>> futures;
futures.reserve(positions.size()); futures.reserve(positions.size());
for (size_t i : positions) { for (size_t i : positions) {
if (i >= detectors.size()) if (i >= modules.size())
throw sls::RuntimeError("Detector out of range"); throw sls::RuntimeError("Module out of range");
futures.push_back(std::async(std::launch::async, somefunc, futures.push_back(std::async(std::launch::async, somefunc,
detectors[i].get(), Args...)); modules[i].get(), Args...));
} }
for (auto &i : futures) { for (auto &i : futures) {
i.get(); i.get();
@ -193,12 +191,12 @@ class DetectorImpl : public virtual slsDetectorDefs {
/** set acquiring flag in shared memory */ /** set acquiring flag in shared memory */
void setAcquiringFlag(bool flag); void setAcquiringFlag(bool flag);
/** return multi detector shared memory ID */ /** return detector index in shared memory */
int getMultiId() const; int getDetectorIndex() const;
/** Free specific shared memory from the command line without creating /** Free specific shared memory from the command line without creating
* object */ * object */
static void freeSharedMemory(int multiId, int detPos = -1); static void freeSharedMemory(int detectorIndex, int detPos = -1);
/** Free all modules from current multi Id shared memory and delete members /** Free all modules from current multi Id shared memory and delete members
*/ */
@ -215,24 +213,24 @@ class DetectorImpl : public virtual slsDetectorDefs {
/** /**
* Connect to Virtual Detector Servers at local host * Connect to Virtual Detector Servers at local host
* @param numdet number of detectors * @param numdet number of modules
* @param port starting port number * @param port starting port number
*/ */
void setVirtualDetectorServers(const int numdet, const int port); void setVirtualDetectorServers(const int numdet, const int port);
/** Sets the hostname of all sls detectors in shared memory and updates /** Sets the hostname of all sls modules in shared memory and updates
* local cache */ * local cache */
void setHostname(const std::vector<std::string> &name); void setHostname(const std::vector<std::string> &name);
/** Gets the total number of detectors */ /** Gets the total number of modules */
int size() const; int size() const;
slsDetectorDefs::xy getNumberOfDetectors() const; slsDetectorDefs::xy getNumberOfModules() const;
slsDetectorDefs::xy getNumberOfChannels() const; slsDetectorDefs::xy getNumberOfChannels() const;
/** Must be set before setting hostname /** Must be set before setting hostname
* Sets maximum number of channels of all sls detectors */ * Sets maximum number of channels of all sls modules */
void setNumberOfChannels(const slsDetectorDefs::xy c); void setNumberOfChannels(const slsDetectorDefs::xy c);
/** [Eiger][Jungfrau] */ /** [Eiger][Jungfrau] */
@ -248,14 +246,14 @@ class DetectorImpl : public virtual slsDetectorDefs {
/** /**
* register callback for accessing acquisition final data * register callback for accessing acquisition final data
* @param func function to be called at the end of the acquisition. * @param func function to be called at the end of the acquisition.
* gets detector status and progress index as arguments * gets module status and progress index as arguments
* @param pArg argument * @param pArg argument
*/ */
void registerAcquisitionFinishedCallback(void (*func)(double, int, void *), void registerAcquisitionFinishedCallback(void (*func)(double, int, void *),
void *pArg); void *pArg);
/** /**
* register calbback for accessing detector final data, * register calbback for accessing module final data,
* also enables data streaming in client and receiver * also enables data streaming in client and receiver
* @param userCallback function for plotting/analyzing the data. * @param userCallback function for plotting/analyzing the data.
* Its arguments are * Its arguments are
@ -307,7 +305,7 @@ class DetectorImpl : public virtual slsDetectorDefs {
* one * one
* @param update true to update last user pid, date etc * @param update true to update last user pid, date etc
*/ */
void setupMultiDetector(bool verify = true, bool update = true); void setupDetector(bool verify = true, bool update = true);
/** /**
* Creates shm and initializes shm structure OR * Creates shm and initializes shm structure OR
@ -319,7 +317,7 @@ class DetectorImpl : public virtual slsDetectorDefs {
/** Initialize detector structure for the shared memory just created */ /** Initialize detector structure for the shared memory just created */
void initializeDetectorStructure(); void initializeDetectorStructure();
/** Initialize members (eg. slsDetectors from shm, zmqsockets) /** Initialize members (eg. modules from shm, zmqsockets)
* @param verify true to verify if shm size matches existing one * @param verify true to verify if shm size matches existing one
*/ */
void initializeMembers(bool verify = true); void initializeMembers(bool verify = true);
@ -332,7 +330,7 @@ class DetectorImpl : public virtual slsDetectorDefs {
/** Execute command in terminal and return result */ /** Execute command in terminal and return result */
std::string exec(const char *cmd); std::string exec(const char *cmd);
void addSlsDetector(const std::string &hostname); void addModule(const std::string &hostname);
void updateDetectorSize(); void updateDetectorSize();
@ -380,22 +378,13 @@ class DetectorImpl : public virtual slsDetectorDefs {
*/ */
int kbhit(); int kbhit();
/** Multi detector Id */ const int detectorIndex{0};
const int multiId{0}; sls::SharedMemory<sharedDetector> shm{0, -1};
std::vector<std::unique_ptr<sls::Module>> modules;
/** Shared Memory object */
sls::SharedMemory<sharedMultiSlsDetector> multi_shm{0, -1};
/** pointers to the Module structures */
std::vector<std::unique_ptr<sls::Module>> detectors;
/** data streaming (down stream) enabled in client (zmq sckets created) */ /** data streaming (down stream) enabled in client (zmq sckets created) */
bool client_downstream{false}; bool client_downstream{false};
/** ZMQ Socket - Receiver to Client */
std::vector<std::unique_ptr<ZmqSocket>> zmqSocket; std::vector<std::unique_ptr<ZmqSocket>> zmqSocket;
/** number of zmq sockets running currently */
volatile int numZmqRunning{0}; volatile int numZmqRunning{0};
/** mutex to synchronize main and data processing threads */ /** mutex to synchronize main and data processing threads */

View File

@ -5,11 +5,13 @@
#include "sls/bit_utils.h" #include "sls/bit_utils.h"
#include "sls/container_utils.h" #include "sls/container_utils.h"
#include "sls/file_utils.h" #include "sls/file_utils.h"
#include "sls/md5_helper.h"
#include "sls/network_utils.h" #include "sls/network_utils.h"
#include "sls/sls_detector_exceptions.h" #include "sls/sls_detector_exceptions.h"
#include "sls/sls_detector_funcs.h" #include "sls/sls_detector_funcs.h"
#include "sls/string_utils.h" #include "sls/string_utils.h"
#include "sls/versionAPI.h" #include "sls/versionAPI.h"
#include <algorithm> #include <algorithm>
#include <array> #include <array>
#include <bitset> #include <bitset>
@ -57,7 +59,7 @@ void Module::freeSharedMemory() {
} }
bool Module::isFixedPatternSharedMemoryCompatible() const { bool Module::isFixedPatternSharedMemoryCompatible() const {
return (shm()->shmversion >= SLS_SHMAPIVERSION); return (shm()->shmversion >= MODULE_SHMAPIVERSION);
} }
std::string Module::getHostname() const { return shm()->hostname; } std::string Module::getHostname() const { return shm()->hostname; }
@ -69,7 +71,7 @@ void Module::setHostname(const std::string &hostname,
client.close(); client.close();
try { try {
checkDetectorVersionCompatibility(); checkDetectorVersionCompatibility();
LOG(logINFO) << "Detector Version Compatibility - Success"; LOG(logINFO) << "Module Version Compatibility - Success";
} catch (const DetectorError &e) { } catch (const DetectorError &e) {
if (!initialChecks) { if (!initialChecks) {
LOG(logWARNING) << "Bypassing Initial Checks at your own risk!"; LOG(logWARNING) << "Bypassing Initial Checks at your own risk!";
@ -77,7 +79,7 @@ void Module::setHostname(const std::string &hostname,
throw; throw;
} }
} }
if (shm()->myDetectorType == EIGER) { if (shm()->detType == EIGER) {
setActivate(true); setActivate(true);
} }
} }
@ -107,22 +109,21 @@ int64_t Module::getReceiverSoftwareVersion() const {
// static function // static function
slsDetectorDefs::detectorType slsDetectorDefs::detectorType
Module::getTypeFromDetector(const std::string &hostname, int cport) { Module::getTypeFromDetector(const std::string &hostname, int cport) {
LOG(logDEBUG1) << "Getting detector type "; LOG(logDEBUG1) << "Getting Module type ";
sls::ClientSocket socket("Detector", hostname, cport); sls::ClientSocket socket("Detector", hostname, cport);
socket.Send(F_GET_DETECTOR_TYPE); socket.Send(F_GET_DETECTOR_TYPE);
socket.Receive<int>(); // TODO! Should we look at this OK/FAIL? socket.Receive<int>(); // TODO! Should we look at this OK/FAIL?
auto retval = socket.Receive<detectorType>(); auto retval = socket.Receive<detectorType>();
LOG(logDEBUG1) << "Detector type is " << retval; LOG(logDEBUG1) << "Module type is " << retval;
return retval; return retval;
} }
slsDetectorDefs::detectorType Module::getDetectorType() const { slsDetectorDefs::detectorType Module::getDetectorType() const {
return shm()->myDetectorType; return shm()->detType;
} }
void Module::updateNumberOfChannels() { void Module::updateNumberOfChannels() {
if (shm()->myDetectorType == CHIPTESTBOARD || if (shm()->detType == CHIPTESTBOARD || shm()->detType == MOENCH) {
shm()->myDetectorType == MOENCH) {
std::array<int, 2> retvals{}; std::array<int, 2> retvals{};
sendToDetector(F_GET_NUM_CHANNELS, nullptr, retvals); sendToDetector(F_GET_NUM_CHANNELS, nullptr, retvals);
shm()->nChan.x = retvals[0]; shm()->nChan.x = retvals[0];
@ -137,9 +138,9 @@ slsDetectorDefs::xy Module::getNumberOfChannels() const {
return coord; return coord;
} }
void Module::updateNumberOfDetector(slsDetectorDefs::xy det) { void Module::updateNumberOfModule(slsDetectorDefs::xy det) {
shm()->numberOfDetector = det; shm()->numberOfModule = det;
int args[2] = {shm()->numberOfDetector.y, moduleIndex}; int args[2] = {shm()->numberOfModule.y, moduleIndex};
sendToDetector(F_SET_POSITION, args, nullptr); sendToDetector(F_SET_POSITION, args, nullptr);
} }
@ -148,7 +149,7 @@ slsDetectorDefs::detectorSettings Module::getSettings() const {
} }
void Module::setSettings(detectorSettings isettings) { void Module::setSettings(detectorSettings isettings) {
if (shm()->myDetectorType == EIGER) { if (shm()->detType == EIGER) {
throw RuntimeError( throw RuntimeError(
"Cannot set settings for Eiger. Use threshold energy."); "Cannot set settings for Eiger. Use threshold energy.");
} }
@ -176,7 +177,7 @@ void Module::setThresholdEnergy(int e_eV, detectorSettings isettings,
std::all_of(shm()->trimEnergies.begin(), shm()->trimEnergies.end(), std::all_of(shm()->trimEnergies.begin(), shm()->trimEnergies.end(),
[e_eV](const int &e) { return e != e_eV; }); [e_eV](const int &e) { return e != e_eV; });
sls_detector_module myMod{shm()->myDetectorType}; sls_detector_module myMod{shm()->detType};
if (!interpolate) { if (!interpolate) {
std::string settingsfname = getTrimbitFilename(isettings, e_eV); std::string settingsfname = getTrimbitFilename(isettings, e_eV);
@ -213,7 +214,7 @@ void Module::setThresholdEnergy(int e_eV, detectorSettings isettings,
setModule(myMod, trimbits); setModule(myMod, trimbits);
if (getSettings() != isettings) { if (getSettings() != isettings) {
throw RuntimeError("setThresholdEnergyAndSettings: Could not set " throw RuntimeError("setThresholdEnergyAndSettings: Could not set "
"settings in detector"); "settings in Module");
} }
if (shm()->useReceiverFlag) { if (shm()->useReceiverFlag) {
@ -249,7 +250,7 @@ void Module::setAllThresholdEnergy(std::array<int, 3> e_eV,
M_VDCSH M_VDCSH
}; };
std::vector<sls_detector_module> myMods{shm()->myDetectorType}; std::vector<sls_detector_module> myMods{shm()->detType};
std::vector<int> energy(e_eV.begin(), e_eV.end()); std::vector<int> energy(e_eV.begin(), e_eV.end());
// if all energies are same // if all energies are same
if (allEqualTo(energy, energy[0])) { if (allEqualTo(energy, energy[0])) {
@ -307,7 +308,7 @@ void Module::setAllThresholdEnergy(std::array<int, 3> e_eV,
} }
} }
sls_detector_module myMod{shm()->myDetectorType}; sls_detector_module myMod{shm()->detType};
myMod = myMods[0]; myMod = myMods[0];
// if multiple thresholds, combine // if multiple thresholds, combine
@ -392,7 +393,7 @@ void Module::setAllThresholdEnergy(std::array<int, 3> e_eV,
setModule(myMod, trimbits); setModule(myMod, trimbits);
if (getSettings() != isettings) { if (getSettings() != isettings) {
throw RuntimeError("setThresholdEnergyAndSettings: Could not set " throw RuntimeError("setThresholdEnergyAndSettings: Could not set "
"settings in detector"); "settings in Module");
} }
if (shm()->useReceiverFlag) { if (shm()->useReceiverFlag) {
@ -410,13 +411,13 @@ std::string Module::setSettingsDir(const std::string &dir) {
return shm()->settingsDir; return shm()->settingsDir;
} }
void Module::loadSettingsFile(const std::string &fname) { void Module::loadTrimbits(const std::string &fname) {
// find specific file if it has detid in file name (.snxxx) // find specific file if it has detid in file name (.snxxx)
if (shm()->myDetectorType == EIGER || shm()->myDetectorType == MYTHEN3) { if (shm()->detType == EIGER || shm()->detType == MYTHEN3) {
std::ostringstream ostfn; std::ostringstream ostfn;
ostfn << fname; ostfn << fname;
int moduleIdWidth = 3; int moduleIdWidth = 3;
if (shm()->myDetectorType == MYTHEN3) { if (shm()->detType == MYTHEN3) {
moduleIdWidth = 4; moduleIdWidth = 4;
} }
if ((fname.find(".sn") == std::string::npos) && if ((fname.find(".sn") == std::string::npos) &&
@ -440,7 +441,7 @@ void Module::setAllTrimbits(int val) {
} }
std::vector<int> Module::getTrimEn() const { std::vector<int> Module::getTrimEn() const {
if (shm()->myDetectorType != EIGER && shm()->myDetectorType != MYTHEN3) { if (shm()->detType != EIGER && shm()->detType != MYTHEN3) {
throw RuntimeError("getTrimEn not implemented for this detector."); throw RuntimeError("getTrimEn not implemented for this detector.");
} }
return std::vector<int>(shm()->trimEnergies.begin(), return std::vector<int>(shm()->trimEnergies.begin(),
@ -448,7 +449,7 @@ std::vector<int> Module::getTrimEn() const {
} }
int Module::setTrimEn(const std::vector<int> &energies) { int Module::setTrimEn(const std::vector<int> &energies) {
if (shm()->myDetectorType != EIGER && shm()->myDetectorType != MYTHEN3) { if (shm()->detType != EIGER && shm()->detType != MYTHEN3) {
throw RuntimeError("setTrimEn not implemented for this detector."); throw RuntimeError("setTrimEn not implemented for this detector.");
} }
if (energies.size() > MAX_TRIMEN) { if (energies.size() > MAX_TRIMEN) {
@ -464,7 +465,7 @@ int Module::setTrimEn(const std::vector<int> &energies) {
} }
bool Module::getFlipRows() const { bool Module::getFlipRows() const {
if (shm()->myDetectorType == EIGER) { if (shm()->detType == EIGER) {
const int rxIndex = 0; const int rxIndex = 0;
return sendToReceiver<int>(rxIndex, F_GET_FLIP_ROWS_RECEIVER); return sendToReceiver<int>(rxIndex, F_GET_FLIP_ROWS_RECEIVER);
} }
@ -472,7 +473,7 @@ bool Module::getFlipRows() const {
} }
void Module::setFlipRows(bool value) { void Module::setFlipRows(bool value) {
if (shm()->myDetectorType == EIGER) { if (shm()->detType == EIGER) {
const int rxIndex = -1; const int rxIndex = -1;
sendToReceiver<int>(rxIndex, F_SET_FLIP_ROWS_RECEIVER, static_cast<int>(value)); sendToReceiver<int>(rxIndex, F_SET_FLIP_ROWS_RECEIVER, static_cast<int>(value));
} else { } else {
@ -514,7 +515,7 @@ int64_t Module::getExptime(int gateIndex) const {
void Module::setExptime(int gateIndex, int64_t value) { void Module::setExptime(int gateIndex, int64_t value) {
int64_t prevVal = value; int64_t prevVal = value;
if (shm()->myDetectorType == EIGER) { if (shm()->detType == EIGER) {
prevVal = getExptime(-1); prevVal = getExptime(-1);
} }
int64_t args[]{static_cast<int64_t>(gateIndex), value}; int64_t args[]{static_cast<int64_t>(gateIndex), value};
@ -570,7 +571,7 @@ int Module::getDynamicRange() const {
void Module::setDynamicRange(int dr) { void Module::setDynamicRange(int dr) {
int prev_val = dr; int prev_val = dr;
if (shm()->myDetectorType == EIGER) { if (shm()->detType == EIGER) {
prev_val = getDynamicRange(); prev_val = getDynamicRange();
} }
@ -581,7 +582,7 @@ void Module::setDynamicRange(int dr) {
} }
// update speed // update speed
if (shm()->myDetectorType == EIGER) { if (shm()->detType == EIGER) {
if (dr == 32) { if (dr == 32) {
LOG(logINFO) << "Setting Clock to Quarter Speed to cope with " LOG(logINFO) << "Setting Clock to Quarter Speed to cope with "
"Dynamic Range of 32"; "Dynamic Range of 32";
@ -991,9 +992,7 @@ int Module::getNumberofUDPDestinations() const {
return sendToDetector<int>(F_GET_NUM_DEST_UDP); return sendToDetector<int>(F_GET_NUM_DEST_UDP);
} }
void Module::setNumberofUDPDestinations(const int value) { void Module::clearUDPDestinations() { sendToDetector(F_CLEAR_ALL_UDP_DEST); }
sendToDetector(F_SET_NUM_DEST_UDP, value, nullptr);
}
int Module::getFirstUDPDestination() const { int Module::getFirstUDPDestination() const {
return sendToDetector<int>(F_GET_UDP_FIRST_DEST); return sendToDetector<int>(F_GET_UDP_FIRST_DEST);
@ -1026,7 +1025,7 @@ void Module::setDestinationUDPIP(const IpAddr ip, const int rxIndex) {
if (shm()->useReceiverFlag) { if (shm()->useReceiverFlag) {
sls::MacAddr retval(0LU); sls::MacAddr retval(0LU);
sendToReceiver(rxIndex, F_SET_RECEIVER_UDP_IP, ip, retval); sendToReceiver(rxIndex, F_SET_RECEIVER_UDP_IP, ip, retval);
LOG(logINFO) << "Setting destination udp mac of detector [" << moduleIndex LOG(logINFO) << "Setting destination udp mac of Module [" << moduleIndex
<< ", " << rxIndex << "] to " << retval; << ", " << rxIndex << "] to " << retval;
if (rxIndex == 0) { if (rxIndex == 0) {
sendToDetector(F_SET_DEST_UDP_MAC, retval, nullptr); sendToDetector(F_SET_DEST_UDP_MAC, retval, nullptr);
@ -1063,7 +1062,7 @@ void Module::setDestinationUDPIP2(const IpAddr ip, const int rxIndex) {
if (shm()->useReceiverFlag) { if (shm()->useReceiverFlag) {
sls::MacAddr retval(0LU); sls::MacAddr retval(0LU);
sendToReceiver(rxIndex, F_SET_RECEIVER_UDP_IP2, ip, retval); sendToReceiver(rxIndex, F_SET_RECEIVER_UDP_IP2, ip, retval);
LOG(logINFO) << "Setting destination udp mac2 of detector " << moduleIndex LOG(logINFO) << "Setting destination udp mac2 of Module " << moduleIndex
<< " to " << retval; << " to " << retval;
if (rxIndex == 0) { if (rxIndex == 0) {
sendToDetector(F_SET_DEST_UDP_MAC2, retval, nullptr); sendToDetector(F_SET_DEST_UDP_MAC2, retval, nullptr);
@ -1167,28 +1166,28 @@ void Module::validateUDPConfiguration() {
std::string Module::printReceiverConfiguration(const int rxIndex) { std::string Module::printReceiverConfiguration(const int rxIndex) {
std::ostringstream os; std::ostringstream os;
os << "\n\nDetector " << moduleIndex << "\nReceiver [" << rxIndex << "] Hostname:\t" os << "\n\nModule " << moduleIndex << "\nReceiver [" << rxIndex << "] Hostname:\t"
<< getReceiverHostname(rxIndex); << getReceiverHostname(rxIndex);
if (shm()->myDetectorType == JUNGFRAU) { if (shm()->detType == JUNGFRAU) {
os << "\nNumber of Interfaces:\t" << getNumberofUDPInterfaces() os << "\nNumber of Interfaces:\t" << getNumberofUDPInterfaces()
<< "\nSelected Interface:\t" << getSelectedUDPInterface(); << "\nSelected Interface:\t" << getSelectedUDPInterface();
} }
auto t = getDestinationUDPList(rxIndex); auto t = getDestinationUDPList(rxIndex);
os << "\nDetector UDP IP:\t" << getSourceUDPIP() << "\nDetector UDP MAC:\t" os << "\nSource UDP IP:\t" << getSourceUDPIP() << "\nSource UDP MAC:\t"
<< getSourceUDPMAC() << "\nReceiver UDP IP:\t" << t.ip << getSourceUDPMAC() << "\nDestination UDP IP:\t" << t.ip
<< "\nReceiver UDP MAC:\t" << t.mac; << "\nDestination UDP MAC:\t" << t.mac;
if (shm()->myDetectorType == JUNGFRAU) { if (shm()->detType == JUNGFRAU) {
os << "\nDetector UDP IP2:\t" << getSourceUDPIP2() os << "\nSource UDP IP2:\t" << getSourceUDPIP2()
<< "\nDetector UDP MAC2:\t" << getSourceUDPMAC2() << "\nSource UDP MAC2:\t" << getSourceUDPMAC2()
<< "\nReceiver UDP IP2:\t" << t.ip2 << "\nDestination UDP IP2:\t" << t.ip2
<< "\nReceiver UDP MAC2:\t" << t.mac2; << "\nDestination UDP MAC2:\t" << t.mac2;
} }
os << "\nReceiver UDP Port:\t" << t.port; os << "\nDestination UDP Port:\t" << t.port;
if (shm()->myDetectorType == JUNGFRAU || shm()->myDetectorType == EIGER) { if (shm()->detType == JUNGFRAU || shm()->detType == EIGER) {
os << "\nReceiver UDP Port2:\t" << t.port2; os << "\nDestination UDP Port2:\t" << t.port2;
} }
os << "\n"; os << "\n";
return os.str(); return os.str();
@ -1280,25 +1279,25 @@ void Module::setReceiverHostname(const std::string &receiverIP, const int rxInde
sendToDetector(F_GET_RECEIVER_PARAMETERS, nullptr, retval); sendToDetector(F_GET_RECEIVER_PARAMETERS, nullptr, retval);
// populate from shared memory // populate from shared memory
retval.detType = shm()->myDetectorType; retval.detType = shm()->detType;
retval.numberOfDetector.x = shm()->numberOfDetector.x; retval.numberOfModule.x = shm()->numberOfModule.x;
retval.numberOfDetector.y = shm()->numberOfDetector.y; retval.numberOfModule.y = shm()->numberOfModule.y;
retval.moduleIndex = moduleIndex; retval.moduleIndex = moduleIndex;
memset(retval.hostname, 0, sizeof(retval.hostname)); memset(retval.hostname, 0, sizeof(retval.hostname));
strcpy_safe(retval.hostname, shm()->hostname); strcpy_safe(retval.hostname, shm()->hostname);
sls::MacAddr retvals[2]; sls::MacAddr retvals[2];
sendToReceiver(rxIndex, F_SETUP_RECEIVER, retval, retvals); sendToReceiver(rxIndex, F_SETUP_RECEIVER, retval, retvals);
// update detectors with dest mac // update Modules with dest mac
if (retval.udp_dstmac == 0 && retvals[0] != 0) { if (retval.udp_dstmac == 0 && retvals[0] != 0) {
LOG(logINFO) << "Setting destination udp mac of " LOG(logINFO) << "Setting destination udp mac of "
"detector " "Module "
<< moduleIndex << " to " << retvals[0]; << moduleIndex << " to " << retvals[0];
sendToDetector(F_SET_DEST_UDP_MAC, retvals[0], nullptr); sendToDetector(F_SET_DEST_UDP_MAC, retvals[0], nullptr);
} }
if (retval.udp_dstmac2 == 0 && retvals[1] != 0) { if (retval.udp_dstmac2 == 0 && retvals[1] != 0) {
LOG(logINFO) << "Setting destination udp mac2 of " LOG(logINFO) << "Setting destination udp mac2 of "
"detector " "Module "
<< moduleIndex << " to " << retvals[1]; << moduleIndex << " to " << retvals[1];
sendToDetector(F_SET_DEST_UDP_MAC2, retvals[1], nullptr); sendToDetector(F_SET_DEST_UDP_MAC2, retvals[1], nullptr);
} }
@ -1610,7 +1609,7 @@ int64_t Module::getSubExptime() const {
void Module::setSubExptime(int64_t value) { void Module::setSubExptime(int64_t value) {
int64_t prevVal = value; int64_t prevVal = value;
if (shm()->myDetectorType == EIGER) { if (shm()->detType == EIGER) {
prevVal = getSubExptime(); prevVal = getSubExptime();
} }
sendToDetector(F_SET_SUB_EXPTIME, value, nullptr); sendToDetector(F_SET_SUB_EXPTIME, value, nullptr);
@ -1977,7 +1976,7 @@ void Module::getVetoPhoton(const int chipIndex,
void Module::setVetoPhoton(const int chipIndex, const int numPhotons, void Module::setVetoPhoton(const int chipIndex, const int numPhotons,
const int energy, const std::string &fname) { const int energy, const std::string &fname) {
if (shm()->myDetectorType != GOTTHARD2) { if (shm()->detType != GOTTHARD2) {
throw RuntimeError( throw RuntimeError(
"Set Veto reference is not implemented for this detector"); "Set Veto reference is not implemented for this detector");
} }
@ -2058,7 +2057,7 @@ void Module::setVetoReference(const int gainIndex, const int value) {
} }
void Module::setVetoFile(const int chipIndex, const std::string &fname) { void Module::setVetoFile(const int chipIndex, const std::string &fname) {
if (shm()->myDetectorType != GOTTHARD2) { if (shm()->detType != GOTTHARD2) {
throw RuntimeError( throw RuntimeError(
"Set Veto file is not implemented for this detector"); "Set Veto file is not implemented for this detector");
} }
@ -2386,7 +2385,7 @@ void Module::setReadoutMode(const slsDetectorDefs::readoutMode mode) {
auto arg = static_cast<uint32_t>(mode); // TODO! unit? auto arg = static_cast<uint32_t>(mode); // TODO! unit?
sendToDetector(F_SET_READOUT_MODE, arg, nullptr); sendToDetector(F_SET_READOUT_MODE, arg, nullptr);
// update #nchan, as it depends on #samples, adcmask, // update #nchan, as it depends on #samples, adcmask,
if (shm()->myDetectorType == CHIPTESTBOARD) { if (shm()->detType == CHIPTESTBOARD) {
updateNumberOfChannels(); updateNumberOfChannels();
} }
if (shm()->useReceiverFlag) { if (shm()->useReceiverFlag) {
@ -2651,7 +2650,7 @@ void Module::setAdditionalJsonParameter(const std::string &key,
// Advanced // Advanced
void Module::programFPGA(std::vector<char> buffer) { void Module::programFPGA(std::vector<char> buffer) {
switch (shm()->myDetectorType) { switch (shm()->detType) {
case JUNGFRAU: case JUNGFRAU:
case CHIPTESTBOARD: case CHIPTESTBOARD:
case MOENCH: case MOENCH:
@ -3197,42 +3196,42 @@ slsDetectorDefs::detectorType Module::getDetectorTypeFromShm(int det_id,
} }
shm.OpenSharedMemory(); shm.OpenSharedMemory();
if (verify && shm()->shmversion != SLS_SHMVERSION) { if (verify && shm()->shmversion != MODULE_SHMVERSION) {
std::ostringstream ss; std::ostringstream ss;
ss << "Single shared memory (" << det_id << "-" << moduleIndex ss << "Single shared memory (" << det_id << "-" << moduleIndex
<< ":)version mismatch (expected 0x" << std::hex << SLS_SHMVERSION << ":)version mismatch (expected 0x" << std::hex << MODULE_SHMVERSION
<< " but got 0x" << shm()->shmversion << ")" << std::dec << " but got 0x" << shm()->shmversion << ")" << std::dec
<< ". Clear Shared memory to continue."; << ". Clear Shared memory to continue.";
shm.UnmapSharedMemory(); shm.UnmapSharedMemory();
throw SharedMemoryError(ss.str()); throw SharedMemoryError(ss.str());
} }
return shm()->myDetectorType; return shm()->detType;
} }
void Module::initSharedMemory(detectorType type, int det_id, bool verify) { void Module::initSharedMemory(detectorType type, int det_id, bool verify) {
shm = SharedMemory<sharedSlsDetector>(det_id, moduleIndex); shm = SharedMemory<sharedModule>(det_id, moduleIndex);
if (!shm.IsExisting()) { if (!shm.IsExisting()) {
shm.CreateSharedMemory(); shm.CreateSharedMemory();
initializeDetectorStructure(type); initializeModuleStructure(type);
} else { } else {
shm.OpenSharedMemory(); shm.OpenSharedMemory();
if (verify && shm()->shmversion != SLS_SHMVERSION) { if (verify && shm()->shmversion != MODULE_SHMVERSION) {
std::ostringstream ss; std::ostringstream ss;
ss << "Single shared memory (" << det_id << "-" << moduleIndex ss << "Single shared memory (" << det_id << "-" << moduleIndex
<< ":) version mismatch (expected 0x" << std::hex << ":) version mismatch (expected 0x" << std::hex
<< SLS_SHMVERSION << " but got 0x" << shm()->shmversion << ")" << MODULE_SHMVERSION << " but got 0x" << shm()->shmversion << ")"
<< std::dec << ". Clear Shared memory to continue."; << std::dec << ". Clear Shared memory to continue.";
throw SharedMemoryError(ss.str()); throw SharedMemoryError(ss.str());
} }
} }
} }
void Module::initializeDetectorStructure(detectorType type) { void Module::initializeModuleStructure(detectorType type) {
shm()->shmversion = SLS_SHMVERSION; shm()->shmversion = MODULE_SHMVERSION;
memset(shm()->hostname, 0, MAX_STR_LENGTH); memset(shm()->hostname, 0, MAX_STR_LENGTH);
shm()->myDetectorType = type; shm()->detType = type;
shm()->numberOfDetector.x = 0; shm()->numberOfModule.x = 0;
shm()->numberOfDetector.y = 0; shm()->numberOfModule.y = 0;
shm()->controlPort = DEFAULT_PORTNO; shm()->controlPort = DEFAULT_PORTNO;
shm()->stopPort = DEFAULT_PORTNO + 1; shm()->stopPort = DEFAULT_PORTNO + 1;
sls::strcpy_safe(shm()->settingsDir, getenv("HOME")); sls::strcpy_safe(shm()->settingsDir, getenv("HOME"));
@ -3243,12 +3242,12 @@ void Module::initializeDetectorStructure(detectorType type) {
} }
shm()->useReceiverFlag = false; shm()->useReceiverFlag = false;
shm()->zmqport = DEFAULT_ZMQ_CL_PORTNO + shm()->zmqport = DEFAULT_ZMQ_CL_PORTNO +
(moduleIndex * ((shm()->myDetectorType == EIGER) ? 2 : 1)); (moduleIndex * ((shm()->detType == EIGER) ? 2 : 1));
shm()->zmqip = IpAddr{}; shm()->zmqip = IpAddr{};
shm()->numUDPInterfaces = 1; shm()->numUDPInterfaces = 1;
shm()->stoppedFlag = false; shm()->stoppedFlag = false;
// get the detector parameters based on type // get the Module parameters based on type
detParameters parameters{type}; detParameters parameters{type};
shm()->nChan.x = parameters.nChanX; shm()->nChan.x = parameters.nChanX;
shm()->nChan.y = parameters.nChanY; shm()->nChan.y = parameters.nChanY;
@ -3259,7 +3258,7 @@ void Module::initializeDetectorStructure(detectorType type) {
void Module::checkDetectorVersionCompatibility() { void Module::checkDetectorVersionCompatibility() {
int64_t arg = 0; int64_t arg = 0;
switch (shm()->myDetectorType) { switch (shm()->detType) {
case EIGER: case EIGER:
arg = APIEIGER; arg = APIEIGER;
break; break;
@ -3338,7 +3337,7 @@ int Module::sendModule(sls_detector_module *myMod, sls::ClientSocket &client) {
ts += n; ts += n;
LOG(level) << "dacs sent. " << n << " bytes"; LOG(level) << "dacs sent. " << n << " bytes";
if (shm()->myDetectorType == EIGER || shm()->myDetectorType == MYTHEN3) { if (shm()->detType == EIGER || shm()->detType == MYTHEN3) {
n = client.Send(myMod->chanregs, sizeof(int) * (myMod->nchan)); n = client.Send(myMod->chanregs, sizeof(int) * (myMod->nchan));
ts += n; ts += n;
LOG(level) << "channels sent. " << n << " bytes"; LOG(level) << "channels sent. " << n << " bytes";
@ -3386,12 +3385,12 @@ sls_detector_module Module::interpolateTrim(sls_detector_module *a,
const int energy, const int e1, const int energy, const int e1,
const int e2, bool trimbits) { const int e2, bool trimbits) {
// dacs specified only for eiger and mythen3 // dacs specified only for eiger and mythen3
if (shm()->myDetectorType != EIGER && shm()->myDetectorType != MYTHEN3) { if (shm()->detType != EIGER && shm()->detType != MYTHEN3) {
throw NotImplementedError( throw NotImplementedError(
"Interpolation of Trim values not implemented for this detector!"); "Interpolation of Trim values not implemented for this detector!");
} }
sls_detector_module myMod{shm()->myDetectorType}; sls_detector_module myMod{shm()->detType};
enum eiger_DacIndex { enum eiger_DacIndex {
E_SVP, E_SVP,
E_VTR, E_VTR,
@ -3431,7 +3430,7 @@ sls_detector_module Module::interpolateTrim(sls_detector_module *a,
// create copy and interpolate dac lists // create copy and interpolate dac lists
std::vector<int> dacs_to_copy, dacs_to_interpolate; std::vector<int> dacs_to_copy, dacs_to_interpolate;
if (shm()->myDetectorType == EIGER) { if (shm()->detType == EIGER) {
dacs_to_copy.insert( dacs_to_copy.insert(
dacs_to_copy.end(), dacs_to_copy.end(),
{E_SVP, E_VTR, E_SVN, E_VTGSTV, E_RXB_RB, E_RXB_LB, E_VCN, E_VIS}); {E_SVP, E_VTR, E_SVN, E_VTGSTV, E_RXB_RB, E_RXB_LB, E_VCN, E_VIS});
@ -3466,7 +3465,7 @@ sls_detector_module Module::interpolateTrim(sls_detector_module *a,
} }
// Copy irrelevant dacs (without failing) // Copy irrelevant dacs (without failing)
if (shm()->myDetectorType == EIGER) { if (shm()->detType == EIGER) {
// CAL // CAL
if (a->dacs[E_CAL] != b->dacs[E_CAL]) { if (a->dacs[E_CAL] != b->dacs[E_CAL]) {
LOG(logWARNING) LOG(logWARNING)
@ -3514,16 +3513,16 @@ std::string Module::getTrimbitFilename(detectorSettings s, int e_eV) {
} }
std::ostringstream ostfn; std::ostringstream ostfn;
ostfn << shm()->settingsDir << ssettings << "/" << e_eV << "eV"; ostfn << shm()->settingsDir << ssettings << "/" << e_eV << "eV";
if (shm()->myDetectorType == EIGER) { if (shm()->detType == EIGER) {
ostfn << "/noise.sn"; ostfn << "/noise.sn";
} else if (shm()->myDetectorType == MYTHEN3) { } else if (shm()->detType == MYTHEN3) {
ostfn << "/trim.sn"; ostfn << "/trim.sn";
} else { } else {
throw RuntimeError( throw RuntimeError(
"Settings or trimbit files not defined for this detector."); "Settings or trimbit files not defined for this detector.");
} }
int moduleIdWidth = 3; int moduleIdWidth = 3;
if (shm()->myDetectorType == MYTHEN3) { if (shm()->detType == MYTHEN3) {
moduleIdWidth = 4; moduleIdWidth = 4;
} }
ostfn << std::setfill('0') << std::setw(moduleIdWidth) << std::dec ostfn << std::setfill('0') << std::setw(moduleIdWidth) << std::dec
@ -3534,10 +3533,10 @@ std::string Module::getTrimbitFilename(detectorSettings s, int e_eV) {
sls_detector_module Module::readSettingsFile(const std::string &fname, sls_detector_module Module::readSettingsFile(const std::string &fname,
bool trimbits) { bool trimbits) {
LOG(logDEBUG1) << "Read settings file " << fname; LOG(logDEBUG1) << "Read settings file " << fname;
sls_detector_module myMod(shm()->myDetectorType); sls_detector_module myMod(shm()->detType);
// open file // open file
std::ifstream infile; std::ifstream infile;
if (shm()->myDetectorType == EIGER || shm()->myDetectorType == MYTHEN3) { if (shm()->detType == EIGER || shm()->detType == MYTHEN3) {
infile.open(fname.c_str(), std::ifstream::binary); infile.open(fname.c_str(), std::ifstream::binary);
} else { } else {
infile.open(fname.c_str(), std::ios_base::in); infile.open(fname.c_str(), std::ios_base::in);
@ -3549,7 +3548,7 @@ sls_detector_module Module::readSettingsFile(const std::string &fname,
auto file_size = getFileSize(infile); auto file_size = getFileSize(infile);
// eiger // eiger
if (shm()->myDetectorType == EIGER) { if (shm()->detType == EIGER) {
infile.read(reinterpret_cast<char *>(myMod.dacs), infile.read(reinterpret_cast<char *>(myMod.dacs),
sizeof(int) * (myMod.ndac)); sizeof(int) * (myMod.ndac));
infile.read(reinterpret_cast<char *>(&myMod.iodelay), infile.read(reinterpret_cast<char *>(&myMod.iodelay),
@ -3572,7 +3571,7 @@ sls_detector_module Module::readSettingsFile(const std::string &fname,
} }
// mythen3 (dacs, trimbits) // mythen3 (dacs, trimbits)
else if (shm()->myDetectorType == MYTHEN3) { else if (shm()->detType == MYTHEN3) {
int expected_size = sizeof(int) * myMod.ndac + int expected_size = sizeof(int) * myMod.ndac +
sizeof(int) * myMod.nchan + sizeof(myMod.reg); sizeof(int) * myMod.nchan + sizeof(myMod.reg);
if (file_size != expected_size) { if (file_size != expected_size) {
@ -3606,107 +3605,192 @@ sls_detector_module Module::readSettingsFile(const std::string &fname,
} }
void Module::programFPGAviaBlackfin(std::vector<char> buffer) { void Module::programFPGAviaBlackfin(std::vector<char> buffer) {
uint64_t filesize = buffer.size();
// send program from memory to detector // send program from memory to detector
LOG(logINFO) << "Sending programming binary (from pof) to detector " LOG(logINFO) << "Sending programming binary (from pof) to module "
<< moduleIndex << " (" << shm()->hostname << ")"; << moduleIndex << " (" << shm()->hostname << ")";
auto client = DetectorSocket(shm()->hostname, shm()->controlPort); auto client = DetectorSocket(shm()->hostname, shm()->controlPort);
client.Send(F_PROGRAM_FPGA); client.Send(F_PROGRAM_FPGA);
uint64_t filesize = buffer.size();
client.Send(filesize); client.Send(filesize);
// error in detector at opening file pointer to flash
// checksum
std::string checksum = sls::md5_calculate_checksum(buffer.data(), filesize);
LOG(logDEBUG1) << "Checksum:" << checksum;
char cChecksum[MAX_STR_LENGTH];
memset(cChecksum, 0, MAX_STR_LENGTH);
strcpy(cChecksum, checksum.c_str());
client.Send(cChecksum);
// opening file fail
if (client.Receive<int>() == FAIL) { if (client.Receive<int>() == FAIL) {
std::cout << '\n';
std::ostringstream os; std::ostringstream os;
os << "Detector " << moduleIndex << " (" << shm()->hostname << ")" os << "Module " << moduleIndex << " (" << shm()->hostname << ")"
<< " returned error: " << client.readErrorMessage(); << " returned error: " << client.readErrorMessage();
throw RuntimeError(os.str()); throw RuntimeError(os.str());
} }
// erasing flash
LOG(logINFO) << "Erasing Flash for detector " << moduleIndex << " ("
<< shm()->hostname << ")";
printf("%d%%\r", 0);
std::cout << std::flush;
// erasing takes 65 seconds, printing here (otherwise need threads
// in server-unnecessary)
const int ERASE_TIME = 65;
int count = ERASE_TIME + 1;
while (count > 0) {
std::this_thread::sleep_for(std::chrono::seconds(1));
--count;
printf(
"%d%%\r",
static_cast<int>(
(static_cast<double>(ERASE_TIME - count) / ERASE_TIME) * 100));
std::cout << std::flush;
}
printf("\n");
LOG(logINFO) << "Writing to Flash to detector " << moduleIndex << " ("
<< shm()->hostname << ")";
printf("%d%%\r", 0);
std::cout << std::flush;
// sending program in parts of 2mb each // sending program in parts of 2mb each
uint64_t unitprogramsize = 0; uint64_t unitprogramsize = 0;
int currentPointer = 0; int currentPointer = 0;
uint64_t totalsize = filesize;
while (filesize > 0) { while (filesize > 0) {
unitprogramsize = MAX_FPGAPROGRAMSIZE; // 2mb unitprogramsize = MAX_FPGAPROGRAMSIZE; // 2mb
if (unitprogramsize > filesize) { // less than 2mb if (unitprogramsize > filesize) { // less than 2mb
unitprogramsize = filesize; unitprogramsize = filesize;
} }
LOG(logDEBUG1) << "unitprogramsize:" << unitprogramsize LOG(logDEBUG) << "unitprogramsize:" << unitprogramsize
<< "\t filesize:" << filesize; << "\t filesize:" << filesize;
client.Send(&buffer[currentPointer], unitprogramsize); client.Send(&buffer[currentPointer], unitprogramsize);
if (client.Receive<int>() == FAIL) { if (client.Receive<int>() == FAIL) {
std::cout << '\n'; std::cout << '\n';
std::ostringstream os; std::ostringstream os;
os << "Detector " << moduleIndex << " (" << shm()->hostname << ")" os << "Module " << moduleIndex << " (" << shm()->hostname << ")"
<< " returned error: " << client.readErrorMessage(); << " returned error: " << client.readErrorMessage();
throw RuntimeError(os.str()); throw RuntimeError(os.str());
} }
filesize -= unitprogramsize; filesize -= unitprogramsize;
currentPointer += unitprogramsize; currentPointer += unitprogramsize;
// print progress
printf(
"%d%%\r",
static_cast<int>(
(static_cast<double>(totalsize - filesize) / totalsize) * 100));
std::cout << std::flush;
} }
std::cout << '\n';
// fpga has picked up from flash successfully // checksum
if (client.Receive<int>() == FAIL) { if (client.Receive<int>() == FAIL) {
std::ostringstream os; std::ostringstream os;
os << "Detector " << moduleIndex << " (" << shm()->hostname << ")" os << "Module " << moduleIndex << " (" << shm()->hostname << ")"
<< " returned error: " << client.readErrorMessage(); << " returned error: " << client.readErrorMessage();
throw RuntimeError(os.str()); throw RuntimeError(os.str());
} }
LOG(logINFO) << "Checksum verified for module " << moduleIndex << " ("
<< shm()->hostname << ")";
// simulating erasing flash
{
LOG(logINFO) << "(Simulating) Erasing Flash for module " << moduleIndex << " ("
<< shm()->hostname << ")";
printf("%d%%\r", 0);
std::cout << std::flush;
// erasing takes 65 seconds, printing here (otherwise need threads
// in server-unnecessary)
const int ERASE_TIME = 65;
int count = ERASE_TIME + 1;
while (count > 0) {
std::this_thread::sleep_for(std::chrono::seconds(1));
--count;
printf(
"%d%%\r",
static_cast<int>(
(static_cast<double>(ERASE_TIME - count) / ERASE_TIME) * 100));
std::cout << std::flush;
}
printf("\n");
}
// simulating writing to flash
{
LOG(logINFO) << "(Simulating) Writing to Flash for module " << moduleIndex << " (" << shm()->hostname << ")";
printf("%d%%\r", 0);
std::cout << std::flush;
// writing takes 30 seconds, printing here (otherwise need threads
// in server-unnecessary)
const int ERASE_TIME = 30;
int count = ERASE_TIME + 1;
while (count > 0) {
std::this_thread::sleep_for(std::chrono::seconds(1));
--count;
printf(
"%d%%\r",
static_cast<int>(
(static_cast<double>(ERASE_TIME - count) / ERASE_TIME) * 100));
std::cout << std::flush;
}
printf("\n");
}
if (client.Receive<int>() == FAIL) {
std::ostringstream os;
os << "Module " << moduleIndex << " (" << shm()->hostname << ")"
<< " returned error: " << client.readErrorMessage();
throw RuntimeError(os.str());
}
if (moduleIndex == 0) {
LOG(logINFO) << "Copied to flash and checksum verified";
}
LOG(logINFO) << "FPGA programmed successfully"; LOG(logINFO) << "FPGA programmed successfully";
rebootController(); rebootController();
} }
void Module::programFPGAviaNios(std::vector<char> buffer) { void Module::programFPGAviaNios(std::vector<char> buffer) {
LOG(logINFO) << "Sending programming binary (from rbf) to detector " LOG(logINFO) << "Sending programming binary (from rbf) to Module "
<< moduleIndex << " (" << shm()->hostname << ")"; << moduleIndex << " (" << shm()->hostname << ")";
auto client = DetectorSocket(shm()->hostname, shm()->controlPort); auto client = DetectorSocket(shm()->hostname, shm()->controlPort);
client.Send(F_PROGRAM_FPGA); client.Send(F_PROGRAM_FPGA);
uint64_t filesize = buffer.size(); uint64_t filesize = buffer.size();
client.Send(filesize); client.Send(filesize);
// checksum
std::string checksum = sls::md5_calculate_checksum(buffer.data(), filesize);
LOG(logDEBUG1) << "Checksum:" << checksum;
char cChecksum[MAX_STR_LENGTH];
memset(cChecksum, 0, MAX_STR_LENGTH);
strcpy(cChecksum, checksum.c_str());
client.Send(cChecksum);
// validate file size before sending program
if (client.Receive<int>() == FAIL) { if (client.Receive<int>() == FAIL) {
std::ostringstream os; std::ostringstream os;
os << "Detector " << moduleIndex << " (" << shm()->hostname << ")" os << "Module " << moduleIndex << " (" << shm()->hostname << ")"
<< " returned error: " << client.readErrorMessage(); << " returned error: " << client.readErrorMessage();
throw RuntimeError(os.str()); throw RuntimeError(os.str());
} }
client.Send(buffer); client.Send(buffer);
// simulating erasing flash
{
LOG(logINFO) << "(Simulating) Erasing Flash for module " << moduleIndex << " ("
<< shm()->hostname << ")";
printf("%d%%\r", 0);
std::cout << std::flush;
// erasing takes 10 seconds, printing here (otherwise need threads
// in server-unnecessary)
const int ERASE_TIME = 10;
int count = ERASE_TIME + 1;
while (count > 0) {
std::this_thread::sleep_for(std::chrono::seconds(1));
--count;
printf(
"%d%%\r",
static_cast<int>(
(static_cast<double>(ERASE_TIME - count) / ERASE_TIME) * 100));
std::cout << std::flush;
}
printf("\n");
}
// simulating writing to flash
{
LOG(logINFO) << "(Simulating) Writing to Flash for module " << moduleIndex << " (" << shm()->hostname << ")";
printf("%d%%\r", 0);
std::cout << std::flush;
// writing takes 45 seconds, printing here (otherwise need threads
// in server-unnecessary)
const int ERASE_TIME = 45;
int count = ERASE_TIME + 1;
while (count > 0) {
std::this_thread::sleep_for(std::chrono::seconds(1));
--count;
printf(
"%d%%\r",
static_cast<int>(
(static_cast<double>(ERASE_TIME - count) / ERASE_TIME) * 100));
std::cout << std::flush;
}
printf("\n");
}
if (client.Receive<int>() == FAIL) { if (client.Receive<int>() == FAIL) {
std::ostringstream os; std::ostringstream os;
os << "Detector " << moduleIndex << " (" << shm()->hostname << ")" os << "Module " << moduleIndex << " (" << shm()->hostname << ")"
<< " returned error: " << client.readErrorMessage(); << " returned error: " << client.readErrorMessage();
throw RuntimeError(os.str()); throw RuntimeError(os.str());
} }

View File

@ -14,8 +14,8 @@
class ServerInterface; class ServerInterface;
#define SLS_SHMAPIVERSION 0x190726 #define MODULE_SHMAPIVERSION 0x190726
#define SLS_SHMVERSION 0x210913 #define MODULE_SHMVERSION 0x210913
namespace sls { namespace sls {
@ -25,24 +25,24 @@ struct sharedReceiver {
}; };
/** /**
* @short structure allocated in shared memory to store detector settings for * @short structure allocated in shared memory to store Module settings for
* IPC and cache * IPC and cache
*/ */
struct sharedSlsDetector { struct sharedModule {
/* FIXED PATTERN FOR STATIC FUNCTIONS. DO NOT CHANGE, ONLY APPEND ------*/ /* FIXED PATTERN FOR STATIC FUNCTIONS. DO NOT CHANGE, ONLY APPEND ------*/
int shmversion; int shmversion;
char hostname[MAX_STR_LENGTH]; char hostname[MAX_STR_LENGTH];
slsDetectorDefs::detectorType myDetectorType; slsDetectorDefs::detectorType detType;
/** END OF FIXED PATTERN -----------------------------------------------*/ /** END OF FIXED PATTERN -----------------------------------------------*/
slsDetectorDefs::xy numberOfDetector; slsDetectorDefs::xy numberOfModule;
int controlPort; int controlPort;
int stopPort; int stopPort;
char settingsDir[MAX_STR_LENGTH]; char settingsDir[MAX_STR_LENGTH];
/** list of the energies at which the detector has been trimmed */ /** list of the energies at which the Module has been trimmed */
sls::StaticVector<int, MAX_TRIMEN> trimEnergies; sls::StaticVector<int, MAX_TRIMEN> trimEnergies;
/** number of channels per chip */ /** number of channels per chip */
slsDetectorDefs::xy nChan; slsDetectorDefs::xy nChan;
@ -84,7 +84,7 @@ class Module : public virtual slsDetectorDefs {
virtual ~Module(); virtual ~Module();
/** Frees shared memory and deletes shared memory structure /** Frees shared memory and deletes shared memory structure
Safe to call only if detector shm also deleted or its numberOfDetectors is Safe to call only if detector shm also deleted or its numberOfModules is
updated */ updated */
void freeSharedMemory(); void freeSharedMemory();
bool isFixedPatternSharedMemoryCompatible() const; bool isFixedPatternSharedMemoryCompatible() const;
@ -107,7 +107,7 @@ class Module : public virtual slsDetectorDefs {
detectorType getDetectorType() const; detectorType getDetectorType() const;
void updateNumberOfChannels(); void updateNumberOfChannels();
slsDetectorDefs::xy getNumberOfChannels() const; slsDetectorDefs::xy getNumberOfChannels() const;
void updateNumberOfDetector(slsDetectorDefs::xy det); void updateNumberOfModule(slsDetectorDefs::xy det);
detectorSettings getSettings() const; detectorSettings getSettings() const;
void setSettings(detectorSettings isettings); void setSettings(detectorSettings isettings);
int getThresholdEnergy() const; int getThresholdEnergy() const;
@ -118,7 +118,7 @@ class Module : public virtual slsDetectorDefs {
detectorSettings isettings, bool trimbits); detectorSettings isettings, bool trimbits);
std::string getSettingsDir() const; std::string getSettingsDir() const;
std::string setSettingsDir(const std::string &dir); std::string setSettingsDir(const std::string &dir);
void loadSettingsFile(const std::string &fname); void loadTrimbits(const std::string &fname);
int getAllTrimbits() const; int getAllTrimbits() const;
void setAllTrimbits(int val); void setAllTrimbits(int val);
std::vector<int> getTrimEn() const; std::vector<int> getTrimEn() const;
@ -232,7 +232,7 @@ class Module : public virtual slsDetectorDefs {
sls::UdpDestination getDestinationUDPList(const uint32_t entry) const; sls::UdpDestination getDestinationUDPList(const uint32_t entry) const;
void setDestinationUDPList(const sls::UdpDestination dest); void setDestinationUDPList(const sls::UdpDestination dest);
int getNumberofUDPDestinations() const; int getNumberofUDPDestinations() const;
void setNumberofUDPDestinations(const int value); void clearUDPDestinations();
int getFirstUDPDestination() const; int getFirstUDPDestination() const;
void setFirstUDPDestination(const int value); void setFirstUDPDestination(const int value);
sls::IpAddr getDestinationUDPIP(const int rxIndex) const; sls::IpAddr getDestinationUDPIP(const int rxIndex) const;
@ -718,9 +718,9 @@ class Module : public virtual slsDetectorDefs {
verify is if shm size matches existing one */ verify is if shm size matches existing one */
void initSharedMemory(detectorType type, int det_id, bool verify = true); void initSharedMemory(detectorType type, int det_id, bool verify = true);
/** Initialize detector structure to defaults, /** Initialize module structure to defaults,
Called when new shared memory is created */ Called when new shared memory is created */
void initializeDetectorStructure(detectorType type); void initializeModuleStructure(detectorType type);
void checkDetectorVersionCompatibility(); void checkDetectorVersionCompatibility();
void checkReceiverVersionCompatibility(); void checkReceiverVersionCompatibility();
@ -763,7 +763,7 @@ class Module : public virtual slsDetectorDefs {
void programFPGAviaNios(std::vector<char> buffer); void programFPGAviaNios(std::vector<char> buffer);
const int moduleIndex; const int moduleIndex;
mutable sls::SharedMemory<sharedSlsDetector> shm{0, 0}; mutable sls::SharedMemory<sharedModule> shm{0, 0};
}; };
} // namespace sls } // namespace sls

View File

@ -22,8 +22,8 @@
#include <sys/stat.h> // fstat #include <sys/stat.h> // fstat
#include <unistd.h> #include <unistd.h>
#define SHM_MULTI_PREFIX "/slsDetectorPackage_multi_" #define SHM_DETECTOR_PREFIX "/slsDetectorPackage_detector_"
#define SHM_SLS_PREFIX "_sls_" #define SHM_MODULE_PREFIX "_module_"
#define SHM_ENV_NAME "SLSDETNAME" #define SHM_ENV_NAME "SLSDETNAME"
#include <iostream> #include <iostream>
@ -35,13 +35,10 @@ template <typename T> class SharedMemory {
public: public:
/** /**
* Constructor * moduleid of -1 creates a detector only shared memory
* creates the single/multi detector shared memory name
* @param multiId multi detector id
* @param slsId sls detector id, -1 if a multi detector shared memory
*/ */
SharedMemory(int multiId, int slsId) { SharedMemory(int detectorId, int moduleIndex) {
name = ConstructSharedMemoryName(multiId, slsId); name = ConstructSharedMemoryName(detectorId, moduleIndex);
} }
/** /**
@ -208,11 +205,11 @@ template <typename T> class SharedMemory {
/** /**
* Create Shared memory name * Create Shared memory name
* throws exception if name created is longer than required 255(manpages) * throws exception if name created is longer than required 255(manpages)
* @param multiId multi detector id * @param detectorId detector id
* @param slsId sls detector id, -1 if a multi detector shared memory * @param moduleIndex module id, -1 if a detector shared memory
* @returns shared memory name * @returns shared memory name
*/ */
std::string ConstructSharedMemoryName(int multiId, int slsId) { std::string ConstructSharedMemoryName(int detectorId, int moduleIndex) {
// using environment path // using environment path
std::string sEnvPath; std::string sEnvPath;
@ -223,11 +220,11 @@ template <typename T> class SharedMemory {
} }
std::stringstream ss; std::stringstream ss;
if (slsId < 0) if (moduleIndex < 0)
ss << SHM_MULTI_PREFIX << multiId << sEnvPath; ss << SHM_DETECTOR_PREFIX << detectorId << sEnvPath;
else else
ss << SHM_MULTI_PREFIX << multiId << SHM_SLS_PREFIX << slsId ss << SHM_DETECTOR_PREFIX << detectorId << SHM_MODULE_PREFIX
<< sEnvPath; << moduleIndex << sEnvPath;
std::string temp = ss.str(); std::string temp = ss.str();
if (temp.length() > NAME_MAX_LENGTH) { if (temp.length() > NAME_MAX_LENGTH) {

View File

@ -2215,13 +2215,12 @@ TEST_CASE("udp_dstlist", "[.cmd]") {
CmdProxy proxy(&det); CmdProxy proxy(&det);
auto det_type = det.getDetectorType().squash(); auto det_type = det.getDetectorType().squash();
if (det_type == defs::JUNGFRAU || det_type == defs::EIGER) { if (det_type == defs::JUNGFRAU || det_type == defs::EIGER) {
REQUIRE_NOTHROW(proxy.Call("udp_dstlist", {"0"}, -1, GET)); REQUIRE_NOTHROW(proxy.Call("udp_dstlist", {}, 0, GET, std::cout, 0));
REQUIRE_THROWS(proxy.Call( REQUIRE_THROWS(proxy.Call(
"udp_dstlist", "udp_dstlist", {"ip=0.0.0.0", "mac=00:00:00:00:00:00", "port=1233"},
{"entry=0", "ip=0.0.0.0", "mac=00:00:00:00:00:00", "port=1233"}, -1, -1, PUT, std::cout, 0));
PUT));
} else { } else {
REQUIRE_THROWS(proxy.Call("udp_dstlist", {"0"}, -1, GET)); REQUIRE_THROWS(proxy.Call("udp_dstlist", {}, -1, GET, std::cout, 0));
} }
} }
@ -2230,33 +2229,20 @@ TEST_CASE("udp_numdst", "[.cmd]") {
CmdProxy proxy(&det); CmdProxy proxy(&det);
auto det_type = det.getDetectorType().squash(); auto det_type = det.getDetectorType().squash();
if (det_type == defs::JUNGFRAU || det_type == defs::EIGER) { if (det_type == defs::JUNGFRAU || det_type == defs::EIGER) {
auto prev_val = det.getNumberofUDPDestinations(); REQUIRE_NOTHROW(proxy.Call("udp_numdst", {}, -1, GET));
{
std::ostringstream oss;
proxy.Call("udp_numdst", {"10"}, -1, PUT, oss);
REQUIRE(oss.str() == "udp_numdst 10\n");
}
{
std::ostringstream oss;
proxy.Call("udp_numdst", {}, -1, GET, oss);
REQUIRE(oss.str() == "udp_numdst 10\n");
}
{
std::ostringstream oss;
proxy.Call("udp_numdst", {"32"}, -1, PUT, oss);
REQUIRE(oss.str() == "udp_numdst 32\n");
}
REQUIRE_THROWS(proxy.Call("udp_numdst", {"0"}, -1, PUT));
REQUIRE_THROWS(proxy.Call("udp_numdst", {"33"}, -1, PUT));
for (int i = 0; i != det.size(); ++i) {
det.setNumberofUDPDestinations(prev_val[i], {i});
}
} else { } else {
REQUIRE_THROWS(proxy.Call("udp_numdst", {}, -1, GET)); REQUIRE_THROWS(proxy.Call("udp_numdst", {}, -1, GET));
} }
} }
TEST_CASE("udp_cleardst", "[.cmd]") {
Detector det;
CmdProxy proxy(&det);
REQUIRE_THROWS(proxy.Call("udp_cleardst", {}, -1, GET));
REQUIRE_NOTHROW(proxy.Call("udp_cleardst", {}, -1, PUT));
}
TEST_CASE("udp_firstdst", "[.cmd]") { TEST_CASE("udp_firstdst", "[.cmd]") {
Detector det; Detector det;
CmdProxy proxy(&det); CmdProxy proxy(&det);

View File

@ -29,7 +29,7 @@ TEST_CASE("Is shm fixed pattern shm compatible") {
REQUIRE(m.isFixedPatternSharedMemoryCompatible() == true); REQUIRE(m.isFixedPatternSharedMemoryCompatible() == true);
// Set shm version to 0 // Set shm version to 0
sls::SharedMemory<sls::sharedSlsDetector> shm(0, 0); sls::SharedMemory<sls::sharedModule> shm(0, 0);
REQUIRE(shm.IsExisting() == true); REQUIRE(shm.IsExisting() == true);
shm.OpenSharedMemory(); shm.OpenSharedMemory();
shm()->shmversion = 0; shm()->shmversion = 0;

View File

@ -42,3 +42,17 @@ void BinaryMasterFile::CreateMasterFile(const std::string filePath,
attr->WriteMasterBinaryAttributes(fd_); attr->WriteMasterBinaryAttributes(fd_);
CloseFile(); CloseFile();
} }
void BinaryMasterFile::UpdateMasterFile(MasterAttributes *attr,
bool silentMode) {
if (nullptr == (fd_ = fopen((const char *)fileName_.c_str(), "a"))) {
fd_ = nullptr;
throw sls::RuntimeError("Could not append binary master file " +
fileName_);
}
attr->WriteFinalBinaryAttributes(fd_);
CloseFile();
if (!silentMode) {
LOG(logINFO) << "Updated Master File";
}
}

View File

@ -15,6 +15,7 @@ class BinaryMasterFile : private virtual slsDetectorDefs, public File {
const uint64_t fileIndex, const bool overWriteEnable, const uint64_t fileIndex, const bool overWriteEnable,
const bool silentMode, const bool silentMode,
MasterAttributes *attr) override; MasterAttributes *attr) override;
void UpdateMasterFile(MasterAttributes *attr, bool silentMode) override;
private: private:
FILE *fd_{nullptr}; FILE *fd_{nullptr};

View File

@ -35,7 +35,7 @@ ClientInterface::~ClientInterface() {
} }
ClientInterface::ClientInterface(int portNumber) ClientInterface::ClientInterface(int portNumber)
: myDetectorType(GOTTHARD), : detType(GOTTHARD),
portNumber(portNumber > 0 ? portNumber : DEFAULT_PORTNO + 2), portNumber(portNumber > 0 ? portNumber : DEFAULT_PORTNO + 2),
server(portNumber) { server(portNumber) {
functionTable(); functionTable();
@ -334,7 +334,7 @@ int ClientInterface::setup_receiver(Interface &socket) {
// basic setup // basic setup
setDetectorType(arg.detType); setDetectorType(arg.detType);
{ {
int msize[2] = {arg.numberOfDetector.x, arg.numberOfDetector.y}; int msize[2] = {arg.numberOfModule.x, arg.numberOfModule.y};
impl()->setDetectorSize(msize); impl()->setDetectorSize(msize);
} }
impl()->setModulePositionId(arg.moduleIndex); impl()->setModulePositionId(arg.moduleIndex);
@ -359,7 +359,7 @@ int ClientInterface::setup_receiver(Interface &socket) {
} }
impl()->setUDPPortNumber(arg.udp_dstport); impl()->setUDPPortNumber(arg.udp_dstport);
impl()->setUDPPortNumber2(arg.udp_dstport2); impl()->setUDPPortNumber2(arg.udp_dstport2);
if (myDetectorType == JUNGFRAU || myDetectorType == GOTTHARD2) { if (detType == JUNGFRAU || detType == GOTTHARD2) {
try { try {
impl()->setNumberofUDPInterfaces(arg.udpInterfaces); impl()->setNumberofUDPInterfaces(arg.udpInterfaces);
} catch (const RuntimeError &e) { } catch (const RuntimeError &e) {
@ -372,13 +372,13 @@ int ClientInterface::setup_receiver(Interface &socket) {
// acquisition parameters // acquisition parameters
impl()->setNumberOfFrames(arg.frames); impl()->setNumberOfFrames(arg.frames);
impl()->setNumberOfTriggers(arg.triggers); impl()->setNumberOfTriggers(arg.triggers);
if (myDetectorType == GOTTHARD2) { if (detType == GOTTHARD2) {
impl()->setNumberOfBursts(arg.bursts); impl()->setNumberOfBursts(arg.bursts);
} }
if (myDetectorType == JUNGFRAU) { if (detType == JUNGFRAU) {
impl()->setNumberOfAdditionalStorageCells(arg.additionalStorageCells); impl()->setNumberOfAdditionalStorageCells(arg.additionalStorageCells);
} }
if (myDetectorType == MOENCH || myDetectorType == CHIPTESTBOARD) { if (detType == MOENCH || detType == CHIPTESTBOARD) {
try { try {
impl()->setNumberofAnalogSamples(arg.analogSamples); impl()->setNumberofAnalogSamples(arg.analogSamples);
} catch (const RuntimeError &e) { } catch (const RuntimeError &e) {
@ -387,7 +387,7 @@ int ClientInterface::setup_receiver(Interface &socket) {
" due to fifo structure memory allocation."); " due to fifo structure memory allocation.");
} }
} }
if (myDetectorType == CHIPTESTBOARD) { if (detType == CHIPTESTBOARD) {
try { try {
impl()->setNumberofDigitalSamples(arg.digitalSamples); impl()->setNumberofDigitalSamples(arg.digitalSamples);
} catch (const RuntimeError &e) { } catch (const RuntimeError &e) {
@ -396,11 +396,11 @@ int ClientInterface::setup_receiver(Interface &socket) {
" due to fifo structure memory allocation."); " due to fifo structure memory allocation.");
} }
} }
if (myDetectorType != MYTHEN3) { if (detType != MYTHEN3) {
impl()->setAcquisitionTime(std::chrono::nanoseconds(arg.expTimeNs)); impl()->setAcquisitionTime(std::chrono::nanoseconds(arg.expTimeNs));
} }
impl()->setAcquisitionPeriod(std::chrono::nanoseconds(arg.periodNs)); impl()->setAcquisitionPeriod(std::chrono::nanoseconds(arg.periodNs));
if (myDetectorType == EIGER) { if (detType == EIGER) {
impl()->setSubExpTime(std::chrono::nanoseconds(arg.subExpTimeNs)); impl()->setSubExpTime(std::chrono::nanoseconds(arg.subExpTimeNs));
impl()->setSubPeriod(std::chrono::nanoseconds(arg.subExpTimeNs) + impl()->setSubPeriod(std::chrono::nanoseconds(arg.subExpTimeNs) +
std::chrono::nanoseconds(arg.subDeadTimeNs)); std::chrono::nanoseconds(arg.subDeadTimeNs));
@ -416,17 +416,17 @@ int ClientInterface::setup_receiver(Interface &socket) {
} }
impl()->setThresholdEnergy(arg.thresholdEnergyeV[0]); impl()->setThresholdEnergy(arg.thresholdEnergyeV[0]);
} }
if (myDetectorType == EIGER || myDetectorType == JUNGFRAU) { if (detType == EIGER || detType == JUNGFRAU) {
impl()->setReadNRows(arg.readNRows); impl()->setReadNRows(arg.readNRows);
} }
if (myDetectorType == MYTHEN3) { if (detType == MYTHEN3) {
std::array<int, 3> val; std::array<int, 3> val;
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
val[i] = arg.thresholdEnergyeV[i]; val[i] = arg.thresholdEnergyeV[i];
} }
impl()->setThresholdEnergy(val); impl()->setThresholdEnergy(val);
} }
if (myDetectorType == EIGER || myDetectorType == MYTHEN3) { if (detType == EIGER || detType == MYTHEN3) {
try { try {
impl()->setDynamicRange(arg.dynamicRange); impl()->setDynamicRange(arg.dynamicRange);
} catch (const RuntimeError &e) { } catch (const RuntimeError &e) {
@ -436,15 +436,15 @@ int ClientInterface::setup_receiver(Interface &socket) {
} }
} }
impl()->setTimingMode(arg.timMode); impl()->setTimingMode(arg.timMode);
if (myDetectorType == EIGER || myDetectorType == MOENCH || if (detType == EIGER || detType == MOENCH || detType == CHIPTESTBOARD ||
myDetectorType == CHIPTESTBOARD || myDetectorType == MYTHEN3) { detType == MYTHEN3) {
try { try {
impl()->setTenGigaEnable(arg.tenGiga); impl()->setTenGigaEnable(arg.tenGiga);
} catch (const RuntimeError &e) { } catch (const RuntimeError &e) {
throw RuntimeError("Could not set 10GbE."); throw RuntimeError("Could not set 10GbE.");
} }
} }
if (myDetectorType == CHIPTESTBOARD) { if (detType == CHIPTESTBOARD) {
try { try {
impl()->setReadoutMode(arg.roMode); impl()->setReadoutMode(arg.roMode);
} catch (const RuntimeError &e) { } catch (const RuntimeError &e) {
@ -452,7 +452,7 @@ int ClientInterface::setup_receiver(Interface &socket) {
"due to fifo memory allocation."); "due to fifo memory allocation.");
} }
} }
if (myDetectorType == CHIPTESTBOARD || myDetectorType == MOENCH) { if (detType == CHIPTESTBOARD || detType == MOENCH) {
try { try {
impl()->setADCEnableMask(arg.adcMask); impl()->setADCEnableMask(arg.adcMask);
} catch (const RuntimeError &e) { } catch (const RuntimeError &e) {
@ -466,14 +466,14 @@ int ClientInterface::setup_receiver(Interface &socket) {
"due to fifo memory allcoation"); "due to fifo memory allcoation");
} }
} }
if (myDetectorType == GOTTHARD) { if (detType == GOTTHARD) {
try { try {
impl()->setROI(arg.roi); impl()->setROI(arg.roi);
} catch (const RuntimeError &e) { } catch (const RuntimeError &e) {
throw RuntimeError("Could not set ROI"); throw RuntimeError("Could not set ROI");
} }
} }
if (myDetectorType == MYTHEN3) { if (detType == MYTHEN3) {
impl()->setCounterMask(arg.countermask); impl()->setCounterMask(arg.countermask);
impl()->setAcquisitionTime1(std::chrono::nanoseconds(arg.expTime1Ns)); impl()->setAcquisitionTime1(std::chrono::nanoseconds(arg.expTime1Ns));
impl()->setAcquisitionTime2(std::chrono::nanoseconds(arg.expTime2Ns)); impl()->setAcquisitionTime2(std::chrono::nanoseconds(arg.expTime2Ns));
@ -483,7 +483,7 @@ int ClientInterface::setup_receiver(Interface &socket) {
impl()->setGateDelay3(std::chrono::nanoseconds(arg.gateDelay3Ns)); impl()->setGateDelay3(std::chrono::nanoseconds(arg.gateDelay3Ns));
impl()->setNumberOfGates(arg.gates); impl()->setNumberOfGates(arg.gates);
} }
if (myDetectorType == GOTTHARD2) { if (detType == GOTTHARD2) {
impl()->setBurstMode(arg.burstType); impl()->setBurstMode(arg.burstType);
} }
impl()->setScan(arg.scanParams); impl()->setScan(arg.scanParams);
@ -507,9 +507,9 @@ void ClientInterface::setDetectorType(detectorType arg) {
} }
try { try {
myDetectorType = GENERIC; detType = GENERIC;
receiver = sls::make_unique<Implementation>(arg); receiver = sls::make_unique<Implementation>(arg);
myDetectorType = arg; detType = arg;
} catch (...) { } catch (...) {
throw RuntimeError("Could not set detector type"); throw RuntimeError("Could not set detector type");
} }
@ -535,7 +535,7 @@ int ClientInterface::set_roi(Interface &socket) {
auto arg = socket.Receive<ROI>(); auto arg = socket.Receive<ROI>();
LOG(logDEBUG1) << "Set ROI: [" << arg.xmin << ", " << arg.xmax << "]"; LOG(logDEBUG1) << "Set ROI: [" << arg.xmin << ", " << arg.xmax << "]";
if (myDetectorType != GOTTHARD) if (detType != GOTTHARD)
functionNotImplemented(); functionNotImplemented();
verifyIdle(socket); verifyIdle(socket);
@ -616,7 +616,7 @@ int ClientInterface::set_burst_mode(Interface &socket) {
int ClientInterface::set_num_analog_samples(Interface &socket) { int ClientInterface::set_num_analog_samples(Interface &socket) {
auto value = socket.Receive<int>(); auto value = socket.Receive<int>();
LOG(logDEBUG1) << "Setting num analog samples to " << value; LOG(logDEBUG1) << "Setting num analog samples to " << value;
if (myDetectorType != CHIPTESTBOARD && myDetectorType != MOENCH) { if (detType != CHIPTESTBOARD && detType != MOENCH) {
functionNotImplemented(); functionNotImplemented();
} }
try { try {
@ -632,7 +632,7 @@ int ClientInterface::set_num_analog_samples(Interface &socket) {
int ClientInterface::set_num_digital_samples(Interface &socket) { int ClientInterface::set_num_digital_samples(Interface &socket) {
auto value = socket.Receive<int>(); auto value = socket.Receive<int>();
LOG(logDEBUG1) << "Setting num digital samples to " << value; LOG(logDEBUG1) << "Setting num digital samples to " << value;
if (myDetectorType != CHIPTESTBOARD) { if (detType != CHIPTESTBOARD) {
functionNotImplemented(); functionNotImplemented();
} }
try { try {
@ -654,7 +654,7 @@ int ClientInterface::set_exptime(Interface &socket) {
<< " (gateIndex: " << gateIndex << ")"; << " (gateIndex: " << gateIndex << ")";
switch (gateIndex) { switch (gateIndex) {
case -1: case -1:
if (myDetectorType == MYTHEN3) { if (detType == MYTHEN3) {
impl()->setAcquisitionTime1(value); impl()->setAcquisitionTime1(value);
impl()->setAcquisitionTime2(value); impl()->setAcquisitionTime2(value);
impl()->setAcquisitionTime3(value); impl()->setAcquisitionTime3(value);
@ -663,19 +663,19 @@ int ClientInterface::set_exptime(Interface &socket) {
} }
break; break;
case 0: case 0:
if (myDetectorType != MYTHEN3) { if (detType != MYTHEN3) {
functionNotImplemented(); functionNotImplemented();
} }
impl()->setAcquisitionTime1(value); impl()->setAcquisitionTime1(value);
break; break;
case 1: case 1:
if (myDetectorType != MYTHEN3) { if (detType != MYTHEN3) {
functionNotImplemented(); functionNotImplemented();
} }
impl()->setAcquisitionTime2(value); impl()->setAcquisitionTime2(value);
break; break;
case 2: case 2:
if (myDetectorType != MYTHEN3) { if (detType != MYTHEN3) {
functionNotImplemented(); functionNotImplemented();
} }
impl()->setAcquisitionTime3(value); impl()->setAcquisitionTime3(value);
@ -723,19 +723,19 @@ int ClientInterface::set_dynamic_range(Interface &socket) {
exists = true; exists = true;
break; break;
/*case 1: //TODO: Not yet implemented in firmware /*case 1: //TODO: Not yet implemented in firmware
if (myDetectorType == MYTHEN3) { if (detType == MYTHEN3) {
exists = true; exists = true;
} }
break; break;
*/ */
case 4: case 4:
if (myDetectorType == EIGER) { if (detType == EIGER) {
exists = true; exists = true;
} }
break; break;
case 8: case 8:
case 32: case 32:
if (myDetectorType == EIGER || myDetectorType == MYTHEN3) { if (detType == EIGER || detType == MYTHEN3) {
exists = true; exists = true;
} }
break; break;
@ -935,8 +935,8 @@ int ClientInterface::get_overwrite(Interface &socket) {
int ClientInterface::enable_tengiga(Interface &socket) { int ClientInterface::enable_tengiga(Interface &socket) {
auto val = socket.Receive<int>(); auto val = socket.Receive<int>();
if (myDetectorType != EIGER && myDetectorType != CHIPTESTBOARD && if (detType != EIGER && detType != CHIPTESTBOARD && detType != MOENCH &&
myDetectorType != MOENCH && myDetectorType != MYTHEN3) detType != MYTHEN3)
functionNotImplemented(); functionNotImplemented();
if (val >= 0) { if (val >= 0) {
@ -974,7 +974,7 @@ int ClientInterface::set_fifo_depth(Interface &socket) {
int ClientInterface::set_activate(Interface &socket) { int ClientInterface::set_activate(Interface &socket) {
auto enable = socket.Receive<int>(); auto enable = socket.Receive<int>();
if (myDetectorType != EIGER) if (detType != EIGER)
functionNotImplemented(); functionNotImplemented();
if (enable >= 0) { if (enable >= 0) {
@ -1025,7 +1025,7 @@ int ClientInterface::set_streaming_timer(Interface &socket) {
} }
int ClientInterface::get_flip_rows(Interface &socket) { int ClientInterface::get_flip_rows(Interface &socket) {
if (myDetectorType != EIGER) if (detType != EIGER)
functionNotImplemented(); functionNotImplemented();
int retval = impl()->getFlipRows(); int retval = impl()->getFlipRows();
@ -1036,7 +1036,7 @@ int ClientInterface::get_flip_rows(Interface &socket) {
int ClientInterface::set_flip_rows(Interface &socket) { int ClientInterface::set_flip_rows(Interface &socket) {
auto arg = socket.Receive<int>(); auto arg = socket.Receive<int>();
if (myDetectorType != EIGER) if (detType != EIGER)
functionNotImplemented(); functionNotImplemented();
if (arg != 0 && arg != 1) { if (arg != 0 && arg != 1) {
@ -1277,7 +1277,7 @@ int ClientInterface::get_padding_enable(Interface &socket) {
int ClientInterface::set_deactivated_padding_enable(Interface &socket) { int ClientInterface::set_deactivated_padding_enable(Interface &socket) {
auto enable = socket.Receive<int>(); auto enable = socket.Receive<int>();
if (myDetectorType != EIGER) { if (detType != EIGER) {
functionNotImplemented(); functionNotImplemented();
} }
if (enable < 0) { if (enable < 0) {
@ -1291,7 +1291,7 @@ int ClientInterface::set_deactivated_padding_enable(Interface &socket) {
} }
int ClientInterface::get_deactivated_padding_enable(Interface &socket) { int ClientInterface::get_deactivated_padding_enable(Interface &socket) {
if (myDetectorType != EIGER) if (detType != EIGER)
functionNotImplemented(); functionNotImplemented();
auto retval = static_cast<int>(impl()->getDeactivatedPadding()); auto retval = static_cast<int>(impl()->getDeactivatedPadding());
LOG(logDEBUG1) << "Deactivated Padding Enable: " << retval; LOG(logDEBUG1) << "Deactivated Padding Enable: " << retval;
@ -1301,7 +1301,7 @@ int ClientInterface::get_deactivated_padding_enable(Interface &socket) {
int ClientInterface::set_readout_mode(Interface &socket) { int ClientInterface::set_readout_mode(Interface &socket) {
auto arg = socket.Receive<readoutMode>(); auto arg = socket.Receive<readoutMode>();
if (myDetectorType != CHIPTESTBOARD) if (detType != CHIPTESTBOARD)
functionNotImplemented(); functionNotImplemented();
if (arg >= 0) { if (arg >= 0) {
@ -1345,7 +1345,7 @@ int ClientInterface::set_adc_mask(Interface &socket) {
int ClientInterface::set_dbit_list(Interface &socket) { int ClientInterface::set_dbit_list(Interface &socket) {
sls::StaticVector<int, MAX_RX_DBIT> args; sls::StaticVector<int, MAX_RX_DBIT> args;
socket.Receive(args); socket.Receive(args);
if (myDetectorType != CHIPTESTBOARD) if (detType != CHIPTESTBOARD)
functionNotImplemented(); functionNotImplemented();
LOG(logDEBUG1) << "Setting DBIT list"; LOG(logDEBUG1) << "Setting DBIT list";
for (auto &it : args) { for (auto &it : args) {
@ -1358,7 +1358,7 @@ int ClientInterface::set_dbit_list(Interface &socket) {
} }
int ClientInterface::get_dbit_list(Interface &socket) { int ClientInterface::get_dbit_list(Interface &socket) {
if (myDetectorType != CHIPTESTBOARD) if (detType != CHIPTESTBOARD)
functionNotImplemented(); functionNotImplemented();
sls::StaticVector<int, MAX_RX_DBIT> retval; sls::StaticVector<int, MAX_RX_DBIT> retval;
retval = impl()->getDbitList(); retval = impl()->getDbitList();
@ -1368,7 +1368,7 @@ int ClientInterface::get_dbit_list(Interface &socket) {
int ClientInterface::set_dbit_offset(Interface &socket) { int ClientInterface::set_dbit_offset(Interface &socket) {
auto arg = socket.Receive<int>(); auto arg = socket.Receive<int>();
if (myDetectorType != CHIPTESTBOARD) if (detType != CHIPTESTBOARD)
functionNotImplemented(); functionNotImplemented();
if (arg < 0) { if (arg < 0) {
throw RuntimeError("Invalid dbit offset: " + std::to_string(arg)); throw RuntimeError("Invalid dbit offset: " + std::to_string(arg));
@ -1380,7 +1380,7 @@ int ClientInterface::set_dbit_offset(Interface &socket) {
} }
int ClientInterface::get_dbit_offset(Interface &socket) { int ClientInterface::get_dbit_offset(Interface &socket) {
if (myDetectorType != CHIPTESTBOARD) if (detType != CHIPTESTBOARD)
functionNotImplemented(); functionNotImplemented();
int retval = impl()->getDbitOffset(); int retval = impl()->getDbitOffset();
LOG(logDEBUG1) << "Dbit offset retval: " << retval; LOG(logDEBUG1) << "Dbit offset retval: " << retval;
@ -1410,7 +1410,7 @@ int ClientInterface::set_read_n_rows(Interface &socket) {
auto arg = socket.Receive<int>(); auto arg = socket.Receive<int>();
if (arg >= 0) { if (arg >= 0) {
verifyIdle(socket); verifyIdle(socket);
if (myDetectorType != EIGER && myDetectorType != JUNGFRAU) { if (detType != EIGER && detType != JUNGFRAU) {
throw RuntimeError("Could not set number of rows. Not implemented for this detector"); throw RuntimeError("Could not set number of rows. Not implemented for this detector");
} }
LOG(logDEBUG1) << "Setting number of rows:" << arg; LOG(logDEBUG1) << "Setting number of rows:" << arg;
@ -1436,7 +1436,7 @@ sls::MacAddr ClientInterface::setUdpIp(sls::IpAddr arg) {
<< ". Got " << eth; << ". Got " << eth;
} }
impl()->setEthernetInterface(eth); impl()->setEthernetInterface(eth);
if (myDetectorType == EIGER) { if (detType == EIGER) {
impl()->setEthernetInterface2(eth); impl()->setEthernetInterface2(eth);
} }
// get mac address // get mac address
@ -1485,7 +1485,7 @@ sls::MacAddr ClientInterface::setUdpIp2(sls::IpAddr arg) {
int ClientInterface::set_udp_ip2(Interface &socket) { int ClientInterface::set_udp_ip2(Interface &socket) {
auto arg = socket.Receive<sls::IpAddr>(); auto arg = socket.Receive<sls::IpAddr>();
verifyIdle(socket); verifyIdle(socket);
if (myDetectorType != JUNGFRAU && myDetectorType != GOTTHARD2) { if (detType != JUNGFRAU && detType != GOTTHARD2) {
throw RuntimeError( throw RuntimeError(
"UDP Destination IP2 not implemented for this detector"); "UDP Destination IP2 not implemented for this detector");
} }
@ -1504,8 +1504,7 @@ int ClientInterface::set_udp_port(Interface &socket) {
int ClientInterface::set_udp_port2(Interface &socket) { int ClientInterface::set_udp_port2(Interface &socket) {
auto arg = socket.Receive<int>(); auto arg = socket.Receive<int>();
verifyIdle(socket); verifyIdle(socket);
if (myDetectorType != JUNGFRAU && myDetectorType != EIGER && if (detType != JUNGFRAU && detType != EIGER && detType != GOTTHARD2) {
myDetectorType != GOTTHARD2) {
throw RuntimeError( throw RuntimeError(
"UDP Destination Port2 not implemented for this detector"); "UDP Destination Port2 not implemented for this detector");
} }
@ -1518,7 +1517,7 @@ int ClientInterface::set_num_interfaces(Interface &socket) {
auto arg = socket.Receive<int>(); auto arg = socket.Receive<int>();
arg = (arg > 1 ? 2 : 1); arg = (arg > 1 ? 2 : 1);
verifyIdle(socket); verifyIdle(socket);
if (myDetectorType != JUNGFRAU && myDetectorType != GOTTHARD2) { if (detType != JUNGFRAU && detType != GOTTHARD2) {
throw RuntimeError( throw RuntimeError(
"Number of interfaces not implemented for this detector"); "Number of interfaces not implemented for this detector");
} }
@ -1596,7 +1595,7 @@ int ClientInterface::get_progress(Interface &socket) {
int ClientInterface::set_num_gates(Interface &socket) { int ClientInterface::set_num_gates(Interface &socket) {
auto value = socket.Receive<int>(); auto value = socket.Receive<int>();
LOG(logDEBUG1) << "Setting num gates to " << value; LOG(logDEBUG1) << "Setting num gates to " << value;
if (myDetectorType != MYTHEN3) { if (detType != MYTHEN3) {
functionNotImplemented(); functionNotImplemented();
} }
impl()->setNumberOfGates(value); impl()->setNumberOfGates(value);
@ -1610,7 +1609,7 @@ int ClientInterface::set_gate_delay(Interface &socket) {
auto value = std::chrono::nanoseconds(args[1]); auto value = std::chrono::nanoseconds(args[1]);
LOG(logDEBUG1) << "Setting gate delay to " << sls::ToString(value) LOG(logDEBUG1) << "Setting gate delay to " << sls::ToString(value)
<< " (gateIndex: " << gateIndex << ")"; << " (gateIndex: " << gateIndex << ")";
if (myDetectorType != MYTHEN3) { if (detType != MYTHEN3) {
functionNotImplemented(); functionNotImplemented();
} }
switch (gateIndex) { switch (gateIndex) {
@ -1685,7 +1684,7 @@ int ClientInterface::set_scan(Interface &socket) {
int ClientInterface::set_threshold(Interface &socket) { int ClientInterface::set_threshold(Interface &socket) {
auto arg = socket.Receive<int>(); auto arg = socket.Receive<int>();
LOG(logDEBUG) << "Threshold: " << arg << " eV"; LOG(logDEBUG) << "Threshold: " << arg << " eV";
if (myDetectorType != EIGER) if (detType != EIGER)
functionNotImplemented(); functionNotImplemented();
verifyIdle(socket); verifyIdle(socket);
impl()->setThresholdEnergy(arg); impl()->setThresholdEnergy(arg);
@ -1712,7 +1711,7 @@ int ClientInterface::set_streaming_hwm(Interface &socket) {
int ClientInterface::set_all_threshold(Interface &socket) { int ClientInterface::set_all_threshold(Interface &socket) {
auto eVs = socket.Receive<std::array<int, 3>>(); auto eVs = socket.Receive<std::array<int, 3>>();
LOG(logDEBUG) << "Threshold:" << sls::ToString(eVs); LOG(logDEBUG) << "Threshold:" << sls::ToString(eVs);
if (myDetectorType != MYTHEN3) if (detType != MYTHEN3)
functionNotImplemented(); functionNotImplemented();
verifyIdle(socket); verifyIdle(socket);
impl()->setThresholdEnergy(eVs); impl()->setThresholdEnergy(eVs);
@ -1733,7 +1732,7 @@ int ClientInterface::set_detector_datastream(Interface &socket) {
bool enable = static_cast<int>(args[1]); bool enable = static_cast<int>(args[1]);
LOG(logDEBUG1) << "Setting datastream (" << sls::ToString(port) << ") to " LOG(logDEBUG1) << "Setting datastream (" << sls::ToString(port) << ") to "
<< sls::ToString(enable); << sls::ToString(enable);
if (myDetectorType != EIGER) if (detType != EIGER)
functionNotImplemented(); functionNotImplemented();
verifyIdle(socket); verifyIdle(socket);
impl()->setDetectorDataStream(port, enable); impl()->setDetectorDataStream(port, enable);

View File

@ -11,7 +11,7 @@ class ServerInterface;
class ClientInterface : private virtual slsDetectorDefs { class ClientInterface : private virtual slsDetectorDefs {
enum numberMode { DEC, HEX }; enum numberMode { DEC, HEX };
detectorType myDetectorType; detectorType detType;
int portNumber{0}; int portNumber{0};
sls::ServerSocket server; sls::ServerSocket server;
std::unique_ptr<Implementation> receiver; std::unique_ptr<Implementation> receiver;

View File

@ -17,6 +17,7 @@
#include "HDF5VirtualFile.h" #include "HDF5VirtualFile.h"
#endif #endif
#include "DataStreamer.h" #include "DataStreamer.h"
#include "sls/container_utils.h"
#include "sls/sls_detector_exceptions.h" #include "sls/sls_detector_exceptions.h"
#include <cerrno> #include <cerrno>
@ -56,6 +57,10 @@ bool DataProcessor::GetStartedFlag() { return startedFlag_; }
uint64_t DataProcessor::GetNumFramesCaught() { return numFramesCaught_; } uint64_t DataProcessor::GetNumFramesCaught() { return numFramesCaught_; }
uint64_t DataProcessor::GetNumCompleteFramesCaught() {
return numCompleteFramesCaught_;
}
uint64_t DataProcessor::GetCurrentFrameIndex() { return currentFrameIndex_; } uint64_t DataProcessor::GetCurrentFrameIndex() { return currentFrameIndex_; }
uint64_t DataProcessor::GetProcessedIndex() { uint64_t DataProcessor::GetProcessedIndex() {
@ -68,6 +73,7 @@ void DataProcessor::ResetParametersforNewAcquisition() {
StopRunning(); StopRunning();
startedFlag_ = false; startedFlag_ = false;
numFramesCaught_ = 0; numFramesCaught_ = 0;
numCompleteFramesCaught_ = 0;
firstIndex_ = 0; firstIndex_ = 0;
currentFrameIndex_ = 0; currentFrameIndex_ = 0;
firstStreamerFrame_ = true; firstStreamerFrame_ = true;
@ -248,6 +254,41 @@ void DataProcessor::LinkDataInMasterFile(const bool silentMode) {
} }
#endif #endif
void DataProcessor::UpdateMasterFile(bool silentMode) {
if (masterFile_) {
// final attributes
std::unique_ptr<MasterAttributes> masterAttributes;
switch (detectorType_) {
case GOTTHARD:
masterAttributes = sls::make_unique<GotthardMasterAttributes>();
break;
case JUNGFRAU:
masterAttributes = sls::make_unique<JungfrauMasterAttributes>();
break;
case EIGER:
masterAttributes = sls::make_unique<EigerMasterAttributes>();
break;
case MYTHEN3:
masterAttributes = sls::make_unique<Mythen3MasterAttributes>();
break;
case GOTTHARD2:
masterAttributes = sls::make_unique<Gotthard2MasterAttributes>();
break;
case MOENCH:
masterAttributes = sls::make_unique<MoenchMasterAttributes>();
break;
case CHIPTESTBOARD:
masterAttributes = sls::make_unique<CtbMasterAttributes>();
break;
default:
throw sls::RuntimeError(
"Unknown detector type to set up master file attributes");
}
masterAttributes->framesInFile = numFramesCaught_;
masterFile_->UpdateMasterFile(masterAttributes.get(), silentMode);
}
}
void DataProcessor::ThreadExecution() { void DataProcessor::ThreadExecution() {
char *buffer = nullptr; char *buffer = nullptr;
fifo_->PopAddress(buffer); fifo_->PopAddress(buffer);
@ -306,9 +347,10 @@ uint64_t DataProcessor::ProcessAnImage(char *buf) {
sls_detector_header header = rheader->detHeader; sls_detector_header header = rheader->detHeader;
uint64_t fnum = header.frameNumber; uint64_t fnum = header.frameNumber;
currentFrameIndex_ = fnum; currentFrameIndex_ = fnum;
numFramesCaught_++;
uint32_t nump = header.packetNumber; uint32_t nump = header.packetNumber;
if (nump == generalData_->packetsPerFrame) { if (nump == generalData_->packetsPerFrame) {
numFramesCaught_++; numCompleteFramesCaught_++;
} }
LOG(logDEBUG1) << "DataProcessing " << index << ": fnum:" << fnum; LOG(logDEBUG1) << "DataProcessing " << index << ": fnum:" << fnum;

View File

@ -37,6 +37,7 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject {
bool GetStartedFlag(); bool GetStartedFlag();
uint64_t GetNumFramesCaught(); uint64_t GetNumFramesCaught();
uint64_t GetNumCompleteFramesCaught();
/** (-1 if no frames have been caught */ /** (-1 if no frames have been caught */
uint64_t GetCurrentFrameIndex(); uint64_t GetCurrentFrameIndex();
/** (-1 if no frames have been caught) */ /** (-1 if no frames have been caught) */
@ -76,6 +77,7 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject {
const int numModY); const int numModY);
void LinkDataInMasterFile(const bool silentMode); void LinkDataInMasterFile(const bool silentMode);
#endif #endif
void UpdateMasterFile(bool silentMode);
/** /**
* Call back for raw data * Call back for raw data
* args to raw data ready callback are * args to raw data ready callback are
@ -174,9 +176,12 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject {
std::atomic<uint64_t> firstIndex_{0}; std::atomic<uint64_t> firstIndex_{0};
// for statistics // for statistics
/** Number of complete frames caught */ /** Number of frames caught */
uint64_t numFramesCaught_{0}; uint64_t numFramesCaught_{0};
/** Number of complete frames caught */
uint64_t numCompleteFramesCaught_{0};
/** Frame Number of latest processed frame number */ /** Frame Number of latest processed frame number */
std::atomic<uint64_t> currentFrameIndex_{0}; std::atomic<uint64_t> currentFrameIndex_{0};

View File

@ -118,6 +118,11 @@ class File : private virtual slsDetectorDefs {
"should be overloaded by a derived class"; "should be overloaded by a derived class";
}; };
virtual void UpdateMasterFile(MasterAttributes *attr, bool silentMode) {
LOG(logERROR) << "This is a generic function UpdateMasterFile that "
"should be overloaded by a derived class";
};
protected: protected:
slsDetectorDefs::fileFormat format_; slsDetectorDefs::fileFormat format_;
}; };

View File

@ -117,6 +117,9 @@ void HDF5MasterFile::CreateMasterFile(const std::string filePath,
Group group5(group3.createGroup("detector")); Group group5(group3.createGroup("detector"));
Group group6(group1.createGroup("sample")); Group group6(group1.createGroup("sample"));
// TODO find a way to get complete group link
attrGroupName_ = "/entry/instrument/detector";
attr->WriteMasterHDF5Attributes(fd_, &group5); attr->WriteMasterHDF5Attributes(fd_, &group5);
fd_->close(); fd_->close();
@ -129,4 +132,29 @@ void HDF5MasterFile::CreateMasterFile(const std::string filePath,
if (!silentMode) { if (!silentMode) {
LOG(logINFO) << "Master File: " << fileName_; LOG(logINFO) << "Master File: " << fileName_;
} }
}
void HDF5MasterFile::UpdateMasterFile(MasterAttributes *attr, bool silentMode) {
std::lock_guard<std::mutex> lock(*hdf5Lib_);
try {
Exception::dontPrint(); // to handle errors
FileAccPropList flist;
flist.setFcloseDegree(H5F_CLOSE_STRONG);
fd_ = new H5File(fileName_.c_str(), H5F_ACC_RDWR,
FileCreatPropList::DEFAULT, flist);
Group group = fd_->openGroup(attrGroupName_.c_str());
attr->WriteFinalHDF5Attributes(fd_, &group);
fd_->close();
} catch (const Exception &error) {
error.printErrorStack();
CloseFile();
throw sls::RuntimeError(
"Could not create/overwrite master HDF5 handles");
}
if (!silentMode) {
LOG(logINFO) << "Updated Master File";
}
} }

View File

@ -19,9 +19,11 @@ class HDF5MasterFile : private virtual slsDetectorDefs, public File {
const uint64_t fileIndex, const bool overWriteEnable, const uint64_t fileIndex, const bool overWriteEnable,
const bool silentMode, const bool silentMode,
MasterAttributes *attr) override; MasterAttributes *attr) override;
void UpdateMasterFile(MasterAttributes *attr, bool silentMode) override;
private: private:
std::mutex *hdf5Lib_; std::mutex *hdf5Lib_;
H5File *fd_{nullptr}; H5File *fd_{nullptr};
std::string fileName_; std::string fileName_;
std::string attrGroupName_;
}; };

View File

@ -429,7 +429,7 @@ uint64_t Implementation::getFramesCaught() const {
for (const auto &it : dataProcessor) { for (const auto &it : dataProcessor) {
flagsum += it->GetStartedFlag(); flagsum += it->GetStartedFlag();
min = std::min(min, it->GetNumFramesCaught()); min = std::min(min, it->GetNumCompleteFramesCaught());
} }
// no data processed // no data processed
if (flagsum != dataProcessor.size()) if (flagsum != dataProcessor.size())
@ -571,6 +571,13 @@ void Implementation::stopReceiver() {
} }
} }
#endif #endif
if (fileWriteEnable && masterFileWriteEnable && modulePos == 0) {
try {
dataProcessor[0]->UpdateMasterFile(silentMode);
} catch (...) {
; // ignore it and just print it
}
}
// wait for the processes (dataStreamer) to be done // wait for the processes (dataStreamer) to be done
running = true; running = true;
@ -589,7 +596,7 @@ void Implementation::stopReceiver() {
std::vector<uint64_t> mp = getNumMissingPackets(); std::vector<uint64_t> mp = getNumMissingPackets();
uint64_t tot = 0; uint64_t tot = 0;
for (int i = 0; i < numThreads; i++) { for (int i = 0; i < numThreads; i++) {
int nf = dataProcessor[i]->GetNumFramesCaught(); int nf = dataProcessor[i]->GetNumCompleteFramesCaught();
tot += nf; tot += nf;
std::string mpMessage = std::to_string((int64_t)mp[i]); std::string mpMessage = std::to_string((int64_t)mp[i]);
if ((int64_t)mp[i] < 0) { if ((int64_t)mp[i] < 0) {

View File

@ -16,6 +16,7 @@ using namespace H5;
using ns = std::chrono::nanoseconds; using ns = std::chrono::nanoseconds;
struct MasterAttributes { struct MasterAttributes {
// (before acquisition)
slsDetectorDefs::detectorType detType{slsDetectorDefs::GENERIC}; slsDetectorDefs::detectorType detType{slsDetectorDefs::GENERIC};
slsDetectorDefs::timingMode timingMode{slsDetectorDefs::AUTO_TIMING}; slsDetectorDefs::timingMode timingMode{slsDetectorDefs::AUTO_TIMING};
uint32_t imageSize{0}; uint32_t imageSize{0};
@ -57,6 +58,9 @@ struct MasterAttributes {
uint32_t gates; uint32_t gates;
std::map<std::string, std::string> additionalJsonHeader; std::map<std::string, std::string> additionalJsonHeader;
// Final Attributes (after acquisition)
uint64_t framesInFile{0};
MasterAttributes(){}; MasterAttributes(){};
virtual ~MasterAttributes(){}; virtual ~MasterAttributes(){};
@ -87,30 +91,42 @@ struct MasterAttributes {
}; };
void WriteBinaryAttributes(FILE *fd, std::string message) { void WriteBinaryAttributes(FILE *fd, std::string message) {
if (fwrite((void *)message.c_str(), 1, message.length(), fd) !=
message.length()) {
throw sls::RuntimeError(
"Master binary file incorrect number of bytes written to file");
}
};
void WriteFinalBinaryAttributes(FILE *fd) {
// adding few common parameters to the end // adding few common parameters to the end
std::ostringstream oss;
if (!additionalJsonHeader.empty()) { if (!additionalJsonHeader.empty()) {
std::ostringstream oss;
oss << "Additional Json Header : " oss << "Additional Json Header : "
<< sls::ToString(additionalJsonHeader) << '\n'; << sls::ToString(additionalJsonHeader) << '\n';
message += oss.str();
} }
oss << "Frames in File : " << framesInFile << '\n';
// adding sls_receiver header format // adding sls_receiver header format
message += std::string("\n#Frame Header\n" oss << '\n'
"Frame Number : 8 bytes\n" << "#Frame Header" << '\n'
"SubFrame Number/ExpLength : 4 bytes\n" << "Frame Number : 8 bytes" << '\n'
"Packet Number : 4 bytes\n" << "SubFrame Number/ExpLength : 4 bytes" << '\n'
"Bunch ID : 8 bytes\n" << "Packet Number : 4 bytes" << '\n'
"Timestamp : 8 bytes\n" << "Bunch ID : 8 bytes" << '\n'
"Module Id : 2 bytes\n" << "Timestamp : 8 bytes" << '\n'
"Row : 2 bytes\n" << "Module Id : 2 bytes" << '\n'
"Column : 2 bytes\n" << "Row : 2 bytes" << '\n'
"Reserved : 2 bytes\n" << "Column : 2 bytes" << '\n'
"Debug : 4 bytes\n" << "Reserved : 2 bytes" << '\n'
"Round Robin Number : 2 bytes\n" << "Debug : 4 bytes" << '\n'
"Detector Type : 1 byte\n" << "Round Robin Number : 2 bytes" << '\n'
"Header Version : 1 byte\n" << "Detector Type : 1 byte" << '\n'
"Packets Caught Mask : 64 bytes\n"); << "Header Version : 1 byte" << '\n'
<< "Packets Caught Mask : 64 bytes" << '\n';
std::string message = oss.str();
// writing to file // writing to file
if (fwrite((void *)message.c_str(), 1, message.length(), fd) != if (fwrite((void *)message.c_str(), 1, message.length(), fd) !=
@ -233,6 +249,18 @@ struct MasterAttributes {
"Total Frames", PredType::STD_U64LE, dataspace); "Total Frames", PredType::STD_U64LE, dataspace);
dataset.write(&totalFrames, PredType::STD_U64LE); dataset.write(&totalFrames, PredType::STD_U64LE);
} }
};
void WriteFinalHDF5Attributes(H5File *fd, Group *group) {
char c[1024];
memset(c, 0, sizeof(c));
// Total Frames in file
{
DataSpace dataspace = DataSpace(H5S_SCALAR);
DataSet dataset = group->createDataSet(
"Frames in File", PredType::STD_U64LE, dataspace);
dataset.write(&framesInFile, PredType::STD_U64LE);
}
// additional json header // additional json header
if (!additionalJsonHeader.empty()) { if (!additionalJsonHeader.empty()) {
std::string json = sls::ToString(additionalJsonHeader); std::string json = sls::ToString(additionalJsonHeader);

View File

@ -10,7 +10,7 @@ set(SOURCES
src/ZmqSocket.cpp src/ZmqSocket.cpp
src/UdpRxSocket.cpp src/UdpRxSocket.cpp
src/sls_detector_exceptions.cpp src/sls_detector_exceptions.cpp
# src/sls_detector_defs.cpp src/md5_helper.cpp
) )
# Header files to install as a part of the library # Header files to install as a part of the library
@ -44,9 +44,25 @@ if(SLS_DEVEL_HEADERS)
include/sls/versionAPI.h include/sls/versionAPI.h
include/sls/ZmqSocket.h include/sls/ZmqSocket.h
include/sls/bit_utils.h include/sls/bit_utils.h
include/sls/mdf5.h
include/sls/md5_helper.h
) )
endif() endif()
# Library for md5 c code that we are using (and potentially other c code)
# Maybe this should be broken out into it's own folder etc.
add_library(md5sls STATIC
src/md5.c
)
target_include_directories(md5sls
PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
)
# Create an object library to avoid building the library twice # Create an object library to avoid building the library twice
add_library(slsSupportObject OBJECT add_library(slsSupportObject OBJECT
${SOURCES} ${SOURCES}
@ -65,7 +81,8 @@ target_link_libraries(slsSupportObject
libzmq libzmq
rapidjson rapidjson
PRIVATE PRIVATE
slsProjectWarnings slsProjectWarnings
md5sls
) )
if (SLS_USE_TESTS) if (SLS_USE_TESTS)
@ -103,6 +120,9 @@ if((CMAKE_BUILD_TYPE STREQUAL "Release") AND SLS_LTO_AVAILABLE)
set_property(TARGET ${SUPPORT_LIBRARY_TARGETS} PROPERTY INTERPROCEDURAL_OPTIMIZATION True) set_property(TARGET ${SUPPORT_LIBRARY_TARGETS} PROPERTY INTERPROCEDURAL_OPTIMIZATION True)
endif() endif()
list(APPEND SUPPORT_LIBRARY_TARGETS md5sls)
install(TARGETS ${SUPPORT_LIBRARY_TARGETS} install(TARGETS ${SUPPORT_LIBRARY_TARGETS}
EXPORT "${TARGETS_EXPORT_NAME}" EXPORT "${TARGETS_EXPORT_NAME}"
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}

View File

@ -0,0 +1,385 @@
/*
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* Modifications 2021 Paul Scherrer Institut
* Removed most of the code that is not relevant for our scope.
* Snippets copied from md5_local.h or md32_common.h has been marked
*/
#ifndef HEADER_MD5_H
# define HEADER_MD5_H
# include <stddef.h>
# ifdef __cplusplus
/*
* Modifications 2021 Paul Scherrer Institut
* namespace sls added
*/
namespace sls {
extern "C" {
# endif
/*
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* ! MD5_LONG has to be at least 32 bits wide. !
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
# define MD5_LONG unsigned int
# define MD5_CBLOCK 64
# define MD5_LBLOCK (MD5_CBLOCK/4)
# define MD5_DIGEST_LENGTH 16
/**
* Modification 2021 Paul Scherrer Institut
* Comment from md32_common.h
*/
/*-
* This is a generic 32 bit "collector" for message digest algorithms.
* Whenever needed it collects input character stream into chunks of
* 32 bit values and invokes a block function that performs actual hash
* calculations.
*
* Porting guide.
*
* Obligatory macros:
*
* DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN
* this macro defines byte order of input stream.
* HASH_CBLOCK
* size of a unit chunk HASH_BLOCK operates on.
* HASH_LONG
* has to be at least 32 bit wide.
* HASH_CTX
* context structure that at least contains following
* members:
* typedef struct {
* ...
* HASH_LONG Nl,Nh;
* either {
* HASH_LONG data[HASH_LBLOCK];
* unsigned char data[HASH_CBLOCK];
* };
* unsigned int num;
* ...
* } HASH_CTX;
* data[] vector is expected to be zeroed upon first call to
* HASH_UPDATE.
* HASH_UPDATE
* name of "Update" function, implemented here.
* HASH_TRANSFORM
* name of "Transform" function, implemented here.
* HASH_FINAL
* name of "Final" function, implemented here.
* HASH_BLOCK_DATA_ORDER
* name of "block" function capable of treating *unaligned* input
* message in original (data) byte order, implemented externally.
* HASH_MAKE_STRING
* macro converting context variables to an ASCII hash string.
*
* MD5 example:
*
* #define DATA_ORDER_IS_LITTLE_ENDIAN
*
* #define HASH_LONG MD5_LONG
* #define HASH_CTX MD5_CTX
* #define HASH_CBLOCK MD5_CBLOCK
* #define HASH_UPDATE MD5_Update_SLS
* #define HASH_TRANSFORM MD5_Transform
* #define HASH_FINAL MD5_Final_SLS
* #define HASH_BLOCK_DATA_ORDER md5_block_data_order
*/
# define MD32_REG_T int
/**
* Modification 2021 Paul Scherrer Institut
* Made default little endian if big endian not defined
*/
#ifndef DATA_ORDER_IS_BIG_ENDIAN
#define DATA_ORDER_IS_LITTLE_ENDIAN
#endif
/**
* Modification 2021 Paul Scherrer Institut
* Macros exported from md32_common.h
*/
#define HASH_LONG MD5_LONG
#define HASH_CTX MD5_CTX
#define HASH_CBLOCK MD5_CBLOCK
#define HASH_UPDATE MD5_Update_SLS
#define HASH_TRANSFORM MD5_Transform
#define HASH_FINAL MD5_Final_SLS
#define HASH_BLOCK_DATA_ORDER md5_block_data_order
#define HASH_MAKE_STRING(c,s) do { \
unsigned long ll; \
ll=(c)->A; (void)HOST_l2c(ll,(s)); \
ll=(c)->B; (void)HOST_l2c(ll,(s)); \
ll=(c)->C; (void)HOST_l2c(ll,(s)); \
ll=(c)->D; (void)HOST_l2c(ll,(s)); \
} while (0)
#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
#if defined(DATA_ORDER_IS_BIG_ENDIAN)
# define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \
l|=(((unsigned long)(*((c)++)))<<16), \
l|=(((unsigned long)(*((c)++)))<< 8), \
l|=(((unsigned long)(*((c)++))) ) )
# define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \
*((c)++)=(unsigned char)(((l)>>16)&0xff), \
*((c)++)=(unsigned char)(((l)>> 8)&0xff), \
*((c)++)=(unsigned char)(((l) )&0xff), \
l)
#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
# define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \
l|=(((unsigned long)(*((c)++)))<< 8), \
l|=(((unsigned long)(*((c)++)))<<16), \
l|=(((unsigned long)(*((c)++)))<<24) )
# define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \
*((c)++)=(unsigned char)(((l)>> 8)&0xff), \
*((c)++)=(unsigned char)(((l)>>16)&0xff), \
*((c)++)=(unsigned char)(((l)>>24)&0xff), \
l)
#endif
typedef struct MD5state_st {
MD5_LONG A, B, C, D;
MD5_LONG Nl, Nh;
MD5_LONG data[MD5_LBLOCK];
unsigned int num;
} MD5_CTX;
int MD5_Init_SLS(MD5_CTX *c);
int MD5_Update_SLS(MD5_CTX *c, const void *data, size_t len);
int MD5_Final_SLS(unsigned char *md, MD5_CTX *c);
/**
* Modification 2021 Paul Scherrer Institut
* from md32_common.h
*/
void md5_block_data_order(MD5_CTX *c, const void *p, size_t num);
# ifdef __cplusplus
}
} // namespace sls
# endif
# endif

View File

@ -0,0 +1,7 @@
#pragma once
#include <string>
namespace sls {
std::string md5_calculate_checksum(char *buffer, ssize_t bytes);
} // namespace sls

View File

@ -54,7 +54,8 @@
#define MAX_TRIMEN 100 #define MAX_TRIMEN 100
/** maximum unit size of program sent to detector */ /** maximum unit size of program sent to detector */
#define MAX_FPGAPROGRAMSIZE (2 * 1024 * 1024) //#define MAX_FPGAPROGRAMSIZE (2 * 1024 * 1024)
#define MAX_FPGAPROGRAMSIZE (128 * 1024)
#define GET_FLAG -1 #define GET_FLAG -1
@ -499,7 +500,7 @@ typedef struct {
*/ */
struct rxParameters { struct rxParameters {
detectorType detType{GENERIC}; detectorType detType{GENERIC};
xy numberOfDetector; xy numberOfModule;
int moduleIndex{0}; int moduleIndex{0};
char hostname[MAX_STR_LENGTH]; char hostname[MAX_STR_LENGTH];
int udpInterfaces{1}; int udpInterfaces{1};

View File

@ -247,7 +247,7 @@ enum detFuncs {
F_GET_DEST_UDP_LIST, F_GET_DEST_UDP_LIST,
F_SET_DEST_UDP_LIST, F_SET_DEST_UDP_LIST,
F_GET_NUM_DEST_UDP, F_GET_NUM_DEST_UDP,
F_SET_NUM_DEST_UDP, F_CLEAR_ALL_UDP_DEST,
F_GET_UDP_FIRST_DEST, F_GET_UDP_FIRST_DEST,
F_SET_UDP_FIRST_DEST, F_SET_UDP_FIRST_DEST,
@ -604,7 +604,7 @@ const char* getFunctionNameFromEnum(enum detFuncs func) {
case F_GET_DEST_UDP_LIST: return "F_GET_DEST_UDP_LIST"; case F_GET_DEST_UDP_LIST: return "F_GET_DEST_UDP_LIST";
case F_SET_DEST_UDP_LIST: return "F_SET_DEST_UDP_LIST"; case F_SET_DEST_UDP_LIST: return "F_SET_DEST_UDP_LIST";
case F_GET_NUM_DEST_UDP: return "F_GET_NUM_DEST_UDP"; case F_GET_NUM_DEST_UDP: return "F_GET_NUM_DEST_UDP";
case F_SET_NUM_DEST_UDP: return "F_SET_NUM_DEST_UDP"; case F_CLEAR_ALL_UDP_DEST: return "F_CLEAR_ALL_UDP_DEST";
case F_GET_UDP_FIRST_DEST: return "F_GET_UDP_FIRST_DEST"; case F_GET_UDP_FIRST_DEST: return "F_GET_UDP_FIRST_DEST";
case F_SET_UDP_FIRST_DEST: return "F_SET_UDP_FIRST_DEST"; case F_SET_UDP_FIRST_DEST: return "F_SET_UDP_FIRST_DEST";

View File

@ -1,14 +1,13 @@
/** API versions */ /** API versions */
#define GITBRANCH "roundrobin" #define GITBRANCH "udp_numdst"
#define APILIB 0x210831
#define APIRECEIVER 0x210831 #define APICTB 0x210917
#define APIGOTTHARD 0x210917
#define APIMYTHEN3 0x210917
#define APIMOENCH 0x210917
#define APIEIGER 0x210917
#define APILIB 0x210917
#define APIRECEIVER 0x210917
#define APIGUI 0x210819 #define APIGUI 0x210819
#define APIJUNGFRAU 0x210927
#define APIGOTTHARD2 0x210927
#define APICTB 0x210909
#define APIGOTTHARD 0x210909
#define APIGOTTHARD2 0x210909
#define APIJUNGFRAU 0x210909
#define APIMYTHEN3 0x210909
#define APIMOENCH 0x210909
#define APIEIGER 0x210909

View File

@ -26,8 +26,8 @@ std::ostream &operator<<(std::ostream &os, const slsDetectorDefs::ROI &roi) {
std::string ToString(const slsDetectorDefs::rxParameters &r) { std::string ToString(const slsDetectorDefs::rxParameters &r) {
std::ostringstream oss; std::ostringstream oss;
oss << '[' << "detType:" << r.detType << std::endl oss << '[' << "detType:" << r.detType << std::endl
<< "numberOfDetector.x:" << r.numberOfDetector.x << std::endl << "numberOfModule.x:" << r.numberOfModule.x << std::endl
<< "numberOfDetector.y:" << r.numberOfDetector.y << std::endl << "numberOfModule.y:" << r.numberOfModule.y << std::endl
<< "moduleIndex:" << r.moduleIndex << std::endl << "moduleIndex:" << r.moduleIndex << std::endl
<< "hostname:" << r.hostname << std::endl << "hostname:" << r.hostname << std::endl
<< "udpInterfaces:" << r.udpInterfaces << std::endl << "udpInterfaces:" << r.udpInterfaces << std::endl

515
slsSupportLib/src/md5.c Normal file
View File

@ -0,0 +1,515 @@
/*
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
* Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* MD5 low level APIs are deprecated for public use, but still ok for
* internal use.
*/
/*
* Modifications 2021 Paul Scherrer Institut
* Removed most of the code that is not relevant for our scope
* from md5_dgst.c and renamed to md5.c
* from md32_common.h and replaced their macros with their defines
*/
#include <stdio.h>
/**
* Modification 2021 Paul Scherrer Institut
* Header included was md5_local.h
* and string.h header was included
* sls namespace added
*/
#include "sls/md5.h"
#include <string.h>
#ifdef __cplusplus
namespace sls {
#endif
/**
* Modification 2021 Paul Scherrer Institut
* Macros exported from md5_local.h
*/
#define F(b,c,d) ((((c) ^ (d)) & (b)) ^ (d))
#define G(b,c,d) ((((b) ^ (c)) & (d)) ^ (c))
#define H(b,c,d) ((b) ^ (c) ^ (d))
#define I(b,c,d) (((~(d)) | (b)) ^ (c))
#define R0(a,b,c,d,k,s,t) { \
a+=((k)+(t)+F((b),(c),(d))); \
a=ROTATE(a,s); \
a+=b; };
#define R1(a,b,c,d,k,s,t) { \
a+=((k)+(t)+G((b),(c),(d))); \
a=ROTATE(a,s); \
a+=b; };
#define R2(a,b,c,d,k,s,t) { \
a+=((k)+(t)+H((b),(c),(d))); \
a=ROTATE(a,s); \
a+=b; };
#define R3(a,b,c,d,k,s,t) { \
a+=((k)+(t)+I((b),(c),(d))); \
a=ROTATE(a,s); \
a+=b; };
/*
* Implemented from RFC1321 The MD5 Message-Digest Algorithm
*/
#define INIT_DATA_A (unsigned long)0x67452301L
#define INIT_DATA_B (unsigned long)0xefcdab89L
#define INIT_DATA_C (unsigned long)0x98badcfeL
#define INIT_DATA_D (unsigned long)0x10325476L
int MD5_Init_SLS(MD5_CTX *c)
{
memset(c, 0, sizeof(*c));
c->A = INIT_DATA_A;
c->B = INIT_DATA_B;
c->C = INIT_DATA_C;
c->D = INIT_DATA_D;
return 1;
}
void md5_block_data_order(MD5_CTX *c, const void *data_, size_t num)
{
const unsigned char *data = data_;
register unsigned MD32_REG_T A, B, C, D, l;
/* See comment in crypto/sha/sha_local.h for details. */
unsigned MD32_REG_T XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7,
XX8, XX9, XX10, XX11, XX12, XX13, XX14, XX15;
# define X(i) XX##i
A = c->A;
B = c->B;
C = c->C;
D = c->D;
for (; num--;) {
(void)HOST_c2l(data, l);
X(0) = l;
(void)HOST_c2l(data, l);
X(1) = l;
/* Round 0 */
R0(A, B, C, D, X(0), 7, 0xd76aa478L);
(void)HOST_c2l(data, l);
X(2) = l;
R0(D, A, B, C, X(1), 12, 0xe8c7b756L);
(void)HOST_c2l(data, l);
X(3) = l;
R0(C, D, A, B, X(2), 17, 0x242070dbL);
(void)HOST_c2l(data, l);
X(4) = l;
R0(B, C, D, A, X(3), 22, 0xc1bdceeeL);
(void)HOST_c2l(data, l);
X(5) = l;
R0(A, B, C, D, X(4), 7, 0xf57c0fafL);
(void)HOST_c2l(data, l);
X(6) = l;
R0(D, A, B, C, X(5), 12, 0x4787c62aL);
(void)HOST_c2l(data, l);
X(7) = l;
R0(C, D, A, B, X(6), 17, 0xa8304613L);
(void)HOST_c2l(data, l);
X(8) = l;
R0(B, C, D, A, X(7), 22, 0xfd469501L);
(void)HOST_c2l(data, l);
X(9) = l;
R0(A, B, C, D, X(8), 7, 0x698098d8L);
(void)HOST_c2l(data, l);
X(10) = l;
R0(D, A, B, C, X(9), 12, 0x8b44f7afL);
(void)HOST_c2l(data, l);
X(11) = l;
R0(C, D, A, B, X(10), 17, 0xffff5bb1L);
(void)HOST_c2l(data, l);
X(12) = l;
R0(B, C, D, A, X(11), 22, 0x895cd7beL);
(void)HOST_c2l(data, l);
X(13) = l;
R0(A, B, C, D, X(12), 7, 0x6b901122L);
(void)HOST_c2l(data, l);
X(14) = l;
R0(D, A, B, C, X(13), 12, 0xfd987193L);
(void)HOST_c2l(data, l);
X(15) = l;
R0(C, D, A, B, X(14), 17, 0xa679438eL);
R0(B, C, D, A, X(15), 22, 0x49b40821L);
/* Round 1 */
R1(A, B, C, D, X(1), 5, 0xf61e2562L);
R1(D, A, B, C, X(6), 9, 0xc040b340L);
R1(C, D, A, B, X(11), 14, 0x265e5a51L);
R1(B, C, D, A, X(0), 20, 0xe9b6c7aaL);
R1(A, B, C, D, X(5), 5, 0xd62f105dL);
R1(D, A, B, C, X(10), 9, 0x02441453L);
R1(C, D, A, B, X(15), 14, 0xd8a1e681L);
R1(B, C, D, A, X(4), 20, 0xe7d3fbc8L);
R1(A, B, C, D, X(9), 5, 0x21e1cde6L);
R1(D, A, B, C, X(14), 9, 0xc33707d6L);
R1(C, D, A, B, X(3), 14, 0xf4d50d87L);
R1(B, C, D, A, X(8), 20, 0x455a14edL);
R1(A, B, C, D, X(13), 5, 0xa9e3e905L);
R1(D, A, B, C, X(2), 9, 0xfcefa3f8L);
R1(C, D, A, B, X(7), 14, 0x676f02d9L);
R1(B, C, D, A, X(12), 20, 0x8d2a4c8aL);
/* Round 2 */
R2(A, B, C, D, X(5), 4, 0xfffa3942L);
R2(D, A, B, C, X(8), 11, 0x8771f681L);
R2(C, D, A, B, X(11), 16, 0x6d9d6122L);
R2(B, C, D, A, X(14), 23, 0xfde5380cL);
R2(A, B, C, D, X(1), 4, 0xa4beea44L);
R2(D, A, B, C, X(4), 11, 0x4bdecfa9L);
R2(C, D, A, B, X(7), 16, 0xf6bb4b60L);
R2(B, C, D, A, X(10), 23, 0xbebfbc70L);
R2(A, B, C, D, X(13), 4, 0x289b7ec6L);
R2(D, A, B, C, X(0), 11, 0xeaa127faL);
R2(C, D, A, B, X(3), 16, 0xd4ef3085L);
R2(B, C, D, A, X(6), 23, 0x04881d05L);
R2(A, B, C, D, X(9), 4, 0xd9d4d039L);
R2(D, A, B, C, X(12), 11, 0xe6db99e5L);
R2(C, D, A, B, X(15), 16, 0x1fa27cf8L);
R2(B, C, D, A, X(2), 23, 0xc4ac5665L);
/* Round 3 */
R3(A, B, C, D, X(0), 6, 0xf4292244L);
R3(D, A, B, C, X(7), 10, 0x432aff97L);
R3(C, D, A, B, X(14), 15, 0xab9423a7L);
R3(B, C, D, A, X(5), 21, 0xfc93a039L);
R3(A, B, C, D, X(12), 6, 0x655b59c3L);
R3(D, A, B, C, X(3), 10, 0x8f0ccc92L);
R3(C, D, A, B, X(10), 15, 0xffeff47dL);
R3(B, C, D, A, X(1), 21, 0x85845dd1L);
R3(A, B, C, D, X(8), 6, 0x6fa87e4fL);
R3(D, A, B, C, X(15), 10, 0xfe2ce6e0L);
R3(C, D, A, B, X(6), 15, 0xa3014314L);
R3(B, C, D, A, X(13), 21, 0x4e0811a1L);
R3(A, B, C, D, X(4), 6, 0xf7537e82L);
R3(D, A, B, C, X(11), 10, 0xbd3af235L);
R3(C, D, A, B, X(2), 15, 0x2ad7d2bbL);
R3(B, C, D, A, X(9), 21, 0xeb86d391L);
A = c->A += A;
B = c->B += B;
C = c->C += C;
D = c->D += D;
}
}
/**
* Modification 2021 Paul Scherrer Institut
* from md32_common.h
*/
int HASH_UPDATE(HASH_CTX *c, const void *data_, size_t len)
{
const unsigned char *data = data_;
unsigned char *p;
HASH_LONG l;
size_t n;
if (len == 0)
return 1;
l = (c->Nl + (((HASH_LONG) len) << 3)) & 0xffffffffUL;
if (l < c->Nl) /* overflow */
c->Nh++;
c->Nh += (HASH_LONG) (len >> 29); /* might cause compiler warning on
* 16-bit */
c->Nl = l;
n = c->num;
if (n != 0) {
p = (unsigned char *)c->data;
if (len >= HASH_CBLOCK || len + n >= HASH_CBLOCK) {
memcpy(p + n, data, HASH_CBLOCK - n);
HASH_BLOCK_DATA_ORDER(c, p, 1);
n = HASH_CBLOCK - n;
data += n;
len -= n;
c->num = 0;
/*
* We use memset rather than OPENSSL_cleanse() here deliberately.
* Using OPENSSL_cleanse() here could be a performance issue. It
* will get properly cleansed on finalisation so this isn't a
* security problem.
*/
memset(p, 0, HASH_CBLOCK); /* keep it zeroed */
} else {
memcpy(p + n, data, len);
c->num += (unsigned int)len;
return 1;
}
}
n = len / HASH_CBLOCK;
if (n > 0) {
HASH_BLOCK_DATA_ORDER(c, data, n);
n *= HASH_CBLOCK;
data += n;
len -= n;
}
if (len != 0) {
p = (unsigned char *)c->data;
c->num = (unsigned int)len;
memcpy(p, data, len);
}
return 1;
}
/**
* Modification 2021 Paul Scherrer Institut
* from md32_common.h
*/
int HASH_FINAL(unsigned char *md, HASH_CTX *c)
{
unsigned char *p = (unsigned char *)c->data;
size_t n = c->num;
p[n] = 0x80; /* there is always room for one */
n++;
if (n > (HASH_CBLOCK - 8)) {
memset(p + n, 0, HASH_CBLOCK - n);
n = 0;
HASH_BLOCK_DATA_ORDER(c, p, 1);
}
memset(p + n, 0, HASH_CBLOCK - 8 - n);
p += HASH_CBLOCK - 8;
#if defined(DATA_ORDER_IS_BIG_ENDIAN)
(void)HOST_l2c(c->Nh, p);
(void)HOST_l2c(c->Nl, p);
#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
(void)HOST_l2c(c->Nl, p);
(void)HOST_l2c(c->Nh, p);
#endif
p -= HASH_CBLOCK;
HASH_BLOCK_DATA_ORDER(c, p, 1);
c->num = 0;
// OPENSSL_cleanse(p, HASH_CBLOCK);
//Erik: Since we don't do encryption secure cleaning is not needed
memset(p, 0, HASH_CBLOCK);
HASH_MAKE_STRING(c, md);
return 1;
}
#ifdef __cplusplus
} // namespace sls
#endif

View File

@ -0,0 +1,30 @@
#include "sls/md5_helper.h"
#include "sls/md5.h"
#include <iomanip>
#include <sstream>
#include <stdexcept>
namespace sls {
std::string md5_calculate_checksum(char *buffer, ssize_t bytes) {
MD5_CTX c;
if (!MD5_Init_SLS(&c)) {
throw std::runtime_error(
"Could not calculate md5 checksum.[initializing]");
}
if (!MD5_Update_SLS(&c, buffer, bytes)) {
throw std::runtime_error("Could not calculate md5 checksum.[Updating]");
}
unsigned char out[MD5_DIGEST_LENGTH];
if (!MD5_Final_SLS(out, &c)) {
throw std::runtime_error("Could not calculate md5 checksum.[Final]");
}
std::ostringstream oss;
for (int i = 0; i != MD5_DIGEST_LENGTH; ++i)
oss << std::hex << std::setw(2) << std::setfill('0') << +out[i];
return oss.str();
}
} // namespace sls