Compare commits

...

8 Commits

23 changed files with 808 additions and 100 deletions

View File

@ -1,2 +1,114 @@
Draft SLS Detector Package 5.0.0-rc1 released on 25.09.2020 (Release Candidate 1)
- dr 4, 8, 16 in eiger -> speed 0, 32 stays same (speed 1) ===========================================================================
CONTENTS
--------
1. Firmware Requirements
2. Download, Documentation & Support
1. Firmware Requirements
========================
Eiger
=====
Minimum compatible version : 27
Latest compatible version : 27
Jungfrau
========
Minimum compatible version (PCB v1.0) : 24.07.2020 (v0.8)
Latest compatible version (PCB v1.0) : 24.07.2020 (v0.8)
Minimum compatible version (PCB v2.0) : 21.07.2020 (v2.1)
Latest compatible version (PCB v2.0) : 21.07.2020 (v2.1)
Gotthard
========
Minimum compatible version : 11.01.2013
Latest compatible version : 08.02.2018 (50um and 25um Master)
09.02.2018 (25 um Slave)
Mythen3
=======
Minimum compatible version : 25.09.2020
Latest compatible version : 25.09.2020
Gotthard2
=========
Minimum compatible version : 25.09.2020
Latest compatible version : 25.09.2020
Moench
======
Minimum compatible version : 02.03.2020
Latest compatible version : 02.03.2020
Ctb
===
Minimum compatible version : 27.11.2019
Latest compatible version : 27.11.2019
Detector Upgrade
================
Eiger Remotely via bit files
Jungfrau Remotely using sls_detector_put programfpga <pof>
Gotthard Cannot be upgraded remotely. Requires programming via USB blaster
Mythen3 Remotely using sls_detector_put programfpga <rbf>
Gotthard2 Remotely using sls_detector_put programfpga <rbf>
Moench Remotely using sls_detector_put programfpga <pof>
Ctb Remotely using sls_detector_put programfpga <pof>
Instructions available at
https://slsdetectorgroup.github.io/devdoc/firmware.html
Please refer to the link below for more details on the firmware versions.
https://www.psi.ch/en/detectors/firmware
2. Download, Documentation & Support
====================================
Download
--------
The Source Code (Default C++ API):
https://github.com/slsdetectorgroup/slsDetectorPackage
Documentation
-------------
Installation:
https://slsdetectorgroup.github.io/devdoc/installation.html#
Consuming slsDetectorPackage:
https://slsdetectorgroup.github.io/devdoc/consuming.html
Command Line Documentation:
https://slsdetectorgroup.github.io/devdoc/commandline.html
C++ API Documentation:
https://slsdetectorgroup.github.io/devdoc/detector.html
C++ API Example:
https://slsdetectorgroup.github.io/devdoc/examples.html#
Python API Documentation:
https://slsdetectorgroup.github.io/devdoc/pygettingstarted.html
Python API Example:
https://slsdetectorgroup.github.io/devdoc/pyexamples.html
TroubleShooting:
https://www.psi.ch/en/detectors/troubleshooting
Further Documentation:
https://www.psi.ch/en/detectors/users-support
Support
-------
dhanya.thattil@psi.ch
erik.frojdh@psi.ch
anna.bergamaschi@psi.ch

View File

@ -45,6 +45,8 @@ set(SPHINX_SOURCE_FILES
src/ToString.rst src/ToString.rst
src/examples.rst src/examples.rst
src/pygettingstarted.rst src/pygettingstarted.rst
src/firmware.rst
src/serverupgrade.rst
) )

View File

@ -4,12 +4,28 @@ Command line interface
Usage Usage
------------- -------------
Commands can be uses either with sls_detector_get or sls_detector_put Commands can be used either with sls_detector_get or sls_detector_put
.. code-block:: .. code-block::
sls_detector_get vrf sls_detector_get vrf
Help
--------
.. code-block::
# get list of commands
sls_detector_get list
# search for a particular command using a word
sls_detector_get list | grep adc
# get help for a particular command
sls_detector_get -h fpath
sls_detector_help fpath
Commands Commands
----------- -----------

357
docs/src/firmware.rst Normal file
View File

