Compare commits

...

65 Commits

Author SHA1 Message Date
c1d841abbc doc wip 2020-10-28 13:30:28 +01:00
e57f49086d allowing multi receiver with just 2 arguments (without call back as default) 2020-10-28 11:43:53 +01:00
07cc28f91b Merge pull request #210 from slsdetectorgroup/bugfcloseserver
Bugfcloseserver
2020-10-27 18:18:14 +01:00
f6189072bc binaries in 2020-10-27 18:17:37 +01:00
453908c7cb m3 and g2: bugfix to close fd in server after reading detector type 2020-10-27 18:16:42 +01:00
23d9d5fa81 wip doc 2020-10-27 18:14:21 +01:00
671ee3179e bug fix for gap pixels with multi frames in gui (issue with overwriting original npixelsx and npixelsy with gap values 2020-10-27 16:50:42 +01:00
de4c834b44 doc WIP 2020-10-27 16:34:41 +01:00
9c19ce602d doc WIP 2020-10-27 16:34:26 +01:00
47018b61cd M3readout (#209)
* m3: readout command
2020-10-26 16:13:48 +01:00
91ad7b0594 removed broken symlink 2020-10-26 15:15:56 +01:00
e3ffc9a57b updating jungfrau examples 2020-10-23 15:38:42 +02:00
b9234ee7f2 update doc 2020-10-23 15:34:20 +02:00
559b02e167 Merge pull request #208 from slsdetectorgroup/m3trimbits
M3trimbits
2020-10-22 13:18:42 +02:00
a5d70c1214 print missing packets in signed 2020-10-20 15:47:09 +02:00
cefddff848 scan trimbits_scan changed to trimbits 2020-10-20 12:31:08 +02:00
0460d7e531 Merge pull request #207 from slsdetectorgroup/m3counter
M3counter
2020-10-20 12:06:51 +02:00
b31f8a5ca6 binary in 2020-10-20 12:05:18 +02:00
f4a2702996 m3: exptime and gatedelay values set from reg variables but not converted to time first 2020-10-20 12:03:46 +02:00
476afed516 updated docs on programfpga troubleshooting 2020-10-20 09:49:01 +02:00
3d414e6438 Merge pull request #204 from slsdetectorgroup/programfpga
Programfpga
2020-10-16 16:14:21 +02:00
df376c47d4 fix a typo and makefile 2020-10-16 15:09:56 +02:00
a86d70235c binaries in 2020-10-16 15:03:56 +02:00
5cd89487b6 blackfin fpga programming: if client socket killed or failure while writing to flash, only file pointer closed but fpga not asked to pick up from flash and client exception thrown. If all good and picking up from flash takes more than 10s, it will also throw exception in client. Client exception will prevent a reboot and hence allowing user to try to flash again. 2020-10-16 15:02:45 +02:00
acf29b6db8 Merge pull request #203 from slsdetectorgroup/m3trigger
M3trigger
2020-10-15 09:29:58 +02:00
fddc93ba8d binaries in 2020-10-15 09:28:41 +02:00
ae960fcb57 WIP 2020-10-15 09:28:17 +02:00
9f2bc85a18 m3: trigger enable moved to config reg, always enabling trigger flow for all timing modes for m3 2020-10-15 09:27:06 +02:00
3021594e20 updating the slsImageReconstruction Makefile part 2020-10-12 17:33:17 +02:00
9e8208dc0a update docs 2020-10-12 11:33:14 +02:00
21ad6b3a8a Merge pull request #201 from slsdetectorgroup/m3exptime
M3exptime
2020-10-09 17:59:47 +02:00
12abf3e58b binary in 2020-10-09 17:56:36 +02:00
6ddde13b87 m3: exptime and gate delay registers 1 2 3 are updated only if counters enabled, when counters enabled, the registers are updated back 2020-10-09 17:54:35 +02:00
e4226d34dc Merge pull request #200 from slsdetectorgroup/m3clk
M3clk
2020-10-09 17:09:05 +02:00
c1c885edd2 merge conflict resolved 2020-10-09 17:07:01 +02:00
a310ab9bfa updated all servers 2020-10-09 16:59:46 +02:00
904d10eb43 wip 2020-10-09 16:54:46 +02:00
e364fbcf32 m3: changed run clk div to 10, change run clkdiv to 40 while trimming, set default pipeline adif reg 2020-10-09 16:52:24 +02:00
95f816ad64 binaries in 2020-10-09 15:06:14 +02:00
2bd796cfff back to developer 2020-10-09 15:04:52 +02:00
794e579e12 update tag version in client version 2020-10-09 15:03:00 +02:00
bc6626aa7b docs 2020-10-09 08:55:03 +02:00
6fb2479178 updated docs 2020-10-09 08:52:19 +02:00
6053f2adff update docs 2020-10-08 16:04:58 +02:00
e0e2c2efba updated binaries 2020-10-08 15:55:24 +02:00
6d5f2e66ae updated client APIs 2020-10-08 15:46:26 +02:00
33d85dbfc0 all servers compiled 2020-10-08 15:45:29 +02:00
a838830090 ran tests and fixed 2020-10-08 15:44:15 +02:00
b9a459faa1 Merge branch 'developer' of github.com:slsdetectorgroup/slsDetectorPackage into developer 2020-10-08 14:47:21 +02:00
d4806eb48b Eiger manual with 5.x updates 2020-10-08 14:42:02 +02:00
7f189629fb commands, set multi level but get module level enabled 2020-10-08 14:31:18 +02:00
bee6bcc7a3 Merge pull request #199 from slsdetectorgroup/zmqhwm
Zmqhwm
2020-10-08 13:42:36 +02:00
2f2399d550 minor 2020-10-08 13:29:46 +02:00
6c1035aa99 zmq hwm are specified to 2 for gui and restreaming of receiver if all zmq not closed at end of acquiistion 2020-10-08 13:01:01 +02:00
c9bba6fbdc Merge branch 'developer' into zmqhwm 2020-10-07 18:02:53 +02:00
6d929ce96f Merge pull request #196 from slsdetectorgroup/semfail
Semfail
2020-10-07 18:00:24 +02:00
a36ce8cb1c binaries in 2020-10-07 17:05:38 +02:00
38cc365c01 setting shared mutex attribute for non blackfins 2020-10-07 17:01:16 +02:00
688fe4e3f7 fix zmqport and rx_zmqport, must restart zmq streaming 2020-10-07 14:17:34 +02:00
5c0dff29ed binaries in 2020-10-07 12:27:35 +02:00
51bfa17c6a switching to pthread with shared process attribute as sem_init doesnt work for blackfin 2020-10-07 12:25:14 +02:00
3b619f4488 Update README.md 2020-10-07 11:13:14 +02:00
6f96821275 wip, doc 2020-10-06 18:56:39 +02:00
6e58d845e9 updated ctb and moench server versions 2020-10-06 15:59:27 +02:00
ff3c79eaaa doc update 2020-10-06 15:57:27 +02:00
66 changed files with 1869 additions and 823 deletions

View File

@ -1,3 +1,8 @@
### Note
Please do not update to any xxxx.xx.xx.dev0 tags. They are not releases, but tags for internal usage.
Use only releases with tags such as x.x.x or x.x.x-rcx.
### Documentation
Detailed documentation can be found on the [official site.](https://www.psi.ch/detectors/users-support)

View File

@ -1,4 +1,4 @@
SLS Detector Package 5.0.0-rc2 released on 05.10.2020 (Release Candidate 2)
SLS Detector Package 5.0.0-rc2 released on 09.10.2020 (Release Candidate 2)
===========================================================================
CONTENTS
@ -12,58 +12,56 @@ SLS Detector Package 5.0.0-rc2 released on 05.10.2020 (Release Candidate 2)
Eiger
=====
Minimum compatible version : 27
Latest compatible version : 27
Compatible version : 08.09.2020 (v27)
Jungfrau
========
Minimum compatible version (PCB v1.0) : 24.07.2020 (v1.1)
Latest compatible version (PCB v1.0) : 24.07.2020 (v1.1)
Minimum compatible version (PCB v2.0) : 21.07.2020 (v2.1)
Latest compatible version (PCB v2.0) : 21.07.2020 (v2.1)
Compatible version : 24.07.2020 (v1.1, PCB v1.0)
: 21.07.2020 (v2.1, PCB v2.0)
Gotthard
========
Minimum compatible version : 11.01.2013
Latest compatible version : 08.02.2018 (50um and 25um Master)
09.02.2018 (25 um Slave)
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
Compatible version : 25.09.2020 (development)
Gotthard2
=========
Minimum compatible version : 25.09.2020
Latest compatible version : 25.09.2020
Compatible version : 25.09.2020 (development)
Moench
======
Minimum compatible version : 02.03.2020
Latest compatible version : 02.03.2020
Compatible version : 10.05.2020 (v1.0)
Ctb
===
Minimum compatible version : 27.11.2019
Latest compatible version : 27.11.2019
Compatible version : 10.05.2019 (v1.0)
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>
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
https://slsdetectorgroup.github.io/devdoc/firmware.html
and
https://slsdetectorgroup.github.io/devdoc/serverupgrade.html
Please refer to the link below for more details on the firmware versions.
https://www.psi.ch/en/detectors/firmware
Please refer to the link below for more details on the firmware versions.
https://www.psi.ch/en/detectors/firmware
2. Download, Documentation & Support
@ -72,7 +70,7 @@ SLS Detector Package 5.0.0-rc2 released on 05.10.2020 (Release Candidate 2)
Download
--------
The Source Code (Default C++ API):
The Source Code:
https://github.com/slsdetectorgroup/slsDetectorPackage
Documentation
@ -80,12 +78,24 @@ SLS Detector Package 5.0.0-rc2 released on 05.10.2020 (Release Candidate 2)
Installation:
https://slsdetectorgroup.github.io/devdoc/installation.html#
Firmware Upgrade:
https://slsdetectorgroup.github.io/devdoc/firmware.html
Detector Server upgrade:
https://slsdetectorgroup.github.io/devdoc/serverupgrade.html
Detector Simulators:
https://slsdetectorgroup.github.io/devdoc/virtualserver.html
Consuming slsDetectorPackage:
https://slsdetectorgroup.github.io/devdoc/consuming.html
Command Line Documentation:
https://slsdetectorgroup.github.io/devdoc/commandline.html
Quick Start Guide:
https://slsdetectorgroup.github.io/devdoc/quick_start_guide.html
C++ API Documentation:
https://slsdetectorgroup.github.io/devdoc/detector.html
@ -100,12 +110,15 @@ SLS Detector Package 5.0.0-rc2 released on 05.10.2020 (Release Candidate 2)
https://slsdetectorgroup.github.io/devdoc/pyexamples.html
TroubleShooting:
https://www.psi.ch/en/detectors/troubleshooting
https://slsdetectorgroup.github.io/devdoc/troubleshooting.html
Further Documentation:
https://www.psi.ch/en/detectors/users-support
https://www.psi.ch/en/detectors/documentation
Old Release notes:
https://www.psi.ch/en/detectors/latest-installation
Support
-------

View File

@ -51,7 +51,8 @@ set(SPHINX_SOURCE_FILES
src/serverdefaults.rst
src/quick_start_guide.rst
src/troubleshooting.rst
src/receivers.rst
src/slsreceiver.rst
)
foreach(filename ${SPHINX_SOURCE_FILES})

View File

@ -5,31 +5,43 @@ 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
Download
^^^^^^^^^^^^^
- `bcp script <https://github.com/slsdetectorgroup/slsDetectorFirmware/blob/master/binaries/eiger/bcp>`__
**Release candidate 5.0.0-rc1**
.. code-block:: bash
- detector server corresponding to package in slsDetectorPackage/serverBin
Minimum compatible version : 27
Latest compatible version : 27
`Older versions <https://www.psi.ch/en/detectors/latest-installation>`_
- bit files
.. list-table::
:widths: 25 10 30 25 10
:header-rows: 1
* - Software
- Hardware
- Firmware Date
- Firmware Link
- Comments
* - v5.0.0-rcx
-
- 08.09.2020
- `v27 <https://github.com/slsdetectorgroup/slsDetectorFirmware/blob/master/binaries/eiger/v27/>`__
-
* - v4.0.0 - v4.2.0
-
- 30.07.2019
- `v24 <https://github.com/slsdetectorgroup/slsDetectorFirmware/blob/master/binaries/eiger/v24/>`__
-
* - v3.1.0 - v3.1.5
-
- 17.08.2017
- `v20 <https://github.com/slsdetectorgroup/slsDetectorFirmware/blob/master/binaries/eiger/v20/>`__
-
Corrsponding Detector Server
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| **Location:**
| 5.0.0-rc1: slsDetectorPackage/slsDetectorServer/eigerDetectorServer/bin/eigerDetectorServer_developer
Upgrade
^^^^^^^^
#. Tftp must be already installed on your pc to use the bcp executable.
#. Tftp must be already installed on your pc to use the bcp script.
#. Kill the on-board servers and copy new servers to the board.
@ -99,36 +111,49 @@ Upgrade
Jungfrau
-------------
.. note ::
| Jungfrau firmware can be upgraded remotely.
| The corresponding programming file (pof) is provided by the SLS Detector group.
Compatibility
Download
^^^^^^^^^^^^^
- detector server corresponding to package in slsDetectorPackage/serverBin
**Release candidate 5.0.0-rc1**
- pof files
.. list-table::
:widths: 25 10 30 25 10
:header-rows: 1
.. code-block:: bash
* - Software
- Hardware
- Firmware Date
- Firmware Link
- Comments
* - v5.0.0-rcx
- 2.0
- 21.07.2020
- `v2.1 <https://github.com/slsdetectorgroup/slsDetectorFirmware/blob/master/binaries/jungfrau/v2_1/jungfrau_v2_1.pof>`__
-
* - v5.0.0-rcx
- 1.0
- 24.07.2020
- `v1.1 <https://github.com/slsdetectorgroup/slsDetectorFirmware/blob/master/binaries/jungfrau/v1_1/jungfrau_v1_1.pof>`__
-
* - v4.0.1 - v4.2.0
- 1.0
- 06.12.2018
- `v0.7 <https://github.com/slsdetectorgroup/slsDetectorFirmware/blob/master/binaries/jungfrau/v0_7/jungfrau_v0_7.pof>`__
-
* - v3.1.0 - v3.1.5
- 1.0
- 13.11.2017
- `v0.6 <https://github.com/slsdetectorgroup/slsDetectorFirmware/blob/master/binaries/jungfrau/v0_6/jungfrau_v0_6.pof>`__
-
# PCB v1.0
Minimum compatible version : 24.07.2020 (v1.1)
Latest compatible version : 24.07.2020 (v1.1)
# 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>`_
Corrsponding Detector Server
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| **Location:**
| 5.0.0-rc1: slsDetectorPackage/slsDetectorServer/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer
Upgrade (from v4.x.x)
^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^
Check :ref:`firmware troubleshooting <blackfin firmware troubleshooting>` if you run into issues while programming firmware.
#. Tftp must be installed on pc.
#. Update client package to the latest (5.0.0-rc1).
@ -179,8 +204,11 @@ Upgrade (from v4.x.x)
jungfrauDetectorServervxxx --stop-server 1953
Upgrade (from v5.0.0-rc1)
^^^^^^^^^^^^^^^^^^^^^^^^
Upgrade (from v5.0.0-rcx)
^^^^^^^^^^^^^^^^^^^^^^^^^^
Check :ref:`firmware troubleshooting <blackfin firmware troubleshooting>` if you run into issues while programming firmware.
#. Program from console
.. code-block:: bash
@ -194,36 +222,49 @@ Upgrade (from v5.0.0-rc1)
sls_detector_put programfpga xxx.pof
Gotthard
---------
Download
^^^^^^^^^^^^^
- detector server corresponding to package in slsDetectorPackage/serverBin
- pof files
.. list-table::
:widths: 15 15 15 15 5
:header-rows: 1
* - Software
- Hardware
- Firmware Date
- Firmware Link
- Comments
* - All versions
- 50um
- 08.02.2018
- `50um <https://github.com/slsdetectorgroup/slsDetectorFirmware/blob/master/binaries/gotthard_I/50um/gotthard_I_50um.pof>`__
-
* - All versions
- 25um (master)
- 08.02.2018
- `25um (master) <https://github.com/slsdetectorgroup/slsDetectorFirmware/blob/master/binaries/gotthard_I/25um/master/gotthard_I_25um_master.pof>`__
-
* - All versions
- 25um (slave)
- 09.02.2018
- `25um (slave) <https://github.com/slsdetectorgroup/slsDetectorFirmware/blob/master/binaries/gotthard_I/25um/slave/gotthard_I_25um_slave.pof>`__
-
.. _firmware upgrade using blaster for blackfin:
Upgrade
^^^^^^^^
.. 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>`_
Corrsponding Detector Server
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| **Location:**
| 5.0.0-rc1: slsDetectorPackage/slsDetectorServer/gotthardDetectorServer/bin/gotthardDetectorServer_developer
Upgrade
^^^^^^^^
#. Download `Altera Quartus software or Quartus programmer <https://fpgasoftware.intel.com/20.1/?edition=standard&platform=linux&product=qprogrammer#tabs-4>`_.
#. 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.
@ -243,28 +284,35 @@ Upgrade
Mythen3
-------
.. note ::
| Mythen3 firmware can be upgraded remotely.
| The corresponding programming file (rbf) is provided by the SLS Detector group.
.. note ::
Compatibility
As it is still in developement, the rbf files must be picked up from the SLS Detector Group.
Download
^^^^^^^^^^^^^
**Release candidate 5.0.0-rc1**
- detector server corresponding to package in slsDetectorPackage/serverBin
.. code-block:: bash
- rbf files
.. list-table::
:widths: 25 10 30 25 10
:header-rows: 1
Minimum compatible version : 25.09.2020
Latest compatible version : 25.09.2020
Corrsponding Detector Server
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| **Location:**
| 5.0.0-rc1: slsDetectorPackage/slsDetectorServer/mythen3DetectorServer/bin/mythen3DetectorServer_developer
* - Software
- Hardware
- Firmware Date
- Firmware Link
- Comments
* - v5.0.0-rcx
-
- 25.09.2020
-
- development
Upgrade (from v5.0.0-rc1)
^^^^^^^^^^^^^^^^^^^^^^^^
Upgrade (from v5.0.0-rcx)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
#. Program from console
.. code-block:: bash
@ -279,29 +327,34 @@ Upgrade (from v5.0.0-rc1)
Gotthard2
----------
.. note ::
| Gotthard2 firmware can be upgraded remotely.
| The corresponding programming file (rbf) is provided by the SLS Detector group.
-------------
.. note ::
Compatibility
As it is still in developement, the rbf files must be picked up from the SLS Detector Group.
Download
^^^^^^^^^^^^^
- detector server corresponding to package in slsDetectorPackage/serverBin
**Release candidate 5.0.0-rc1**
- rbf files
.. list-table::
:widths: 25 10 30 25 10
:header-rows: 1
.. code-block:: bash
* - Software
- Hardware
- Firmware Date
- Firmware Link
- Comments
* - v5.0.0-rcx
-
- 25.09.2020
-
- development
Minimum compatible version : 25.09.2020
Latest compatible version : 25.09.2020
Corrsponding Detector Server
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| **Location:**
| 5.0.0-rc1: slsDetectorPackage/slsDetectorServer/gotthard2DetectorServer/bin/gotthard2DetectorServer_developer
Upgrade (from v5.0.0-rc1)
^^^^^^^^^^^^^^^^^^^^^^^^
Upgrade (from v5.0.0-rcx)
^^^^^^^^^^^^^^^^^^^^^^^^^^
#. Program from console
.. code-block:: bash
@ -316,29 +369,37 @@ Upgrade (from v5.0.0-rc1)
Moench
------
.. note ::
| Moench firmware can be upgraded remotely.
| The corresponding programming file (pof) is provided by the SLS Detector group.
-------
Compatibility
Download
^^^^^^^^^^^^^
- detector server corresponding to package in slsDetectorPackage/serverBin
**Release candidate 5.0.0-rc1**
- pof files
.. list-table::
:widths: 25 10 30 25 10
:header-rows: 1
.. code-block:: bash
* - Software
- Hardware
- Firmware Date
- Firmware Link
- Comments
* - v5.0.0-rcx
- EPCQ128
- 05.10.2020
- `v1.0 <https://github.com/slsdetectorgroup/slsDetectorFirmware/blob/master/binaries/moench/EPCQ128/v1_0/moench_v1_0_201005.pof>`__
-
* - v5.0.0-rcx
- EPCS128
- 05.10.2020
- `v1.0 <https://github.com/slsdetectorgroup/slsDetectorFirmware/blob/master/binaries/moench/EPCS128/v1_0/moench_v1_0_201005.pof>`__
-
Minimum compatible version : 02.03.2020
Latest compatible version : 02.03.2020
Corrsponding Detector Server
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| **Location:**
| 5.0.0-rc1: slsDetectorPackage/slsDetectorServer/moenchDetectorServer/bin/moenchDetectorServer_developer
Upgrade (from v5.0.0-rcx)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Upgrade (from v5.0.0-rc1)
^^^^^^^^^^^^^^^^^^^^^^^^
Check :ref:`firmware troubleshooting <blackfin firmware troubleshooting>` if you run into issues while programming firmware.
#. Program from console
.. code-block:: bash
@ -352,29 +413,37 @@ Upgrade (from v5.0.0-rc1)
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
Download
^^^^^^^^^^^^^
- detector server corresponding to package in slsDetectorPackage/serverBin
**Release candidate 5.0.0-rc1**
- pof files
.. list-table::
:widths: 25 10 30 25 10
:header-rows: 1
.. code-block:: bash
* - Software
- Hardware
- Firmware Date
- Firmware Link
- Comments
* - v5.0.0-rcx
- EPCQ128
- 05.10.2020
- `v1.0 <https://github.com/slsdetectorgroup/slsDetectorFirmware/blob/master/binaries/ctb/EPCQ128/v1_0/ctb_v1_0_201005.pof>`__
-
* - v5.0.0-rcx
- EPCS128
- 05.10.2020
- `v1.0 <https://github.com/slsdetectorgroup/slsDetectorFirmware/blob/master/binaries/ctb/EPCS128/v1_0/ctb_v1_0_201005.pof>`__
-
Minimum compatible version : 27.11.2019
Latest compatible version : 27.11.2019
Corrsponding Detector Server
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| **Location:**
| 5.0.0-rc1: slsDetectorPackage/slsDetectorServer/ctbDetectorServer/bin/ctbDetectorServer_developer
Upgrade (from v5.0.0-rcx)
^^^^^^^^^^^^^^^^^^^^^^^^^^
Upgrade (from v5.0.0-rc1)
^^^^^^^^^^^^^^^^^^^^^^^^
Check :ref:`firmware troubleshooting <blackfin firmware troubleshooting>` if you run into issues while programming firmware.
#. Program from console
.. code-block:: bash
@ -385,4 +454,58 @@ Upgrade (from v5.0.0-rc1)
sls_detector_put update ctbDetectorServervxxx pcxxx xx.pof
# Or only program firmware
sls_detector_put programfpga xxx.pof
sls_detector_put programfpga xxx.pof
.. _blackfin firmware troubleshooting:
Firmware Troubleshooting with blackfin
----------------------------------------
#. v4.x.x client after programming will most likely reboot the blackfin processor, regardless of error.
#. v5.x.x-rcx client after programming will not reboot the blackfin processor, if error occurred.
#. If a reboot occured with an incomplete firmware in flash, the blackfin will most likely not find the mtd3 drive. To see if this drive exists:
.. code-block:: bash
# connect to the board
telnet bchipxxx
# view of mtd3 existing
root:/> more /proc/mtd
dev: size erasesize name
mtd0: 00040000 00020000 "bootloader(nor)"
mtd1: 00100000 00020000 "linux kernel(nor)"
mtd2: 002c0000 00020000 "file system(nor)"
mtd3: 01000000 00010000 "bitfile(spi)"
4. If one can see the mtd3 drive, one can already try to flash again using the **programfpga** command (without rebooting blackfin or detector).
#. 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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This might take a few reruns (maybe even 10) until the mtd drive is accessed by the blackfin upon linux startup.
.. code-block:: bash
# step 1: connect to the board
telnet bchipxxx
# step 2: check if mtd3 drive listed
more /proc/mtd
# step 3: tell fpga not to touch flash and reboot
echo 9 > /sys/class/gpio/export;
echo out > /sys/class/gpio/gpio9/direction;
echo 0 > /sys/class/gpio/gpio9/value;
reboot
# step 4: repeat steps 1 - 3 until you see the mtd3 drive
Last Resort using USB Blaster
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If none of these steps work, the last resort might be physically upgrading the firmware using a USB blaster, which also requires opening up the detector. Instructions for all the blackfin detectors are the same as the one for :ref:`gotthard firmware upgrade <firmware upgrade using blaster for blackfin>`.

View File

@ -66,6 +66,13 @@ Welcome to slsDetectorPackage's documentation!
virtualserver
serverdefaults
.. toctree::
:caption: Receiver
:maxdepth: 2
receivers
slsreceiver
.. toctree::
:caption: Troubleshooting

View File

@ -70,12 +70,6 @@ exposed to Python through pybind11.
.. autoclass:: masterFlags
:undoc-members:
.. autoclass:: frameModeType
:undoc-members:
.. autoclass:: detectorModeType
:undoc-members:
.. autoclass:: burstMode
:undoc-members:

View File

@ -217,9 +217,9 @@ The enums can be found in slsdet.enums
import slsdet
>>> [e for e in dir(slsdet.enums) if not e.startswith('_')]
['burstMode', 'clockIndex', 'dacIndex', 'detectorModeType',
['burstMode', 'clockIndex', 'dacIndex',
'detectorSettings', 'detectorType', 'dimension', 'externalSignalFlag',
'fileFormat', 'frameDiscardPolicy', 'frameModeType', 'masterFlags',
'fileFormat', 'frameDiscardPolicy', 'masterFlags',
'readoutMode', 'runStatus', 'speedLevel', 'timingMode',
'timingSourceType']

View File

@ -133,7 +133,8 @@ Compile with SLS_USE_GUI=ON in cmake or -g option in cmk.sh script. One can also
.. note ::
| The streaming frequency (commmand: rx_zmqfreq) is set by default in the receiver to 1 (send every frame).
| At Gui startup, this value is set to 0. It will set to use a timer of 500 ms. Hence, every frame will not be streamed to the gui. This is done to reduce the load for fast and large detectors for display purposes.
| One can still change this setting in the gui in the Plot tab (Plotting frequency) or from the command line (rx_zmqfreq).
| First frame is always streamed out, no matter if timer or frequency is used.
| The streaming high water mark (commmand: rx_zmqhwm) and the receiving high water mark (command: zmqhwm) is by default the lib zmq's default (currently 1000).
| At Gui startup, these values are set to 2. Hence, for very fast detectors, many frames will be dropped to be able to view the latest in the gui.
| One can still change this setting in the gui in the Plot tab (ZMQ Streaming), from the command line or API.
| Both hwm's can be set to a -1 to use the lib's default.
| Since the dummy end of acquisition packet streamed from receiver might also be lost, receiver restreams until gui acknowledges.

50
docs/src/receivers.rst Normal file
View File

@ -0,0 +1,50 @@
Receivers
=================
Receiver processes can be run on same or different machines as the client, receives the data from the detector (via UDP packets).
When using the slsReceiver/ slsMultiReceiver, they can be further configured by the client control software (via TCP/IP) to set file name, file path, progress of acquisition etc.
Detector UDP Header
---------------------
| The UDP data format for the packets consist of a common header for all detectors, followed by the data for that one packet.
**The SLS Detector Header**
.. table:: <-------------------------------- 8 bytes -------------------------------->
:align: center
:widths: 30,30,30,30
+--------------------------------------------------------------------+
|frameNumber |
+---------------------------------+----------------------------------+
|expLength |packetNumber |
+---------------------------------+----------------------------------+
|bunchId |
+--------------------------------------------------------------------+
|timestamp |
+----------------+----------------+----------------+-----------------+
|modId |row |column |reserved |
+----------------+----------------+----------------+--------+--------+
|debug |roundRNumber |detType |version |
+---------------------------------+----------------+--------+--------+
UDP configuration in Config file
----------------------------------
#. UDP source port is hardcoded in detector server, starting at 32410.
#. **udp_dstport** : UDP destination port number. Port in receiver pc to listen to packets from the detector.
#. **udp_dstip** : IP address of UDP destination interface. IP address of interface in receiver pc to listen to packets from detector. If **auto** is used (only when using slsReceiver/ slsMultiReceiver), the IP of **rx_hostname** is picked up.
#. **udp_dstmac** : Mac address of UDP destination interface. MAC address of interface in receiver pc to list to packets from detector. Only required when using custom receiver, else slsReceiver/slsMultiReceiver picks it up from **udp_dstip**.
#. **udp_srcip** : IP address of UDP source interface. IP address of detector UDP interface to send packets from. Do not use for Eiger 1Gb interface (uses its hardware IP). For others, must be in the same subnet as **udp_dstip**.
#. **udp_srcmac** : MAC address of UDP source interface. MAC address of detector UDP interface to send packets from. Do not use for Eiger (uses hardware mac). For others, it is not necessary, but can help for switch and debugging to put unique values for each module.
Custom Receiver
----------------
| When using custom receiver with our package, ensure that **udp_dstmac** is also configured in the config file. This parameter is not required when using slsReceiver.
| Cannot use "auto" for **udp_dstip**.
| Also ensure that there are no **rx_** commands in the config file. These commands are for configuring the slsReceiver.

View File

@ -1,6 +1,32 @@
Detector Servers
=================
Location
---------
slsDetectorPackage/serverBin/ folder in every release.
.. _Detector Server Arguments:
Arguments
---------
.. code-block:: bash
Possible arguments are:
-v, --version : Software version
-p, --port <port> : TCP communication port with client.
-g, --nomodule : [Mythen3][Gotthard2] Generic or No Module mode.
Skips detector type checks.
-f, --phaseshift <value> : [Gotthard] only. Sets phase shift.
-d, --devel : Developer mode. Skips firmware checks.
-u, --update : Update mode. Skips firmware checks and initial detector setup.
-s, --stopserver : Stop server. Do not use as it is created by control server
Basics
------------
Detector Servers include:
* Control server [default port: 1952]
* Almost all client communication.
@ -8,18 +34,3 @@ Detector Servers include:
* Client requests for detector status, stop acquisition, temperature, advanced read/write registers.
When using a blocking acquire command (sls_detector_acquire or Detector::acquire), the control server is blocked until end of acquisition. However, stop server commands could be used in parallel.
.. _Detector Server Arguments:
Arguments
---------
.. code-block:: bash
Possible arguments are:
-v, --version : Software version
-p, --port <port> : TCP communication port with client.
-g, --nomodule : [Mythen3][Gotthard2] Generic or No Module mode. Skips detector type checks.
-f, --phaseshift <value> : [Gotthard] only. Sets phase shift.
-d, --devel : Developer mode. Skips firmware checks.
-u, --update : Update mode. Skips firmware checks and initial detector setup.
-s, --stopserver : Stop server. Do not use as it is created by control server

View File

@ -7,8 +7,7 @@ Eiger
-------------
| **Location:**
| 5.0.0-rc1: slsDetectorPackage/slsDetectorServer/eigerDetectorServer/bin/eigerDetectorServer_developer
**Location:** slsDetectorPackage/serverBin/ folder for every release.
#. Kill old server and copy new server
@ -39,11 +38,10 @@ Eiger
Jungfrau
-------------
| **Location:**
| 5.0.0-rc1: slsDetectorPackage/slsDetectorServer/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer
**Location:** slsDetectorPackage/serverBin/ folder for every release.
#. Install tftp and copy detector server binary to tftp folder
#. Program from console (only from 5.0.0-rc1)
#. Program from console (only from 5.0.0-rcx)
.. code-block:: bash
# copies new server from pc tftp folder, respawns and reboots
@ -53,11 +51,10 @@ Jungfrau
Gotthard
---------
| **Location:**
| 5.0.0-rc1: slsDetectorPackage/slsDetectorServer/gotthardDetectorServer/bin/gotthardDetectorServer_developer
**Location:** slsDetectorPackage/serverBin/ folder for every release.
#. Install tftp and copy detector server binary to tftp folder
#. Program from console (only from 5.0.0-rc1)
#. Program from console (only from 5.0.0-rcx)
.. code-block:: bash
# copies new server from pc tftp folder, respawns and reboots
@ -68,11 +65,10 @@ Gotthard
Mythen3
-------
| **Location:**
| 5.0.0-rc1: slsDetectorPackage/slsDetectorServer/mythen3DetectorServer/bin/mythen3DetectorServer_developer
**Location:** slsDetectorPackage/serverBin/ folder for every release.
#. Install tftp and copy detector server binary to tftp folder
#. Program from console (only from 5.0.0-rc1)
#. Program from console (only from 5.0.0-rcx)
.. code-block:: bash
# copies new server from pc tftp folder and reboots (does not respawn)
@ -82,11 +78,10 @@ Mythen3
Gotthard2
----------
| **Location:**
| 5.0.0-rc1: slsDetectorPackage/slsDetectorServer/gotthard2DetectorServer/bin/gotthard2DetectorServer_developer
**Location:** slsDetectorPackage/serverBin/ folder for every release.
#. Install tftp and copy detector server binary to tftp folder
#. Program from console (only from 5.0.0-rc1)
#. Program from console (only from 5.0.0-rcx)
.. code-block:: bash
# copies new server from pc tftp folder and reboots (does not respawn)
@ -96,11 +91,10 @@ Gotthard2
Moench
------
| **Location:**
| 5.0.0-rc1: slsDetectorPackage/slsDetectorServer/moenchDetectorServer/bin/moenchDetectorServer_developer
**Location:** slsDetectorPackage/serverBin/ folder for every release.
#. Install tftp and copy detector server binary to tftp folder
#. Program from console (only from 5.0.0-rc1)
#. Program from console (only from 5.0.0-rcx)
.. code-block:: bash
# copies new server from pc tftp folder, respawns and reboots
@ -110,11 +104,10 @@ Moench
Ctb
---
| **Location:**
| 5.0.0-rc1: slsDetectorPackage/slsDetectorServer/ctbDetectorServer/bin/ctbDetectorServer_developer
**Location:** slsDetectorPackage/serverBin/ folder for every release.
#. Install tftp and copy detector server binary to tftp folder
#. Program from console (only from 5.0.0-rc1)
#. Program from console (only from 5.0.0-rcx)
.. code-block:: bash
# copies new server from pc tftp folder, respawns and reboots

159
docs/src/slsreceiver.rst Normal file
View File

@ -0,0 +1,159 @@
slsReceiver/ slsMultiReceiver
================================
| One has to start the slsReceiver before loading config file or using any receiver commands (prefix: **rx_** )
For a Single Module
.. code-block:: bash
# default port 1954
slsReceiver
# custom port 2012
slsReceiver -t2012
For Multiple Modules
.. code-block:: bash
# each receiver (for each module) requires a unique tcp port (if all on same machine)
# using slsReceiver in multiple consoles
slsReceiver
slsReceiver -t1955
# slsMultiReceiver [starting port] [number of receivers]
slsMultiReceiver 2012 2
# slsMultiReceiver [starting port] [number of receivers] [print each frame header for debugging]
slsMultiReceiver 2012 2 1
Client Commands
-----------------
| One can remove **udp_dstmac** from the config file, as the slsReceiver fetches this from the **udp_ip**.
| One can use "auto" for **udp_dstip** if one wants to use default ip of **rx_hostname**.
| The first command to the receiver (**rx_** commands) should be **rx_hostname**. The following are the different ways to establish contact.
.. code-block:: bash
# default receiver tcp port (1954)
rx_hostname xxx
# custom receiver port
rx_hostname xxx:1957
# custom receiver port
rx_tcpport 1954
rx_hostname xxx
# multi modules with custom ports
rx_hostname xxx:1955+xxx:1956+
# multi modules with custom ports on same rxr pc
0:rx_tcpport 1954
1:rx_tcpport 1955
2:rx_tcpport 1956
rx_hostname xxx
# multi modules with custom ports on different rxr pc
0:rx_tcpport 1954
0:rx_hostname xxx
1:rx_tcpport 1955
1:rx_hostname yyy
| Example commands:
.. code-block:: bash
# to get a list of receiver commands (these dont include file commands)
sls_detector_get list | grep rx_
# some file commands are:
fwrite
foverwrite
findex
fpath
fname
fmaster
fformat
# to get help on a single commands
sls_detector_get -h rx_framescaught
File format
--------------
* The file name format is [fpath]/[fname]_dx_fy_[findex].raw, where x is module index and y is file index. **fname** is file name prefix and by default "run". **fpath** is '/' by default.
* Each acquisition will have an increasing acquisition index or findex (if file write enabled). This can be retrieved by using **findex** command.
* Each acquisition can have multiple files (the file index number **y**), with **rx_framesperfile** being the maximum number of frames per file. The default varies for each detector type.
* Some file name examples:
.. code-block:: bash
# first file
path-to-file/run_d0_f0_0.raw
# second file after reaching max frames in first file
path-to-file/run_d0_f1_0.raw
# second acquisition, first file
path-to-file/run_d0_f0_1.raw
* Each acquisition will create a master file that can be enabled/disabled using **fmaster**. This should have parameters relevant to the acquisition.
* SLS Receiver Header consist of SLS Detector Header + 64 bytes of bitmask, altogether 112 bytes. The packetNumber in the sls detector header part, will be updated to number of packets caught by receiver for that frame. Furthermore, the bit mask will specify which packets have been received.
**Binary file format**
* This is the default file format.
* Each data file will consist of frames, each consisting of slsReceiver Header followed by data for 1 frame.
* Master file is of ASCII format and will also include the format of the slsReceiver Header.
**HDF5 file formats**
#. Compile the package with HDF5 option enabled
#. Using cmk script: ./cmk.sh -hj9 -d [path of hdf5 dir]
#. Enable using cmake **-DCMAKE_INSTALL_PREFIX=/path/to/hdf/installation** and **-DSLS_USE_HDF5=ON**
#. Start Receiver process
#. Load config file
#. Set file format from client or in config file
.. code-block:: bash
sls_detector_put fformat hdf5
| For multiple, modules, a virtual file linking all the modules is created. Both the data files and virtual files are linked in the master file.
Performance
-------------
Please refer to Receiver PC Tuning options and slsReceiver Tuning under `Troubleshooting <https://slsdetectorgroup.github.io/devdoc/troubleshooting.html>`_.
Using Callbacks
----------------
| One can get a callback in the receiver for each frame to:
* manipulate the data that will be written to file, or
* disable file writing in slsReceiver and take care of the data for each call back
| When handling callbacks, the control should be returned as soon as possible, to prevent packet loss from fifo being full.

View File

@ -13,7 +13,7 @@ Compilation
* Using cmk.sh script,
.. code-block:: bash
./cmk.sh -b**s**j9 #option s is for simulator
./cmk.sh -bsj9 #option s is for simulator
Binaries

View File

@ -8,18 +8,15 @@ rx_hostname pcmoench01
udp_dstport 50004
# udp destination ip (receiver)
#udp_dstip 172.24.8.84
# or to get ip from rx_hostname
udp_dstip auto
udp_dstip 10.0.1.100
# udp source ip (same subnet as udp_dstip)
udp_srcip 172.24.8.254
udp_srcip 10.0.1.184
# PCBv2.0 (using 2 interfaces)
# PCBv2.0 (using 2 interfaces, top)
udp_dstport2 50005
udp_dstip2 auto
udp_srcip2 172.24.8.111
udp_dstip2 10.0.2.100
udp_srcip2 10.0.2.184
# enable two interfaces
numinterfaces 2
# select inner interface(effective only when numinterfaces is 1)

View File

@ -316,7 +316,11 @@ You can then reset to zero the number of frames caught (in releases<5.0), then
\item {\tt{sls\_detector\_put 0-receiver start}}
\item {\tt{sls\_detector\_put 0-status start}}
\end{enumerate}
In release \textcolor{red}{5.0} it is not needed to reset the frames caughts.
In release \textcolor{red}{5.0} it is not needed to reset the frames caughts and the commands are:
\begin{enumerate}
\item \textcolor{red}{{\tt{sls\_detector\_put 0-rx\_start}}}
\item \textcolor{red}{{\tt{sls\_detector\_put 0-start}}}
\end{enumerate}
You can poll the detector status using:
\begin{verbatim}
@ -325,17 +329,17 @@ sls_detector_get 0-status
When the detector is {\tt{idle}}, then the acquisition is done but the receiver could still be receiving data. If you want, you can check if the receiver is finished receiving as many frames as you were expecting (this is optional but required for many many frames acquisition or when using some delays to send data at very high frame rate.
\begin{enumerate}
\setcounter{enumi}{3}
\item {\tt{sls\_detector\_get framescaught}}
\item {\tt{sls\_detector\_get framescaught}} (\textcolor{red}{rx\_framescaught})
\end{enumerate}
Then you can stop the receiver as well now:
\begin{enumerate}
\setcounter{enumi}{4}
\item {\tt{sls\_detector\_put 0-receiver stop}}
\item {\tt{sls\_detector\_put 0-receiver stop} (\textcolor{red}{sls\_detector\_put 0-rx\_stop})}
\end{enumerate}
The detector will not accept other commands while acquiring. If an acquisition wishes to be properly aborted, then:
\begin{itemize}
\item {\tt{sls\_detector\_put 0-status stop}}
\item {\tt{sls\_detector\_put 0-status stop} (\textcolor{red}{sls\_detector\_put 0-stop})}
\end{itemize}
this same command can be used after a non proper abortion of the acquisition to reset to normal status the detector.
@ -979,6 +983,7 @@ mount -t tmpfs none /mnt/ramdisk -o size=10G
\end{verbatim}
check how many GB memory you can allocate, to avoid swapping otherwise
\section{Offline processing and monitoring}
\subsection{Data out of the detector: UDP packets}\label{UDP}
@ -1013,28 +1018,31 @@ white the option {\tt{n:flippeddatax 1}}, which flips in vertical the content of
\subsection{``raw'' files}
If you use the option of writing raw files, you will have a raw file for each UDP port (meaning most likely 2 chips), 4 files per module. In addition to the raw files, you will get also a ``master'' file, containing in ascii some detector general parameters and the explanation of how to interpret the data from the raw files.
The master file is named: {\tt{filename\_master\_0.raw}} and for version ``4.0.0'' of the slsDetectorSoftware looks like:
\begin{verbatim}
Version : 4.0
Detector Type : 3
The master file is named: {\tt{filename\_master\_0.raw}} and for version ``5.0'' of the slsDetectorSoftware looks like:
\begin{verbatim}
Version : 6.2
TimeStamp : Thu Oct 8 11:10:07 2020
Detector Type : Eiger
Timing Mode : auto
Image Size : 524288 bytes
Pixels : [512, 256]
Max Frames Per File : 10000
Frame Discard Policy : nodiscard
Frame Padding : 1
Scan Parameters : [disabled]
Total Frames : 10
Dynamic Range : 32
Ten Giga : 1
Image Size : 524288 bytes
nPixelsX : 512 pixels
nPixelsY : 256 pixels
Max Frames Per File : 10000
Total Frames : 3
Exptime (ns) : 10000000
SubExptime (ns) : 2621440
SubPeriod(ns) : 2621440
Period (ns) : 0
Gap Pixels Enable : 0
Quad Enable : 0
Timestamp : Wed Aug 21 16:30:20 2019
Exptime : 1s
Period : 50us
SubExptime : 2.62144ms
SubPeriod : 2.62144ms
Quad : 0
Number of Lines read out : 256
Rate Corrections : [0, 0]
#Frame Header
\#Frame Header
Frame Number : 8 bytes
SubFrame Number/ExpLength : 4 bytes
Packet Number : 4 bytes
@ -1056,20 +1064,35 @@ Note that if one wants to reconstruct the real time the detector was acquiring
\subsection{Offline image reconstruction}
The offline image reconstruction{\tt{slsImageReconstruction}} is not part of the package anymore. However, it can be retrieved from \\
{\tt{git clone https://github.com/slsdetectorgroup/slsImageReconstruction.git slsImageReconstruction}}.\\
Checkout the {\tt{v3.1}} branch if in a 3.1.X release, the {\tt{v4.0.0}} branch if in 4.0.X release, or the {\tt{v4.1}} branch if in 4.1.X release of the {\tt{slsDetector}} code. There is a {\tt{developer}} branch that has newer updates but needs to be tested.
Checkout the {\tt{v3.1}} branch if in a 3.1.X release, the {\tt{v4.0.0}} branch if in 4.0.X release, or the {\tt{v4.1}} branch if in 4.1.X release of the {\tt{slsDetector}} code. There is a {\tt{developer}} branch that is following the 5.X chnages but it is not official yet.
Three possible conversions are possible: into \textbf{cbf}, \textbf{hdf5}. \textbf{tiff} and \textbf{root} format. The detector writes 2 raw files per receiver. An offline image reconstruction executable has been written to collate the possible files together and produce output files. By default an interpolation between the values of the large pixels is performed. Gap pixels between modules are also inserted.
Four possible conversions are possible: into \textbf{cbf}, \textbf{hdf5}. \textbf{tiff} and \textbf{root} format. The detector writes 2 raw files per receiver. An offline image reconstruction executable has been written to collate the possible files together and produce output files. By default an interpolation between the values of the large pixels is performed. Gap pixels between modules are also inserted.
Note that the number of images per file in the 3.1.X release is hardcoded and needs to match whatever you are using in \\
\subsection{Releases}
Note for different releases:
\begin{itemize}
\item Note that the number of images per file in the 3.1.X release is hardcoded and needs to match whatever you are using in \\
{\tt{slsDetectorsPackage/slsReceiverSoftware/include/sls\_receiver\_defs.h}}:
\begin{verbatim}
#define EIGER_MAX_FRAMES_PER_FILE 2000
\end{verbatim}
The default is 2000 in the 3.1.X release. The default has been changed to 10000 frm realease 4.0.X and now this is picked up automatically without doing anything.
\item From release 4.1.x, it is not needed to change the options in the \tt{slsImageReconstruction/src/main\_csaxs.cpp} file, but it is enough to change the options in the compiler. Options are:
\begin{enumerate}
\item [cbf] if you want header style supperted at MS beamline (in reality the lines are just hardcoded with no real information in them, just to have all required filesds) analyser (Krysalis?) choose -DMSHeader
\item [hdf5] If you want a master file, which contains a virtual dataset pointing at dataset written in subfiles, use the option -DMASTERVIRTUAL . This option however is not supported neither by Matlab2018, nor by Albula and Nedved installed at the MS beamlines.
\item [hdf5] The master file contains links to the datasets of other files, use -DMASTERLINK option. Although this version is very unconfortable if you need to open writing your code different events, but it is what Albula, Nedved and so on uses (it is compatible to Dectris). So it has more portability.
\item [hdf5]to compress using zlib, use the -DZLIB. Very slow compression, not used
\item [hdf5] -DBITSHUFFLE should have lz4 and bitshuffle implemented. I am not sure it works. NEEDS to be tested. Not to be used if not for debugging.
\end{enumerate}
\end{itemize}
\subsubsection{cbf}
The cbf executable executable uses the CBFlib-0.9.5 library (downloaded from the web as it downloads architecture dependent packages at installation).Edit the Makefile to correclty point at it.\\
\underline{At cSAXS, the CBFlib-0.9.5 has been compiled -such that the required packages are}\\\underline{ downloaded in /sls/X12SA/data/x12saop/EigerPackage/CBFlib-0.9.5.}\\
To use it for a single module:
\begin{verbatim}
@ -1124,7 +1147,7 @@ make cbfMaker; make cbfMakerOMNY;
\end{verbatim}
\subsubsection{hdf5}
In case of HDF5 output file, we rely on having the HDF5 1.10.1 library installed and {\tt{HDF5-External-Filter-Plugins}} installed. With HDF5 1.10.3, no need of the external plugings package is needed, but a small modification to the file is needed. Edit the Makefile to correclty point at it. Different compression methods are being tried so different external filters might be to be installed. This work is not finished yet.
In case of HDF5 output file, we rely on having the hdf5/1.10.3 (previously was 1.10.1 library installed and {\tt{HDF5-External-Filter-Plugins}} installed). Edit the Makefile to correclty point at Different compression methods (so far only the not efficien gzip is implemented) are being tried so different external filters might be to be installed. This work is not finished yet.
To choose HDF5, with ZLIB implementation, open {\tt{slsImageReconstruction/src/main\_csaxs.cpp}} and make sure that
\begin{verbatim}
@ -1197,6 +1220,28 @@ The HV can also be set and read through the software:
\end{verbatim}
Note that the get {\tt{vhighvoltage}}(\tt{\textcolor{red}{highvoltage}}) would return the measured HV from the master module only. If getting the highvoltage for individual halfmodules, only the master will have a value different from -999.
\section{Run the sum of counts in the receiver}
In the package {\tt{slsImageReconstruction}} there is also a very basic executable that allows to run receivers that sum all the counts in the UDP port and writes them as a text files in the {\tt{outdir}} directory in the same directory as the data files, with the same {\tt{fname}}. This is to use EIGER as a simple normalization detector.
The code is in {\tt{slsImageReconstruction/src/ReceiverSum.cpp}}.
For the compilation you need to be in {\tt{slsImageReconstruction}}
\begin{verbatim}
make -f Makefile.zmq receiverSum
\end{verbatim}
you might need to edit the path to the {\tt{slsDetectorPackage}} that you are using in the {\tt{Makefile.zmq}}.
Usage is:
\begin{verbatim}
export LD_LIBRARY_PATH=pathtoslsDetectorPackage/build/bin
./bin/receiverSum
./bin/receiverSum rx_tcppport 1955
\end{verbatim}
For now, to work peoperly there are some requirements that need to make more general if the code wants to be used more:
\begin{enumerate}
\item You can use the code only for a module (2 Receivers)
\item The first receiver has to run using tcp\_port 1954 (the second port is not fixed but we use 1955 normally)
\item Set the option {\tt{enablefwrite 0}} (\textcolor{red}{\tt{fwrite 0}}) as we do not write raw data but only the text files.
\item As a bit of time is required to make the sum compared to a normal receiver, use the option {\tt sls\_detector\_put rx\_fifodepth 50000}.
\end{enumerate}
File like fnamed0\_findex.txt, fnamed1\_findex.txt, fnamed2\_findex.txt and fnamed3\_findex.txt will be written, containing 2 columns: the frame number and the sum of counts for the port.
\appendix
\section{Kill the server, copy a new server, start the server}\label{server}

View File

@ -1 +0,0 @@
../../slsDetectorSoftware/slsDetector/slsDetectorCommand.cpp

View File

@ -75,7 +75,7 @@
<property name="spacing">
<number>6</number>
</property>
<item row="1" column="4" colspan="4">
<item row="1" column="3" colspan="4">
<widget class="QGroupBox" name="box2D">
<property name="enabled">
<bool>true</bool>
@ -1388,7 +1388,7 @@ Displays minimum, maximum and sum of values for each plot.
</layout>
</widget>
</item>
<item row="2" column="0" colspan="7">
<item row="2" column="0" colspan="6">
<widget class="QGroupBox" name="boxPlotAxis">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
@ -1789,7 +1789,7 @@ Displays minimum, maximum and sum of values for each plot.
</layout>
</widget>
</item>
<item row="2" column="7">
<item row="2" column="6">
<widget class="QGroupBox" name="boxSave">
<property name="enabled">
<bool>true</bool>
@ -1990,23 +1990,7 @@ Displays minimum, maximum and sum of values for each plot.
</layout>
</widget>
</item>
<item row="0" column="3">
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="4" colspan="4">
<item row="0" column="0" colspan="7">
<widget class="QGroupBox" name="boxFrequency">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@ -2016,7 +2000,7 @@ Displays minimum, maximum and sum of values for each plot.
</property>
<property name="minimumSize">
<size>
<width>0</width>
<width>350</width>
<height>65</height>
</size>
</property>
@ -2024,7 +2008,7 @@ Displays minimum, maximum and sum of values for each plot.
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Sets the pace at which the receiver streams out images. Images in between the timeout or frequency are not sent out.&lt;br/&gt;&lt;br/&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Time Interval&lt;/span&gt;: Streaming time interval when an image should be streamed. &lt;br/&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Every nth Image&lt;/span&gt;: Only every nth image is streamed. &lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="title">
<string>Receiver Streaming Frequency / Timer</string>
<string>ZMQ Streaming</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
@ -2052,6 +2036,31 @@ Displays minimum, maximum and sum of values for each plot.
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QCheckBox" name="chkNoPlot">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If checked, there is no call back and no images are plotted.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>No Plot</string>
</property>
</widget>
</item>
<item row="0" column="11">
<widget class="QComboBox" name="comboFrequency">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
@ -2061,13 +2070,13 @@ Displays minimum, maximum and sum of values for each plot.
</property>
<property name="minimumSize">
<size>
<width>150</width>
<width>135</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<width>135</width>
<height>16777215</height>
</size>
</property>
@ -2150,29 +2159,25 @@ Displays minimum, maximum and sum of values for each plot.
</item>
</widget>
</item>
<item row="0" column="1">
<spacer name="horizontalSpacer_14">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<item row="0" column="13">
<widget class="QStackedWidget" name="stackedTimeInterval">
<property name="maximumSize">
<size>
<width>80</width>
<height>20</height>
<width>150</width>
<height>16777215</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="2">
<widget class="QStackedWidget" name="stackedTimeInterval">
<property name="currentIndex">
<number>1</number>
<number>0</number>
</property>
<widget class="QWidget" name="pageTimeGap">
<layout class="QHBoxLayout" name="horizontalLayout_14">
<property name="spacing">
<number>2</number>
</property>
<property name="leftMargin">
<number>2</number>
</property>
<item>
<widget class="QDoubleSpinBox" name="spinTimeGap">
<property name="sizePolicy">
@ -2181,11 +2186,17 @@ Displays minimum, maximum and sum of values for each plot.
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>90</width>
<height>30</height>
</size>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
<property name="decimals">
<number>3</number>
<number>2</number>
</property>
<property name="maximum">
<double>999999.000000000000000</double>
@ -2238,6 +2249,9 @@ Displays minimum, maximum and sum of values for each plot.
</widget>
<widget class="QWidget" name="pageFrequency">
<layout class="QHBoxLayout" name="horizontalLayout_13">
<property name="leftMargin">
<number>2</number>
</property>
<item>
<widget class="QSpinBox" name="spinNthFrame">
<property name="sizePolicy">
@ -2267,78 +2281,8 @@ Displays minimum, maximum and sum of values for each plot.
</widget>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="boxPlotType">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>350</width>
<height>65</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="title">
<string>Plot Type</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="flat">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="horizontalSpacing">
<number>2</number>
</property>
<property name="verticalSpacing">
<number>0</number>
</property>
<item row="0" column="2">
<widget class="QRadioButton" name="radioDataGraph">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Data Graph</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<spacer name="horizontalSpacer_5">
<item row="0" column="10">
<spacer name="horizontalSpacer_18">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
@ -2347,22 +2291,159 @@ Displays minimum, maximum and sum of values for each plot.
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<width>30</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="radioNoPlot">
<item row="0" column="2">
<widget class="QLabel" name="lblSndHwm">
<property name="text">
<string>Snd Hwm: </string>
</property>
</widget>
</item>
<item row="0" column="1">
<spacer name="horizontalSpacer_25">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>30</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="4">
<spacer name="horizontalSpacer_14">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>30</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="6">
<widget class="QSpinBox" name="spinRcvHwm">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>25</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>30</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;High water mark for inbound messages for gui.&lt;/p&gt;&lt;p&gt; #zmqhwm#&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="statusTip">
<string/>
</property>
<property name="whatsThis">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
<property name="suffix">
<string/>
</property>
<property name="prefix">
<string/>
</property>
<property name="minimum">
<number>-1</number>
</property>
<property name="maximum">
<number>99999</number>
</property>
<property name="value">
<number>1000</number>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QSpinBox" name="spinSndHwm">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>25</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>30</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;High water mark for outbound messages for receiver.&lt;/p&gt;&lt;p&gt;#rx_zmqhwm#&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="statusTip">
<string/>
</property>
<property name="whatsThis">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
<property name="suffix">
<string/>
</property>
<property name="prefix">
<string/>
</property>
<property name="minimum">
<number>-1</number>
</property>
<property name="maximum">
<number>99999</number>
</property>
<property name="value">
<number>1000</number>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QLabel" name="lblRcvHwm">
<property name="text">
<string>No Plot</string>
<string>Rcv Hwm: </string>
</property>
</widget>
</item>
@ -2370,7 +2451,6 @@ Displays minimum, maximum and sum of values for each plot.
</widget>
</item>
</layout>
<zorder>boxPlotType</zorder>
<zorder>box1D</zorder>
<zorder>boxFrequency</zorder>
<zorder>box2D</zorder>
@ -2378,8 +2458,6 @@ Displays minimum, maximum and sum of values for each plot.
<zorder>boxSave</zorder>
</widget>
<tabstops>
<tabstop>radioNoPlot</tabstop>
<tabstop>radioDataGraph</tabstop>
<tabstop>comboFrequency</tabstop>
<tabstop>spinTimeGap</tabstop>
<tabstop>comboTimeGapUnit</tabstop>

View File

@ -40,6 +40,7 @@ class qDefs : public QWidget {
static const int Q_FONT_SIZE = 9;
static const int DATA_GAIN_PLOT_RATIO = 5;
static const int MIN_HEIGHT_GAIN_PLOT_1D = 75;
static const int GUI_ZMQ_RCV_HWM = 2;
static void DisplayExceptions(std::string emsg, std::string src) {
try {

View File

@ -3,7 +3,6 @@
#include "ui_form_tab_plot.h"
class qDrawPlot;
class QButtonGroup;
class qTabPlot : public QWidget, private Ui::TabPlotObject {
Q_OBJECT
@ -35,6 +34,8 @@ class qTabPlot : public QWidget, private Ui::TabPlotObject {
void CheckAspectRatio();
void SetZRange();
void SetStreamingFrequency();
void SetStreamingHwm(int value);
void SetReceivingHwm(int value);
signals:
void DisableZoomSignal(bool);
@ -45,6 +46,8 @@ class qTabPlot : public QWidget, private Ui::TabPlotObject {
void Select1DPlot(bool enable);
void GetGapPixels();
void GetStreamingFrequency();
void GetStreamingHwm();
void GetReceivingHwm();
void SetXYRange();
void MaintainAspectRatio(int dimension);
@ -52,8 +55,6 @@ class qTabPlot : public QWidget, private Ui::TabPlotObject {
qDrawPlot *plot;
bool is1d;
QButtonGroup *btnGroupPlotType{nullptr};
/** default plot and axis titles */
static QString defaultPlotTitle;
static QString defaultHistXAxisTitle;

View File

@ -1,8 +1,6 @@
#include "qTabPlot.h"
#include "qDefs.h"
#include "qDrawPlot.h"
#include <QAbstractButton>
#include <QButtonGroup>
#include <QStackedLayout>
#include <QStandardItemModel>
@ -20,14 +18,9 @@ qTabPlot::qTabPlot(QWidget *parent, sls::Detector *detector, qDrawPlot *p)
LOG(logDEBUG) << "Plot ready";
}
qTabPlot::~qTabPlot() { delete btnGroupPlotType; }
qTabPlot::~qTabPlot() {}
void qTabPlot::SetupWidgetWindow() {
// button group for plot type
btnGroupPlotType = new QButtonGroup(this);
btnGroupPlotType->addButton(radioNoPlot, 0);
btnGroupPlotType->addButton(radioDataGraph, 1);
// 1D and 2D options
stackedWidget1D->setCurrentIndex(0);
stackedWidget2D->setCurrentIndex(0);
@ -76,19 +69,18 @@ void qTabPlot::SetupWidgetWindow() {
Initialization();
Refresh();
// set default timer
spinTimeGap->setValue(DEFAULT_STREAMING_TIMER_IN_MS);
// set to streaming timer
stackedTimeInterval->setCurrentIndex(0);
comboFrequency->setCurrentIndex(0);
// set zmq high water mark to GUI_ZMQ_RCV_HWM (2)
spinSndHwm->setValue(qDefs::GUI_ZMQ_RCV_HWM);
spinRcvHwm->setValue(qDefs::GUI_ZMQ_RCV_HWM);
}
void qTabPlot::Initialization() {
// Plot arguments box
connect(btnGroupPlotType, SIGNAL(buttonClicked(int)), this,
SLOT(SetPlot()));
// Plotting frequency box
connect(chkNoPlot, SIGNAL(toggled(bool)), this, SLOT(SetPlot()));
connect(spinSndHwm, SIGNAL(valueChanged(int)), this,
SLOT(SetStreamingHwm(int)));
connect(spinRcvHwm, SIGNAL(valueChanged(int)), this,
SLOT(SetReceivingHwm(int)));
connect(comboFrequency, SIGNAL(currentIndexChanged(int)), this,
SLOT(SetStreamingFrequency()));
connect(comboTimeGapUnit, SIGNAL(currentIndexChanged(int)), this,
@ -214,13 +206,18 @@ void qTabPlot::Select1DPlot(bool enable) {
void qTabPlot::SetPlot() {
bool plotEnable = false;
if (radioNoPlot->isChecked()) {
if (chkNoPlot->isChecked()) {
LOG(logINFO) << "Setting Plot Type: No Plot";
} else if (radioDataGraph->isChecked()) {
} else {
LOG(logINFO) << "Setting Plot Type: Datagraph";
plotEnable = true;
}
boxFrequency->setEnabled(plotEnable);
comboFrequency->setEnabled(plotEnable);
lblSndHwm->setEnabled(plotEnable);
spinSndHwm->setEnabled(plotEnable);
lblRcvHwm->setEnabled(plotEnable);
spinRcvHwm->setEnabled(plotEnable);
stackedTimeInterval->setEnabled(plotEnable);
box1D->setEnabled(plotEnable);
box2D->setEnabled(plotEnable);
boxSave->setEnabled(plotEnable);
@ -705,17 +702,68 @@ void qTabPlot::SetStreamingFrequency() {
&qTabPlot::GetStreamingFrequency)
}
void qTabPlot::GetStreamingHwm() {
LOG(logDEBUG) << "Getting Streaming Hwm for receiver";
disconnect(spinSndHwm, SIGNAL(valueChanged(int)), this,
SLOT(SetStreamingHwm(int)));
try {
int value = det->getRxZmqHwm().tsquash(
"Inconsistent streaming hwm for all receivers.");
LOG(logDEBUG) << "Got streaming hwm for receiver " << value;
spinSndHwm->setValue(value);
}
CATCH_DISPLAY("Could not get streaming hwm for receiver.",
"qTabPlot::GetStreamingHwm")
connect(spinSndHwm, SIGNAL(valueChanged(int)), this,
SLOT(SetStreamingHwm(int)));
}
void qTabPlot::SetStreamingHwm(int value) {
LOG(logINFO) << "Setting Streaming Hwm for receiver to " << value;
try {
det->setRxZmqHwm(value);
}
CATCH_HANDLE("Could not set streaming hwm for receiver.",
"qTabPlot::SetStreamingHwm", this, &qTabPlot::GetStreamingHwm)
}
void qTabPlot::GetReceivingHwm() {
LOG(logDEBUG) << "Getting Receiving Hwm for client";
try {
int value = det->getClientZmqHwm();
LOG(logDEBUG) << "Got receiving hwm for client " << value;
}
CATCH_DISPLAY("Could not get receiving hwm for client.",
"qTabPlot::GetReceivingHwm")
}
void qTabPlot::SetReceivingHwm(int value) {
LOG(logINFO) << "Setting Streaming Hwm to " << value;
try {
det->setClientZmqHwm(value);
}
CATCH_HANDLE("Could not set receiving hwm from client.",
"qTabPlot::SetReceivingHwm", this, &qTabPlot::GetReceivingHwm)
}
void qTabPlot::Refresh() {
LOG(logDEBUG) << "**Updating Plot Tab";
if (!plot->GetIsRunning()) {
boxPlotType->setEnabled(true);
boxFrequency->setEnabled(true);
// streaming frequency
if (!radioNoPlot->isChecked()) {
boxFrequency->setEnabled(true);
if (!chkNoPlot->isChecked()) {
comboFrequency->setEnabled(true);
stackedTimeInterval->setEnabled(true);
lblSndHwm->setEnabled(true);
spinSndHwm->setEnabled(true);
lblRcvHwm->setEnabled(true);
spinRcvHwm->setEnabled(true);
}
GetStreamingFrequency();
GetStreamingHwm();
GetReceivingHwm();
// gain plot, gap pixels enable
switch (det->getDetectorType().squash()) {
case slsDetectorDefs::EIGER:
@ -734,7 +782,6 @@ void qTabPlot::Refresh() {
break;
}
} else {
boxPlotType->setEnabled(false);
boxFrequency->setEnabled(false);
chkGainPlot->setEnabled(false);
chkGainPlot1D->setEnabled(false);

View File

@ -3,7 +3,7 @@
#include "sls_detector_defs.h"
#define MIN_REQRD_VRSN_T_RD_API 0x181130
#define REQRD_FRMWR_VRSN 0x191127
#define REQRD_FRMWR_VRSN 0x201005
#define CTRL_SRVR_INIT_TIME_US (2 * 1000 * 1000)

View File

@ -1766,6 +1766,7 @@ int checkDetectorType() {
char buffer[MAX_STR_LENGTH];
memset(buffer, 0, sizeof(buffer));
fread(buffer, MAX_STR_LENGTH, sizeof(char), fd);
fclose(fd);
if (strlen(buffer) == 0) {
LOG(logERROR,
("Could not read file %s to get type of the module attached\n",

View File

@ -3,7 +3,7 @@
#include "sls_detector_defs.h"
#define MIN_REQRD_VRSN_T_RD_API 0x180314
#define REQRD_FRMWR_VRSN 0x200302
#define REQRD_FRMWR_VRSN 0x201005
#define CTRL_SRVR_INIT_TIME_US (2 * 1000 * 1000)

View File

@ -119,6 +119,9 @@
#define CONFIG_DYNAMIC_RANGE_8_VAL ((0x1 << CONFIG_DYNAMIC_RANGE_OFST) & CONFIG_DYNAMIC_RANGE_MSK)
#define CONFIG_DYNAMIC_RANGE_16_VAL ((0x2 << CONFIG_DYNAMIC_RANGE_OFST) & CONFIG_DYNAMIC_RANGE_MSK)
#define CONFIG_DYNAMIC_RANGE_24_VAL ((0x3 << CONFIG_DYNAMIC_RANGE_OFST) & CONFIG_DYNAMIC_RANGE_MSK)
#define CONFIG_TRIGGER_ENA_OFST (8)
#define CONFIG_TRIGGER_ENA_MSK (0x00000001 << CONFIG_TRIGGER_ENA_OFST)
/* Control RW register */
#define CONTROL_REG (0x21 * REG_OFFSET + BASE_CONTROL)
@ -129,7 +132,7 @@
#define CONTROL_STP_ACQSTN_MSK (0x00000001 << CONTROL_STP_ACQSTN_OFST)
#define CONTROL_STRT_PATTERN_OFST (2)
#define CONTROL_STRT_PATTERN_MSK (0x00000001 << CONTROL_STRT_PATTERN_OFST)
#define CONTROL_STRT_READOUT_OFST (3) // not connected in software yet
#define CONTROL_STRT_READOUT_OFST (3)
#define CONTROL_STRT_READOUT_MSK (0x00000001 << CONTROL_STRT_READOUT_OFST)
#define CONTROL_STRT_SW_TRIGGER_OFST (4)
#define CONTROL_STRT_SW_TRIGGER_MSK (0x00000001 << CONTROL_STRT_SW_TRIGGER_OFST)
@ -148,6 +151,16 @@
#define DTA_OFFSET_REG (0x24 * REG_OFFSET + BASE_CONTROL)
/* Formatting for adif core -----------------------------------------------*/
#define ADIF_CONFIG_REG (0x00 * REG_OFFSET + BASE_ADIF)
#define ADIF_ADDTNL_OFST_OFST (0)
#define ADIF_ADDTNL_OFST_MSK (0x00000003 << ADIF_ADDTNL_OFST_OFST)
#define ADIF_PIPELINE_OFST (4)
#define ADIF_PIPELINE_MSK (0x0000000F << ADIF_PIPELINE_OFST)
/* Formatting for data core -----------------------------------------------*/
#define FMT_CONFIG_REG (0x00 * REG_OFFSET + BASE_FMT)
@ -456,11 +469,11 @@
#define SET_PERIOD_LSB_REG (0x28 * REG_OFFSET + BASE_FLOW_CONTROL)
#define SET_PERIOD_MSB_REG (0x29 * REG_OFFSET + BASE_FLOW_CONTROL)
/* External Signal register */
#define EXT_SIGNAL_REG (0x30 * REG_OFFSET + BASE_FLOW_CONTROL)
/* Flow Trigger register (for all timing modes) */
#define FLOW_TRIGGER_REG (0x30 * REG_OFFSET + BASE_FLOW_CONTROL)
#define EXT_SIGNAL_OFST (0)
#define EXT_SIGNAL_MSK (0x00000001 << EXT_SIGNAL_OFST)
#define FLOW_TRIGGER_OFST (0)
#define FLOW_TRIGGER_MSK (0x00000001 << FLOW_TRIGGER_OFST)
/* Trigger Delay 64 bit register */
#define SET_TRIGGER_DELAY_LSB_REG (0x32 * REG_OFFSET + BASE_FLOW_CONTROL)

View File

@ -50,6 +50,8 @@ uint32_t clkDivider[NUM_CLOCKS] = {};
int highvoltage = 0;
int detPos[2] = {};
int64_t exptimeReg[3] = {0, 0, 0};
int64_t gateDelayReg[3] = {0, 0, 0};
int isInitCheckDone() { return initCheckDone; }
@ -418,6 +420,10 @@ void setupDetector() {
setHighVoltage(DEFAULT_HIGH_VOLTAGE);
setDefaultDacs();
setASICDefaults();
setADIFDefaults();
// set trigger flow for m3 (for all timing modes)
bus_w(FLOW_TRIGGER_REG, bus_r(FLOW_TRIGGER_REG) | FLOW_TRIGGER_MSK);
// dynamic range
setDynamicRange(DEFAULT_DYNAMIC_RANGE);
@ -514,6 +520,17 @@ void setASICDefaults() {
bus_w(ASIC_RDO_CONFIG_REG, val);
}
void setADIFDefaults() {
uint32_t addr = ADIF_CONFIG_REG;
bus_w(addr, ((bus_r(addr) & ~ADIF_ADDTNL_OFST_MSK) & ~ADIF_PIPELINE_MSK));
bus_w(addr,
(bus_r(addr) | ((DEFAULT_ADIF_PIPELINE_VAL << ADIF_PIPELINE_OFST) &
ADIF_PIPELINE_MSK)));
bus_w(addr,
(bus_r(addr) | ((DEFAULT_ADIF_ADD_OFST_VAL << ADIF_ADDTNL_OFST_OFST) &
ADIF_ADDTNL_OFST_MSK)));
}
/* firmware functions (resets) */
void cleanFifos() {
@ -681,7 +698,7 @@ void updateGatePeriod() {
}
}
}
LOG(logINFO, ("\tSetting Gate Period to %lld ns\n", (long long int)max));
LOG(logINFO, ("\tUpdating Gate Period to %lld ns\n", (long long int)max));
max *= (1E-9 * getFrequency(SYSTEM_C0));
set64BitReg(max, ASIC_EXP_GATE_PERIOD_LSB_REG,
ASIC_EXP_GATE_PERIOD_MSB_REG);
@ -714,14 +731,22 @@ int setExpTime(int gateIndex, int64_t val) {
return FAIL;
}
if (val < 0) {
LOG(logERROR, ("Invalid exptime (index:%d): %lld ns\n", gateIndex,
(long long int)val));
LOG(logERROR,
("Invalid exptime%d : %lld ns\n", gateIndex, (long long int)val));
return FAIL;
}
LOG(logINFO, ("Setting exptime %lld ns (index:%d)\n", (long long int)val,
gateIndex));
LOG(logINFO,
("Setting exptime%d to %lld ns\n", gateIndex, (long long int)val));
val *= (1E-9 * getFrequency(SYSTEM_C0));
set64BitReg(val, alsb, amsb);
// set in register only if counter enabled
exptimeReg[gateIndex] = val;
if (getCounterMask() & (1 << gateIndex)) {
set64BitReg(val, alsb, amsb);
} else {
LOG(logWARNING, ("Writing 0 to reg (counter disabled)\n"));
set64BitReg(0, alsb, amsb);
}
// validate for tolerance
int64_t retval = getExpTime(gateIndex);
@ -755,7 +780,15 @@ int64_t getExpTime(int gateIndex) {
LOG(logERROR, ("Invalid gate index: %d\n", gateIndex));
return -1;
}
return get64BitReg(alsb, amsb) / (1E-9 * getFrequency(SYSTEM_C0));
uint64_t retval = 0;
// read from register if counter enabled
if (getCounterMask() & (1 << gateIndex)) {
retval = get64BitReg(alsb, amsb);
} else {
retval = exptimeReg[gateIndex];
}
return retval / (1E-9 * getFrequency(SYSTEM_C0));
}
int setGateDelay(int gateIndex, int64_t val) {
@ -779,14 +812,22 @@ int setGateDelay(int gateIndex, int64_t val) {
return FAIL;
}
if (val < 0) {
LOG(logERROR, ("Invalid gate delay (index:%d): %lld ns\n", gateIndex,
LOG(logERROR, ("Invalid gate delay%d : %lld ns\n", gateIndex,
(long long int)val));
return FAIL;
}
LOG(logINFO, ("Setting gate delay %lld ns (index:%d)\n", (long long int)val,
gateIndex));
LOG(logINFO,
("Setting gate delay%d to %lld ns\n", gateIndex, (long long int)val));
val *= (1E-9 * getFrequency(SYSTEM_C0));
set64BitReg(val, alsb, amsb);
// set in register only if counter enabled
gateDelayReg[gateIndex] = val;
if (getCounterMask() & (1 << gateIndex)) {
set64BitReg(val, alsb, amsb);
} else {
LOG(logWARNING, ("Writing 0 to reg (counter disabled)\n"));
set64BitReg(0, alsb, amsb);
}
// validate for tolerance
int64_t retval = getGateDelay(gateIndex);
@ -820,7 +861,15 @@ int64_t getGateDelay(int gateIndex) {
LOG(logERROR, ("Invalid gate index: %d\n", gateIndex));
return -1;
}
return get64BitReg(alsb, amsb) / (1E-9 * getFrequency(SYSTEM_C0));
uint64_t retval = 0;
// read from register if counter enabled
if (getCounterMask() & (1 << gateIndex)) {
retval = get64BitReg(alsb, amsb);
} else {
retval = gateDelayReg[gateIndex];
}
return retval / (1E-9 * getFrequency(SYSTEM_C0));
}
void setCounterMask(uint32_t arg) {
@ -835,7 +884,13 @@ void setCounterMask(uint32_t arg) {
LOG(logDEBUG, ("Config Reg: 0x%x\n", bus_r(addr)));
updatePacketizing();
updateGatePeriod();
LOG(logINFO, ("\tUpdating Exptime and Gate Delay\n"));
for (int i = 0; i < 3; ++i) {
uint64_t ns = exptimeReg[i] / (1E-9 * getFrequency(SYSTEM_C0));
setExpTime(i, ns);
ns = gateDelayReg[i] / (1E-9 * getFrequency(SYSTEM_C0));
setGateDelay(i, ns);
}
}
uint32_t getCounterMask() {
@ -844,6 +899,7 @@ uint32_t getCounterMask() {
}
void updatePacketizing() {
LOG(logINFO, ("\tUpdating Packetizing\n"));
const int ncounters = __builtin_popcount(getCounterMask());
const int tgEnable = enableTenGigabitEthernet(-1);
int packetsPerFrame = 0;
@ -1025,9 +1081,24 @@ int setTrimbits(int *trimbits) {
LOG(logINFO, ("Trimbits validated\n"));
trimmingPrint = logDEBUG5;
// remember previous run clock
uint32_t prevRunClk = clkDivider[SYSTEM_C0];
// set to trimming clock
if (setClockDivider(SYSTEM_C0, DEFAULT_TRIMMING_RUN_CLKDIV) == FAIL) {
LOG(logERROR,
("Could not start trimming. Could not set to trimming clock\n"));
return FAIL;
}
// trimming
int error = 0;
uint64_t patword = 0;
int iaddr = 0;
for (int ichip = 0; ichip < NCHIP; ichip++) {
if (error != 0) {
break;
}
LOG(logDEBUG1, (" Chip %d\n", ichip));
iaddr = 0;
patword = 0;
@ -1118,8 +1189,8 @@ int setTrimbits(int *trimbits) {
if (iaddr >= MAX_PATTERN_LENGTH) {
LOG(logERROR, ("Addr 0x%x is past max_address_length 0x%x!\n",
iaddr, MAX_PATTERN_LENGTH));
trimmingPrint = logINFO;
return FAIL;
error = 1;
break;
}
// set pattern wait address
@ -1141,12 +1212,25 @@ int setTrimbits(int *trimbits) {
startPattern();
}
// copy trimbits locally
for (int ichan = 0; ichan < ((detectorModules)->nchan); ++ichan) {
detectorChans[ichan] = trimbits[ichan];
if (error == 0) {
// copy trimbits locally
for (int ichan = 0; ichan < ((detectorModules)->nchan); ++ichan) {
detectorChans[ichan] = trimbits[ichan];
}
LOG(logINFO, ("All trimbits have been loaded\n"));
}
trimmingPrint = logINFO;
LOG(logINFO, ("All trimbits have been loaded\n"));
// set back to previous clock
if (setClockDivider(SYSTEM_C0, prevRunClk) == FAIL) {
LOG(logERROR, ("Could not set to previous run clock after trimming\n"));
return FAIL;
}
if (error != 0) {
return FAIL;
}
return OK;
}
@ -1268,29 +1352,30 @@ int setHighVoltage(int val) {
/* parameters - timing */
void setTiming(enum timingMode arg) {
uint32_t addr = CONFIG_REG;
switch (arg) {
case AUTO_TIMING:
LOG(logINFO, ("Set Timing: Auto (Int. Trigger, Int. Gating)\n"));
bus_w(EXT_SIGNAL_REG, bus_r(EXT_SIGNAL_REG) & ~EXT_SIGNAL_MSK);
bus_w(addr, bus_r(addr) & ~CONFIG_TRIGGER_ENA_MSK);
bus_w(ASIC_EXP_STATUS_REG,
bus_r(ASIC_EXP_STATUS_REG) & ~ASIC_EXP_STAT_GATE_SRC_EXT_MSK);
break;
case TRIGGER_EXPOSURE:
LOG(logINFO, ("Set Timing: Trigger (Ext. Trigger, Int. Gating)\n"));
bus_w(EXT_SIGNAL_REG, bus_r(EXT_SIGNAL_REG) | EXT_SIGNAL_MSK);
bus_w(addr, bus_r(addr) | CONFIG_TRIGGER_ENA_MSK);
bus_w(ASIC_EXP_STATUS_REG,
bus_r(ASIC_EXP_STATUS_REG) & ~ASIC_EXP_STAT_GATE_SRC_EXT_MSK);
break;
case GATED:
LOG(logINFO, ("Set Timing: Gating (Int. Trigger, Ext. Gating)\n"));
bus_w(EXT_SIGNAL_REG, bus_r(EXT_SIGNAL_REG) & ~EXT_SIGNAL_MSK);
bus_w(addr, bus_r(addr) & ~CONFIG_TRIGGER_ENA_MSK);
bus_w(ASIC_EXP_STATUS_REG,
bus_r(ASIC_EXP_STATUS_REG) | ASIC_EXP_STAT_GATE_SRC_EXT_MSK);
break;
case TRIGGER_GATED:
LOG(logINFO,
("Set Timing: Trigger_Gating (Ext. Trigger, Ext. Gating)\n"));
bus_w(EXT_SIGNAL_REG, bus_r(EXT_SIGNAL_REG) | EXT_SIGNAL_MSK);
bus_w(addr, bus_r(addr) | CONFIG_TRIGGER_ENA_MSK);
bus_w(ASIC_EXP_STATUS_REG,
bus_r(ASIC_EXP_STATUS_REG) | ASIC_EXP_STAT_GATE_SRC_EXT_MSK);
break;
@ -1301,7 +1386,7 @@ void setTiming(enum timingMode arg) {
}
enum timingMode getTiming() {
uint32_t extTrigger = (bus_r(EXT_SIGNAL_REG) & EXT_SIGNAL_MSK);
uint32_t extTrigger = (bus_r(CONFIG_REG) & CONFIG_TRIGGER_ENA_MSK);
uint32_t extGate =
(bus_r(ASIC_EXP_STATUS_REG) & ASIC_EXP_STAT_GATE_SRC_EXT_MSK);
if (extTrigger) {
@ -1891,6 +1976,7 @@ int checkDetectorType() {
char buffer[MAX_STR_LENGTH];
memset(buffer, 0, sizeof(buffer));
fread(buffer, MAX_STR_LENGTH, sizeof(char), fd);
fclose(fd);
if (strlen(buffer) == 0) {
LOG(logERROR,
("Could not read file %s to get type of the module attached\n",
@ -2322,6 +2408,22 @@ int softwareTrigger() {
return OK;
}
int startReadOut() {
LOG(logINFOBLUE, ("Starting Readout\n"));
#ifdef VIRTUAL
// cannot set #frames and exptiem temporarily to 1 and 0,
// because have to set it back after readout (but this is non blocking)
return startStateMachine();
#endif
cleanFifos();
// start readout
bus_w(CONTROL_REG, bus_r(CONTROL_REG) | CONTROL_STRT_READOUT_MSK);
LOG(logINFO, ("Status Register: %08x\n", bus_r(STATUS_REG)));
return OK;
}
enum runStatus getRunStatus() {
LOG(logDEBUG1, ("Getting status\n"));
// scan error or running

View File

@ -39,14 +39,17 @@
#define DEFAULT_TIMING_MODE (AUTO_TIMING)
#define DEFAULT_READOUT_C0 (10) //(100000000) // rdo_clk, 100 MHz
#define DEFAULT_READOUT_C1 (10) //(100000000) // smp sample clk (x2), 100 MHz
#define DEFAULT_SYSTEM_C0 (20) // (50000000) // run_clk, 50 MHz
#define DEFAULT_SYSTEM_C0 (10) //(100000000) // run_clk, 100 MHz
#define DEFAULT_SYSTEM_C1 (10) //(100000000) // sync_clk, 100 MHz
#define DEFAULT_SYSTEM_C2 (10) //(100000000) // str_clk, 100 MHz
#define DEFAULT_SYSTEM_C3 (5) //(200000000) // smp_clk, 200 MHz
// (DEFAULT_SYSTEM_C3 only for timing receiver) should not be changed
#define DEFAULT_TRIMMING_RUN_CLKDIV (40) // (25000000) // 25 MHz
#define DEFAULT_ASIC_LATCHING_NUM_PULSES (10)
#define DEFAULT_MSTR_OTPT_P1_NUM_PULSES (20)
#define DEFAULT_ADIF_PIPELINE_VAL (8)
#define DEFAULT_ADIF_ADD_OFST_VAL (0)
/* Firmware Definitions */
#define MAX_TIMESLOT_VAL (0xFFFFFF)

View File

@ -40,8 +40,10 @@ int startWritingFPGAprogram(FILE **filefp);
* 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)
*/
void stopWritingFPGAprogram(FILE *filefp);
int stopWritingFPGAprogram(FILE *filefp);
/**
* Write FPGA Program to flash

View File

@ -120,6 +120,7 @@ int setDefaultDacs();
#endif
#ifdef MYTHEN3D
void setASICDefaults();
void setADIFDefaults();
#endif
#if defined(GOTTHARD2D) || defined(EIGERD)
int readConfigFile();
@ -566,8 +567,7 @@ int stopStateMachine();
#if defined(EIGERD) || defined(MYTHEN3D)
int softwareTrigger();
#endif
#ifdef EIGERD
#if defined(EIGERD) || defined(MYTHEN3D)
int startReadOut();
#endif
enum runStatus getRunStatus();

View File

@ -239,4 +239,5 @@ int get_bad_channels(int);
int set_bad_channels(int);
int reconfigure_udp(int);
int validate_udp_configuration(int);
int get_bursts_left(int);
int get_bursts_left(int);
int start_readout(int);

View File

@ -7,7 +7,8 @@
#include <unistd.h> // usleep
/* global variables */
#define MTDSIZE 10
#define MTDSIZE 10
#define MAX_TIME_FPGA_TOUCH_FLASH_US (10 * 1000 * 1000) // 10s
int gpioDefined = 0;
char mtdvalue[MTDSIZE] = {0};
@ -99,32 +100,36 @@ int startWritingFPGAprogram(FILE **filefp) {
return 0;
}
void stopWritingFPGAprogram(FILE *filefp) {
int stopWritingFPGAprogram(FILE *filefp) {
LOG(logDEBUG1, ("Stopping of writing FPGA program\n"));
int wait = 0;
if (filefp != NULL) {
fclose(filefp);
wait = 1;
}
// touch and program
FPGATouchFlash();
if (wait) {
LOG(logDEBUG1, ("Waiting for FPGA to program from flash\n"));
// waiting for success or done
char output[255];
int res = 0;
while (res == 0) {
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, ("Waiting for FPGA to program from flash\n"));
// waiting for success or done
char output[255];
int res = 0;
int timeSpent = 0;
while (res == 0) {
// time taken for fpga to pick up from flash
usleep(1000);
timeSpent += 1000;
if (timeSpent >= MAX_TIME_FPGA_TOUCH_FLASH_US) {
return 1;
}
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) {

View File

@ -2,26 +2,22 @@
#include "clogger.h"
#include <errno.h>
#include <semaphore.h>
#include <pthread.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#define SHM_NAME "sls_server_shared_memory"
#ifdef EIGERD
#define SHM_VERSION 0x200915
#else
#define SHM_VERSION 0x200625
#endif
#define SHM_KEY 5678
#define MEM_SIZE 128
#define SHM_NAME "sls_server_shared_memory"
#define SHM_VERSION 0x201007
#define SHM_KEY 5678
#define MEM_SIZE 128
typedef struct Memory {
int version;
sem_t semStatus;
pthread_mutex_t lockStatus;
#ifdef EIGERD
sem_t semLocalLink;
pthread_mutex_t lockLocalLink;
#endif
enum runStatus scanStatus; // idle, running or error
int scanStop;
@ -87,14 +83,59 @@ int sharedMemory_create(int port) {
int sharedMemory_initialize() {
shm->version = SHM_VERSION;
if (sem_init(&(shm->semStatus), 1, 1) != 0) {
LOG(logERROR, ("Failed to initialize semaphore semStatus for "
// powerpc, Nios and normal pc allows setting mutex attribute to shared
#if defined(EIGERD) || defined(GOTTHARD2D) || defined(MYTHEN3D) || \
defined(VIRTUAL)
pthread_mutexattr_t lockStatusAttribute;
if (pthread_mutexattr_init(&lockStatusAttribute) != 0) {
LOG(logERROR,
("Failed to initialize mutex attribute for lockStatus for "
"shared memory\n"));
return FAIL;
}
if (pthread_mutexattr_setpshared(&lockStatusAttribute,
PTHREAD_PROCESS_SHARED) != 0) {
LOG(logERROR, ("Failed to set attribute property to process shared for "
"lockStatus for shared memory\n"));
return FAIL;
}
if (pthread_mutex_init(&(shm->lockStatus), &lockStatusAttribute) != 0) {
LOG(logERROR, ("Failed to initialize pthread_mutex_t lockStatus for "
"shared memory\n"));
return FAIL;
}
// only blackfins cannot set mutex attribute (but it is shared by default)
#else
if (pthread_mutex_init(&(shm->lockStatus), NULL) != 0) {
LOG(logERROR, ("Failed to initialize pthread_mutex_t lockStatus for "
"shared memory\n"));
return FAIL;
}
#endif
#ifdef EIGERD
if (sem_init(&(shm->semLocalLink), 1, 1) != 0) {
LOG(logERROR, ("Failed to initialize semaphore semLocalLink for "
pthread_mutexattr_t lockLocalLinkAttribute;
if (pthread_mutexattr_init(&lockLocalLinkAttribute) != 0) {
LOG(logERROR,
("Failed to initialize mutex attribute for lockLocalLink for "
"shared memory\n"));
return FAIL;
}
if (pthread_mutexattr_setpshared(&lockLocalLinkAttribute,
PTHREAD_PROCESS_SHARED) != 0) {
LOG(logERROR, ("Failed to set attribute property to process shared for "
"lockLocalLink for shared memory\n"));
return FAIL;
}
if (pthread_mutex_init(&(shm->lockLocalLink), &lockLocalLinkAttribute) !=
0) {
LOG(logERROR, ("Failed to initialize pthread_mutex_t lockLocalLink for "
"shared memory\n"));
return FAIL;
}
@ -155,9 +196,9 @@ int sharedMemory_remove() {
return OK;
}
void sharedMemory_lockStatus() { sem_wait(&(shm->semStatus)); }
void sharedMemory_lockStatus() { pthread_mutex_lock(&(shm->lockStatus)); }
void sharedMemory_unlockStatus() { sem_post(&(shm->semStatus)); }
void sharedMemory_unlockStatus() { pthread_mutex_unlock(&(shm->lockStatus)); }
#ifdef VIRTUAL
void sharedMemory_setStatus(enum runStatus s) {
@ -218,7 +259,9 @@ int sharedMemory_getScanStop() {
}
#ifdef EIGERD
void sharedMemory_lockLocalLink() { sem_wait(&(shm->semLocalLink)); }
void sharedMemory_lockLocalLink() { pthread_mutex_lock(&(shm->lockLocalLink)); }
void sharedMemory_unlockLocalLink() { sem_post(&(shm->semLocalLink)); }
void sharedMemory_unlockLocalLink() {
pthread_mutex_unlock(&(shm->lockLocalLink));
}
#endif

View File

@ -358,6 +358,7 @@ void function_table() {
flist[F_RECONFIGURE_UDP] = &reconfigure_udp;
flist[F_VALIDATE_UDP_CONFIG] = &validate_udp_configuration;
flist[F_GET_BURSTS_LEFT] = &get_bursts_left;
flist[F_START_READOUT] = &start_readout;
// check
if (NUM_DET_FUNCTIONS >= RECEIVER_ENUM_START) {
@ -3719,6 +3720,7 @@ int program_fpga(int file_des) {
}
// writing to flash part by part
int clientSocketCrash = 0;
while (ret != FAIL && filesize) {
unitprogramsize = MAX_FPGAPROGRAMSIZE; // 2mb
@ -3729,42 +3731,61 @@ int program_fpga(int file_des) {
(long long unsigned int)filesize));
// receive part of program
if (receiveData(file_des, fpgasrc, unitprogramsize, OTHER) < 0)
return printSocketReadError();
if (receiveData(file_des, fpgasrc, unitprogramsize, OTHER) < 0) {
printSocketReadError();
clientSocketCrash = 1;
ret = FAIL;
}
// client has not crashed yet, so write to flash and send ret
else {
if (!(unitprogramsize - filesize)) {
fpgasrc[unitprogramsize] = '\0';
filesize -= unitprogramsize;
unitprogramsize++;
} else
filesize -= unitprogramsize;
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) {
LOG(logERROR, ("Failure: Breaking out of program receiving\n"));
} else {
// print progress
LOG(logINFO,
("Writing to Flash:%d%%\r",
(int)(((double)(totalsize - filesize) / totalsize) *
100)));
fflush(stdout);
// 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));
}
}
// closing file pointer to flash and informing FPGA
stopWritingFPGAprogram(fp);
// free resources
free(fpgasrc);
if (fp != NULL)
fclose(fp);
// send final ret (if no client crash)
if (clientSocketCrash == 0) {
Server_SendResult(file_des, INT32, NULL, 0);
}
#endif // end of Blackfin programming
if (ret == FAIL) {
LOG(logERROR, ("Program FPGA FAIL!\n"));
@ -8083,4 +8104,44 @@ int get_bursts_left(int file_des) {
LOG(logDEBUG1, ("retval num bursts left %lld\n", (long long int)retval));
#endif
return Server_SendResult(file_des, INT64, &retval, sizeof(retval));
}
}
int start_readout(int file_des) {
ret = OK;
memset(mess, 0, sizeof(mess));
#ifndef MYTHEN3D
functionNotImplemented();
#else
if (Server_VerifyLock() == OK) {
enum runStatus s = getRunStatus();
if (s == RUNNING || s == WAITING) {
ret = FAIL;
strcpy(mess, "Could not start readout because the detector is "
"already running!\n");
LOG(logERROR, (mess));
} else if (configured == FAIL) {
ret = FAIL;
strcpy(mess, "Could not start readout because ");
strcat(mess, configureMessage);
LOG(logERROR, (mess));
} else {
memset(scanErrMessage, 0, MAX_STR_LENGTH);
sharedMemory_setScanStop(0);
sharedMemory_setScanStatus(IDLE); // if it was error
// start readout
ret = startReadOut();
if (ret == FAIL) {
#ifdef VIRTUAL
sprintf(mess,
"Could not start readout. Could not create udp "
"socket in server. Check udp_dstip & udp_dstport.\n");
#else
sprintf(mess, "Could not start readout\n");
#endif
LOG(logERROR, (mess));
}
}
}
#endif
return Server_SendResult(file_des, INT32, NULL, 0);
}

View File

@ -456,6 +456,11 @@ class Detector {
* WAITING and automatically returns to idle at the end of acquisition. */
void startDetector();
/** [Mythen3] Non blocking: start detector readout of counters in chip.
* Status changes to TRANSMITTING and automatically returns to idle at the
* end of readout. */
void startDetectorReadout();
/** Non blocking: Abort detector acquisition. Status changes to IDLE or
* STOPPED. Goes to stop server. */
void stopDetector();
@ -887,6 +892,26 @@ class Detector {
* if enabled.
*/
void setClientZmqIp(const IpAddr ip, Positions pos = {});
int getClientZmqHwm() const;
/** Client's zmq receive high water mark. \n Default is the zmq library's
* default (1000), can also be set here using -1. \n This is a high number
* and can be set to 2 for gui purposes. \n One must also set the receiver's
* send high water mark to similar value. Final effect is sum of them.
*/
void setClientZmqHwm(const int limit);
Result<int> getRxZmqHwm(Positions pos = {}) const;
/** Receiver's zmq send high water mark. \n Default is the zmq library's
* default (1000) \n This is a high number and can be set to 2 for gui
* purposes. \n One must also set the client's receive high water mark to
* similar value. Final effect is sum of them. Also restarts receiver zmq
* streaming if enabled. \n Can set to -1 to set default.
*/
void setRxZmqHwm(const int limit);
///@{
/** @name Eiger Specific */

View File

@ -486,39 +486,6 @@ std::string CmdProxy::Exptime(int action) {
return os.str();
}
std::string CmdProxy::DynamicRange(int action) {
std::ostringstream os;
os << cmd << ' ';
if (action == defs::HELP_ACTION) {
os << "[value]\n\tDynamic Range or number of bits per "
"pixel in detector.\n\t"
"[Eiger] Options: 4, 8, 16, 32. If set to 32, also sets "
"clkdivider to 2, else to 0.\n\t"
"[Mythen3] Options: 8, 16, 32\n\t"
"[Jungfrau][Gotthard][Ctb][Moench][Mythen3][Gotthard2] 16"
<< '\n';
} else if (action == defs::GET_ACTION) {
if (!args.empty()) {
WrongNumberOfParameters(0);
}
auto t = det->getDynamicRange(std::vector<int>{det_id});
os << OutString(t) << '\n';
} else if (action == defs::PUT_ACTION) {
if (det_id != -1) {
throw sls::RuntimeError(
"Cannot execute dynamic range at module level");
}
if (args.size() != 1) {
WrongNumberOfParameters(1);
}
det->setDynamicRange(StringTo<int>(args[0]));
os << args.front() << '\n';
} else {
throw sls::RuntimeError("Unknown action");
}
return os.str();
}
std::string CmdProxy::Speed(int action) {
std::ostringstream os;
os << cmd << ' ';
@ -1060,12 +1027,12 @@ std::string CmdProxy::Scan(int action) {
std::ostringstream os;
os << cmd << ' ';
if (action == defs::HELP_ACTION) {
os << "[dac_name|0|trimbit_scan] [start_val] [stop_val] "
os << "[dac_name|0|trimbits] [start_val] [stop_val] "
"[step_size] [dac settling time ns|us|ms|s]\n\tEnables/ disables "
"scans for dac and trimbits \n\tEnabling scan sets number of "
"frames to number of steps in receiver. \n\tTo cancel scan "
"configuration, set dac to '0', which also sets number of frames "
"to 1. \n\t[Eiger][Mythen3] Use trimbit_scan as dac name for a "
"to 1. \n\t[Eiger][Mythen3] Use trimbits as dac name for a "
"trimbit scan."
<< '\n';
} else if (action == defs::GET_ACTION) {
@ -1257,7 +1224,40 @@ std::string CmdProxy::ReceiverHostname(int action) {
return os.str();
}
/* File */
/* ZMQ Streaming Parameters (Receiver<->Client) */
std::string CmdProxy::ZMQHWM(int action) {
std::ostringstream os;
os << cmd << ' ';
if (action == defs::HELP_ACTION) {
os << "[n_limit] \n\tClient's zmq receive high water mark. Default is "
"the zmq library's default (1000), can also be set here using "
"-1. \n This is a high number and can be set to 2 for gui "
"purposes. \n One must also set the receiver's send high water "
"mark to similar value. Final effect is sum of them.\n\t Setting "
"it via command line is useful only before zmq enabled (before "
"opening gui)."
<< '\n';
} else if (action == defs::GET_ACTION) {
if (!args.empty()) {
WrongNumberOfParameters(0);
}
auto t = det->getClientZmqHwm();
os << t << '\n';
} else if (action == defs::PUT_ACTION) {
if (args.size() != 1) {
WrongNumberOfParameters(1);
}
int t = StringTo<int>(args[0]);
det->setClientZmqHwm(t);
os << det->getClientZmqHwm() << '\n';
} else {
throw sls::RuntimeError("Unknown action");
}
return os.str();
}
/* Eiger Specific */
std::string CmdProxy::Threshold(int action) {
@ -2681,7 +2681,7 @@ std::string CmdProxy::ExecuteCommand(int action) {
throw sls::RuntimeError("Cannot get.");
} else if (action == defs::PUT_ACTION) {
std::string command;
for (auto &i: args) {
for (auto &i : args) {
command += (i + ' ');
}
auto t = det->executeCommand(command, std::vector<int>{det_id});

View File

@ -235,6 +235,36 @@
return os.str(); \
}
/** int, set no id, get id */
#define INTEGER_COMMAND_SET_NOID_GET_ID(CMDNAME, GETFCN, SETFCN, CONV, HLPSTR) \
std::string CMDNAME(const int action) { \
std::ostringstream os; \
os << cmd << ' '; \
if (action == slsDetectorDefs::HELP_ACTION) \
os << HLPSTR << '\n'; \
else if (action == slsDetectorDefs::GET_ACTION) { \
if (!args.empty()) { \
WrongNumberOfParameters(0); \
} \
auto t = det->GETFCN(std::vector<int>{det_id}); \
os << OutString(t) << '\n'; \
} else if (action == slsDetectorDefs::PUT_ACTION) { \
if (det_id != -1) { \
throw sls::RuntimeError( \
"Cannot execute this at module level"); \
} \
if (args.size() != 1) { \
WrongNumberOfParameters(1); \
} \
auto val = CONV(args[0]); \
det->SETFCN(val); \
os << args.front() << '\n'; \
} else { \
throw sls::RuntimeError("Unknown action"); \
} \
return os.str(); \
}
/** int, no id */
#define INTEGER_COMMAND_NOID(CMDNAME, GETFCN, SETFCN, CONV, HLPSTR) \
std::string CMDNAME(const int action) { \
@ -754,7 +784,7 @@ class CmdProxy {
{"triggersl", &CmdProxy::triggersl},
{"delayl", &CmdProxy::delayl},
{"periodl", &CmdProxy::periodl},
{"dr", &CmdProxy::DynamicRange},
{"dr", &CmdProxy::dr},
{"drlist", &CmdProxy::drlist},
{"timing", &CmdProxy::timing},
{"timinglist", &CmdProxy::timinglist},
@ -805,6 +835,7 @@ class CmdProxy {
{"rx_start", &CmdProxy::rx_start},
{"rx_stop", &CmdProxy::rx_stop},
{"start", &CmdProxy::start},
{"readout", &CmdProxy::readout},
{"stop", &CmdProxy::stop},
{"rx_status", &CmdProxy::ReceiverStatus},
{"status", &CmdProxy::DetectorStatus},
@ -868,6 +899,8 @@ class CmdProxy {
{"zmqport", &CmdProxy::zmqport},
{"rx_zmqip", &CmdProxy::rx_zmqip},
{"zmqip", &CmdProxy::zmqip},
{"zmqhwm", &CmdProxy::ZMQHWM},
{"rx_zmqhwm", &CmdProxy::rx_zmqhwm},
/* Eiger Specific */
{"subexptime", &CmdProxy::subexptime},
@ -1071,6 +1104,7 @@ class CmdProxy {
std::string ReceiverHostname(int action);
/* File */
/* ZMQ Streaming Parameters (Receiver<->Client) */
std::string ZMQHWM(int action);
/* Eiger Specific */
std::string Threshold(int action);
std::string ThresholdNoTb(int action);
@ -1186,17 +1220,17 @@ class CmdProxy {
/* acquisition parameters */
INTEGER_COMMAND_NOID(
INTEGER_COMMAND_SET_NOID_GET_ID(
frames, getNumberOfFrames, setNumberOfFrames, StringTo<int64_t>,
"[n_frames]\n\tNumber of frames per acquisition. In "
"trigger mode, number of frames per trigger. \n\tCannot be set in "
"modular level. \n\tIn scan mode, number of frames is set to number of "
"steps.\n\t[Gotthard2] Burst mode has a maximum of 2720 frames.");
INTEGER_COMMAND_NOID(triggers, getNumberOfTriggers, setNumberOfTriggers,
StringTo<int64_t>,
"[n_triggers]\n\tNumber of triggers per aquire. Set "
"timing mode to use triggers.");
INTEGER_COMMAND_SET_NOID_GET_ID(
triggers, getNumberOfTriggers, setNumberOfTriggers, StringTo<int64_t>,
"[n_triggers]\n\tNumber of triggers per aquire. Set "
"timing mode to use triggers.");
TIME_COMMAND(
period, getPeriod, setPeriod,
@ -1227,6 +1261,15 @@ class CmdProxy {
" Period left for current frame."
"\n\t[Gotthard2] only in continuous mode.");
INTEGER_COMMAND_SET_NOID_GET_ID(
dr, getDynamicRange, setDynamicRange, StringTo<int>,
"[value]\n\tDynamic Range or number of bits per "
"pixel in detector.\n\t"
"[Eiger] Options: 4, 8, 16, 32. If set to 32, also sets "
"clkdivider to 2, else to 0.\n\t"
"[Mythen3] Options: 8, 16, 32\n\t"
"[Jungfrau][Gotthard][Ctb][Moench][Mythen3][Gotthard2] 16");
GET_COMMAND_NOID(drlist, getDynamicRangeList,
"\n\tGets the list of dynamic ranges for this detector.");
@ -1387,7 +1430,14 @@ class CmdProxy {
EXECUTE_SET_COMMAND_NOID(
start, startDetector,
"\n\tStarts detector acquisition. Status changes to RUNNING or WAITING "
"and automatically returns to idle at the end of acquisition.");
"and automatically returns to idle at the end of acquisition. If the "
"acquisition was abruptly stopped, some detectors come back to "
"STOPPED.");
EXECUTE_SET_COMMAND_NOID(
readout, startDetectorReadout,
"\n\t[Mythen3] Starts detector readout. Status changes to TRANSMITTING "
"and automatically returns to idle at the end of readout.");
EXECUTE_SET_COMMAND_NOID(stop, stopDetector,
"\n\tAbort detector acquisition. Status changes "
@ -1444,7 +1494,8 @@ class CmdProxy {
udp_srcip2, getSourceUDPIP2, setSourceUDPIP2, IpAddr,
"[x.x.x.x]\n\t[Jungfrau][Gotthard2] Ip address of the detector "
"(source) udp interface 2. Must be same subnet as destination udp "
"ip2.\n\t [Jungfrau] bottom half \n\t [Gotthard2] veto debugging.");
"ip2.\n\t [Jungfrau] top half or inner interface\n\t [Gotthard2] veto "
"debugging.");
INTEGER_COMMAND_VEC_ID(
udp_srcmac, getSourceUDPMAC, setSourceUDPMAC, MacAddr,
@ -1452,10 +1503,10 @@ class CmdProxy {
"interface. \n\t[Eiger] Do not set as detector will replace with its "
"own DHCP Mac (1G) or DHCP Mac + 1 (10G).");
INTEGER_COMMAND_VEC_ID(
udp_srcmac2, getSourceUDPMAC2, setSourceUDPMAC2, MacAddr,
"[x:x:x:x:x:x]\n\t[Jungfrau] Mac address of the bottom "
"half of detector (source) udp interface. ");
INTEGER_COMMAND_VEC_ID(udp_srcmac2, getSourceUDPMAC2, setSourceUDPMAC2,
MacAddr,
"[x:x:x:x:x:x]\n\t[Jungfrau] Mac address of the top "
"half or inner (source) udp interface. ");
INTEGER_COMMAND_VEC_ID(
udp_dstmac, getDestinationUDPMAC, setDestinationUDPMAC, MacAddr,
@ -1469,7 +1520,8 @@ class CmdProxy {
"[x:x:x:x:x:x]\n\t[Jungfrau] Mac address of the receiver (destination) "
"udp interface 2. Not mandatory to set as udp_dstip2 retrieves it from "
"slsReceiver process but must be set if you use a custom receiver (not "
"slsReceiver). \n\t [Jungfrau] bottom half \n\t [Gotthard2] veto "
"slsReceiver). \n\t [Jungfrau] top half or inner interface \n\t "
"[Gotthard2] veto "
"debugging.");
INTEGER_COMMAND_VEC_ID_GET(
@ -1485,7 +1537,8 @@ class CmdProxy {
"[n]\n\t[Jungfrau][Eiger][Gotthard2] Port number of the "
"receiver (destination) udp interface 2. Default is 50002. "
"\n\tIf multi command, ports for each module is calculated "
"(incremented by 2) \n\t[Jungfrau] bottom half \n\t[Eiger] "
"(incremented by 2) \n\t[Jungfrau] top half or inner interface "
"\n\t[Eiger] "
"right half \n\t[Gotthard2] veto debugging");
EXECUTE_SET_COMMAND(
@ -1692,6 +1745,15 @@ class CmdProxy {
"an intermediate process between receiver and client(gui). Also "
"restarts client zmq streaming if enabled.");
INTEGER_COMMAND_SET_NOID_GET_ID(
rx_zmqhwm, getRxZmqHwm, setRxZmqHwm, StringTo<int>,
"[n_value]\n\tReceiver's zmq send high water mark. Default is the zmq "
"library's default (1000). This is a high number and can be set to 2 "
"for gui purposes. One must also set the client's receive high water "
"mark to similar value. Final effect is sum of them. Also restarts "
"receiver zmq streaming if enabled. Can set to -1 to set default "
"value.");
/* Eiger Specific */
TIME_COMMAND(subexptime, getSubExptime, setSubExptime,
@ -1778,7 +1840,7 @@ class CmdProxy {
"0 or this mode disabled(comparator enabled throughout). 1 enables "
"mode. 0 disables mode. ");
INTEGER_COMMAND_NOID(
INTEGER_COMMAND_SET_NOID_GET_ID(
storagecells, getNumberOfAdditionalStorageCells,
setNumberOfAdditionalStorageCells, StringTo<int>,
"[0-15]\n\t[Jungfrau] Number of additional storage cells. Default is "
@ -1803,7 +1865,7 @@ class CmdProxy {
"left for current frame. ");
/* Gotthard2 Specific */
INTEGER_COMMAND_NOID(
INTEGER_COMMAND_SET_NOID_GET_ID(
bursts, getNumberOfBursts, setNumberOfBursts, StringTo<int64_t>,
"[n_bursts]\n\t[Gotthard2] Number of bursts per aquire. Only in auto "
"timing mode and burst mode. Use timing command to set timing mode and "

View File

@ -593,6 +593,10 @@ void Detector::startDetector() {
pimpl->Parallel(&Module::startAcquisition, {});
}
void Detector::startDetectorReadout() {
pimpl->Parallel(&Module::startReadout, {});
}
void Detector::stopDetector() { pimpl->Parallel(&Module::stopAcquisition, {}); }
Result<defs::runStatus> Detector::getDetectorStatus(Positions pos) const {
@ -643,7 +647,7 @@ Result<int> Detector::getNumberofUDPInterfaces(Positions pos) const {
}
void Detector::setNumberofUDPInterfaces(int n, Positions pos) {
int previouslyClientStreaming = pimpl->getDataStreamingToClient();
bool previouslyClientStreaming = pimpl->getDataStreamingToClient();
bool useReceiver = getUseReceiverFlag().squash(false);
bool previouslyReceiverStreaming = false;
if (useReceiver) {
@ -656,7 +660,7 @@ void Detector::setNumberofUDPInterfaces(int n, Positions pos) {
setRxZmqPort(startingPort, -1);
}
// redo the zmq sockets if enabled
if (previouslyClientStreaming != 0) {
if (previouslyClientStreaming) {
pimpl->setDataStreamingToClient(false);
pimpl->setDataStreamingToClient(true);
}
@ -1042,6 +1046,8 @@ Result<int> Detector::getRxZmqPort(Positions pos) const {
}
void Detector::setRxZmqPort(int port, int module_id) {
bool previouslyReceiverStreaming =
getRxZmqDataStream(std::vector<int>{module_id}).squash(false);
if (module_id == -1) {
std::vector<int> port_list = getPortNumbers(port);
for (int idet = 0; idet < size(); ++idet) {
@ -1051,6 +1057,10 @@ void Detector::setRxZmqPort(int port, int module_id) {
} else {
pimpl->Parallel(&Module::setReceiverStreamingPort, {module_id}, port);
}
if (previouslyReceiverStreaming) {
setRxZmqDataStream(false, std::vector<int>{module_id});
setRxZmqDataStream(true, std::vector<int>{module_id});
}
}
Result<IpAddr> Detector::getRxZmqIP(Positions pos) const {
@ -1071,6 +1081,7 @@ Result<int> Detector::getClientZmqPort(Positions pos) const {
}
void Detector::setClientZmqPort(int port, int module_id) {
bool previouslyClientStreaming = pimpl->getDataStreamingToClient();
if (module_id == -1) {
std::vector<int> port_list = getPortNumbers(port);
for (int idet = 0; idet < size(); ++idet) {
@ -1080,6 +1091,10 @@ void Detector::setClientZmqPort(int port, int module_id) {
} else {
pimpl->Parallel(&Module::setClientStreamingPort, {module_id}, port);
}
if (previouslyClientStreaming) {
pimpl->setDataStreamingToClient(false);
pimpl->setDataStreamingToClient(true);
}
}
Result<IpAddr> Detector::getClientZmqIp(Positions pos) const {
@ -1087,14 +1102,33 @@ Result<IpAddr> Detector::getClientZmqIp(Positions pos) const {
}
void Detector::setClientZmqIp(const IpAddr ip, Positions pos) {
int previouslyClientStreaming = pimpl->getDataStreamingToClient();
bool previouslyClientStreaming = pimpl->getDataStreamingToClient();
pimpl->Parallel(&Module::setClientStreamingIP, pos, ip);
if (previouslyClientStreaming != 0) {
if (previouslyClientStreaming) {
pimpl->setDataStreamingToClient(false);
pimpl->setDataStreamingToClient(true);
}
}
int Detector::getClientZmqHwm() const { return pimpl->getClientStreamingHwm(); }
void Detector::setClientZmqHwm(const int limit) {
pimpl->setClientStreamingHwm(limit);
}
Result<int> Detector::getRxZmqHwm(Positions pos) const {
return pimpl->Parallel(&Module::getReceiverStreamingHwm, pos);
}
void Detector::setRxZmqHwm(const int limit) {
bool previouslyReceiverStreaming = getRxZmqDataStream().squash(false);
pimpl->Parallel(&Module::setReceiverStreamingHwm, {}, limit);
if (previouslyReceiverStreaming) {
setRxZmqDataStream(false, {});
setRxZmqDataStream(true, {});
}
}
// Eiger Specific
Result<ns> Detector::getSubExptime(Positions pos) const {

View File

@ -158,6 +158,8 @@ void DetectorImpl::initializeDetectorStructure() {
multi_shm()->acquiringFlag = false;
multi_shm()->initialChecks = true;
multi_shm()->gapPixels = false;
// zmqlib default
multi_shm()->zmqHwm = -1;
}
void DetectorImpl::initializeMembers(bool verify) {
@ -377,16 +379,17 @@ void DetectorImpl::setGapPixelsinCallback(const bool enable) {
multi_shm()->gapPixels = enable;
}
int DetectorImpl::createReceivingDataSockets(const bool destroy) {
if (destroy) {
LOG(logINFO) << "Going to destroy data sockets";
// close socket
zmqSocket.clear();
int DetectorImpl::destroyReceivingDataSockets() {
LOG(logINFO) << "Going to destroy data sockets";
// close socket
zmqSocket.clear();
client_downstream = false;
LOG(logINFO) << "Destroyed Receiving Data Socket(s)";
return OK;
}
client_downstream = false;
LOG(logINFO) << "Destroyed Receiving Data Socket(s)";
return OK;
}
int DetectorImpl::createReceivingDataSockets() {
if (client_downstream) {
return OK;
}
@ -417,11 +420,21 @@ int DetectorImpl::createReceivingDataSockets(const bool destroy) {
.str()
.c_str(),
portnum));
// set high water mark
int hwm = multi_shm()->zmqHwm;
if (hwm >= 0) {
zmqSocket[iSocket]->SetReceiveHighWaterMark(hwm);
if (zmqSocket[iSocket]->GetReceiveHighWaterMark() != hwm) {
throw sls::ZmqSocketError("Could not set zmq rcv hwm to " +
std::to_string(hwm));
}
}
LOG(logINFO) << "Zmq Client[" << iSocket << "] at "
<< zmqSocket.back()->GetZmqServerAddress();
<< zmqSocket.back()->GetZmqServerAddress() << "[hwm: "
<< zmqSocket.back()->GetReceiveHighWaterMark() << "]";
} catch (...) {
LOG(logERROR) << "Could not create Zmq socket on port " << portnum;
createReceivingDataSockets(true);
destroyReceivingDataSockets();
return FAIL;
}
}
@ -449,12 +462,12 @@ void DetectorImpl::readFrameFromReceiver() {
}
std::vector<bool> runningList(zmqSocket.size());
std::vector<bool> connectList(zmqSocket.size());
int numRunning = 0;
numZmqRunning = 0;
for (size_t i = 0; i < zmqSocket.size(); ++i) {
if (zmqSocket[i]->Connect() == 0) {
connectList[i] = true;
runningList[i] = true;
++numRunning;
++numZmqRunning;
} else {
// to remember the list it connected to, to disconnect later
connectList[i] = false;
@ -480,14 +493,14 @@ void DetectorImpl::readFrameFromReceiver() {
uint32_t currentSubFrameIndex = -1, coordX = -1, coordY = -1,
flippedDataX = -1;
while (numRunning != 0) {
while (numZmqRunning != 0) {
// reset data
data = false;
if (multiframe != nullptr) {
memset(multiframe.get(), 0xFF, multisize);
}
completeImage = (numRunning == (int)zmqSocket.size());
completeImage = (numZmqRunning == (int)zmqSocket.size());
// get each frame
for (unsigned int isocket = 0; isocket < zmqSocket.size(); ++isocket) {
@ -505,7 +518,7 @@ void DetectorImpl::readFrameFromReceiver() {
// socket
runningList[isocket] = false;
completeImage = false;
--numRunning;
--numZmqRunning;
continue;
}
@ -627,24 +640,26 @@ void DetectorImpl::readFrameFromReceiver() {
if (data) {
char *callbackImage = multiframe.get();
int imagesize = multisize;
int nDetActualPixelsX = nDetPixelsX;
int nDetActualPixelsY = nDetPixelsY;
if (gapPixels) {
int n = InsertGapPixels(multiframe.get(), multigappixels,
quadEnable, dynamicRange, nDetPixelsX,
nDetPixelsY);
quadEnable, dynamicRange,
nDetActualPixelsX, nDetActualPixelsY);
callbackImage = multigappixels;
imagesize = n;
}
LOG(logDEBUG) << "Image Info:"
<< "\n\tnDetPixelsX: " << nDetPixelsX
<< "\n\tnDetPixelsY: " << nDetPixelsY
<< "\n\tnDetActualPixelsX: " << nDetActualPixelsX
<< "\n\tnDetActualPixelsY: " << nDetActualPixelsY
<< "\n\timagesize: " << imagesize
<< "\n\tdynamicRange: " << dynamicRange;
thisData =
new detectorData(currentProgress, currentFileName, nDetPixelsX,
nDetPixelsY, callbackImage, imagesize,
dynamicRange, currentFileIndex, completeImage);
thisData = new detectorData(currentProgress, currentFileName,
nDetActualPixelsX, nDetActualPixelsY,
callbackImage, imagesize, dynamicRange,
currentFileIndex, completeImage);
dataReady(
thisData, currentFrameIndex,
@ -967,7 +982,7 @@ bool DetectorImpl::getDataStreamingToClient() { return client_downstream; }
void DetectorImpl::setDataStreamingToClient(bool enable) {
// destroy data threads
if (!enable) {
createReceivingDataSockets(true);
destroyReceivingDataSockets();
// create data threads
} else {
if (createReceivingDataSockets() == FAIL) {
@ -976,6 +991,51 @@ void DetectorImpl::setDataStreamingToClient(bool enable) {
}
}
int DetectorImpl::getClientStreamingHwm() const {
// disabled
if (!client_downstream) {
return multi_shm()->zmqHwm;
}
// enabled
sls::Result<int> result;
result.reserve(zmqSocket.size());
for (auto &it : zmqSocket) {
result.push_back(it->GetReceiveHighWaterMark());
}
int res = result.tsquash("Inconsistent zmq receive hwm values");
return res;
}
void DetectorImpl::setClientStreamingHwm(const int limit) {
if (limit < -1) {
throw sls::RuntimeError(
"Cannot set hwm to less than -1 (-1 is lib default).");
}
// update shm
multi_shm()->zmqHwm = limit;
// streaming enabled
if (client_downstream) {
// custom limit, set it directly
if (limit >= 0) {
for (auto &it : zmqSocket) {
it->SetReceiveHighWaterMark(limit);
if (it->GetReceiveHighWaterMark() != limit) {
multi_shm()->zmqHwm = -1;
throw sls::ZmqSocketError("Could not set zmq rcv hwm to " +
std::to_string(limit));
}
}
LOG(logINFO) << "Setting Client Zmq socket rcv hwm to " << limit;
}
// default, disable and enable to get default
else {
setDataStreamingToClient(false);
setDataStreamingToClient(true);
}
}
}
void DetectorImpl::registerAcquisitionFinishedCallback(void (*func)(double, int,
void *),
void *pArg) {
@ -1042,6 +1102,12 @@ int DetectorImpl::acquire() {
if (dataReady == nullptr) {
setJoinThreadFlag(true);
}
if (receiver) {
while (numZmqRunning != 0) {
Parallel(&Module::restreamStopFromReceiver, {});
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
}
dataProcessingThread.join();
if (acquisition_finished != nullptr) {

View File

@ -16,7 +16,7 @@ class detectorData;
#include <vector>
#define MULTI_SHMAPIVERSION 0x190809
#define MULTI_SHMVERSION 0x200319
#define MULTI_SHMVERSION 0x201007
#define SHORT_STRING_LENGTH 50
#include <future>
@ -62,6 +62,8 @@ struct sharedMultiSlsDetector {
bool acquiringFlag;
bool initialChecks;
bool gapPixels;
/** high water mark of listening tcp port (only data) */
int zmqHwm;
};
class DetectorImpl : public virtual slsDetectorDefs {
@ -240,6 +242,8 @@ class DetectorImpl : public virtual slsDetectorDefs {
bool getDataStreamingToClient();
void setDataStreamingToClient(bool enable);
int getClientStreamingHwm() const;
void setClientStreamingHwm(const int limit);
/**
* register callback for accessing acquisition final data
@ -324,12 +328,8 @@ class DetectorImpl : public virtual slsDetectorDefs {
void updateDetectorSize();
/**
* Create Receiving Data Sockets
* @param destroy is true to destroy all the sockets
* @returns OK or FAIL
*/
int createReceivingDataSockets(const bool destroy = false);
int destroyReceivingDataSockets();
int createReceivingDataSockets();
/**
* Reads frames from receiver through a constant socket
@ -387,6 +387,9 @@ class DetectorImpl : public virtual slsDetectorDefs {
/** ZMQ Socket - Receiver to Client */
std::vector<std::unique_ptr<ZmqSocket>> zmqSocket;
/** number of zmq sockets running currently */
volatile int numZmqRunning{0};
/** mutex to synchronize main and data processing threads */
mutable std::mutex mp;

View File

@ -407,6 +407,11 @@ void Module::startAcquisition() {
sendToDetector(F_START_ACQUISITION);
}
void Module::startReadout() {
shm()->stoppedFlag = false;
sendToDetector(F_START_READOUT);
}
void Module::stopAcquisition() {
// get status before stopping acquisition
runStatus s = ERROR, r = ERROR;
@ -431,6 +436,10 @@ void Module::stopAcquisition() {
}
}
void Module::restreamStopFromReceiver() {
sendToReceiver(F_RESTREAM_STOP_FROM_RECEIVER);
}
void Module::startAndReadAll() {
shm()->stoppedFlag = false;
sendToDetector(F_START_AND_READ_ALL);
@ -1041,6 +1050,14 @@ void Module::setClientStreamingIP(const sls::IpAddr ip) {
shm()->zmqip = ip;
}
int Module::getReceiverStreamingHwm() const {
return sendToReceiver<int>(F_GET_RECEIVER_STREAMING_HWM);
}
void Module::setReceiverStreamingHwm(const int limit) {
sendToReceiver(F_SET_RECEIVER_STREAMING_HWM, limit, nullptr);
}
// Eiger Specific
int64_t Module::getSubExptime() const {
@ -2781,10 +2798,6 @@ void Module::checkReceiverVersionCompatibility() {
sendToReceiver(F_RECEIVER_CHECK_VERSION, int64_t(APIRECEIVER), nullptr);
}
void Module::restreamStopFromReceiver() {
sendToReceiver(F_RESTREAM_STOP_FROM_RECEIVER);
}
int Module::sendModule(sls_detector_module *myMod, sls::ClientSocket &client) {
constexpr TLogLevel level = logDEBUG1;
LOG(level) << "Sending Module";
@ -3158,6 +3171,15 @@ void Module::programFPGAviaBlackfin(std::vector<char> buffer) {
std::cout << std::flush;
}
std::cout << '\n';
// fpga has picked up from flash successfully
if (client.Receive<int>() == FAIL) {
std::ostringstream os;
os << "Detector " << moduleId << " (" << shm()->hostname << ")"
<< " returned error: " << client.readErrorMessage();
throw RuntimeError(os.str());
}
LOG(logINFO) << "FPGA programmed successfully";
rebootController();
}

View File

@ -160,7 +160,9 @@ class Module : public virtual slsDetectorDefs {
void startReceiver();
void stopReceiver();
void startAcquisition();
void startReadout();
void stopAcquisition();
void restreamStopFromReceiver();
void startAndReadAll();
runStatus getRunStatus() const;
runStatus getReceiverStatus() const;
@ -290,6 +292,8 @@ class Module : public virtual slsDetectorDefs {
void setClientStreamingPort(int port);
sls::IpAddr getClientStreamingIP() const;
void setClientStreamingIP(const sls::IpAddr ip);
int getReceiverStreamingHwm() const;
void setReceiverStreamingHwm(const int limit);
/**************************************************
* *
@ -665,7 +669,6 @@ class Module : public virtual slsDetectorDefs {
void checkDetectorVersionCompatibility();
void checkReceiverVersionCompatibility();
void restreamStopFromReceiver();
void setModule(sls_detector_module &module, bool trimbits = true);
int sendModule(sls_detector_module *myMod, sls::ClientSocket &client);
void updateReceiverStreamingIP();

View File

@ -110,23 +110,23 @@ TEST_CASE("adcvpp", "[.cmd][.new]") {
{
std::ostringstream oss;
proxy.Call("adcvpp", {"1"}, -1, PUT, oss);
REQUIRE(oss.str() == "adcvpp 1\n");
REQUIRE(oss.str() == "dac adcvpp 1\n");
}
{
std::ostringstream oss;
proxy.Call("adcvpp", {"1140", "mv"}, -1, PUT, oss);
REQUIRE(oss.str() == "adcvpp 1140 mv\n");
REQUIRE(oss.str() == "dac adcvpp 1140 mV\n");
}
{
std::ostringstream oss;
proxy.Call("adcvpp", {"mv"}, -1, GET, oss);
REQUIRE(oss.str() == "adcvpp 1140 mv\n");
REQUIRE(oss.str() == "dac adcvpp 1140 mV\n");
}
for (int i = 0; i != det.size(); ++i) {
det.setDAC(defs::ADC_VPP, prev_val[i], false, {i});
}
} else {
REQUIRE_THROWS(proxy.Call("adcvpp", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("dac adcvpp", {}, -1, GET));
}
}
@ -777,7 +777,7 @@ TEST_CASE("adc", "[.cmd][.new]") {
CmdProxy proxy(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::CHIPTESTBOARD) {
for (int i = 0; i <= 8; ++i) {
for (int i = 0; i <= 7; ++i) {
REQUIRE_NOTHROW(proxy.Call("adc", {std::to_string(i)}, -1, GET));
REQUIRE_THROWS(proxy.Call("adc", {"0"}, -1, PUT));
}

View File

@ -160,12 +160,12 @@ TEST_CASE("Setting and reading back EIGER dacs", "[.cmd][.dacs][.new]") {
{
std::ostringstream oss;
proxy.Call("vthreshold", {"1234"}, -1, PUT, oss);
REQUIRE(oss.str() == "vthreshold 1234\n");
REQUIRE(oss.str() == "dac vthreshold 1234\n");
}
{
std::ostringstream oss;
proxy.Call("vthreshold", {}, -1, GET, oss);
REQUIRE(oss.str() == "vthreshold 1234\n");
REQUIRE(oss.str() == "dac vthreshold 1234\n");
}
// Reset dacs after test
@ -231,44 +231,6 @@ TEST_CASE("Setting and reading back EIGER dacs", "[.cmd][.dacs][.new]") {
/* acquisition */
TEST_CASE("trigger", "[.cmd][.new]") {
Detector det;
CmdProxy proxy(&det);
REQUIRE_THROWS(proxy.Call("trigger", {}, -1, GET));
auto det_type = det.getDetectorType().squash();
if (det_type != defs::EIGER) {
REQUIRE_THROWS(proxy.Call("trigger", {}, -1, PUT));
} else {
auto prev_timing =
det.getTimingMode().tsquash("inconsistent timing mode in test");
auto prev_frames =
det.getNumberOfFrames().tsquash("inconsistent #frames in test");
auto prev_exptime =
det.getExptime().tsquash("inconsistent exptime in test");
auto prev_period =
det.getPeriod().tsquash("inconsistent period in test");
det.setTimingMode(defs::TRIGGER_EXPOSURE);
det.setNumberOfFrames(1);
det.setExptime(std::chrono::milliseconds(1));
det.setPeriod(std::chrono::milliseconds(1));
auto startingfnum = det.getStartingFrameNumber().tsquash(
"inconsistent frame nr in test");
det.startDetector();
{
std::ostringstream oss;
proxy.Call("trigger", {}, -1, PUT, oss);
REQUIRE(oss.str() == "trigger successful\n");
}
std::this_thread::sleep_for(std::chrono::seconds(2));
auto currentfnum = det.getStartingFrameNumber().tsquash(
"inconsistent frame nr in test");
REQUIRE(startingfnum + 1 == currentfnum);
det.stopDetector();
det.setTimingMode(prev_timing);
det.setNumberOfFrames(prev_frames);
}
}
/* Network Configuration (Detector<->Receiver) */
TEST_CASE("txndelay_left", "[.cmd][.new]") {
@ -431,36 +393,6 @@ TEST_CASE("settingspath", "[.cmd][.new]") {
}
}
TEST_CASE("parallel", "[.cmd][.new]") {
Detector det;
CmdProxy proxy(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
auto prev_val = det.getParallelMode();
{
std::ostringstream oss;
proxy.Call("parallel", {"1"}, -1, PUT, oss);
REQUIRE(oss.str() == "parallel 1\n");
}
{
std::ostringstream oss;
proxy.Call("parallel", {"0"}, -1, PUT, oss);
REQUIRE(oss.str() == "parallel 0\n");
}
{
std::ostringstream oss;
proxy.Call("parallel", {}, -1, GET, oss);
REQUIRE(oss.str() == "parallel 0\n");
}
for (int i = 0; i != det.size(); ++i) {
det.setParallelMode(prev_val[i], {i});
}
} else {
REQUIRE_THROWS(proxy.Call("parallel", {}, -1, GET));
}
}
TEST_CASE("overflow", "[.cmd][.new]") {
Detector det;
CmdProxy proxy(&det);

View File

@ -28,9 +28,9 @@ void test_dac(defs::dacIndex index, const std::string &dacname, int dacvalue) {
// other detectors
else {
proxy.Call(dacname, {dacstr}, -1, PUT, oss_set);
REQUIRE(oss_set.str() == dacname + " " + dacstr + "\n");
REQUIRE(oss_set.str() == "dac " + dacname + " " + dacstr + "\n");
proxy.Call(dacname, {}, -1, GET, oss_get);
REQUIRE(oss_get.str() == dacname + " " + dacstr + "\n");
REQUIRE(oss_get.str() == "dac " + dacname + " " + dacstr + "\n");
}
// Reset all dacs to previous value
for (int i = 0; i != det.size(); ++i) {

View File

@ -106,121 +106,3 @@ TEST_CASE("Setting and reading back MOENCH dacs", "[.cmd][.dacs][.new]") {
REQUIRE_THROWS(proxy.Call("vcom_adc2", {}, -1, GET));
}
}
/* Moench */
TEST_CASE("emin", "[.cmd][.new]") {
Detector det;
CmdProxy proxy(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::MOENCH) {
{
std::ostringstream oss;
proxy.Call("emin", {"100"}, -1, PUT, oss);
REQUIRE(oss.str() == "emin 100\n");
}
{
std::ostringstream oss;
proxy.Call("emin", {"200"}, -1, PUT, oss);
REQUIRE(oss.str() == "emin 200\n");
}
{
std::ostringstream oss;
proxy.Call("emin", {}, -1, GET, oss);
REQUIRE(oss.str() == "emin 200\n");
}
} else {
REQUIRE_THROWS(proxy.Call("emin", {}, -1, GET));
}
}
TEST_CASE("emax", "[.cmd][.new]") {
Detector det;
CmdProxy proxy(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::MOENCH) {
{
std::ostringstream oss;
proxy.Call("emax", {"100"}, -1, PUT, oss);
REQUIRE(oss.str() == "emax 100\n");
}
{
std::ostringstream oss;
proxy.Call("emax", {"200"}, -1, PUT, oss);
REQUIRE(oss.str() == "emax 200\n");
}
{
std::ostringstream oss;
proxy.Call("emax", {}, -1, GET, oss);
REQUIRE(oss.str() == "emax 200\n");
}
} else {
REQUIRE_THROWS(proxy.Call("emax", {}, -1, GET));
}
}
TEST_CASE("framemode", "[.cmd][.new]") {
Detector det;
CmdProxy proxy(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::MOENCH) {
{
std::ostringstream oss;
proxy.Call("framemode", {"pedestal"}, -1, PUT, oss);
REQUIRE(oss.str() == "framemode pedestal\n");
}
{
std::ostringstream oss;
proxy.Call("framemode", {"newpedestal"}, -1, PUT, oss);
REQUIRE(oss.str() == "framemode newpedestal\n");
}
{
std::ostringstream oss;
proxy.Call("framemode", {"flatfield"}, -1, PUT, oss);
REQUIRE(oss.str() == "framemode flatfield\n");
}
{
std::ostringstream oss;
proxy.Call("framemode", {"newflatfield"}, -1, PUT, oss);
REQUIRE(oss.str() == "framemode newflatfield\n");
}
{
std::ostringstream oss;
proxy.Call("framemode", {}, -1, GET, oss);
REQUIRE(oss.str() == "framemode newflatfield\n");
}
REQUIRE_THROWS(proxy.Call("framemode", {"counting"}, -1, PUT));
} else {
REQUIRE_THROWS(proxy.Call("framemode", {}, -1, GET));
}
}
TEST_CASE("detectormode", "[.cmd][.new]") {
Detector det;
CmdProxy proxy(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::MOENCH) {
{
std::ostringstream oss;
proxy.Call("detectormode", {"counting"}, -1, PUT, oss);
REQUIRE(oss.str() == "detectormode counting\n");
}
{
std::ostringstream oss;
proxy.Call("detectormode", {"interpolating"}, -1, PUT, oss);
REQUIRE(oss.str() == "detectormode interpolating\n");
}
{
std::ostringstream oss;
proxy.Call("detectormode", {"analog"}, -1, PUT, oss);
REQUIRE(oss.str() == "detectormode analog\n");
}
std::ostringstream oss;
proxy.Call("detectormode", {}, -1, GET, oss);
REQUIRE(oss.str() == "detectormode analog\n");
REQUIRE_THROWS(proxy.Call("detectormode", {"pedestal"}, -1, PUT));
} else {
REQUIRE_THROWS(proxy.Call("detectormode", {}, -1, GET));
}
}

View File

@ -53,12 +53,12 @@ TEST_CASE("Setting and reading back MYTHEN3 dacs", "[.cmd][.dacs][.new]") {
{
std::ostringstream oss;
proxy.Call("vthreshold", {"1234"}, -1, PUT, oss);
REQUIRE(oss.str() == "vthreshold 1234\n");
REQUIRE(oss.str() == "dac vthreshold 1234\n");
}
{
std::ostringstream oss;
proxy.Call("vthreshold", {}, -1, GET, oss);
REQUIRE(oss.str() == "vthreshold 1234\n");
REQUIRE(oss.str() == "dac vthreshold 1234\n");
}
// Reset dacs after test
@ -115,6 +115,23 @@ TEST_CASE("Setting and reading back MYTHEN3 dacs", "[.cmd][.dacs][.new]") {
}
}
/* acquisition */
TEST_CASE("readout", "[.cmd][.new]") {
Detector det;
CmdProxy proxy(&det);
// PUT only command
REQUIRE_THROWS(proxy.Call("readout", {}, -1, GET));
auto det_type = det.getDetectorType().squash();
if (det_type != defs::MYTHEN3) {
REQUIRE_THROWS(proxy.Call("readout", {}, -1, GET));
} else {
std::ostringstream oss;
proxy.Call("readout", {}, -1, PUT, oss);
REQUIRE(oss.str() == "readout successful\n");
}
}
/* Mythen3 Specific */
TEST_CASE("counters", "[.cmd][.new]") {

View File

@ -706,6 +706,34 @@ TEST_CASE("rx_zmqip", "[.cmd][.rx][.new]") {
}
}
TEST_CASE("rx_zmqhwm", "[.cmd][.new]") {
Detector det;
CmdProxy proxy(&det);
auto prev_val =
det.getRxZmqHwm().tsquash("Inconsistent values for rx_zmqhwm to test");
{
std::ostringstream oss;
proxy.Call("rx_zmqhwm", {"50"}, -1, PUT, oss);
REQUIRE(oss.str() == "rx_zmqhwm 50\n");
}
{
std::ostringstream oss;
proxy.Call("rx_zmqhwm", {}, -1, GET, oss);
REQUIRE(oss.str() == "rx_zmqhwm 50\n");
}
{
std::ostringstream oss;
proxy.Call("rx_zmqhwm", {"0"}, -1, PUT, oss);
REQUIRE(oss.str() == "rx_zmqhwm 0\n");
}
{
std::ostringstream oss;
proxy.Call("rx_zmqhwm", {"-1"}, -1, PUT, oss);
REQUIRE(oss.str() == "rx_zmqhwm -1\n");
}
det.setRxZmqHwm(prev_val);
}
/* CTB Specific */
TEST_CASE("rx_dbitlist", "[.cmd][.rx][.new]") {

View File

@ -1051,6 +1051,36 @@ TEST_CASE("extsig", "[.cmd][.new]") {
}
}
TEST_CASE("parallel", "[.cmd][.new]") {
Detector det;
CmdProxy proxy(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER || det_type == defs::MYTHEN3) {
auto prev_val = det.getParallelMode();
{
std::ostringstream oss;
proxy.Call("parallel", {"1"}, -1, PUT, oss);
REQUIRE(oss.str() == "parallel 1\n");
}
{
std::ostringstream oss;
proxy.Call("parallel", {"0"}, -1, PUT, oss);
REQUIRE(oss.str() == "parallel 0\n");
}
{
std::ostringstream oss;
proxy.Call("parallel", {}, -1, GET, oss);
REQUIRE(oss.str() == "parallel 0\n");
}
for (int i = 0; i != det.size(); ++i) {
det.setParallelMode(prev_val[i], {i});
}
} else {
REQUIRE_THROWS(proxy.Call("parallel", {}, -1, GET));
}
}
/** temperature */
TEST_CASE("templist", "[.cmd][.new]") {
@ -1116,6 +1146,46 @@ TEST_CASE("dacvalues", "[.cmd][.new]") {
/* acquisition */
TEST_CASE("trigger", "[.cmd][.new]") {
Detector det;
CmdProxy proxy(&det);
REQUIRE_THROWS(proxy.Call("trigger", {}, -1, GET));
auto det_type = det.getDetectorType().squash();
if (det_type != defs::EIGER && det_type != defs::MYTHEN3) {
REQUIRE_THROWS(proxy.Call("trigger", {}, -1, PUT));
} else if (det_type == defs::MYTHEN3) {
REQUIRE_NOTHROW(proxy.Call("trigger", {}, -1, PUT));
} else if (det_type == defs::EIGER) {
auto prev_timing =
det.getTimingMode().tsquash("inconsistent timing mode in test");
auto prev_frames =
det.getNumberOfFrames().tsquash("inconsistent #frames in test");
auto prev_exptime =
det.getExptime().tsquash("inconsistent exptime in test");
auto prev_period =
det.getPeriod().tsquash("inconsistent period in test");
det.setTimingMode(defs::TRIGGER_EXPOSURE);
det.setNumberOfFrames(1);
det.setExptime(std::chrono::milliseconds(1));
det.setPeriod(std::chrono::milliseconds(1));
auto startingfnum = det.getStartingFrameNumber().tsquash(
"inconsistent frame nr in test");
det.startDetector();
{
std::ostringstream oss;
proxy.Call("trigger", {}, -1, PUT, oss);
REQUIRE(oss.str() == "trigger successful\n");
}
std::this_thread::sleep_for(std::chrono::seconds(2));
auto currentfnum = det.getStartingFrameNumber().tsquash(
"inconsistent frame nr in test");
REQUIRE(startingfnum + 1 == currentfnum);
det.stopDetector();
det.setTimingMode(prev_timing);
det.setNumberOfFrames(prev_frames);
}
}
TEST_CASE("clearbusy", "[.cmd][.new]") {
Detector det;
CmdProxy proxy(&det);
@ -1353,15 +1423,15 @@ TEST_CASE("scan", "[.cmd][.new]") {
if (det_type == defs::MYTHEN3 || defs::EIGER) {
{
std::ostringstream oss;
proxy.Call("scan", {"trimbit_scan", "0", "63", "16", "2s"}, -1, PUT,
proxy.Call("scan", {"trimbits", "0", "63", "16", "2s"}, -1, PUT,
oss);
CHECK(oss.str() == "scan [trimbit_scan, 0, 63, 16, 2s]\n");
CHECK(oss.str() == "scan [trimbits, 0, 63, 16, 2s]\n");
}
{
std::ostringstream oss;
proxy.Call("scan", {}, -1, GET, oss);
CHECK(oss.str() ==
"scan [enabled\ndac trimbit_scan\nstart 0\nstop 48\nstep "
"scan [enabled\ndac trimbits\nstart 0\nstop 48\nstep "
"16\nsettleTime 2s\n]\n");
}
}
@ -1757,6 +1827,33 @@ TEST_CASE("zmqip", "[.cmd][.new]") {
}
}
TEST_CASE("zmqhwm", "[.cmd][.new]") {
Detector det;
CmdProxy proxy(&det);
auto prev_val = det.getClientZmqHwm();
{
std::ostringstream oss;
proxy.Call("zmqhwm", {"50"}, -1, PUT, oss);
REQUIRE(oss.str() == "zmqhwm 50\n");
}
{
std::ostringstream oss;
proxy.Call("zmqhwm", {}, -1, GET, oss);
REQUIRE(oss.str() == "zmqhwm 50\n");
}
{
std::ostringstream oss;
proxy.Call("zmqhwm", {"0"}, -1, PUT, oss);
REQUIRE(oss.str() == "zmqhwm 0\n");
}
{
std::ostringstream oss;
proxy.Call("zmqhwm", {"-1"}, -1, PUT, oss);
REQUIRE(oss.str() == "zmqhwm -1\n");
}
det.setClientZmqHwm(prev_val);
}
/* Advanced */
TEST_CASE("programfpga", "[.cmd][.new]") {

View File

@ -206,6 +206,8 @@ int ClientInterface::functionTable(){
flist[F_SET_RECEIVER_RATE_CORRECT] = &ClientInterface::set_rate_correct;
flist[F_SET_RECEIVER_SCAN] = &ClientInterface::set_scan;
flist[F_RECEIVER_SET_THRESHOLD] = &ClientInterface::set_threshold;
flist[F_GET_RECEIVER_STREAMING_HWM] = &ClientInterface::get_streaming_hwm;
flist[F_SET_RECEIVER_STREAMING_HWM] = &ClientInterface::set_streaming_hwm;
for (int i = NUM_DET_FUNCTIONS + 1; i < NUM_REC_FUNCTIONS ; i++) {
LOG(logDEBUG1) << "function fnum: " << i << " (" <<
@ -1657,4 +1659,21 @@ int ClientInterface::set_threshold(Interface &socket) {
verifyIdle(socket);
impl()->setThresholdEnergy(arg);
return socket.Send(OK);
}
}
int ClientInterface::get_streaming_hwm(Interface &socket) {
int retval = impl()->getStreamingHwm();
LOG(logDEBUG1) << "zmq send hwm limit:" << retval;
return socket.sendResult(retval);
}
int ClientInterface::set_streaming_hwm(Interface &socket) {
auto limit = socket.Receive<int>();
if (limit < -1) {
throw RuntimeError("Invalid zmq send hwm limit " +
std::to_string(limit));
}
verifyIdle(socket);
impl()->setStreamingHwm(limit);
return socket.Send(OK);
}

View File

@ -159,6 +159,8 @@ class ClientInterface : private virtual slsDetectorDefs {
int set_rate_correct(sls::ServerInterface &socket);
int set_scan(sls::ServerInterface &socket);
int set_threshold(sls::ServerInterface &socket);
int get_streaming_hwm(sls::ServerInterface &socket);
int set_streaming_hwm(sls::ServerInterface &socket);
Implementation *impl() {
if (receiver != nullptr) {

View File

@ -75,18 +75,28 @@ void DataStreamer::SetAdditionalJsonHeader(
}
void DataStreamer::CreateZmqSockets(int *nunits, uint32_t port,
const sls::IpAddr ip) {
const sls::IpAddr ip, int hwm) {
uint32_t portnum = port + index;
std::string sip = ip.str();
try {
zmqSocket = new ZmqSocket(portnum, (ip != 0 ? sip.c_str() : nullptr));
// set if custom
if (hwm >= 0) {
zmqSocket->SetSendHighWaterMark(hwm);
if (zmqSocket->GetSendHighWaterMark() != hwm) {
throw sls::RuntimeError(
"Could not set zmq send high water mark to " +
std::to_string(hwm));
}
}
} catch (...) {
LOG(logERROR) << "Could not create Zmq socket on port " << portnum
<< " for Streamer " << index;
throw;
}
LOG(logINFO) << index << " Streamer: Zmq Server started at "
<< zmqSocket->GetZmqServerAddress();
<< zmqSocket->GetZmqServerAddress()
<< "[hwm: " << zmqSocket->GetSendHighWaterMark() << "]";
}
void DataStreamer::CloseZmqSocket() {

View File

@ -86,8 +86,10 @@ class DataStreamer : private virtual slsDetectorDefs, public ThreadObject {
* @param nunits pointer to number of theads/ units per detector
* @param port streaming port start index
* @param ip streaming source ip
* @param hwm streaming high water mark
*/
void CreateZmqSockets(int *nunits, uint32_t port, const sls::IpAddr ip);
void CreateZmqSockets(int *nunits, uint32_t port, const sls::IpAddr ip,
int hwm);
/**
* Shuts down and deletes Zmq Sockets

View File

@ -585,7 +585,7 @@ void Implementation::stopReceiver() {
// udp port number could be the second if selected interface is
// 2 for jungfrau
"Summary of Port " << udpPortNum[i]
<< "\n\tMissing Packets\t\t: " << mp[i]
<< "\n\tMissing Packets\t\t: " << (int64_t)mp[i]
<< "\n\tComplete Frames\t\t: " << nf
<< "\n\tLast Frame Caught\t: "
<< listener[i]->GetLastFrameIndexCaught();
@ -876,7 +876,8 @@ void Implementation::setNumberofUDPInterfaces(const int n) {
(int *)nd, &quadEnable, &numberOfTotalFrames));
dataStreamer[i]->SetGeneralData(generalData);
dataStreamer[i]->CreateZmqSockets(
&numThreads, streamingPort, streamingSrcIP);
&numThreads, streamingPort, streamingSrcIP,
streamingHwm);
dataStreamer[i]->SetAdditionalJsonHeader(
additionalJsonHeader);
@ -1004,7 +1005,8 @@ void Implementation::setDataStreamEnable(const bool enable) {
(int *)nd, &quadEnable, &numberOfTotalFrames));
dataStreamer[i]->SetGeneralData(generalData);
dataStreamer[i]->CreateZmqSockets(
&numThreads, streamingPort, streamingSrcIP);
&numThreads, streamingPort, streamingSrcIP,
streamingHwm);
dataStreamer[i]->SetAdditionalJsonHeader(
additionalJsonHeader);
} catch (...) {
@ -1063,6 +1065,14 @@ void Implementation::setStreamingSourceIP(const sls::IpAddr ip) {
LOG(logINFO) << "Streaming Source IP: " << streamingSrcIP;
}
int Implementation::getStreamingHwm() const { return streamingHwm; }
void Implementation::setStreamingHwm(const int i) {
streamingHwm = i;
LOG(logINFO) << "Streaming Hwm: "
<< (i == -1 ? "Default (-1)" : std::to_string(streamingHwm));
}
std::map<std::string, std::string>
Implementation::getAdditionalJsonHeader() const {
return additionalJsonHeader;

View File

@ -130,6 +130,8 @@ class Implementation : private virtual slsDetectorDefs {
void setStreamingPort(const uint32_t i);
sls::IpAddr getStreamingSourceIP() const;
void setStreamingSourceIP(const sls::IpAddr ip);
int getStreamingHwm() const;
void setStreamingHwm(const int i);
std::map<std::string, std::string> getAdditionalJsonHeader() const;
void setAdditionalJsonHeader(const std::map<std::string, std::string> &c);
std::string getAdditionalJsonParameter(const std::string &key) const;
@ -312,6 +314,7 @@ class Implementation : private virtual slsDetectorDefs {
uint32_t streamingStartFnum{0};
uint32_t streamingPort{0};
sls::IpAddr streamingSrcIP = sls::IpAddr{};
int streamingHwm{-1};
std::map<std::string, std::string> additionalJsonHeader;
// detector parameters

View File

@ -30,9 +30,12 @@ void sigInterruptHandler(int p) { sem_post(&semaphore); }
* prints usage of this example program
*/
void printHelp() {
cprintf(RESET, "Usage:\n"
"./slsMultiReceiver(detReceiver) [start_tcp_port] "
"[num_receivers] [1 for call back, 0 for none]\n\n");
cprintf(
RESET,
"Usage:\n"
"./slsMultiReceiver(detReceiver) [start_tcp_port] "
"[num_receivers] [optional: 1 for call back (print frame header for "
"debugging), 0 for none (default)]\n\n");
exit(EXIT_FAILURE);
}
@ -157,10 +160,16 @@ int main(int argc, char *argv[]) {
/** - get number of receivers and start tcp port from command line
* arguments */
if ((argc != 4) || (!sscanf(argv[1], "%d", &startTCPPort)) ||
(!sscanf(argv[2], "%d", &numReceivers)) ||
(!sscanf(argv[3], "%d", &withCallback)))
if (argc != 3 && argc != 4)
printHelp();
if ((argc == 3) && ((!sscanf(argv[1], "%d", &startTCPPort)) ||
(!sscanf(argv[2], "%d", &numReceivers))))
printHelp();
if ((argc == 4) && ((!sscanf(argv[1], "%d", &startTCPPort)) ||
(!sscanf(argv[2], "%d", &numReceivers)) ||
(!sscanf(argv[3], "%d", &withCallback))))
printHelp();
cprintf(BLUE, "Parent Process Created [ Tid: %ld ]\n",
(long)syscall(SYS_gettid));
cprintf(RESET, "Number of Receivers: %d\n", numReceivers);

View File

@ -93,6 +93,18 @@ class ZmqSocket {
*/
ZmqSocket(const uint32_t portnumber, const char *ethip);
/** Returns high water mark for outbound messages */
int GetSendHighWaterMark();
/** Sets high water mark for outbound messages. Default 1000 (zmqlib) */
void SetSendHighWaterMark(int limit);
/** Returns high water mark for inbound messages */
int GetReceiveHighWaterMark();
/** Sets high water mark for inbound messages. Default 1000 (zmqlib) */
void SetReceiveHighWaterMark(int limit);
/**
* Returns Port Number
* @returns Port Number

View File

@ -214,6 +214,7 @@ enum detFuncs {
F_RECONFIGURE_UDP,
F_VALIDATE_UDP_CONFIG,
F_GET_BURSTS_LEFT,
F_START_READOUT,
NUM_DET_FUNCTIONS,
RECEIVER_ENUM_START = 256, /**< detector function should not exceed this
@ -315,6 +316,8 @@ enum detFuncs {
F_SET_RECEIVER_RATE_CORRECT,
F_SET_RECEIVER_SCAN,
F_RECEIVER_SET_THRESHOLD,
F_GET_RECEIVER_STREAMING_HWM,
F_SET_RECEIVER_STREAMING_HWM,
NUM_REC_FUNCTIONS
};
@ -531,6 +534,7 @@ const char* getFunctionNameFromEnum(enum detFuncs func) {
case F_RECONFIGURE_UDP: return "F_RECONFIGURE_UDP";
case F_VALIDATE_UDP_CONFIG: return "F_VALIDATE_UDP_CONFIG";
case F_GET_BURSTS_LEFT: return "F_GET_BURSTS_LEFT";
case F_START_READOUT: return "F_START_READOUT";
case NUM_DET_FUNCTIONS: return "NUM_DET_FUNCTIONS";
case RECEIVER_ENUM_START: return "RECEIVER_ENUM_START";
@ -631,6 +635,9 @@ const char* getFunctionNameFromEnum(enum detFuncs func) {
case F_SET_RECEIVER_RATE_CORRECT: return "F_SET_RECEIVER_RATE_CORRECT";
case F_SET_RECEIVER_SCAN: return "F_SET_RECEIVER_SCAN";
case F_RECEIVER_SET_THRESHOLD: return "F_RECEIVER_SET_THRESHOLD";
case F_GET_RECEIVER_STREAMING_HWM: return "F_GET_RECEIVER_STREAMING_HWM";
case F_SET_RECEIVER_STREAMING_HWM: return "F_SET_RECEIVER_STREAMING_HWM";
case NUM_REC_FUNCTIONS: return "NUM_REC_FUNCTIONS";
default: return "Unknown Function";

View File

@ -1,12 +1,12 @@
/** API versions */
#define GITBRANCH "5.0.0-rc2"
#define APILIB 0x201002
#define APIRECEIVER 0x201002
#define APIGUI 0x201002
#define APICTB 0x201005
#define APIGOTTHARD 0x201005
#define APIGOTTHARD2 0x201005
#define APIJUNGFRAU 0x201005
#define APIMYTHEN3 0x201005
#define APIMOENCH 0x201005
#define APIEIGER 0x201005
#define GITBRANCH "developer"
#define APILIB 0x201008
#define APIRECEIVER 0x201008
#define APIGUI 0x201009
#define APIEIGER 0x201009
#define APICTB 0x201016
#define APIGOTTHARD 0x201016
#define APIJUNGFRAU 0x201016
#define APIMOENCH 0x201013
#define APIMYTHEN3 0x201027
#define APIGOTTHARD2 0x201027

View File

@ -485,8 +485,10 @@ std::string ToString(const defs::dacIndex s) {
return std::string("vipre_cds");
case defs::IBIAS_SFP:
return std::string("ibias_sfp");
case defs::ADC_VPP:
return std::string("adcvpp");
case defs::TRIMBIT_SCAN:
return std::string("trimbit_scan");
return std::string("trimbits");
case defs::HIGH_VOLTAGE:
return std::string("highvoltage");
case defs::IO_DELAY:
@ -696,31 +698,31 @@ template <> defs::dacIndex StringTo(const std::string &s) {
return defs::DAC_3;
if (s == "dac 4" || s == "4")
return defs::DAC_4;
if (s == "dac 5"|| s == "5")
if (s == "dac 5" || s == "5")
return defs::DAC_5;
if (s == "dac 6"|| s == "6")
if (s == "dac 6" || s == "6")
return defs::DAC_6;
if (s == "dac 7"|| s == "7")
if (s == "dac 7" || s == "7")
return defs::DAC_7;
if (s == "dac 8"|| s == "8")
if (s == "dac 8" || s == "8")
return defs::DAC_8;
if (s == "dac 9"|| s == "9")
if (s == "dac 9" || s == "9")
return defs::DAC_9;
if (s == "dac 10"|| s == "10")
if (s == "dac 10" || s == "10")
return defs::DAC_10;
if (s == "dac 11"|| s == "11")
if (s == "dac 11" || s == "11")
return defs::DAC_11;
if (s == "dac 12"|| s == "12")
if (s == "dac 12" || s == "12")
return defs::DAC_12;
if (s == "dac 13"|| s == "13")
if (s == "dac 13" || s == "13")
return defs::DAC_13;
if (s == "dac 14"|| s == "14")
if (s == "dac 14" || s == "14")
return defs::DAC_14;
if (s == "dac 15"|| s == "15")
if (s == "dac 15" || s == "15")
return defs::DAC_15;
if (s == "dac 16"|| s == "16")
if (s == "dac 16" || s == "16")
return defs::DAC_16;
if (s == "dac 17"|| s == "17")
if (s == "dac 17" || s == "17")
return defs::DAC_17;
if (s == "vsvp")
return defs::VSVP;
@ -844,7 +846,9 @@ template <> defs::dacIndex StringTo(const std::string &s) {
return defs::VIPRE_CDS;
if (s == "ibias_sfp")
return defs::IBIAS_SFP;
if (s == "trimbit_scan")
if (s == "adcvpp")
return defs::ADC_VPP;
if (s == "trimbits")
return defs::TRIMBIT_SCAN;
if (s == "highvoltage")
return defs::HIGH_VOLTAGE;

View File

@ -48,6 +48,8 @@ ZmqSocket::ZmqSocket(const char *const hostname_or_ip,
PrintError();
throw sls::ZmqSocketError("Could not set ZMQ_LINGER");
}
LOG(logDEBUG) << "Default receive high water mark:"
<< GetReceiveHighWaterMark();
}
ZmqSocket::ZmqSocket(const uint32_t portnumber, const char *ethip)
@ -63,6 +65,7 @@ ZmqSocket::ZmqSocket(const uint32_t portnumber, const char *ethip)
PrintError();
throw sls::ZmqSocketError("Could not create socket");
}
LOG(logDEBUG) << "Default send high water mark:" << GetSendHighWaterMark();
// construct address, can be refactored with libfmt
std::ostringstream oss;
@ -79,6 +82,44 @@ ZmqSocket::ZmqSocket(const uint32_t portnumber, const char *ethip)
std::this_thread::sleep_for(std::chrono::milliseconds(200));
};
int ZmqSocket::GetSendHighWaterMark() {
int value = 0;
size_t value_size = sizeof(value);
if (zmq_getsockopt(sockfd.socketDescriptor, ZMQ_SNDHWM, &value,
&value_size)) {
PrintError();
throw sls::ZmqSocketError("Could not get ZMQ_SNDHWM");
}
return value;
}
void ZmqSocket::SetSendHighWaterMark(int limit) {
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_SNDHWM, &limit,
sizeof(limit))) {
PrintError();
throw sls::ZmqSocketError("Could not set ZMQ_SNDHWM");
}
}
int ZmqSocket::GetReceiveHighWaterMark() {
int value = 0;
size_t value_size = sizeof(value);
if (zmq_getsockopt(sockfd.socketDescriptor, ZMQ_RCVHWM, &value,
&value_size)) {
PrintError();
throw sls::ZmqSocketError("Could not get ZMQ_SNDHWM");
}
return value;
}
void ZmqSocket::SetReceiveHighWaterMark(int limit) {
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_RCVHWM, &limit,
sizeof(limit))) {
PrintError();
throw sls::ZmqSocketError("Could not set ZMQ_SNDHWM");
}
}
int ZmqSocket::Connect() {
if (zmq_connect(sockfd.socketDescriptor, sockfd.serverAddress.c_str())) {
PrintError();