@ -0,0 +1,357 @@
Firmware Upgrade
=================
Eiger
-------------
.. note ::
| Eiger firmware can be upgraded remotely.
| The programming executable (bcp) and corresponding bit files are provided by the SLS Detector group.
Compatibility
^^^^^^^^^^^^^
**Release candidate 5.0.0-rc1**
.. code-block:: bash
Minimum compatible version : 27
Latest compatible version : 27
`Older versions <https://www.psi.ch/en/detectors/latest-installation>`_
Upgrade
^^^^^^^^
#. Tftp must be already installed on your pc to use the bcp executable.
#. Kill the on-board servers and copy new servers to the board.
.. code-block:: bash
# Option 1: from detector console
# kill old server
ssh root@bebxxx
killall eigerDetectorServer
# copy new server
cd executables
scp user@pc:/path/eigerDetectorServerxxx .
chmod 777 eigerDetectorServerxxx
ln -sf eigerDetectorServerxxx eigerDetectorServer
sync
# Options 2: from client console for multiple modules
for i in bebxxx bebyyy;
do ssh root@$i killall eigerDetectorServer;
scp eigerDetectorServerxxx root@$i:~/executables/eigerDetectorServer;
ssh root@$i sync; done
* This is crucial when registers between firmwares change. Failure to do so will result in linux on boards to crash and boards can't be pinged anymore.
#. Bring the board into programmable mode using either of the 2 ways. Both methods result in only the central LED blinking.
* **Manual:**
Do a hard reset for each half module on back panel boards, between the LEDs, closer to each of the 1G ethernet connectors. Push until all LEDs start to blink.
* Software:
.. code-block:: bash
ssh root@bebxxx
cd executables
./boot_recovery
#. Start a terminal for each half module and run the following to see progress.
.. code-block:: bash
nc -p 3000 -u bebxxx 3000
# Press enter twice to see prompt with board name.
> bebxxx
# After each bcp command, wait for this terminal to print "Success".
#. In another terminal, run the following to update firmware. Please update bit files with great caution as it could make your board inaccessible, if done incorrectly.
.. code-block:: bash
#update back end fpga
bcp download.bit bebxxx:/fw0
#update front left fpga
bcp download.bit bebxxx:/febl
#update front right fpga
bcp download.bit bebxxx:/febr
#update kernel (only if required by the SLS Detector Group)
bcp download.bit bebxxx:/kernel
#. Reboot the detector.
Jungfrau
-------------
.. note ::
| Jungfrau firmware can be upgraded remotely.
| The corresponding programming file (pof) is provided by the SLS Detector group.
Compatibility
^^^^^^^^^^^^^
**Release candidate 5.0.0-rc1**
.. code-block:: bash
# PCB v1.0
Minimum compatible version : 24.07.2020 (v0.8)
Latest compatible version : 24.07.2020 (v0.8)
# PCB v2.0
Minimum compatible version : 21.07.2020 (v2.1)
Latest compatible version : 21.07.2020 (v2.1)
`Older versions <https://www.psi.ch/en/detectors/latest-installation>`_
Upgrade (from v4.x.x)
^^^^^^^^^^^^^^^^^^^^
#. Tftp must be installed on pc.
#. Update client package to the latest (5.0.0-rc1).
#. Disable server respawning or kill old server
.. code-block:: bash
# Option 1: if respawning enabled
telnet bchipxxx
# edit /etc/inittab
# comment out line #ttyS0::respawn:/jungfrauDetectorServervxxx
reboot
# ensure servers did not start up after reboot
telnet bchipxxx
ps
# Option 2: if respawning already disabled
telnet bchipxxx
killall jungfrauDetectorServerv*
#. Copy new server and start in update mode
.. code-block:: bash
tftp pcxxx -r jungfrauDetectorServervxxx -g
chmod 777 jungfrauDetectorServervxxx
./jungfrauDetectorServervxxx -u
#. Program fpga from the client console
.. code-block:: bash
sls_detector_get free
# Crucial that the next command executes without any errors
sls_detector_put hostname bchipxxx
sls_detector_put programfpga xxx.pof
#. After programming, kill update server using Ctrl + C.
#. Enable server respawning if needed
.. code-block:: bash
telnet bchipxxx
# edit /etc/inittab
# uncomment out line #ttyS0::respawn:/jungfrauDetectorServervxxx
# ensure the line has the new server name
reboot
# ensure both servers are running using ps
jungfrauDetectorServervxxx
jungfrauDetectorServervxxx --stop-server 1953
Upgrade (from v5.0.0-rc1)
^^^^^^^^^^^^^^^^^^^^^^^^
#. Program from console
.. code-block:: bash
# copies server from tftp folder of pc, programs fpga,
# removes old server from respawn, sets up new server to respawn
# and reboots
sls_detector_put update jungfrauDetectorServervxxx pcxxx xx.pof
# Or only program firmware
sls_detector_put programfpga xxx.pof
Gotthard
---------
.. warning ::
| Gotthard firmware cannot be upgraded remotely and requires the use of USB-Blaster.
| It is generally updated by the SLS Detector group.
Compatibility
^^^^^^^^^^^^^
**Release candidate 5.0.0-rc1**
.. code-block:: bash
Minimum compatible version : 11.01.2013
Latest compatible version : 08.02.2018 (50um and 25um Master)
09.02.2018 (25 um Slave)
`Older versions <https://www.psi.ch/en/detectors/latest-installation>`_
Upgrade
^^^^^^^^
#. Download `Altera Quartus software or Quartus programmer <https://fpgasoftware.intel.com/20.1/?edition=standard&platform=linux&product=qprogrammer#tabs-4>`_.
#. Start Quartus programmer, click on Hardware Setup. In the "Currently selected hardware" window, select USB-Blaster.
#. In the Mode combo box, select "Active Serial Programming".
#. Plug the end of your USB-Blaster with the adaptor provided to the connector 'AS config' on the Gotthard board.
#. Click on 'Add file'. Select programming (pof) file provided by the SLS Detector group.
#. Check "Program/Configure" and "Verify". Push the start button. Wait until the programming process is finished.
#. In case of error messages, check the polarity of cable (that pin1 corresponds) and that the correct programming connector is selected.
#. Reboot the detector.
Mythen3
-------
.. note ::
| Mythen3 firmware can be upgraded remotely.
| The corresponding programming file (rbf) is provided by the SLS Detector group.
Compatibility
^^^^^^^^^^^^^
**Release candidate 5.0.0-rc1**
.. code-block:: bash
Minimum compatible version : 25.09.2020
Latest compatible version : 25.09.2020
Upgrade (from v5.0.0-rc1)
^^^^^^^^^^^^^^^^^^^^^^^^
#. Program from console
.. code-block:: bash
# copies server from tftp folder of pc, programs fpga,
# and reboots (new server not respawned currently)
sls_detector_put update mythen3DetectorServervxxx pcxxx xxx.rbf
# Or only program firmware
sls_detector_put programfpga xxx.rbf
Gotthard2
----------
.. note ::
| Gotthard2 firmware can be upgraded remotely.
| The corresponding programming file (rbf) is provided by the SLS Detector group.
Compatibility
^^^^^^^^^^^^^
**Release candidate 5.0.0-rc1**
.. code-block:: bash
Minimum compatible version : 25.09.2020
Latest compatible version : 25.09.2020
Upgrade (from v5.0.0-rc1)
^^^^^^^^^^^^^^^^^^^^^^^^
#. Program from console
.. code-block:: bash
# copies server from tftp folder of pc, programs fpga,
# and reboots (new server not respawned currently)
sls_detector_put update gotthard2DetectorServervxxx pcxxx xxx.rbf
# Or only program firmware
sls_detector_put programfpga xxx.rbf
Moench
------
.. note ::
| Moench firmware can be upgraded remotely.
| The corresponding programming file (pof) is provided by the SLS Detector group.
Compatibility
^^^^^^^^^^^^^
**Release candidate 5.0.0-rc1**
.. code-block:: bash
Minimum compatible version : 02.03.2020
Latest compatible version : 02.03.2020
Upgrade (from v5.0.0-rc1)
^^^^^^^^^^^^^^^^^^^^^^^^
#. Program from console
.. code-block:: bash
# copies server from tftp folder of pc, programs fpga,
# removes old server from respawn, sets up new server to respawn
# and reboots
sls_detector_put update moenchDetectorServervxxx pcxxx xx.pof
# Or only program firmware
sls_detector_put programfpga xxx.pof
Ctb
---
.. note ::
| Ctb firmware can be upgraded remotely.
| The corresponding programming file (pof) is provided by the SLS Detector group.
Compatibility
^^^^^^^^^^^^^
**Release candidate 5.0.0-rc1**
.. code-block:: bash
Minimum compatible version : 27.11.2019
Latest compatible version : 27.11.2019
Upgrade (from v5.0.0-rc1)
^^^^^^^^^^^^^^^^^^^^^^^^
#. Program from console
.. code-block:: bash
# copies server from tftp folder of pc, programs fpga,
# removes old server from respawn, sets up new server to respawn
# and reboots
sls_detector_put update ctbDetectorServervxxx pcxxx xx.pof
# Or only program firmware
sls_detector_put programfpga xxx.pof

View File

@ -54,6 +54,12 @@ Welcome to slsDetectorPackage's documentation!
:caption: Servers :caption: Servers
servers servers
serverupgrade
.. toctree::
:caption: Firmware
firmware
.. Indices and tables .. Indices and tables
.. ================== .. ==================

View File

@ -44,6 +44,26 @@ The easiest way to configure options is to use the ccmake utility.
ccmake . ccmake .
Build using cmk.sh script
-------------------------
.. code-block:: bash
# new build and make with 9 parallel threads
./cmk.sh -cbj9
# build with python
./cmk.sh -bpj9
# build with GUI
./cmk.sh -bgj9
# build with hdf5
./cmk.sh -hj9 -d [path of hdf5 dir]
# get all options
./cmk.sh -?
Install binaries using conda Install binaries using conda
-------------------------------- --------------------------------

View File

@ -0,0 +1,88 @@
Server Upgrade
=================
Eiger
-------------
#. Kill old server and copy new server
.. code-block:: bash
# Option 1: from detector console
# kill old server
ssh root@bebxxx
killall eigerDetectorServer
# copy new server
cd executables
scp user@pc:/path/eigerDetectorServerxxx .
chmod 777 eigerDetectorServerxxx
ln -sf eigerDetectorServerxxx eigerDetectorServer
sync
# Options 2: from client console for multiple modules
for i in bebxxx bebyyy;
do ssh root@$i killall eigerDetectorServer;
scp eigerDetectorServerxxx root@$i:~/executables/eigerDetectorServer;
ssh root@$i sync; done
#. Reboot the detector.
Jungfrau
-------------
#. Program from console (only from 5.0.0-rc1)
.. code-block:: bash
# copies new server from pc tftp folder, respawns and reboots
sls_detector_put copydetectorserver jungfrauDetectorServerxxx pcxxx
Gotthard
---------
#. Program from console (only from 5.0.0-rc1)
.. code-block:: bash
# copies new server from pc tftp folder, respawns and reboots
sls_detector_put copydetectorserver gotthardDetectorServerxxx pcxxx
Mythen3
-------
#. Program from console (only from 5.0.0-rc1)
.. code-block:: bash
# copies new server from pc tftp folder and reboots (does not respawn)
sls_detector_put copydetectorserver mythen3DetectorServerxxx pcxxx
Gotthard2
----------
#. Program from console (only from 5.0.0-rc1)
.. code-block:: bash
# copies new server from pc tftp folder and reboots (does not respawn)
sls_detector_put copydetectorserver gotthard2DetectorServerxxx pcxxx
Moench
------
#. Program from console (only from 5.0.0-rc1)
.. code-block:: bash
# copies new server from pc tftp folder, respawns and reboots
sls_detector_put copydetectorserver moenchDetectorServerxxx pcxxx
Ctb
---
#. Program from console (only from 5.0.0-rc1)
.. code-block:: bash
# copies new server from pc tftp folder, respawns and reboots
sls_detector_put copydetectorserver ctbDetectorServerxxx pcxxx

View File

@ -1298,7 +1298,7 @@ class Detector(CppDetectorApi):
@property @property
@element @element
def rx_udpsocksize(self): def rx_udpsocksize(self):
"""UDP socket buffer size in receiver. Tune rmem_default and rmem_max accordingly.""" """UDP socket buffer size in receiver. Tune rmem_default and rmem_max accordingly. Max size: INT_MAX/2."""
return self.getRxUDPSocketBufferSize() return self.getRxUDPSocketBufferSize()
@rx_udpsocksize.setter @rx_udpsocksize.setter
@ -2657,10 +2657,7 @@ class Detector(CppDetectorApi):
@patlimits.setter @patlimits.setter
def patlimits(self, args): def patlimits(self, args):
if isinstance(args, tuple): args = ut.merge_args(-1, args)
args = (-1, *args)
elif isinstance(args, dict):
args = ({k:(-1, *v) for k,v in args.items()},)
ut.set_using_dict(self.setPatternLoopAddresses, *args) ut.set_using_dict(self.setPatternLoopAddresses, *args)
@property @property
@ -2714,7 +2711,7 @@ class Detector(CppDetectorApi):
@patwait0.setter @patwait0.setter
def patwait0(self, addr): def patwait0(self, addr):
addr = ut.add_argument_before(0, addr) addr = ut.merge_args(0, addr)
ut.set_using_dict(self.setPatternWaitAddr, *addr) ut.set_using_dict(self.setPatternWaitAddr, *addr)
@property @property
@ -2734,7 +2731,7 @@ class Detector(CppDetectorApi):
@patwait1.setter @patwait1.setter
def patwait1(self, addr): def patwait1(self, addr):
addr = ut.add_argument_before(1, addr) addr = ut.merge_args(1, addr)
ut.set_using_dict(self.setPatternWaitAddr, *addr) ut.set_using_dict(self.setPatternWaitAddr, *addr)
@property @property
@ -2754,37 +2751,45 @@ class Detector(CppDetectorApi):
@patwait2.setter @patwait2.setter
def patwait2(self, addr): def patwait2(self, addr):
addr = ut.add_argument_before(2, addr) addr = ut.merge_args(2, addr)
ut.set_using_dict(self.setPatternWaitAddr, *addr) ut.set_using_dict(self.setPatternWaitAddr, *addr)
@property @property
@element
def patwaittime0(self): def patwaittime0(self):
"""[Ctb][Moench][Mythen3] Wait 0 time in clock cycles.""" """[Ctb][Moench][Mythen3] Wait 0 time in clock cycles."""
return element_if_equal(self.getPatternWaitTime(0)) return self.getPatternWaitTime(0)
@patwaittime0.setter @patwaittime0.setter
def patwaittime0(self, nclk): def patwaittime0(self, nclk):
self.setPatternWaitTime(0, nclk) nclk = ut.merge_args(0, nclk)
ut.set_using_dict(self.setPatternWaitTime, *nclk)
@property @property
@element
def patwaittime1(self): def patwaittime1(self):
"""[Ctb][Moench][Mythen3] Wait 1 time in clock cycles.""" """[Ctb][Moench][Mythen3] Wait 1 time in clock cycles."""
return element_if_equal(self.getPatternWaitTime(1)) return self.getPatternWaitTime(1)
@patwaittime1.setter @patwaittime1.setter
def patwaittime1(self, nclk): def patwaittime1(self, nclk):
self.setPatternWaitTime(1, nclk) nclk = ut.merge_args(1, nclk)
ut.set_using_dict(self.setPatternWaitTime, *nclk)
@property @property
@element
def patwaittime2(self): def patwaittime2(self):
"""[Ctb][Moench][Mythen3] Wait 2 time in clock cycles.""" """[Ctb][Moench][Mythen3] Wait 2 time in clock cycles."""
return element_if_equal(self.getPatternWaitTime(2)) return self.getPatternWaitTime(2)
@patwaittime2.setter @patwaittime2.setter
def patwaittime2(self, nclk): def patwaittime2(self, nclk):
self.setPatternWaitTime(2, nclk) nclk = ut.merge_args(2, nclk)
ut.set_using_dict(self.setPatternWaitTime, *nclk)
@property @property
@element
def patloop0(self): def patloop0(self):
"""[Ctb][Moench][Mythen3] Limits (start and stop address) of loop 0. """[Ctb][Moench][Mythen3] Limits (start and stop address) of loop 0.
@ -2796,13 +2801,15 @@ class Detector(CppDetectorApi):
>>> [hex(l) for l in d.patloop0] >>> [hex(l) for l in d.patloop0]
['0x0', '0x18c'] ['0x0', '0x18c']
""" """
return element_if_equal(self.getPatternLoopAddresses(0)) return self.getPatternLoopAddresses(0)
@patloop0.setter @patloop0.setter
def patloop0(self, addr): def patloop0(self, addr):
self.setPatternLoopAddresses(0, addr[0], addr[1]) addr = ut.merge_args(0, addr)
ut.set_using_dict(self.setPatternLoopAddresses, *addr)
@property @property
@element
def patloop1(self): def patloop1(self):
"""[Ctb][Moench][Mythen3] Limits (start and stop address) of loop 1. """[Ctb][Moench][Mythen3] Limits (start and stop address) of loop 1.
@ -2815,13 +2822,15 @@ class Detector(CppDetectorApi):
['0x0', '0x18c'] ['0x0', '0x18c']
""" """
return element_if_equal(self.getPatternLoopAddresses(1)) return self.getPatternLoopAddresses(1)
@patloop1.setter @patloop1.setter
def patloop1(self, addr): def patloop1(self, addr):
self.setPatternLoopAddresses(1, addr[0], addr[1]) addr = ut.merge_args(1, addr)
ut.set_using_dict(self.setPatternLoopAddresses, *addr)
@property @property
@element
def patloop2(self): def patloop2(self):
"""[Ctb][Moench][Mythen3] Limits (start and stop address) of loop 2. """[Ctb][Moench][Mythen3] Limits (start and stop address) of loop 2.
@ -2834,38 +2843,45 @@ class Detector(CppDetectorApi):
['0x0', '0x18c'] ['0x0', '0x18c']
""" """
return element_if_equal(self.getPatternLoopAddresses(2)) return self.getPatternLoopAddresses(2)
@patloop2.setter @patloop2.setter
def patloop2(self, addr): def patloop2(self, addr):
self.setPatternLoopAddresses(2, addr[0], addr[1]) addr = ut.merge_args(2, addr)
ut.set_using_dict(self.setPatternLoopAddresses, *addr)
@property @property
@element
def patnloop0(self): def patnloop0(self):
"""[Ctb][Moench][Mythen3] Number of cycles of loop 0.""" """[Ctb][Moench][Mythen3] Number of cycles of loop 0."""
return element_if_equal(self.getPatternLoopCycles(0)) return self.getPatternLoopCycles(0)
@patnloop0.setter @patnloop0.setter
def patnloop0(self, n): def patnloop0(self, n):
self.setPatternLoopCycles(0, n) n = ut.merge_args(0, n)
ut.set_using_dict(self.setPatternLoopCycles, *n)
@property @property
@element
def patnloop1(self): def patnloop1(self):
"""[Ctb][Moench][Mythen3] Number of cycles of loop 1.""" """[Ctb][Moench][Mythen3] Number of cycles of loop 1."""
return element_if_equal(self.getPatternLoopCycles(1)) return self.getPatternLoopCycles(1)
@patnloop1.setter @patnloop1.setter
def patnloop1(self, n): def patnloop1(self, n):
self.setPatternLoopCycles(1, n) n = ut.merge_args(1, n)
ut.set_using_dict(self.setPatternLoopCycles, *n)
@property @property
@element
def patnloop2(self): def patnloop2(self):
"""[Ctb][Moench][Mythen3] Number of cycles of loop 2.""" """[Ctb][Moench][Mythen3] Number of cycles of loop 2."""
return element_if_equal(self.getPatternLoopCycles(2)) return self.getPatternLoopCycles(2)
@patnloop2.setter @patnloop2.setter
def patnloop2(self, n): def patnloop2(self, n):
self.setPatternLoopCycles(2, n) n = ut.merge_args(2, n)
ut.set_using_dict(self.setPatternLoopCycles, *n)
@property @property
@element @element
@ -2875,7 +2891,8 @@ class Detector(CppDetectorApi):
@v_a.setter @v_a.setter
def v_a(self, value): def v_a(self, value):
self.setDAC(dacIndex.V_POWER_A, value, True) value = ut.merge_args(dacIndex.V_POWER_A, value, True)
ut.set_using_dict(self.setDAC, *value)
@property @property
@element @element
@ -2885,7 +2902,8 @@ class Detector(CppDetectorApi):
@v_b.setter @v_b.setter
def v_b(self, value): def v_b(self, value):
self.setDAC(dacIndex.V_POWER_B, value, True) value = ut.merge_args(dacIndex.V_POWER_B, value, True)
ut.set_using_dict(self.setDAC, *value)
@property @property
@element @element
@ -2895,7 +2913,8 @@ class Detector(CppDetectorApi):
@v_c.setter @v_c.setter
def v_c(self, value): def v_c(self, value):
self.setDAC(dacIndex.V_POWER_C, value, True) value = ut.merge_args(dacIndex.V_POWER_C, value, True)
ut.set_using_dict(self.setDAC, *value)
@property @property
@element @element
@ -2905,7 +2924,8 @@ class Detector(CppDetectorApi):
@v_d.setter @v_d.setter
def v_d(self, value): def v_d(self, value):
self.setDAC(dacIndex.V_POWER_D, value, True) value = ut.merge_args(dacIndex.V_POWER_D, value, True)
ut.set_using_dict(self.setDAC, *value)
@property @property
@element @element
@ -2919,7 +2939,8 @@ class Detector(CppDetectorApi):
@v_io.setter @v_io.setter
def v_io(self, value): def v_io(self, value):
self.setDAC(dacIndex.V_POWER_IO, value, True) value = ut.merge_args(dacIndex.V_POWER_IO, value, True)
ut.set_using_dict(self.setDAC, *value)
@property @property
@element @element
@ -2929,7 +2950,9 @@ class Detector(CppDetectorApi):
@v_limit.setter @v_limit.setter
def v_limit(self, value): def v_limit(self, value):
self.setDAC(dacIndex.V_LIMIT, value, True) value = ut.merge_args(dacIndex.V_LIMIT, value, True)
ut.set_using_dict(self.setDAC, *value)
@property @property
@element @element

View File

@ -195,7 +195,6 @@ def add_argument_before(a, args):
"""Add a before the other arguments. Also works with """Add a before the other arguments. Also works with
dict that holds args to several modules. Always puts the dict that holds args to several modules. Always puts the
args in a dict to be compatible with set_using_dict""" args in a dict to be compatible with set_using_dict"""
print(f'{args=}')
if isinstance(args, tuple): if isinstance(args, tuple):
return (a, *args) return (a, *args)
elif isinstance(args, dict): elif isinstance(args, dict):
@ -208,3 +207,55 @@ def add_argument_before(a, args):
return (ret,) return (ret,)
return a, args return a, args
def add_argument_after(args, a):
"""Add a before the other arguments. Also works with
dict that holds args to several modules. Always puts the
args in a dict to be compatible with set_using_dict"""
if isinstance(args, tuple):
return (*args, a)
elif isinstance(args, dict):
ret = {}
for key, value in args.items():
if isinstance(value, tuple):
ret[key] = (*value, a)
else:
ret[key] = (value, a)
return (ret,)
return args, a
def pop_dict(args):
for i,a in enumerate(args):
if isinstance(a, dict):
return args.pop(i), i
def tuplify(args):
if not isinstance(args, tuple):
return (args, )
else:
return args
def merge_args(*args):
n_dict = sum(isinstance(a, dict) for a in args)
if n_dict == 0: #no dict just make a tuple of arguments
ret = []
for a in args:
if isinstance(a, tuple):
ret.extend(a)
else:
ret.append(a)
return tuple(ret)
elif n_dict == 1:
args = [a for a in args] #these are the args to be added
values,pos = pop_dict(args)
ret = {}
for k, v in values.items():
v = tuplify(v)
items = [a for a in args]
items[pos:pos] = v
ret[k] = tuple(items)
return (ret,)
else:
raise ValueError("Multiple dictionaries passes cannot merge args")

View File

@ -321,3 +321,22 @@ def test_add_argument_before_dict():
assert add_argument_before("another", {9: "string"}) == ({ assert add_argument_before("another", {9: "string"}) == ({
9: ("another", "string") 9: ("another", "string")
}, ) }, )
def test_add_argument_after():
assert add_argument_after("a", 5) == ("a", 5)
assert add_argument_after(("a", "b"), 3) == ("a", "b", 3)
def test_add_argument_after_dict():
assert add_argument_after({0: "a"}, "b") == ({0: ("a", "b")},)
assert add_argument_after({0: ("a", 1)}, True) == ({0: ("a", 1, True)}, )
def test_merge_args():
assert merge_args("a", "b", 1) == ("a", "b", 1)
assert merge_args({0:1, 1:2}, "a") == ({0: (1, "a"), 1: (2, "a")},)
def test_merge_args_tuple():
assert merge_args(*("a", "b"), 5) == ("a", "b", 5)
def test_merge_args_dict_with_tuple():
assert merge_args({0: (1,2)}, 3) == ({0: (1,2,3)},)

View File

@ -717,17 +717,17 @@ class Detector {
/** Default: padding enabled. Disabling padding is the fastest */ /** Default: padding enabled. Disabling padding is the fastest */
void setPartialFramesPadding(bool value, Positions pos = {}); void setPartialFramesPadding(bool value, Positions pos = {});
Result<int64_t> getRxUDPSocketBufferSize(Positions pos = {}) const; Result<int> getRxUDPSocketBufferSize(Positions pos = {}) const;
/** UDP socket buffer size in receiver. Tune rmem_default and rmem_max /** UDP socket buffer size in receiver. Tune rmem_default and rmem_max
* accordingly */ * accordingly. Max value is INT_MAX/2. */
void setRxUDPSocketBufferSize(int64_t udpsockbufsize, Positions pos = {}); void setRxUDPSocketBufferSize(int udpsockbufsize, Positions pos = {});
/** TODO: /** TODO:
* Gets actual udp socket buffer size. Double the size of rx_udpsocksize due * Gets actual udp socket buffer size. Double the size of rx_udpsocksize due
* to kernel bookkeeping. * to kernel bookkeeping.
*/ */
Result<int64_t> getRxRealUDPSocketBufferSize(Positions pos = {}) const; Result<int> getRxRealUDPSocketBufferSize(Positions pos = {}) const;
Result<bool> getRxLock(Positions pos = {}); Result<bool> getRxLock(Positions pos = {});

View File

@ -2680,10 +2680,11 @@ std::string CmdProxy::ExecuteCommand(int action) {
} else if (action == defs::GET_ACTION) { } else if (action == defs::GET_ACTION) {
throw sls::RuntimeError("Cannot get."); throw sls::RuntimeError("Cannot get.");
} else if (action == defs::PUT_ACTION) { } else if (action == defs::PUT_ACTION) {
if (args.size() != 1) { std::string command;
WrongNumberOfParameters(1); for (auto &i: args) {
command += (i + ' ');
} }
auto t = det->executeCommand(args[0], std::vector<int>{det_id}); auto t = det->executeCommand(command, std::vector<int>{det_id});
os << OutString(t) << '\n'; os << OutString(t) << '\n';
} else { } else {
throw sls::RuntimeError("Unknown action"); throw sls::RuntimeError("Unknown action");

View File

@ -1568,9 +1568,9 @@ class CmdProxy {
INTEGER_COMMAND_VEC_ID( INTEGER_COMMAND_VEC_ID(
rx_udpsocksize, getRxUDPSocketBufferSize, setRxUDPSocketBufferSize, rx_udpsocksize, getRxUDPSocketBufferSize, setRxUDPSocketBufferSize,
StringTo<int64_t>, StringTo<int>,
"[n_size]\n\tUDP socket buffer size in receiver. Tune rmem_default and " "[n_size]\n\tUDP socket buffer size in receiver. Tune rmem_default and "
"rmem_max accordingly."); "rmem_max accordingly. Max value is INT_MAX/2.");
GET_COMMAND(rx_realudpsocksize, getRxRealUDPSocketBufferSize, GET_COMMAND(rx_realudpsocksize, getRxRealUDPSocketBufferSize,
"\n\tActual udp socket buffer size. Double the size of " "\n\tActual udp socket buffer size. Double the size of "

View File

@ -907,16 +907,16 @@ void Detector::setPartialFramesPadding(bool value, Positions pos) {
pimpl->Parallel(&Module::setPartialFramesPadding, pos, value); pimpl->Parallel(&Module::setPartialFramesPadding, pos, value);
} }
Result<int64_t> Detector::getRxUDPSocketBufferSize(Positions pos) const { Result<int> Detector::getRxUDPSocketBufferSize(Positions pos) const {
return pimpl->Parallel(&Module::getReceiverUDPSocketBufferSize, pos); return pimpl->Parallel(&Module::getReceiverUDPSocketBufferSize, pos);
} }
void Detector::setRxUDPSocketBufferSize(int64_t udpsockbufsize, Positions pos) { void Detector::setRxUDPSocketBufferSize(int udpsockbufsize, Positions pos) {
pimpl->Parallel(&Module::setReceiverUDPSocketBufferSize, pos, pimpl->Parallel(&Module::setReceiverUDPSocketBufferSize, pos,
udpsockbufsize); udpsockbufsize);
} }
Result<int64_t> Detector::getRxRealUDPSocketBufferSize(Positions pos) const { Result<int> Detector::getRxRealUDPSocketBufferSize(Positions pos) const {
return pimpl->Parallel(&Module::getReceiverRealUDPSocketBufferSize, pos); return pimpl->Parallel(&Module::getReceiverRealUDPSocketBufferSize, pos);
} }

View File

@ -844,17 +844,17 @@ void Module::setPartialFramesPadding(bool padding) {
sendToReceiver(F_SET_RECEIVER_PADDING, static_cast<int>(padding), nullptr); sendToReceiver(F_SET_RECEIVER_PADDING, static_cast<int>(padding), nullptr);
} }
int64_t Module::getReceiverUDPSocketBufferSize() const { int Module::getReceiverUDPSocketBufferSize() const {
int64_t arg = GET_FLAG; int arg = GET_FLAG;
return sendToReceiver<int64_t>(F_RECEIVER_UDP_SOCK_BUF_SIZE, arg); return sendToReceiver<int>(F_RECEIVER_UDP_SOCK_BUF_SIZE, arg);
} }
int64_t Module::getReceiverRealUDPSocketBufferSize() const { int Module::getReceiverRealUDPSocketBufferSize() const {
return sendToReceiver<int64_t>(F_RECEIVER_REAL_UDP_SOCK_BUF_SIZE); return sendToReceiver<int>(F_RECEIVER_REAL_UDP_SOCK_BUF_SIZE);
} }
void Module::setReceiverUDPSocketBufferSize(int64_t udpsockbufsize) { void Module::setReceiverUDPSocketBufferSize(int udpsockbufsize) {
sendToReceiver<int64_t>(F_RECEIVER_UDP_SOCK_BUF_SIZE, udpsockbufsize); sendToReceiver<int>(F_RECEIVER_UDP_SOCK_BUF_SIZE, udpsockbufsize);
} }
bool Module::getReceiverLock() const { bool Module::getReceiverLock() const {

View File

@ -236,9 +236,9 @@ class Module : public virtual slsDetectorDefs {
void setReceiverFramesDiscardPolicy(frameDiscardPolicy f); void setReceiverFramesDiscardPolicy(frameDiscardPolicy f);
bool getPartialFramesPadding() const; bool getPartialFramesPadding() const;
void setPartialFramesPadding(bool padding); void setPartialFramesPadding(bool padding);
int64_t getReceiverUDPSocketBufferSize() const; int getReceiverUDPSocketBufferSize() const;
int64_t getReceiverRealUDPSocketBufferSize() const; int getReceiverRealUDPSocketBufferSize() const;
void setReceiverUDPSocketBufferSize(int64_t udpsockbufsize); void setReceiverUDPSocketBufferSize(int udpsockbufsize);
bool getReceiverLock() const; bool getReceiverLock() const;
void setReceiverLock(bool lock); void setReceiverLock(bool lock);
sls::IpAddr getReceiverLastClientIP() const; sls::IpAddr getReceiverLastClientIP() const;

View File

@ -12,6 +12,7 @@
#include <cstdlib> #include <cstdlib>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <limits.h>
#include <map> #include <map>
#include <memory> #include <memory>
#include <sstream> #include <sstream>
@ -1138,15 +1139,22 @@ int ClientInterface::get_additional_json_header(Interface &socket) {
} }
int ClientInterface::set_udp_socket_buffer_size(Interface &socket) { int ClientInterface::set_udp_socket_buffer_size(Interface &socket) {
auto index = socket.Receive<int64_t>(); auto size = socket.Receive<int>();
if (index >= 0) { if (size == 0) {
verifyIdle(socket); throw RuntimeError("Receiver socket buffer size must be > 0.");
LOG(logDEBUG1) << "Setting UDP Socket Buffer size: " << index;
impl()->setUDPSocketBufferSize(index);
} }
int64_t retval = impl()->getUDPSocketBufferSize(); if (size > 0) {
if (index != 0) verifyIdle(socket);
validate(index, retval, if (size > INT_MAX / 2) {
throw RuntimeError(
"Receiver socket buffer size exceeded max (INT_MAX/2)");
}
LOG(logDEBUG1) << "Setting UDP Socket Buffer size: " << size;
impl()->setUDPSocketBufferSize(size);
}
int retval = impl()->getUDPSocketBufferSize();
if (size != 0)
validate(size, retval,
"set udp socket buffer size (No CAP_NET_ADMIN privileges?)", "set udp socket buffer size (No CAP_NET_ADMIN privileges?)",
DEC); DEC);
LOG(logDEBUG1) << "UDP Socket Buffer Size:" << retval; LOG(logDEBUG1) << "UDP Socket Buffer Size:" << retval;

View File

@ -946,12 +946,14 @@ void Implementation::setUDPPortNumber2(const uint32_t i) {
LOG(logINFO) << "UDP Port Number[1]: " << udpPortNum[1]; LOG(logINFO) << "UDP Port Number[1]: " << udpPortNum[1];
} }
int64_t Implementation::getUDPSocketBufferSize() const { int Implementation::getUDPSocketBufferSize() const {
return udpSocketBufferSize; return udpSocketBufferSize;
} }
void Implementation::setUDPSocketBufferSize(const int64_t s) { void Implementation::setUDPSocketBufferSize(const int s) {
int64_t size = (s == 0) ? udpSocketBufferSize : s; // custom setup is not 0 (must complain if set up didnt work)
// testing default setup at startup, argument is 0 to use default values
int size = (s == 0) ? udpSocketBufferSize : s;
size_t listSize = listener.size(); size_t listSize = listener.size();
if (myDetectorType == JUNGFRAU && (int)listSize != numUDPInterfaces) { if (myDetectorType == JUNGFRAU && (int)listSize != numUDPInterfaces) {
throw sls::RuntimeError( throw sls::RuntimeError(
@ -959,12 +961,17 @@ void Implementation::setUDPSocketBufferSize(const int64_t s) {
" do not match listener size " + std::to_string(listSize)); " do not match listener size " + std::to_string(listSize));
} }
for (unsigned int i = 0; i < listSize; ++i) { for (auto &l : listener) {
listener[i]->CreateDummySocketForUDPSocketBufferSize(size); l->CreateDummySocketForUDPSocketBufferSize(size);
}
// custom and didnt set, throw error
if (s != 0 && udpSocketBufferSize != s) {
throw sls::RuntimeError("Could not set udp socket buffer size. (No "
"CAP_NET_ADMIN privileges?)");
} }
} }
int64_t Implementation::getActualUDPSocketBufferSize() const { int Implementation::getActualUDPSocketBufferSize() const {
return actualUDPSocketBufferSize; return actualUDPSocketBufferSize;
} }

View File

@ -108,9 +108,9 @@ class Implementation : private virtual slsDetectorDefs {
uint32_t getUDPPortNumber2() const; uint32_t getUDPPortNumber2() const;
/* [Eiger][Jungfrau] */ /* [Eiger][Jungfrau] */
void setUDPPortNumber2(const uint32_t i); void setUDPPortNumber2(const uint32_t i);
int64_t getUDPSocketBufferSize() const; int getUDPSocketBufferSize() const;
void setUDPSocketBufferSize(const int64_t s); void setUDPSocketBufferSize(const int s);
int64_t getActualUDPSocketBufferSize() const; int getActualUDPSocketBufferSize() const;
/************************************************** /**************************************************
* * * *
@ -302,8 +302,8 @@ class Implementation : private virtual slsDetectorDefs {
std::array<std::string, MAX_NUMBER_OF_LISTENING_THREADS> eth; std::array<std::string, MAX_NUMBER_OF_LISTENING_THREADS> eth;
std::array<uint32_t, MAX_NUMBER_OF_LISTENING_THREADS> udpPortNum{ std::array<uint32_t, MAX_NUMBER_OF_LISTENING_THREADS> udpPortNum{
{DEFAULT_UDP_PORTNO, DEFAULT_UDP_PORTNO + 1}}; {DEFAULT_UDP_PORTNO, DEFAULT_UDP_PORTNO + 1}};
int64_t udpSocketBufferSize{0}; int udpSocketBufferSize{0};
int64_t actualUDPSocketBufferSize{0}; int actualUDPSocketBufferSize{0};
// zmq parameters // zmq parameters
bool dataStreamEnable{false}; bool dataStreamEnable{false};

View File

@ -21,14 +21,12 @@ const std::string Listener::TypeName = "Listener";
Listener::Listener(int ind, detectorType dtype, Fifo *f, Listener::Listener(int ind, detectorType dtype, Fifo *f,
std::atomic<runStatus> *s, uint32_t *portno, std::string *e, std::atomic<runStatus> *s, uint32_t *portno, std::string *e,
uint64_t *nf, int64_t *us, int64_t *as, uint64_t *nf, int *us, int *as, uint32_t *fpf,
uint32_t *fpf, frameDiscardPolicy *fdp, bool *act, frameDiscardPolicy *fdp, bool *act, bool *depaden, bool *sm)
bool *depaden, bool *sm)
: ThreadObject(ind, TypeName), fifo(f), myDetectorType(dtype), status(s), : ThreadObject(ind, TypeName), fifo(f), myDetectorType(dtype), status(s),
udpPortNumber(portno), eth(e), numImages(nf), udpPortNumber(portno), eth(e), numImages(nf), udpSocketBufferSize(us),
udpSocketBufferSize(us), actualUDPSocketBufferSize(as), actualUDPSocketBufferSize(as), framesPerFile(fpf), frameDiscardMode(fdp),
framesPerFile(fpf), frameDiscardMode(fdp), activated(act), activated(act), deactivatedPaddingEnable(depaden), silentMode(sm) {
deactivatedPaddingEnable(depaden), silentMode(sm) {
LOG(logDEBUG) << "Listener " << ind << " created"; LOG(logDEBUG) << "Listener " << ind << " created";
} }
@ -142,7 +140,7 @@ void Listener::ShutDownUDPSocket() {
} }
} }
void Listener::CreateDummySocketForUDPSocketBufferSize(int64_t s) { void Listener::CreateDummySocketForUDPSocketBufferSize(int s) {
LOG(logINFO) << "Testing UDP Socket Buffer size " << s << " with test port " LOG(logINFO) << "Testing UDP Socket Buffer size " << s << " with test port "
<< *udpPortNumber; << *udpPortNumber;
@ -151,7 +149,7 @@ void Listener::CreateDummySocketForUDPSocketBufferSize(int64_t s) {
return; return;
} }
int64_t temp = *udpSocketBufferSize; int temp = *udpSocketBufferSize;
*udpSocketBufferSize = s; *udpSocketBufferSize = s;
// if eth is mistaken with ip address // if eth is mistaken with ip address

View File

@ -41,9 +41,9 @@ class Listener : private virtual slsDetectorDefs, public ThreadObject {
* @param sm pointer to silent mode * @param sm pointer to silent mode
*/ */
Listener(int ind, detectorType dtype, Fifo *f, std::atomic<runStatus> *s, Listener(int ind, detectorType dtype, Fifo *f, std::atomic<runStatus> *s,
uint32_t *portno, std::string *e, uint64_t *nf, uint32_t *portno, std::string *e, uint64_t *nf, int *us, int *as,
int64_t *us, int64_t *as, uint32_t *fpf, frameDiscardPolicy *fdp, uint32_t *fpf, frameDiscardPolicy *fdp, bool *act, bool *depaden,
bool *act, bool *depaden, bool *sm); bool *sm);
/** /**
* Destructor * Destructor
@ -98,7 +98,7 @@ class Listener : private virtual slsDetectorDefs, public ThreadObject {
* to set & get actual buffer size * to set & get actual buffer size
* @param s UDP socket buffer size to be set * @param s UDP socket buffer size to be set
*/ */
void CreateDummySocketForUDPSocketBufferSize(int64_t s); void CreateDummySocketForUDPSocketBufferSize(int s);
/** /**
* Set hard coded (calculated but not from detector) row and column * Set hard coded (calculated but not from detector) row and column
@ -173,10 +173,10 @@ class Listener : private virtual slsDetectorDefs, public ThreadObject {
uint64_t *numImages; uint64_t *numImages;
/** UDP Socket Buffer Size */ /** UDP Socket Buffer Size */
int64_t *udpSocketBufferSize; int *udpSocketBufferSize;
/** actual UDP Socket Buffer Size (double due to kernel bookkeeping) */ /** actual UDP Socket Buffer Size (double due to kernel bookkeeping) */
int64_t *actualUDPSocketBufferSize; int *actualUDPSocketBufferSize;
/** frames per file */ /** frames per file */
uint32_t *framesPerFile; uint32_t *framesPerFile;

View File

@ -14,11 +14,11 @@ class UdpRxSocket {
public: public:
UdpRxSocket(int port, ssize_t packet_size, const char *hostname = nullptr, UdpRxSocket(int port, ssize_t packet_size, const char *hostname = nullptr,
size_t kernel_buffer_size = 0); int kernel_buffer_size = 0);
~UdpRxSocket(); ~UdpRxSocket();
bool ReceivePacket(char *dst) noexcept; bool ReceivePacket(char *dst) noexcept;
size_t getBufferSize() const; int getBufferSize() const;
void setBufferSize(ssize_t size); void setBufferSize(int size);
ssize_t getPacketSize() const noexcept; ssize_t getPacketSize() const noexcept;
void Shutdown(); void Shutdown();

View File

@ -14,7 +14,7 @@
namespace sls { namespace sls {
UdpRxSocket::UdpRxSocket(int port, ssize_t packet_size, const char *hostname, UdpRxSocket::UdpRxSocket(int port, ssize_t packet_size, const char *hostname,
size_t kernel_buffer_size) int kernel_buffer_size)
: packet_size_(packet_size) { : packet_size_(packet_size) {
struct addrinfo hints; struct addrinfo hints;
memset(&hints, 0, sizeof(hints)); memset(&hints, 0, sizeof(hints));
@ -73,15 +73,15 @@ ssize_t UdpRxSocket::ReceiveDataOnly(char *dst) noexcept {
return r; return r;
} }
size_t UdpRxSocket::getBufferSize() const { int UdpRxSocket::getBufferSize() const {
size_t ret = 0; int ret = 0;
socklen_t optlen = sizeof(ret); socklen_t optlen = sizeof(ret);
if (getsockopt(sockfd_, SOL_SOCKET, SO_RCVBUF, &ret, &optlen) == -1) if (getsockopt(sockfd_, SOL_SOCKET, SO_RCVBUF, &ret, &optlen) == -1)
throw RuntimeError("Could not get socket buffer size"); throw RuntimeError("Could not get socket buffer size");
return ret; return ret;
} }
void UdpRxSocket::setBufferSize(ssize_t size) { void UdpRxSocket::setBufferSize(int size) {
if (setsockopt(sockfd_, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size))) if (setsockopt(sockfd_, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)))
throw RuntimeError("Could not set socket buffer size"); throw RuntimeError("Could not set socket buffer size");
} }