mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-06-15 06:17:12 +02:00
Compare commits
81 Commits
dev/multir
...
ctb/contin
Author | SHA1 | Date | |
---|---|---|---|
44bf2db168 | |||
1b0e891912 | |||
292d65491a | |||
36faec6ad3 | |||
062002243e | |||
98b1e287a4 | |||
e1f46d4747 | |||
d8c3fa0df3 | |||
27530fca31 | |||
cc7f13a10e | |||
625f4353fb | |||
2815913d10 | |||
5fa2402ec5 | |||
4d7d3c9138 | |||
c3f1d05033 | |||
0e4cb7cbcd | |||
bace9edf89 | |||
99735c3ee5 | |||
2571397c70 | |||
497c3abfc2 | |||
fca31cc432 | |||
8fe4a78feb | |||
ee170fa2e0 | |||
da760b2b93 | |||
2c8c2a46ea | |||
9625a8058c | |||
4d8bdae836 | |||
3297707ab7 | |||
598154645c | |||
9d8f9a9ba9 | |||
68f163b757 | |||
b8c5bb2045 | |||
b45df191e5 | |||
01cc745787 | |||
f9bc2eb126 | |||
4c86ad3198 | |||
5be0724f82 | |||
7c652498e4 | |||
6c329cffe0 | |||
721d536350 | |||
361437428d | |||
aadbfeaf2d | |||
f119d14e7c | |||
f8b12201f8 | |||
585c92be66 | |||
a138b5b365 | |||
9fde62ae30 | |||
29fe988583 | |||
6740d9b363 | |||
1d1b55b864 | |||
40dcc1e2cf | |||
91ca6fa0f1 | |||
96ae1a1cca | |||
3793e7b7d4 | |||
713e4f6822 | |||
8b3625fc01 | |||
b7e17d1320 | |||
c54b1cb6af | |||
ddb89bce34 | |||
f056f9d31b | |||
d9a50705e4 | |||
f4626c2c81 | |||
e0a48e1e75 | |||
ec4eb1978e | |||
842b376801 | |||
13b2cada66 | |||
a7111726d9 | |||
0a5b5aac4b | |||
e43f1e36fe | |||
9c2367e657 | |||
6e5b058fc1 | |||
ace2b3a938 | |||
bd66228b30 | |||
e1c9754cd2 | |||
ff101e19cd | |||
e8ac048114 | |||
3c79e8d7b2 | |||
a74fb2bcd1 | |||
63bb79d727 | |||
8d87a6ee4e | |||
23aa9c2814 |
29
.gitea/workflows/rh8-native.yml
Normal file
29
.gitea/workflows/rh8-native.yml
Normal file
@ -0,0 +1,29 @@
|
||||
name: Build on RHEL8
|
||||
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: "ubuntu-latest"
|
||||
container:
|
||||
image: gitea.psi.ch/detectors/rhel8-detectors-dev
|
||||
steps:
|
||||
- name: Clone repository
|
||||
run: |
|
||||
echo Cloning ${{ github.ref_name }}
|
||||
git clone https://${{secrets.GITHUB_TOKEN}}@gitea.psi.ch/${{ github.repository }}.git --branch=${{ github.ref_name }} .
|
||||
|
||||
- name: Build library
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake .. -DSLS_USE_PYTHON=ON -DSLS_USE_TESTS=ON
|
||||
make -j 2
|
||||
|
||||
- name: C++ unit tests
|
||||
working-directory: ${{gitea.workspace}}/build
|
||||
run: ctest
|
27
.gitea/workflows/rh9-native.yml
Normal file
27
.gitea/workflows/rh9-native.yml
Normal file
@ -0,0 +1,27 @@
|
||||
name: Build on RHEL9
|
||||
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: "ubuntu-latest"
|
||||
container:
|
||||
image: gitea.psi.ch/detectors/rhel9-detectors-dev
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
|
||||
- name: Build library
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake .. -DSLS_USE_PYTHON=ON -DSLS_USE_TESTS=ON
|
||||
make -j 2
|
||||
|
||||
- name: C++ unit tests
|
||||
working-directory: ${{gitea.workspace}}/build
|
||||
run: ctest
|
2
.github/workflows/conda_python.yaml
vendored
2
.github/workflows/conda_python.yaml
vendored
@ -33,7 +33,7 @@ jobs:
|
||||
run: conda config --set anaconda_upload no
|
||||
|
||||
- name: Build
|
||||
run: conda build conda-recipes/python-client --output-folder build_output
|
||||
run: conda build conda-recipes/python-client --output-folder build_output
|
||||
|
||||
- name: Upload all Conda packages
|
||||
uses: actions/upload-artifact@v4
|
||||
|
@ -44,6 +44,10 @@ endif()
|
||||
# Patch is applied in the FetchContent_Declare
|
||||
set(SLS_LIBZMQ_VERSION "4.3.4")
|
||||
|
||||
find_program(PATCH_EXECUTABLE patch)
|
||||
if(NOT PATCH_EXECUTABLE)
|
||||
message(FATAL_ERROR "The 'patch' tool is required for patching lib zeromq. Please install it.")
|
||||
endif()
|
||||
|
||||
if(SLS_FETCH_ZMQ_FROM_GITHUB)
|
||||
# Opt in to pull down a zmq version from github instead of
|
||||
@ -216,7 +220,7 @@ endif()
|
||||
# to control options for the libraries
|
||||
if(NOT TARGET slsProjectOptions)
|
||||
add_library(slsProjectOptions INTERFACE)
|
||||
target_compile_features(slsProjectOptions INTERFACE cxx_std_11)
|
||||
target_compile_features(slsProjectOptions INTERFACE cxx_std_17)
|
||||
endif()
|
||||
|
||||
if (NOT TARGET slsProjectWarnings)
|
||||
@ -329,7 +333,8 @@ if (SLS_USE_INTEGRATION_TESTS)
|
||||
endif (SLS_USE_INTEGRATION_TESTS)
|
||||
|
||||
if (SLS_USE_PYTHON)
|
||||
find_package (Python 3.8 COMPONENTS Interpreter Development)
|
||||
find_package (Python 3.8 COMPONENTS Interpreter Development.Module REQUIRED)
|
||||
set(PYBIND11_FINDPYTHON ON) # Needed for RH8
|
||||
if(SLS_FETCH_PYBIND11_FROM_GITHUB)
|
||||
FetchContent_Declare(
|
||||
pybind11
|
||||
|
@ -1,11 +1,11 @@
|
||||
package:
|
||||
name: sls_detector_software
|
||||
version: 2025.3.19
|
||||
|
||||
|
||||
source:
|
||||
path: ../..
|
||||
|
||||
{% set version = load_file_regex(load_file = 'VERSION', regex_pattern = '(\d+(?:\.\d+)*(?:[\+\w\.]+))').group(1) %}
|
||||
package:
|
||||
name: sls_detector_software
|
||||
version: {{ version }}
|
||||
|
||||
build:
|
||||
number: 0
|
||||
binary_relocation: True
|
||||
@ -49,8 +49,6 @@ outputs:
|
||||
- libgcc-ng
|
||||
|
||||
|
||||
|
||||
|
||||
- name: slsdetgui
|
||||
script: copy_gui.sh
|
||||
requirements:
|
||||
|
@ -1,10 +1,11 @@
|
||||
package:
|
||||
name: slsdet
|
||||
version: 2025.3.19 #TODO! how to not duplicate this?
|
||||
|
||||
source:
|
||||
path: ../..
|
||||
|
||||
{% set version = load_file_regex(load_file = 'VERSION', regex_pattern = '(\d+(?:\.\d+)*(?:[\+\w\.]+))').group(1) %}
|
||||
package:
|
||||
name: slsdet
|
||||
version: {{ version }}
|
||||
|
||||
build:
|
||||
number: 0
|
||||
script:
|
||||
@ -17,7 +18,6 @@ requirements:
|
||||
- {{ stdlib("c") }}
|
||||
- {{ compiler('cxx') }}
|
||||
|
||||
|
||||
host:
|
||||
- cmake
|
||||
- ninja
|
||||
|
@ -359,6 +359,7 @@ Chip Test Board
|
||||
"Digital Flag": 0,
|
||||
"Digital Samples": 1000,
|
||||
"Dbit Offset": 0,
|
||||
"Dbit Reorder": 1,
|
||||
"Dbit Bitset": 0,
|
||||
"Transceiver Mask": "0x3",
|
||||
"Transceiver Flag": 0,
|
||||
|
@ -345,6 +345,9 @@ Chip Test Board
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Dbit Offset | Digital offset of valid data in bytes |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Dbit Reorder | Reorder such that it groups each signal (0-63) |
|
||||
| | from all the different samples together |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Dbit Bitset | Digital 64 bit mask of bits enabled in receiver |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Transceiver Mask | Mask of channels enabled in Transceiver |
|
||||
|
@ -22,6 +22,7 @@ class SignalsTab(QtWidgets.QWidget):
|
||||
self.plotTab = None
|
||||
self.legend: LegendItem | None = None
|
||||
self.rx_dbitoffset = None
|
||||
self.rx_dbitreorder = None
|
||||
self.rx_dbitlist = None
|
||||
|
||||
def refresh(self):
|
||||
@ -29,6 +30,7 @@ class SignalsTab(QtWidgets.QWidget):
|
||||
self.updateDigitalBitEnable()
|
||||
self.updateIOOut()
|
||||
self.getDBitOffset()
|
||||
self.getDBitReorder()
|
||||
|
||||
def connect_ui(self):
|
||||
for i in range(Defines.signals.count):
|
||||
@ -49,6 +51,7 @@ class SignalsTab(QtWidgets.QWidget):
|
||||
partial(self.setIOOutRange, Defines.signals.half, Defines.signals.count))
|
||||
self.view.lineEditPatIOCtrl.editingFinished.connect(self.setIOOutReg)
|
||||
self.view.spinBoxDBitOffset.editingFinished.connect(self.setDbitOffset)
|
||||
self.view.checkBoxDBitReorder.stateChanged.connect(self.setDbitReorder)
|
||||
|
||||
def setup_ui(self):
|
||||
self.plotTab = self.mainWindow.plotTab
|
||||
@ -87,60 +90,79 @@ class SignalsTab(QtWidgets.QWidget):
|
||||
self.legend.addItem(plot, name)
|
||||
|
||||
@recordOrApplyPedestal
|
||||
def _processWaveformData(self, data, aSamples, dSamples, rx_dbitlist, isPlottedArray, rx_dbitoffset, romode,
|
||||
def _processWaveformData(self, data, aSamples, dSamples, rx_dbitreorder, rx_dbitlist, isPlottedArray, romode,
|
||||
nADCEnabled):
|
||||
"""
|
||||
transform raw waveform data into a processed numpy array
|
||||
@param data: raw waveform data
|
||||
"""
|
||||
dbitoffset = rx_dbitoffset
|
||||
|
||||
#transform raw waveform data into a processed numpy array
|
||||
#@param data: raw waveform data
|
||||
|
||||
start_digital_data = 0
|
||||
if romode == 2:
|
||||
dbitoffset += nADCEnabled * 2 * aSamples
|
||||
digital_array = np.array(np.frombuffer(data, offset=dbitoffset, dtype=np.uint8))
|
||||
nbitsPerDBit = dSamples
|
||||
if nbitsPerDBit % 8 != 0:
|
||||
nbitsPerDBit += (8 - (dSamples % 8))
|
||||
offset = 0
|
||||
arr = []
|
||||
for i in rx_dbitlist:
|
||||
# where numbits * numsamples is not a multiple of 8
|
||||
if offset % 8 != 0:
|
||||
offset += (8 - (offset % 8))
|
||||
if not isPlottedArray[i]:
|
||||
offset += nbitsPerDBit
|
||||
return None
|
||||
waveform = np.zeros(dSamples)
|
||||
for iSample in range(dSamples):
|
||||
# all samples for digital bit together from slsReceiver
|
||||
index = int(offset / 8)
|
||||
iBit = offset % 8
|
||||
bit = (digital_array[index] >> iBit) & 1
|
||||
waveform[iSample] = bit
|
||||
offset += 1
|
||||
arr.append(waveform)
|
||||
start_digital_data += nADCEnabled * 2 * aSamples
|
||||
digital_array = np.array(np.frombuffer(data, offset=start_digital_data, dtype=np.uint8))
|
||||
if rx_dbitreorder:
|
||||
samples_per_bit = np.empty((len(rx_dbitlist), dSamples), dtype=np.uint8) #stored per row all the corresponding signals of all samples
|
||||
nbitsPerDBit = dSamples
|
||||
if nbitsPerDBit % 8 != 0:
|
||||
nbitsPerDBit += (8 - (dSamples % 8))
|
||||
bit_index = 0
|
||||
for idx, i in enumerate(rx_dbitlist):
|
||||
# where numbits * numsamples is not a multiple of 8
|
||||
if bit_index % 8 != 0:
|
||||
bit_index += (8 - (bit_index % 8))
|
||||
if not isPlottedArray[i]:
|
||||
bit_index += nbitsPerDBit
|
||||
samples_per_bit[idx, :] = np.nan
|
||||
continue
|
||||
for iSample in range(dSamples):
|
||||
# all samples for digital bit together from slsReceiver
|
||||
index = int(bit_index / 8)
|
||||
iBit = bit_index % 8
|
||||
bit = (digital_array[index] >> iBit) & 1
|
||||
samples_per_bit[idx,iSample] = bit
|
||||
bit_index += 1
|
||||
return samples_per_bit
|
||||
else:
|
||||
nbitsPerSample = len(rx_dbitlist) if len(rx_dbitlist) % 8 == 0 else len(rx_dbitlist) + (8 - (len(rx_dbitlist) % 8))
|
||||
bits_per_sample = np.empty((dSamples, len(rx_dbitlist)), dtype=np.uint8) #store per row all selected bits of a sample
|
||||
for iSample in range(dSamples):
|
||||
bit_index = nbitsPerSample * iSample
|
||||
for idx, i in enumerate(rx_dbitlist):
|
||||
if not isPlottedArray[i]:
|
||||
bit_index += 1
|
||||
bits_per_sample[iSample, idx] = np.nan
|
||||
|
||||
return np.array(arr)
|
||||
index = int(bit_index/8)
|
||||
iBit = idx % 8
|
||||
bit = (digital_array[index] >> iBit) & 1
|
||||
bits_per_sample[iSample, idx] = bit
|
||||
bit_index += 1
|
||||
return bits_per_sample.T.copy()
|
||||
|
||||
|
||||
|
||||
def processWaveformData(self, data, aSamples, dSamples):
|
||||
"""
|
||||
view function
|
||||
plots processed waveform data
|
||||
data: raw waveform data
|
||||
dsamples: digital samples
|
||||
asamples: analog samples
|
||||
"""
|
||||
|
||||
#view function
|
||||
#plots processed waveform data
|
||||
#data: raw waveform data
|
||||
#dsamples: digital samples
|
||||
#asamples: analog samples
|
||||
|
||||
self.refresh()
|
||||
|
||||
waveforms = {}
|
||||
isPlottedArray = {i: getattr(self.view, f"checkBoxBIT{i}Plot").isChecked() for i in self.rx_dbitlist}
|
||||
|
||||
digital_array = self._processWaveformData(data, aSamples, dSamples, self.rx_dbitlist, isPlottedArray,
|
||||
self.rx_dbitoffset, self.mainWindow.romode.value,
|
||||
digital_array = self._processWaveformData(data, aSamples, dSamples, self.rx_dbitreorder, self.rx_dbitlist, isPlottedArray,
|
||||
self.mainWindow.romode.value,
|
||||
self.mainWindow.nADCEnabled)
|
||||
|
||||
irow = 0
|
||||
for idx, i in enumerate(self.rx_dbitlist):
|
||||
for idx, i in enumerate(self.rx_dbitlist):
|
||||
# bits enabled but not plotting
|
||||
waveform = digital_array[idx]
|
||||
if waveform is None:
|
||||
waveform = digital_array[idx, :]
|
||||
if np.isnan(waveform[0]):
|
||||
continue
|
||||
self.mainWindow.digitalPlots[i].setData(waveform)
|
||||
plotName = getattr(self.view, f"labelBIT{i}").text()
|
||||
@ -151,8 +173,10 @@ class SignalsTab(QtWidgets.QWidget):
|
||||
irow += 1
|
||||
else:
|
||||
self.mainWindow.digitalPlots[i].setY(0)
|
||||
|
||||
return waveforms
|
||||
|
||||
|
||||
def initializeAllDigitalPlots(self):
|
||||
self.mainWindow.plotDigitalWaveform = pg.plot()
|
||||
self.mainWindow.plotDigitalWaveform.addLegend(colCount=Defines.colCount)
|
||||
@ -360,14 +384,25 @@ class SignalsTab(QtWidgets.QWidget):
|
||||
self.view.spinBoxDBitOffset.setValue(self.rx_dbitoffset)
|
||||
self.view.spinBoxDBitOffset.editingFinished.connect(self.setDbitOffset)
|
||||
|
||||
def getDBitReorder(self):
|
||||
self.view.checkBoxDBitReorder.stateChanged.disconnect()
|
||||
self.rx_dbitreorder = self.det.rx_dbitreorder
|
||||
self.view.checkBoxDBitReorder.setChecked(self.rx_dbitreorder)
|
||||
self.view.checkBoxDBitReorder.stateChanged.connect(self.setDbitReorder)
|
||||
|
||||
|
||||
def setDbitOffset(self):
|
||||
self.det.rx_dbitoffset = self.view.spinBoxDBitOffset.value()
|
||||
|
||||
def setDbitReorder(self):
|
||||
self.det.rx_dbitreorder = self.view.checkBoxDBitReorder.isChecked()
|
||||
|
||||
def saveParameters(self) -> list:
|
||||
commands = []
|
||||
dblist = [str(i) for i in range(Defines.signals.count) if getattr(self.view, f"checkBoxBIT{i}DB").isChecked()]
|
||||
if len(dblist) > 0:
|
||||
commands.append(f"rx_dbitlist {', '.join(dblist)}")
|
||||
commands.append(f"rx_dbitoffset {self.view.spinBoxDBitOffset.value()}")
|
||||
commands.append(f"rx_dbitreorder {self.view.checkBoxDBitReorder.isChecked()}")
|
||||
commands.append(f"patioctrl {self.view.lineEditPatIOCtrl.text()}")
|
||||
return commands
|
||||
|
@ -6074,6 +6074,33 @@
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_17">
|
||||
<item row="0" column="4">
|
||||
<widget class="QSpinBox" name="spinBoxDBitOffset">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(255, 255, 255);</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLabel" name="label_66">
|
||||
<property name="font">
|
||||
@ -6086,6 +6113,36 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="6">
|
||||
<widget class="QCheckBox" name="checkBoxDBitReorder">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>DBit Reorder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_48">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>IO Control Register:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineEditPatIOCtrl">
|
||||
<property name="sizePolicy">
|
||||
@ -6133,50 +6190,18 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QSpinBox" name="spinBoxDBitOffset">
|
||||
<property name="minimumSize">
|
||||
<item row="0" column="5">
|
||||
<spacer name="horizontalSpacer_22">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>32</height>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(255, 255, 255);</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_48">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>IO Control Register:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
@ -1,27 +1,33 @@
|
||||
[tool.scikit-build.metadata.version]
|
||||
provider = "scikit_build_core.metadata.regex"
|
||||
input = "VERSION"
|
||||
regex = '^(?P<version>\d+(?:\.\d+)*(?:[\.\+\w]+)?)$'
|
||||
result = "{version}"
|
||||
|
||||
[build-system]
|
||||
requires = ["scikit-build-core>=0.10", "pybind11", "numpy"]
|
||||
requires = [ "scikit-build-core>=0.10", "pybind11", "numpy",]
|
||||
build-backend = "scikit_build_core.build"
|
||||
|
||||
[project]
|
||||
name = "slsdet"
|
||||
version = "2025.3.19"
|
||||
|
||||
dynamic = ["version"]
|
||||
|
||||
[tool.cibuildwheel]
|
||||
before-all = "uname -a"
|
||||
|
||||
[tool.scikit-build]
|
||||
build.verbose = true
|
||||
cmake.build-type = "Release"
|
||||
install.components = ["python"]
|
||||
[tool.scikit-build.build]
|
||||
verbose = true
|
||||
|
||||
[tool.scikit-build.cmake]
|
||||
build-type = "Release"
|
||||
|
||||
[tool.scikit-build.install]
|
||||
components = [ "python",]
|
||||
|
||||
[tool.scikit-build.cmake.define]
|
||||
#Only build the control software and python ext
|
||||
SLS_USE_RECEIVER = "OFF"
|
||||
SLS_USE_RECEIVER_BINARIES = "OFF"
|
||||
SLS_USE_TEXTCLIENT = "OFF"
|
||||
SLS_BUILD_SHARED_LIBRARIES = "OFF"
|
||||
|
||||
SLS_USE_PYTHON = "ON"
|
||||
SLS_INSTALL_PYTHONEXT = "ON"
|
||||
SLS_INSTALL_PYTHONEXT = "ON"
|
||||
|
@ -3463,6 +3463,16 @@ class Detector(CppDetectorApi):
|
||||
def rx_dbitoffset(self, value):
|
||||
ut.set_using_dict(self.setRxDbitOffset, value)
|
||||
|
||||
@property
|
||||
@element
|
||||
def rx_dbitreorder(self):
|
||||
"""[Ctb] Reorder digital data to group together all samples per signal. Default is 1. Setting to 0 means 'do not reorder' and to keep what the board spits out, which is that all signals in a sample are grouped together."""
|
||||
return self.getRxDbitReorder()
|
||||
|
||||
@rx_dbitreorder.setter
|
||||
def rx_dbitreorder(self, value):
|
||||
ut.set_using_dict(self.setRxDbitReorder, value)
|
||||
|
||||
@property
|
||||
@element
|
||||
def maxadcphaseshift(self):
|
||||
|
@ -1664,6 +1664,14 @@ void init_det(py::module &m) {
|
||||
(void (Detector::*)(int, sls::Positions)) &
|
||||
Detector::setRxDbitOffset,
|
||||
py::arg(), py::arg() = Positions{});
|
||||
CppDetectorApi.def("getRxDbitReorder",
|
||||
(Result<bool>(Detector::*)(sls::Positions) const) &
|
||||
Detector::getRxDbitReorder,
|
||||
py::arg() = Positions{});
|
||||
CppDetectorApi.def("setRxDbitReorder",
|
||||
(void (Detector::*)(bool, sls::Positions)) &
|
||||
Detector::setRxDbitReorder,
|
||||
py::arg(), py::arg() = Positions{});
|
||||
CppDetectorApi.def("setDigitalIODelay",
|
||||
(void (Detector::*)(uint64_t, int, sls::Positions)) &
|
||||
Detector::setDigitalIODelay,
|
||||
|
@ -65,8 +65,8 @@
|
||||
(0x000000FF << STATUS_PT_CNTRL_STTS_OFF_OFST)
|
||||
#define STATUS_IDLE_MSK (0x677FF)
|
||||
|
||||
/* Look at me RO register TODO */
|
||||
#define LOOK_AT_ME_REG (0x03 << MEM_MAP_SHIFT)
|
||||
/* Register containing the git hash of the FPGA firmware */
|
||||
#define FIRMWARE_GIT_HASH_REG (0x03 << MEM_MAP_SHIFT)
|
||||
|
||||
/* System Status RO register */
|
||||
#define SYSTEM_STATUS_REG (0x04 << MEM_MAP_SHIFT)
|
||||
@ -198,12 +198,43 @@
|
||||
#define FIFO_TIN_STATUS_FIFO_EMPTY_4_MSK (0x00000001 << FIFO_TIN_STATUS_FIFO_EMPTY_4_OFST)
|
||||
#define FIFO_TIN_STATUS_FIFO_EMPTY_ALL_MSK (0x0000000F << FIFO_TIN_STATUS_FIFO_EMPTY_1_OFST)
|
||||
|
||||
/* FIFO Transceiver Fill level RO register */
|
||||
#define FIFO_TIN_FILL_REG (0x45 << MEM_MAP_SHIFT)
|
||||
#define FIFO_TIN_FILL_FIFO_1_OFST (0)
|
||||
#define FIFO_TIN_FILL_FIFO_1_MSK (0x00003FFF << FIFO_TIN_FILL_FIFO__1_OFST)
|
||||
#define FIFO_TIN_FILL_FIFO_2_OFST (16)
|
||||
#define FIFO_TIN_FILL_FIFO_2_MSK (0x00003FFF << FIFO_TIN_FILL_FIFO__2_OFST)
|
||||
|
||||
/* FIFO ADC Fill level RO register */
|
||||
#define FIFO_ADC_FILL_REG (0x46 << MEM_MAP_SHIFT)
|
||||
#define FIFO_ADC_FILL_FIFO_OFST (0)
|
||||
#define FIFO_ADC_FILL_FIFO_MSK (0x00003FFF << FIFO_ADC_FILL_FIFO_OFST)
|
||||
|
||||
/* Enable continuos readout register */
|
||||
#define CONTINUOUS_RO_ENABLE_REG (0x47 << MEM_MAP_SHIFT)
|
||||
#define CONTINUOUS_RO_ADC_ENABLE_OFST (0)
|
||||
#define CONTINUOUS_RO_TIN_ENABLE_OFST (1)
|
||||
#define CONTINUOUS_RO_DBIT_ENABLE_OFST (2)
|
||||
#define CONTINUOUS_RO_ADC_ENABLE_MSK (0x00000001 << CONTINUOUS_RO_ADC_ENABLE_OFST)
|
||||
#define CONTINUOUS_RO_TIN_ENABLE_MSK (0x00000001 << CONTINUOUS_RO_TIN_ENABLE_OFST)
|
||||
#define CONTINUOUS_RO_DBIT_ENABLE_MSK (0x00000001 << CONTINUOUS_RO_DBIT_ENABLE_OFST)
|
||||
#define DBIT_INJECT_COUNTER_ENA_OFST (3) // continuously injects fake-data into the dbit fifo when enabled.
|
||||
#define DBIT_INJECT_COUNTER_ENA_MSK (0x00000001 << DBIT_INJECT_COUNTER_ENA_OFST)
|
||||
#define DBIT_INJECT_COUNTER_CLKDIV_OFST (8) // Additional clock divider for fake-data injection
|
||||
#define DBIT_INJECT_COUNTER_CLKDIV_MSK (0x000000FF << DBIT_INJECT_COUNTER_CLKDIV_OFST)
|
||||
|
||||
/* 64-bit FPGA chip ID. Unique for every device. read-only */
|
||||
#define FPGA_chipID_0_REG (0x48 << MEM_MAP_SHIFT)
|
||||
#define FPGA_chipID_1_REG (0x49 << MEM_MAP_SHIFT)
|
||||
|
||||
/* FIFO Transceiver In 64 bit RO register */
|
||||
#define FIFO_TIN_LSB_REG (0x31 << MEM_MAP_SHIFT)
|
||||
#define FIFO_TIN_MSB_REG (0x32 << MEM_MAP_SHIFT)
|
||||
|
||||
/* FIFO Digital In Status RO register */
|
||||
#define FIFO_DIN_STATUS_REG (0x3B << MEM_MAP_SHIFT)
|
||||
#define FIFO_DIN_STATUS_FIFO_FILL_OFST (0)
|
||||
#define FIFO_DIN_STATUS_FIFO_FILL_MSK (0x00003FFF)
|
||||
#define FIFO_DIN_STATUS_FIFO_FULL_OFST (30)
|
||||
#define FIFO_DIN_STATUS_FIFO_FULL_MSK (0x00000001 << FIFO_DIN_STATUS_FIFO_FULL_OFST)
|
||||
#define FIFO_DIN_STATUS_FIFO_EMPTY_OFST (31)
|
||||
@ -273,44 +304,6 @@
|
||||
#define DUMMY_TRNSCVR_FIFO_RD_STRBE_OFST (14)
|
||||
#define DUMMY_TRNSCVR_FIFO_RD_STRBE_MSK (0x00000001 << DUMMY_TRNSCVR_FIFO_RD_STRBE_OFST)
|
||||
|
||||
/* Receiver IP Address RW register */
|
||||
#define RX_IP_REG (0x45 << MEM_MAP_SHIFT)
|
||||
|
||||
/* UDP Port RW register */
|
||||
#define UDP_PORT_REG (0x46 << MEM_MAP_SHIFT)
|
||||
|
||||
#define UDP_PORT_RX_OFST (0)
|
||||
#define UDP_PORT_RX_MSK (0x0000FFFF << UDP_PORT_RX_OFST)
|
||||
#define UDP_PORT_TX_OFST (16)
|
||||
#define UDP_PORT_TX_MSK (0x0000FFFF << UDP_PORT_TX_OFST)
|
||||
|
||||
/* Receiver Mac Address 64 bit RW register */
|
||||
#define RX_MAC_LSB_REG (0x47 << MEM_MAP_SHIFT)
|
||||
#define RX_MAC_MSB_REG (0x48 << MEM_MAP_SHIFT)
|
||||
|
||||
#define RX_MAC_LSB_OFST (0)
|
||||
#define RX_MAC_LSB_MSK (0xFFFFFFFF << RX_MAC_LSB_OFST)
|
||||
#define RX_MAC_MSB_OFST (0)
|
||||
#define RX_MAC_MSB_MSK (0x0000FFFF << RX_MAC_MSB_OFST)
|
||||
|
||||
/* Detector/ Transmitter Mac Address 64 bit RW register */
|
||||
#define TX_MAC_LSB_REG (0x49 << MEM_MAP_SHIFT)
|
||||
#define TX_MAC_MSB_REG (0x4A << MEM_MAP_SHIFT)
|
||||
|
||||
#define TX_MAC_LSB_OFST (0)
|
||||
#define TX_MAC_LSB_MSK (0xFFFFFFFF << TX_MAC_LSB_OFST)
|
||||
#define TX_MAC_MSB_OFST (0)
|
||||
#define TX_MAC_MSB_MSK (0x0000FFFF << TX_MAC_MSB_OFST)
|
||||
|
||||
/* Detector/ Transmitter IP Address RW register */
|
||||
#define TX_IP_REG (0x4B << MEM_MAP_SHIFT)
|
||||
|
||||
/* Detector/ Transmitter IP Checksum RW register */
|
||||
#define TX_IP_CHECKSUM_REG (0x4C << MEM_MAP_SHIFT)
|
||||
|
||||
#define TX_IP_CHECKSUM_OFST (0)
|
||||
#define TX_IP_CHECKSUM_MSK (0x0000FFFF << TX_IP_CHECKSUM_OFST)
|
||||
|
||||
/* Configuration RW register */
|
||||
#define CONFIG_REG (0x4D << MEM_MAP_SHIFT)
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "loadPattern.h"
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h> // usleep
|
||||
#ifdef VIRTUAL
|
||||
@ -2258,11 +2259,23 @@ void *start_timer(void *arg) {
|
||||
int packetsPerFrame = ceil((double)imageSize / (double)dataSize);
|
||||
|
||||
// Generate Data
|
||||
char imageData[imageSize];
|
||||
char *imageData = (char *)malloc(imageSize);
|
||||
memset(imageData, 0, imageSize);
|
||||
|
||||
if (imageData == NULL) {
|
||||
LOG(logERROR, ("Can not allocate image Data RAM."
|
||||
"Probable cause: Memory Leak.\n"));
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
for (int i = 0; i < imageSize; i += sizeof(uint16_t)) {
|
||||
*((uint16_t *)(imageData + i)) = i;
|
||||
}
|
||||
*/
|
||||
|
||||
for (int i = 0; i < imageSize; i += 2 * sizeof(uint64_t)) {
|
||||
*((uint64_t *)(imageData + i)) = 0xffffffffffffffff;
|
||||
}
|
||||
|
||||
// Send data
|
||||
uint64_t frameNr = 0;
|
||||
@ -2319,6 +2332,8 @@ void *start_timer(void *arg) {
|
||||
setNextFrameNumber(frameNr + numFrames);
|
||||
}
|
||||
|
||||
free(imageData);
|
||||
|
||||
closeUDPSocket(0);
|
||||
|
||||
sharedMemory_setStatus(IDLE);
|
||||
|
Binary file not shown.
@ -304,7 +304,7 @@ patternParameters *setChannelRegisterChip(int ichip, char *mask,
|
||||
chanReg |= (0x1 << (3 + icounter));
|
||||
}
|
||||
}
|
||||
|
||||
chanReg /= 2;
|
||||
// deserialize
|
||||
if (chanReg & CHAN_REG_BAD_CHANNEL_MSK) {
|
||||
LOG(logINFOBLUE,
|
||||
|
@ -152,12 +152,12 @@ int main(int argc, char *argv[]) {
|
||||
strcpy(version, APIXILINXCTB);
|
||||
#endif
|
||||
LOG(logINFO, ("SLS Detector Server Version: %s\n", version));
|
||||
return EXIT_SUCCESS;
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
case 'p':
|
||||
if (sscanf(optarg, "%d", &portno) != 1) {
|
||||
LOG(logERROR, ("Cannot scan port argument\n%s", helpMessage));
|
||||
return EXIT_FAILURE;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
LOG(logINFO, ("Detected port: %d\n", portno));
|
||||
break;
|
||||
@ -188,7 +188,7 @@ int main(int argc, char *argv[]) {
|
||||
ignoreConfigFileFlag = 1;
|
||||
#else
|
||||
LOG(logERROR, ("No server config files for this detector\n"));
|
||||
return EXIT_FAILURE;
|
||||
exit(EXIT_FAILURE);
|
||||
#endif
|
||||
break;
|
||||
|
||||
@ -196,11 +196,11 @@ int main(int argc, char *argv[]) {
|
||||
#if !defined(VIRTUAL) && !defined(EIGERD)
|
||||
LOG(logERROR, ("Cannot set master via the detector server for this "
|
||||
"detector\n"));
|
||||
return EXIT_FAILURE;
|
||||
exit(EXIT_FAILURE);
|
||||
#elif defined(GOTTHARD2D) || defined(EIGERD) || defined(MYTHEN3D)
|
||||
if (sscanf(optarg, "%d", &masterCommandLine) != 1) {
|
||||
LOG(logERROR, ("Cannot scan master argument\n%s", helpMessage));
|
||||
return EXIT_FAILURE;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (masterCommandLine == 1) {
|
||||
LOG(logINFO, ("Detector Master mode\n"));
|
||||
@ -209,7 +209,7 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
#else
|
||||
LOG(logERROR, ("No master implemented for this detector server\n"));
|
||||
return EXIT_FAILURE;
|
||||
exit(EXIT_FAILURE);
|
||||
#endif
|
||||
break;
|
||||
|
||||
@ -217,7 +217,7 @@ int main(int argc, char *argv[]) {
|
||||
#ifdef EIGERD
|
||||
if (sscanf(optarg, "%d", &topCommandLine) != 1) {
|
||||
LOG(logERROR, ("Cannot scan top argument\n%s", helpMessage));
|
||||
return EXIT_FAILURE;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (topCommandLine == 1) {
|
||||
LOG(logINFO, ("Detector Top mode\n"));
|
||||
@ -226,16 +226,16 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
#else
|
||||
LOG(logERROR, ("No top implemented for this detector server\n"));
|
||||
return EXIT_FAILURE;
|
||||
exit(EXIT_FAILURE);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
printf("%s", helpMessage);
|
||||
return EXIT_SUCCESS;
|
||||
exit(EXIT_SUCCESS);
|
||||
default:
|
||||
printf("\n%s", helpMessage);
|
||||
return EXIT_FAILURE;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -376,5 +376,5 @@ int main(int argc, char *argv[]) {
|
||||
#endif
|
||||
}
|
||||
LOG(logINFO, ("Goodbye!\n"));
|
||||
return EXIT_SUCCESS;
|
||||
return 0;
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ _sd() {
|
||||
local IS_PATH=0
|
||||
|
||||
|
||||
local SLS_COMMANDS=" acquire activate adcclk adcenable adcenable10g adcindex adcinvert adclist adcname adcphase adcpipeline adcreg adcvpp apulse asamples autocompdisable badchannels blockingtrigger burstmode burstperiod bursts burstsl bustest cdsgain chipversion clearbit clearbusy clientversion clkdiv clkfreq clkphase collectionmode column compdisabletime confadc config configtransceiver counters currentsource dac dacindex daclist dacname dacvalues datastream dbitclk dbitphase dbitpipeline defaultdac defaultpattern delay delayl detectorserverversion detsize diodelay dpulse dr drlist dsamples execcommand exptime exptime1 exptime2 exptime3 extrastoragecells extsampling extsamplingsrc extsig fformat filtercells filterresistor findex firmwaretest firmwareversion fliprows flowcontrol10g fmaster fname foverwrite fpath framecounter frames framesl frametime free fwrite gaincaps gainmode gappixels gatedelay gatedelay1 gatedelay2 gatedelay3 gates getbit hardwareversion highvoltage hostname im_a im_b im_c im_d im_io imagetest initialchecks inj_ch interpolation interruptsubframe kernelversion lastclient led lock master maxadcphaseshift maxclkphaseshift maxdbitphaseshift measuredperiod measuredsubperiod moduleid nextframenumber nmod numinterfaces overflow packageversion parallel parameters partialreset patfname patioctrl patlimits patloop patloop0 patloop1 patloop2 patmask patnloop patnloop0 patnloop1 patnloop2 patsetbit pattern patternstart patwait patwait0 patwait1 patwait2 patwaittime patwaittime0 patwaittime1 patwaittime2 patword pedestalmode period periodl polarity port powerchip powerindex powerlist powername powervalues programfpga pulse pulsechip pulsenmove pumpprobe quad ratecorr readnrows readout readoutspeed readoutspeedlist rebootcontroller reg resetdacs resetfpga romode row runclk runtime rx_arping rx_clearroi rx_dbitlist rx_dbitoffset rx_discardpolicy rx_fifodepth rx_frameindex rx_framescaught rx_framesperfile rx_hostname rx_jsonaddheader rx_jsonpara rx_lastclient rx_lock rx_missingpackets rx_padding rx_printconfig rx_realudpsocksize rx_roi rx_silent rx_start rx_status rx_stop rx_tcpport rx_threads rx_udpsocksize rx_version rx_zmqfreq rx_zmqhwm rx_zmqip rx_zmqport rx_zmqstartfnum rx_zmqstream samples savepattern scan scanerrmsg selinterface serialnumber setbit settings settingslist settingspath signalindex signallist signalname sleep slowadc slowadcindex slowadclist slowadcname slowadcvalues start status stop stopport storagecell_delay storagecell_start subdeadtime subexptime sync syncclk temp_10ge temp_adc temp_control temp_dcdc temp_event temp_fpga temp_fpgaext temp_fpgafl temp_fpgafr temp_slowadc temp_sodl temp_sodr temp_threshold templist tempvalues tengiga threshold thresholdnotb timing timing_info_decoder timinglist timingsource top transceiverenable trigger triggers triggersl trimbits trimen trimval tsamples txdelay txdelay_frame txdelay_left txdelay_right type udp_cleardst udp_dstip udp_dstip2 udp_dstlist udp_dstmac udp_dstmac2 udp_dstport udp_dstport2 udp_firstdst udp_numdst udp_reconfigure udp_srcip udp_srcip2 udp_srcmac udp_srcmac2 udp_validate update updatedetectorserver updatekernel updatemode user v_a v_b v_c v_chip v_d v_io v_limit vchip_comp_adc vchip_comp_fe vchip_cs vchip_opa_1st vchip_opa_fd vchip_ref_comp_fe versions veto vetoalg vetofile vetophoton vetoref vetostream virtual vm_a vm_b vm_c vm_d vm_io zmqhwm zmqip zmqport "
|
||||
local SLS_COMMANDS=" acquire activate adcclk adcenable adcenable10g adcindex adcinvert adclist adcname adcphase adcpipeline adcreg adcvpp apulse asamples autocompdisable badchannels blockingtrigger burstmode burstperiod bursts burstsl bustest cdsgain chipversion clearbit clearbusy clientversion clkdiv clkfreq clkphase collectionmode column compdisabletime confadc config configtransceiver counters currentsource dac dacindex daclist dacname dacvalues datastream dbitclk dbitphase dbitpipeline defaultdac defaultpattern delay delayl detectorserverversion detsize diodelay dpulse dr drlist dsamples execcommand exptime exptime1 exptime2 exptime3 extrastoragecells extsampling extsamplingsrc extsig fformat filtercells filterresistor findex firmwaretest firmwareversion fliprows flowcontrol10g fmaster fname foverwrite fpath framecounter frames framesl frametime free fwrite gaincaps gainmode gappixels gatedelay gatedelay1 gatedelay2 gatedelay3 gates getbit hardwareversion highvoltage hostname im_a im_b im_c im_d im_io imagetest initialchecks inj_ch interpolation interruptsubframe kernelversion lastclient led lock master maxadcphaseshift maxclkphaseshift maxdbitphaseshift measuredperiod measuredsubperiod moduleid nextframenumber nmod numinterfaces overflow packageversion parallel parameters partialreset patfname patioctrl patlimits patloop patloop0 patloop1 patloop2 patmask patnloop patnloop0 patnloop1 patnloop2 patsetbit pattern patternstart patwait patwait0 patwait1 patwait2 patwaittime patwaittime0 patwaittime1 patwaittime2 patword pedestalmode period periodl polarity port powerchip powerindex powerlist powername powervalues programfpga pulse pulsechip pulsenmove pumpprobe quad ratecorr readnrows readout readoutspeed readoutspeedlist rebootcontroller reg resetdacs resetfpga romode row runclk runtime rx_arping rx_clearroi rx_dbitlist rx_dbitoffset rx_dbitreorder rx_discardpolicy rx_fifodepth rx_frameindex rx_framescaught rx_framesperfile rx_hostname rx_jsonaddheader rx_jsonpara rx_lastclient rx_lock rx_missingpackets rx_padding rx_printconfig rx_realudpsocksize rx_roi rx_silent rx_start rx_status rx_stop rx_tcpport rx_threads rx_udpsocksize rx_version rx_zmqfreq rx_zmqhwm rx_zmqip rx_zmqport rx_zmqstartfnum rx_zmqstream samples savepattern scan scanerrmsg selinterface serialnumber setbit settings settingslist settingspath signalindex signallist signalname sleep slowadc slowadcindex slowadclist slowadcname slowadcvalues start status stop stopport storagecell_delay storagecell_start subdeadtime subexptime sync syncclk temp_10ge temp_adc temp_control temp_dcdc temp_event temp_fpga temp_fpgaext temp_fpgafl temp_fpgafr temp_slowadc temp_sodl temp_sodr temp_threshold templist tempvalues tengiga threshold thresholdnotb timing timing_info_decoder timinglist timingsource top transceiverenable trigger triggers triggersl trimbits trimen trimval tsamples txdelay txdelay_frame txdelay_left txdelay_right type udp_cleardst udp_dstip udp_dstip2 udp_dstlist udp_dstmac udp_dstmac2 udp_dstport udp_dstport2 udp_firstdst udp_numdst udp_reconfigure udp_srcip udp_srcip2 udp_srcmac udp_srcmac2 udp_validate update updatedetectorserver updatekernel updatemode user v_a v_b v_c v_chip v_d v_io v_limit vchip_comp_adc vchip_comp_fe vchip_cs vchip_opa_1st vchip_opa_fd vchip_ref_comp_fe versions veto vetoalg vetofile vetophoton vetoref vetostream virtual vm_a vm_b vm_c vm_d vm_io zmqhwm zmqip zmqport "
|
||||
__acquire() {
|
||||
FCN_RETURN=""
|
||||
return 0
|
||||
@ -2088,6 +2088,15 @@ fi
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
__rx_dbitreorder() {
|
||||
FCN_RETURN=""
|
||||
if [[ ${IS_GET} -eq 0 ]]; then
|
||||
if [[ "${cword}" == "2" ]]; then
|
||||
FCN_RETURN="0 1"
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
__rx_discardpolicy() {
|
||||
FCN_RETURN=""
|
||||
if [[ ${IS_GET} -eq 0 ]]; then
|
||||
|
@ -4,7 +4,7 @@
|
||||
_sd() {
|
||||
|
||||
|
||||
local SLS_COMMANDS=" acquire activate adcclk adcenable adcenable10g adcindex adcinvert adclist adcname adcphase adcpipeline adcreg adcvpp apulse asamples autocompdisable badchannels blockingtrigger burstmode burstperiod bursts burstsl bustest cdsgain chipversion clearbit clearbusy clientversion clkdiv clkfreq clkphase collectionmode column compdisabletime confadc config configtransceiver counters currentsource dac dacindex daclist dacname dacvalues datastream dbitclk dbitphase dbitpipeline defaultdac defaultpattern delay delayl detectorserverversion detsize diodelay dpulse dr drlist dsamples execcommand exptime exptime1 exptime2 exptime3 extrastoragecells extsampling extsamplingsrc extsig fformat filtercells filterresistor findex firmwaretest firmwareversion fliprows flowcontrol10g fmaster fname foverwrite fpath framecounter frames framesl frametime free fwrite gaincaps gainmode gappixels gatedelay gatedelay1 gatedelay2 gatedelay3 gates getbit hardwareversion highvoltage hostname im_a im_b im_c im_d im_io imagetest initialchecks inj_ch interpolation interruptsubframe kernelversion lastclient led lock master maxadcphaseshift maxclkphaseshift maxdbitphaseshift measuredperiod measuredsubperiod moduleid nextframenumber nmod numinterfaces overflow packageversion parallel parameters partialreset patfname patioctrl patlimits patloop patloop0 patloop1 patloop2 patmask patnloop patnloop0 patnloop1 patnloop2 patsetbit pattern patternstart patwait patwait0 patwait1 patwait2 patwaittime patwaittime0 patwaittime1 patwaittime2 patword pedestalmode period periodl polarity port powerchip powerindex powerlist powername powervalues programfpga pulse pulsechip pulsenmove pumpprobe quad ratecorr readnrows readout readoutspeed readoutspeedlist rebootcontroller reg resetdacs resetfpga romode row runclk runtime rx_arping rx_clearroi rx_dbitlist rx_dbitoffset rx_discardpolicy rx_fifodepth rx_frameindex rx_framescaught rx_framesperfile rx_hostname rx_jsonaddheader rx_jsonpara rx_lastclient rx_lock rx_missingpackets rx_padding rx_printconfig rx_realudpsocksize rx_roi rx_silent rx_start rx_status rx_stop rx_tcpport rx_threads rx_udpsocksize rx_version rx_zmqfreq rx_zmqhwm rx_zmqip rx_zmqport rx_zmqstartfnum rx_zmqstream samples savepattern scan scanerrmsg selinterface serialnumber setbit settings settingslist settingspath signalindex signallist signalname sleep slowadc slowadcindex slowadclist slowadcname slowadcvalues start status stop stopport storagecell_delay storagecell_start subdeadtime subexptime sync syncclk temp_10ge temp_adc temp_control temp_dcdc temp_event temp_fpga temp_fpgaext temp_fpgafl temp_fpgafr temp_slowadc temp_sodl temp_sodr temp_threshold templist tempvalues tengiga threshold thresholdnotb timing timing_info_decoder timinglist timingsource top transceiverenable trigger triggers triggersl trimbits trimen trimval tsamples txdelay txdelay_frame txdelay_left txdelay_right type udp_cleardst udp_dstip udp_dstip2 udp_dstlist udp_dstmac udp_dstmac2 udp_dstport udp_dstport2 udp_firstdst udp_numdst udp_reconfigure udp_srcip udp_srcip2 udp_srcmac udp_srcmac2 udp_validate update updatedetectorserver updatekernel updatemode user v_a v_b v_c v_chip v_d v_io v_limit vchip_comp_adc vchip_comp_fe vchip_cs vchip_opa_1st vchip_opa_fd vchip_ref_comp_fe versions veto vetoalg vetofile vetophoton vetoref vetostream virtual vm_a vm_b vm_c vm_d vm_io zmqhwm zmqip zmqport "
|
||||
local SLS_COMMANDS=" acquire activate adcclk adcenable adcenable10g adcindex adcinvert adclist adcname adcphase adcpipeline adcreg adcvpp apulse asamples autocompdisable badchannels blockingtrigger burstmode burstperiod bursts burstsl bustest cdsgain chipversion clearbit clearbusy clientversion clkdiv clkfreq clkphase collectionmode column compdisabletime confadc config configtransceiver counters currentsource dac dacindex daclist dacname dacvalues datastream dbitclk dbitphase dbitpipeline defaultdac defaultpattern delay delayl detectorserverversion detsize diodelay dpulse dr drlist dsamples execcommand exptime exptime1 exptime2 exptime3 extrastoragecells extsampling extsamplingsrc extsig fformat filtercells filterresistor findex firmwaretest firmwareversion fliprows flowcontrol10g fmaster fname foverwrite fpath framecounter frames framesl frametime free fwrite gaincaps gainmode gappixels gatedelay gatedelay1 gatedelay2 gatedelay3 gates getbit hardwareversion highvoltage hostname im_a im_b im_c im_d im_io imagetest initialchecks inj_ch interpolation interruptsubframe kernelversion lastclient led lock master maxadcphaseshift maxclkphaseshift maxdbitphaseshift measuredperiod measuredsubperiod moduleid nextframenumber nmod numinterfaces overflow packageversion parallel parameters partialreset patfname patioctrl patlimits patloop patloop0 patloop1 patloop2 patmask patnloop patnloop0 patnloop1 patnloop2 patsetbit pattern patternstart patwait patwait0 patwait1 patwait2 patwaittime patwaittime0 patwaittime1 patwaittime2 patword pedestalmode period periodl polarity port powerchip powerindex powerlist powername powervalues programfpga pulse pulsechip pulsenmove pumpprobe quad ratecorr readnrows readout readoutspeed readoutspeedlist rebootcontroller reg resetdacs resetfpga romode row runclk runtime rx_arping rx_clearroi rx_dbitlist rx_dbitoffset rx_dbitreorder rx_discardpolicy rx_fifodepth rx_frameindex rx_framescaught rx_framesperfile rx_hostname rx_jsonaddheader rx_jsonpara rx_lastclient rx_lock rx_missingpackets rx_padding rx_printconfig rx_realudpsocksize rx_roi rx_silent rx_start rx_status rx_stop rx_tcpport rx_threads rx_udpsocksize rx_version rx_zmqfreq rx_zmqhwm rx_zmqip rx_zmqport rx_zmqstartfnum rx_zmqstream samples savepattern scan scanerrmsg selinterface serialnumber setbit settings settingslist settingspath signalindex signallist signalname sleep slowadc slowadcindex slowadclist slowadcname slowadcvalues start status stop stopport storagecell_delay storagecell_start subdeadtime subexptime sync syncclk temp_10ge temp_adc temp_control temp_dcdc temp_event temp_fpga temp_fpgaext temp_fpgafl temp_fpgafr temp_slowadc temp_sodl temp_sodr temp_threshold templist tempvalues tengiga threshold thresholdnotb timing timing_info_decoder timinglist timingsource top transceiverenable trigger triggers triggersl trimbits trimen trimval tsamples txdelay txdelay_frame txdelay_left txdelay_right type udp_cleardst udp_dstip udp_dstip2 udp_dstlist udp_dstmac udp_dstmac2 udp_dstport udp_dstport2 udp_firstdst udp_numdst udp_reconfigure udp_srcip udp_srcip2 udp_srcmac udp_srcmac2 udp_validate update updatedetectorserver updatekernel updatemode user v_a v_b v_c v_chip v_d v_io v_limit vchip_comp_adc vchip_comp_fe vchip_cs vchip_opa_1st vchip_opa_fd vchip_ref_comp_fe versions veto vetoalg vetofile vetophoton vetoref vetostream virtual vm_a vm_b vm_c vm_d vm_io zmqhwm zmqip zmqport "
|
||||
__acquire() {
|
||||
FCN_RETURN=""
|
||||
return 0
|
||||
@ -2012,6 +2012,15 @@ fi
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
__rx_dbitreorder() {
|
||||
FCN_RETURN=""
|
||||
if [[ ${IS_GET} -eq 0 ]]; then
|
||||
if [[ "${cword}" == "2" ]]; then
|
||||
FCN_RETURN="0 1"
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
__rx_discardpolicy() {
|
||||
FCN_RETURN=""
|
||||
if [[ ${IS_GET} -eq 0 ]]; then
|
||||
|
@ -1412,6 +1412,18 @@ lock:
|
||||
function: setDetectorLock
|
||||
input_types: [ bool ]
|
||||
|
||||
|
||||
rx_dbitreorder:
|
||||
help: "[0, 1]\n\t[Ctb] Reorder digital data such that it groups each signal (0-63) from all the different samples together . Default is 1. Setting to 0 means 'do not reorder' and to keep what the board spits out, which is that all signals in a sample are grouped together."
|
||||
inherit_actions: INTEGER_COMMAND_VEC_ID
|
||||
actions:
|
||||
GET:
|
||||
function: getRxDbitReorder
|
||||
PUT:
|
||||
function: setRxDbitReorder
|
||||
input_types: [ bool ]
|
||||
|
||||
|
||||
################# INTEGER_COMMAND_VEC_ID_GET #################
|
||||
|
||||
master:
|
||||
|
@ -8305,6 +8305,48 @@ rx_dbitoffset:
|
||||
help: "[n_bytes]\n\t[Ctb] Offset in bytes in digital data to skip in receiver."
|
||||
infer_action: true
|
||||
template: true
|
||||
rx_dbitreorder:
|
||||
actions:
|
||||
GET:
|
||||
args:
|
||||
- arg_types: []
|
||||
argc: 0
|
||||
cast_input: []
|
||||
check_det_id: false
|
||||
convert_det_id: true
|
||||
function: getRxDbitReorder
|
||||
input: []
|
||||
input_types: []
|
||||
output:
|
||||
- OutString(t)
|
||||
require_det_id: true
|
||||
store_result_in_t: true
|
||||
PUT:
|
||||
args:
|
||||
- arg_types:
|
||||
- bool
|
||||
argc: 1
|
||||
cast_input:
|
||||
- true
|
||||
check_det_id: false
|
||||
convert_det_id: true
|
||||
function: setRxDbitReorder
|
||||
input:
|
||||
- args[0]
|
||||
input_types:
|
||||
- bool
|
||||
output:
|
||||
- args.front()
|
||||
require_det_id: true
|
||||
store_result_in_t: false
|
||||
command_name: rx_dbitreorder
|
||||
function_alias: rx_dbitreorder
|
||||
help: "[0, 1]\n\t[Ctb] Reorder digital data such that it groups each signal (0-63)\
|
||||
\ from all the different samples together . Default is 1. Setting to 0 means 'do\
|
||||
\ not reorder' and to keep what the board spits out, which is that all signals\
|
||||
\ in a sample are grouped together."
|
||||
infer_action: true
|
||||
template: true
|
||||
rx_discardpolicy:
|
||||
actions:
|
||||
GET:
|
||||
|
@ -1729,6 +1729,16 @@ class Detector {
|
||||
/** [CTB] Set number of bytes of digital data to skip in the Receiver */
|
||||
void setRxDbitOffset(int value, Positions pos = {});
|
||||
|
||||
/** [CTB] */
|
||||
Result<bool> getRxDbitReorder(Positions pos = {}) const;
|
||||
|
||||
/** [CTB] Reorder digital data such that it groups each signal (0-63)
|
||||
* from all the different samples together.
|
||||
* Default is true. Setting to false means 'do not reorder' and to keep what
|
||||
* the board spits out, which is that all signals in a sample are grouped
|
||||
* together */
|
||||
void setRxDbitReorder(bool reorder, Positions pos = {});
|
||||
|
||||
/**
|
||||
* [CTB] Set Digital IO Delay
|
||||
* cannot get
|
||||
|
@ -10700,6 +10700,68 @@ std::string Caller::rx_dbitoffset(int action) {
|
||||
return os.str();
|
||||
}
|
||||
|
||||
std::string Caller::rx_dbitreorder(int action) {
|
||||
|
||||
std::ostringstream os;
|
||||
// print help
|
||||
if (action == slsDetectorDefs::HELP_ACTION) {
|
||||
os << R"V0G0N([0, 1]
|
||||
[Ctb] Reorder digital data such that it groups each signal (0-63) from all the different samples together . Default is 1. Setting to 0 means 'do not reorder' and to keep what the board spits out, which is that all signals in a sample are grouped together. )V0G0N"
|
||||
<< std::endl;
|
||||
return os.str();
|
||||
}
|
||||
|
||||
// check if action and arguments are valid
|
||||
if (action == slsDetectorDefs::GET_ACTION) {
|
||||
if (1 && args.size() != 0) {
|
||||
throw RuntimeError("Wrong number of arguments for action GET");
|
||||
}
|
||||
|
||||
if (args.size() == 0) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else if (action == slsDetectorDefs::PUT_ACTION) {
|
||||
if (1 && args.size() != 1) {
|
||||
throw RuntimeError("Wrong number of arguments for action PUT");
|
||||
}
|
||||
|
||||
if (args.size() == 1) {
|
||||
try {
|
||||
StringTo<bool>(args[0]);
|
||||
} catch (...) {
|
||||
throw RuntimeError("Could not convert argument 0 to bool");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
throw RuntimeError("INTERNAL ERROR: Invalid action: supported actions "
|
||||
"are ['GET', 'PUT']");
|
||||
}
|
||||
|
||||
// generate code for each action
|
||||
if (action == slsDetectorDefs::GET_ACTION) {
|
||||
if (args.size() == 0) {
|
||||
auto t = det->getRxDbitReorder(std::vector<int>{det_id});
|
||||
os << OutString(t) << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
if (action == slsDetectorDefs::PUT_ACTION) {
|
||||
if (args.size() == 1) {
|
||||
auto arg0 = StringTo<bool>(args[0]);
|
||||
det->setRxDbitReorder(arg0, std::vector<int>{det_id});
|
||||
os << args.front() << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
std::string Caller::rx_discardpolicy(int action) {
|
||||
|
||||
std::ostringstream os;
|
||||
|
@ -236,6 +236,7 @@ class Caller {
|
||||
std::string rx_clearroi(int action);
|
||||
std::string rx_dbitlist(int action);
|
||||
std::string rx_dbitoffset(int action);
|
||||
std::string rx_dbitreorder(int action);
|
||||
std::string rx_discardpolicy(int action);
|
||||
std::string rx_fifodepth(int action);
|
||||
std::string rx_frameindex(int action);
|
||||
@ -582,6 +583,7 @@ class Caller {
|
||||
{"rx_clearroi", &Caller::rx_clearroi},
|
||||
{"rx_dbitlist", &Caller::rx_dbitlist},
|
||||
{"rx_dbitoffset", &Caller::rx_dbitoffset},
|
||||
{"rx_dbitreorder", &Caller::rx_dbitreorder},
|
||||
{"rx_discardpolicy", &Caller::rx_discardpolicy},
|
||||
{"rx_fifodepth", &Caller::rx_fifodepth},
|
||||
{"rx_frameindex", &Caller::rx_frameindex},
|
||||
|
@ -84,7 +84,7 @@ int main(int argc, char *argv[]) {
|
||||
c.call(parser.command(), parser.arguments(), parser.detector_id(),
|
||||
action, std::cout, parser.receiver_id());
|
||||
} catch (sls::RuntimeError &e) {
|
||||
return EXIT_FAILURE;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
@ -2277,6 +2277,14 @@ void Detector::setRxDbitOffset(int value, Positions pos) {
|
||||
pimpl->Parallel(&Module::setReceiverDbitOffset, pos, value);
|
||||
}
|
||||
|
||||
Result<bool> Detector::getRxDbitReorder(Positions pos) const {
|
||||
return pimpl->Parallel(&Module::getReceiverDbitReorder, pos);
|
||||
}
|
||||
|
||||
void Detector::setRxDbitReorder(bool reorder, Positions pos) {
|
||||
pimpl->Parallel(&Module::setReceiverDbitReorder, pos, reorder);
|
||||
}
|
||||
|
||||
void Detector::setDigitalIODelay(uint64_t pinMask, int delay, Positions pos) {
|
||||
pimpl->Parallel(&Module::setDigitalIODelay, pos, pinMask, delay);
|
||||
}
|
||||
|
@ -2509,6 +2509,15 @@ void Module::setReceiverDbitOffset(int value) {
|
||||
sendToReceiver(F_SET_RECEIVER_DBIT_OFFSET, value, nullptr);
|
||||
}
|
||||
|
||||
bool Module::getReceiverDbitReorder() const {
|
||||
return sendToReceiver<int>(F_GET_RECEIVER_DBIT_REORDER);
|
||||
}
|
||||
|
||||
void Module::setReceiverDbitReorder(bool reorder) {
|
||||
sendToReceiver(F_SET_RECEIVER_DBIT_REORDER, static_cast<int>(reorder),
|
||||
nullptr);
|
||||
}
|
||||
|
||||
void Module::setDigitalIODelay(uint64_t pinMask, int delay) {
|
||||
uint64_t args[]{pinMask, static_cast<uint64_t>(delay)};
|
||||
sendToDetector(F_DIGITAL_IO_DELAY, args, nullptr);
|
||||
|
@ -510,6 +510,8 @@ class Module : public virtual slsDetectorDefs {
|
||||
void setReceiverDbitList(std::vector<int> list);
|
||||
int getReceiverDbitOffset() const;
|
||||
void setReceiverDbitOffset(int value);
|
||||
bool getReceiverDbitReorder() const;
|
||||
void setReceiverDbitReorder(bool value);
|
||||
void setDigitalIODelay(uint64_t pinMask, int delay);
|
||||
bool getLEDEnable() const;
|
||||
void setLEDEnable(bool enable);
|
||||
|
@ -2568,6 +2568,22 @@ int InferAction::rx_dbitoffset() {
|
||||
}
|
||||
}
|
||||
|
||||
int InferAction::rx_dbitreorder() {
|
||||
|
||||
if (args.size() == 0) {
|
||||
return slsDetectorDefs::GET_ACTION;
|
||||
}
|
||||
|
||||
if (args.size() == 1) {
|
||||
return slsDetectorDefs::PUT_ACTION;
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
throw RuntimeError("Could not infer action: Wrong number of arguments");
|
||||
}
|
||||
}
|
||||
|
||||
int InferAction::rx_discardpolicy() {
|
||||
|
||||
if (args.size() == 0) {
|
||||
|
@ -193,6 +193,7 @@ class InferAction {
|
||||
int rx_clearroi();
|
||||
int rx_dbitlist();
|
||||
int rx_dbitoffset();
|
||||
int rx_dbitreorder();
|
||||
int rx_discardpolicy();
|
||||
int rx_fifodepth();
|
||||
int rx_frameindex();
|
||||
@ -527,6 +528,7 @@ class InferAction {
|
||||
{"rx_clearroi", &InferAction::rx_clearroi},
|
||||
{"rx_dbitlist", &InferAction::rx_dbitlist},
|
||||
{"rx_dbitoffset", &InferAction::rx_dbitoffset},
|
||||
{"rx_dbitreorder", &InferAction::rx_dbitreorder},
|
||||
{"rx_discardpolicy", &InferAction::rx_discardpolicy},
|
||||
{"rx_fifodepth", &InferAction::rx_fifodepth},
|
||||
{"rx_frameindex", &InferAction::rx_frameindex},
|
||||
|
@ -445,23 +445,25 @@ TEST_CASE("rx_arping", "[.cmdcall][.rx]") {
|
||||
Detector det;
|
||||
Caller caller(&det);
|
||||
auto prev_val = det.getRxArping();
|
||||
{
|
||||
std::ostringstream oss;
|
||||
caller.call("rx_arping", {"1"}, -1, PUT, oss);
|
||||
REQUIRE(oss.str() == "rx_arping 1\n");
|
||||
}
|
||||
{
|
||||
std::ostringstream oss;
|
||||
caller.call("rx_arping", {}, -1, GET, oss);
|
||||
REQUIRE(oss.str() == "rx_arping 1\n");
|
||||
}
|
||||
{
|
||||
std::ostringstream oss;
|
||||
caller.call("rx_arping", {"0"}, -1, PUT, oss);
|
||||
REQUIRE(oss.str() == "rx_arping 0\n");
|
||||
}
|
||||
for (int i = 0; i != det.size(); ++i) {
|
||||
det.setRxArping(prev_val[i], {i});
|
||||
if (det.getDestinationUDPIP()[0].str() != "127.0.0.1") {
|
||||
{
|
||||
std::ostringstream oss;
|
||||
caller.call("rx_arping", {"1"}, -1, PUT, oss);
|
||||
REQUIRE(oss.str() == "rx_arping 1\n");
|
||||
}
|
||||
{
|
||||
std::ostringstream oss;
|
||||
caller.call("rx_arping", {}, -1, GET, oss);
|
||||
REQUIRE(oss.str() == "rx_arping 1\n");
|
||||
}
|
||||
{
|
||||
std::ostringstream oss;
|
||||
caller.call("rx_arping", {"0"}, -1, PUT, oss);
|
||||
REQUIRE(oss.str() == "rx_arping 0\n");
|
||||
}
|
||||
for (int i = 0; i != det.size(); ++i) {
|
||||
det.setRxArping(prev_val[i], {i});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -583,6 +585,9 @@ TEST_CASE("fpath", "[.cmdcall]") {
|
||||
REQUIRE(oss.str() == "fpath /tmp\n");
|
||||
}
|
||||
for (int i = 0; i != det.size(); ++i) {
|
||||
if (prev_val[i].empty()) {
|
||||
continue;
|
||||
}
|
||||
det.setFilePath(prev_val[i], {i});
|
||||
}
|
||||
}
|
||||
@ -956,6 +961,37 @@ TEST_CASE("rx_dbitoffset", "[.cmdcall][.rx]") {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("rx_dbitreorder", "[.cmdcall][.rx]") {
|
||||
Detector det;
|
||||
Caller caller(&det);
|
||||
auto det_type = det.getDetectorType().squash();
|
||||
if (det_type == defs::CHIPTESTBOARD ||
|
||||
det_type == defs::XILINX_CHIPTESTBOARD) {
|
||||
auto prev_val = det.getRxDbitReorder();
|
||||
{
|
||||
std::ostringstream oss;
|
||||
caller.call("rx_dbitreorder", {"0"}, -1, PUT, oss);
|
||||
REQUIRE(oss.str() == "rx_dbitreorder 0\n");
|
||||
}
|
||||
{
|
||||
std::ostringstream oss;
|
||||
caller.call("rx_dbitreorder", {"1"}, -1, PUT, oss);
|
||||
REQUIRE(oss.str() == "rx_dbitreorder 1\n");
|
||||
}
|
||||
{
|
||||
std::ostringstream oss;
|
||||
caller.call("rx_dbitreorder", {}, -1, GET, oss);
|
||||
REQUIRE(oss.str() == "rx_dbitreorder 1\n");
|
||||
}
|
||||
REQUIRE_THROWS(caller.call("rx_dbitreorder", {"15"}, -1, PUT));
|
||||
for (int i = 0; i != det.size(); ++i) {
|
||||
det.setRxDbitReorder(prev_val[i], {i});
|
||||
}
|
||||
} else {
|
||||
REQUIRE_THROWS(caller.call("rx_dbitreorder", {}, -1, GET));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("rx_jsonaddheader", "[.cmdcall][.rx]") {
|
||||
Detector det;
|
||||
Caller caller(&det);
|
||||
|
@ -18,11 +18,16 @@ struct Data {
|
||||
constexpr int shm_id = 10;
|
||||
|
||||
TEST_CASE("Create SharedMemory read and write", "[detector]") {
|
||||
const char *env_p = std::getenv("SLSDETNAME");
|
||||
std::string env_name = env_p ? ("_" + std::string(env_p)) : "";
|
||||
|
||||
SharedMemory<Data> shm(shm_id, -1);
|
||||
if (shm.exists()) {
|
||||
shm.removeSharedMemory();
|
||||
}
|
||||
shm.createSharedMemory();
|
||||
CHECK(shm.getName() == std::string("/slsDetectorPackage_detector_") +
|
||||
std::to_string(shm_id));
|
||||
std::to_string(shm_id) + env_name);
|
||||
|
||||
shm()->x = 3;
|
||||
shm()->y = 5.7;
|
||||
@ -90,10 +95,12 @@ TEST_CASE("Open two shared memories to the same place", "[detector]") {
|
||||
}
|
||||
|
||||
TEST_CASE("Move SharedMemory", "[detector]") {
|
||||
const char *env_p = std::getenv("SLSDETNAME");
|
||||
std::string env_name = env_p ? ("_" + std::string(env_p)) : "";
|
||||
|
||||
SharedMemory<Data> shm(shm_id, -1);
|
||||
CHECK(shm.getName() == std::string("/slsDetectorPackage_detector_") +
|
||||
std::to_string(shm_id));
|
||||
std::to_string(shm_id) + env_name);
|
||||
shm.createSharedMemory();
|
||||
shm()->x = 9;
|
||||
|
||||
@ -104,15 +111,19 @@ TEST_CASE("Move SharedMemory", "[detector]") {
|
||||
REQUIRE_THROWS(
|
||||
shm()); // trying to access should throw instead of returning a nullptr
|
||||
CHECK(shm2.getName() == std::string("/slsDetectorPackage_detector_") +
|
||||
std::to_string(shm_id));
|
||||
std::to_string(shm_id) + env_name);
|
||||
shm2.removeSharedMemory();
|
||||
}
|
||||
|
||||
TEST_CASE("Create several shared memories", "[detector]") {
|
||||
const char *env_p = std::getenv("SLSDETNAME");
|
||||
std::string env_name = env_p ? ("_" + std::string(env_p)) : "";
|
||||
|
||||
constexpr int N = 5;
|
||||
std::vector<SharedMemory<int>> v;
|
||||
v.reserve(N);
|
||||
for (int i = 0; i != N; ++i) {
|
||||
std::cout << "i:" << i << std::endl;
|
||||
v.emplace_back(shm_id + i, -1);
|
||||
CHECK(v[i].exists() == false);
|
||||
v[i].createSharedMemory();
|
||||
@ -123,7 +134,7 @@ TEST_CASE("Create several shared memories", "[detector]") {
|
||||
for (int i = 0; i != N; ++i) {
|
||||
CHECK(*v[i]() == i);
|
||||
CHECK(v[i].getName() == std::string("/slsDetectorPackage_detector_") +
|
||||
std::to_string(i + shm_id));
|
||||
std::to_string(i + shm_id) + env_name);
|
||||
}
|
||||
|
||||
for (int i = 0; i != N; ++i) {
|
||||
@ -133,8 +144,12 @@ TEST_CASE("Create several shared memories", "[detector]") {
|
||||
}
|
||||
|
||||
TEST_CASE("Create create a shared memory with a tag") {
|
||||
const char *env_p = std::getenv("SLSDETNAME");
|
||||
std::string env_name = env_p ? ("_" + std::string(env_p)) : "";
|
||||
|
||||
SharedMemory<int> shm(0, -1, "ctbdacs");
|
||||
REQUIRE(shm.getName() == "/slsDetectorPackage_detector_0_ctbdacs");
|
||||
REQUIRE(shm.getName() ==
|
||||
"/slsDetectorPackage_detector_0" + env_name + "_ctbdacs");
|
||||
}
|
||||
|
||||
TEST_CASE("Create create a shared memory with a tag when SLSDETNAME is set") {
|
||||
|
@ -13,12 +13,22 @@ class Receiver : private virtual slsDetectorDefs {
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* Starts up a Receiver server.
|
||||
* Assembles a Receiver using TCP and UDP detector interfaces
|
||||
* Starts up a Receiver server. Reads configuration file, options, and
|
||||
* assembles a Receiver using TCP and UDP detector interfaces
|
||||
* throws an exception in case of failure
|
||||
* @param port TCP/IP port number
|
||||
* @param argc from command line
|
||||
* @param argv from command line
|
||||
*/
|
||||
Receiver(uint16_t port = 1954);
|
||||
Receiver(int argc, char *argv[]);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Starts up a Receiver server. Reads configuration file, options, and
|
||||
* assembles a Receiver using TCP and UDP detector interfaces
|
||||
* throws an exception in case of failure
|
||||
* @param tcpip_port_no TCP/IP port number
|
||||
*/
|
||||
Receiver(uint16_t tcpip_port_no = 1954);
|
||||
|
||||
~Receiver();
|
||||
|
||||
|
@ -218,6 +218,8 @@ int ClientInterface::functionTable(){
|
||||
flist[F_RECEIVER_SET_TRANSCEIVER_MASK] = &ClientInterface::set_transceiver_mask;
|
||||
flist[F_RECEIVER_SET_ROW] = &ClientInterface::set_row;
|
||||
flist[F_RECEIVER_SET_COLUMN] = &ClientInterface::set_column;
|
||||
flist[F_GET_RECEIVER_DBIT_REORDER] = &ClientInterface::get_dbit_reorder;
|
||||
flist[F_SET_RECEIVER_DBIT_REORDER] = &ClientInterface::set_dbit_reorder;
|
||||
|
||||
|
||||
for (int i = NUM_DET_FUNCTIONS + 1; i < NUM_REC_FUNCTIONS ; i++) {
|
||||
@ -1789,4 +1791,25 @@ int ClientInterface::set_column(Interface &socket) {
|
||||
return socket.Send(OK);
|
||||
}
|
||||
|
||||
int ClientInterface::get_dbit_reorder(Interface &socket) {
|
||||
if (detType != CHIPTESTBOARD && detType != XILINX_CHIPTESTBOARD)
|
||||
functionNotImplemented();
|
||||
int retval = impl()->getDbitReorder();
|
||||
LOG(logDEBUG1) << "Dbit reorder retval: " << retval;
|
||||
return socket.sendResult(retval);
|
||||
}
|
||||
|
||||
int ClientInterface::set_dbit_reorder(Interface &socket) {
|
||||
auto arg = socket.Receive<int>();
|
||||
if (detType != CHIPTESTBOARD && detType != XILINX_CHIPTESTBOARD)
|
||||
functionNotImplemented();
|
||||
if (arg < 0) {
|
||||
throw RuntimeError("Invalid dbit reorder: " + std::to_string(arg));
|
||||
}
|
||||
verifyIdle(socket);
|
||||
LOG(logDEBUG1) << "Setting Dbit reorder: " << arg;
|
||||
impl()->setDbitReorder(arg);
|
||||
return socket.Send(OK);
|
||||
}
|
||||
|
||||
} // namespace sls
|
||||
|
@ -164,6 +164,8 @@ class ClientInterface : private virtual slsDetectorDefs {
|
||||
int set_transceiver_mask(ServerInterface &socket);
|
||||
int set_row(ServerInterface &socket);
|
||||
int set_column(ServerInterface &socket);
|
||||
int get_dbit_reorder(ServerInterface &socket);
|
||||
int set_dbit_reorder(ServerInterface &socket);
|
||||
|
||||
Implementation *impl() {
|
||||
if (receiver != nullptr) {
|
||||
|
@ -3,7 +3,7 @@
|
||||
/************************************************
|
||||
* @file DataProcessor.cpp
|
||||
* @short creates data processor thread that
|
||||
* pulls pointers to memory addresses from fifos
|
||||
* pulls pointers to memory addresses from fifos
|
||||
* and processes data stored in them & writes them to file
|
||||
***********************************************/
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <numeric>
|
||||
|
||||
namespace sls {
|
||||
|
||||
@ -71,12 +72,6 @@ void DataProcessor::SetStreamingStartFnum(uint32_t value) {
|
||||
|
||||
void DataProcessor::SetFramePadding(bool enable) { framePadding = enable; }
|
||||
|
||||
void DataProcessor::SetCtbDbitList(std::vector<int> value) {
|
||||
ctbDbitList = value;
|
||||
}
|
||||
|
||||
void DataProcessor::SetCtbDbitOffset(int value) { ctbDbitOffset = value; }
|
||||
|
||||
void DataProcessor::SetQuadEnable(bool value) { quadEnable = value; }
|
||||
|
||||
void DataProcessor::SetFlipRows(bool fd) {
|
||||
@ -213,8 +208,9 @@ std::string DataProcessor::CreateVirtualFile(
|
||||
"Skipping virtual hdf5 file since rx_roi is enabled.");
|
||||
}
|
||||
|
||||
bool gotthard25um =
|
||||
(generalData->detType == GOTTHARD2 && (numModX * numModY) == 2);
|
||||
bool gotthard25um = ((generalData->detType == GOTTHARD ||
|
||||
generalData->detType == GOTTHARD2) &&
|
||||
(numModX * numModY) == 2);
|
||||
|
||||
// 0 for infinite files
|
||||
uint32_t framesPerFile =
|
||||
@ -299,7 +295,7 @@ void DataProcessor::ThreadExecution() {
|
||||
memImage->data);
|
||||
} catch (const std::exception &e) {
|
||||
fifo->FreeAddress(buffer);
|
||||
return;
|
||||
throw RuntimeError(e.what());
|
||||
}
|
||||
|
||||
// stream (if time/freq to stream) or free
|
||||
@ -332,6 +328,7 @@ void DataProcessor::StopProcessing(char *buf) {
|
||||
|
||||
void DataProcessor::ProcessAnImage(sls_receiver_header &header, size_t &size,
|
||||
size_t &firstImageIndex, char *data) {
|
||||
|
||||
uint64_t fnum = header.detHeader.frameNumber;
|
||||
LOG(logDEBUG1) << "DataProcessing " << index << ": fnum:" << fnum;
|
||||
currentFrameIndex = fnum;
|
||||
@ -355,9 +352,16 @@ void DataProcessor::ProcessAnImage(sls_receiver_header &header, size_t &size,
|
||||
if (framePadding && nump < generalData->packetsPerFrame)
|
||||
PadMissingPackets(header, data);
|
||||
|
||||
// rearrange ctb digital bits (if ctbDbitlist is not empty)
|
||||
if (!ctbDbitList.empty()) {
|
||||
RearrangeDbitData(size, data);
|
||||
// rearrange ctb digital bits
|
||||
if (!generalData->ctbDbitList.empty()) {
|
||||
ArrangeDbitData(size, data);
|
||||
} else if (generalData->ctbDbitReorder) {
|
||||
std::vector<int> ctbDbitList(64);
|
||||
std::iota(ctbDbitList.begin(), ctbDbitList.end(), 0);
|
||||
generalData->SetctbDbitList(ctbDbitList);
|
||||
ArrangeDbitData(size, data);
|
||||
} else if (generalData->ctbDbitOffset > 0) {
|
||||
RemoveTrailingBits(size, data);
|
||||
}
|
||||
|
||||
// 'stream Image' check has to be done here before crop image
|
||||
@ -519,11 +523,53 @@ void DataProcessor::PadMissingPackets(sls_receiver_header header, char *data) {
|
||||
}
|
||||
}
|
||||
|
||||
void DataProcessor::RemoveTrailingBits(size_t &size, char *data) {
|
||||
|
||||
if (!(generalData->detType == slsDetectorDefs::CHIPTESTBOARD ||
|
||||
generalData->detType == slsDetectorDefs::XILINX_CHIPTESTBOARD)) {
|
||||
throw std::runtime_error("behavior undefined for detector " +
|
||||
std::to_string(generalData->detType));
|
||||
}
|
||||
|
||||
const size_t nAnalogDataBytes = generalData->GetNumberOfAnalogDatabytes();
|
||||
const size_t nDigitalDataBytes = generalData->GetNumberOfDigitalDatabytes();
|
||||
const size_t nTransceiverDataBytes =
|
||||
generalData->GetNumberOfTransceiverDatabytes();
|
||||
const size_t ctbDbitOffset = generalData->ctbDbitOffset;
|
||||
|
||||
const size_t ctbDigitalDataBytes = nDigitalDataBytes - ctbDbitOffset;
|
||||
|
||||
// no digital data
|
||||
if (ctbDigitalDataBytes == 0) {
|
||||
LOG(logWARNING)
|
||||
<< "No digital data for call back, yet ctbDbitOffset is non zero.";
|
||||
return;
|
||||
}
|
||||
|
||||
// update size and copy data
|
||||
memmove(data + nAnalogDataBytes, data + nAnalogDataBytes + ctbDbitOffset,
|
||||
ctbDigitalDataBytes + nTransceiverDataBytes);
|
||||
|
||||
size = nAnalogDataBytes + ctbDigitalDataBytes + nTransceiverDataBytes;
|
||||
}
|
||||
|
||||
/** ctb specific */
|
||||
void DataProcessor::RearrangeDbitData(size_t &size, char *data) {
|
||||
int nAnalogDataBytes = generalData->GetNumberOfAnalogDatabytes();
|
||||
int nDigitalDataBytes = generalData->GetNumberOfDigitalDatabytes();
|
||||
int nTransceiverDataBytes = generalData->GetNumberOfTransceiverDatabytes();
|
||||
void DataProcessor::ArrangeDbitData(size_t &size, char *data) {
|
||||
|
||||
if (!(generalData->detType == slsDetectorDefs::CHIPTESTBOARD ||
|
||||
generalData->detType == slsDetectorDefs::XILINX_CHIPTESTBOARD)) {
|
||||
throw std::runtime_error("behavior undefined for detector " +
|
||||
std::to_string(generalData->detType));
|
||||
}
|
||||
|
||||
const size_t nAnalogDataBytes = generalData->GetNumberOfAnalogDatabytes();
|
||||
const size_t nDigitalDataBytes = generalData->GetNumberOfDigitalDatabytes();
|
||||
const size_t nTransceiverDataBytes =
|
||||
generalData->GetNumberOfTransceiverDatabytes();
|
||||
const size_t ctbDbitOffset = generalData->ctbDbitOffset;
|
||||
const bool ctbDbitReorder = generalData->ctbDbitReorder;
|
||||
const auto ctbDbitList = generalData->ctbDbitList;
|
||||
|
||||
// TODO! (Erik) Refactor and add tests
|
||||
int ctbDigitalDataBytes = nDigitalDataBytes - ctbDbitOffset;
|
||||
|
||||
@ -534,47 +580,101 @@ void DataProcessor::RearrangeDbitData(size_t &size, char *data) {
|
||||
return;
|
||||
}
|
||||
|
||||
char *source = (data + nAnalogDataBytes + ctbDbitOffset);
|
||||
|
||||
const int numDigitalSamples = (ctbDigitalDataBytes / sizeof(uint64_t));
|
||||
|
||||
// const int numResult8Bits = ceil((numDigitalSamples * ctbDbitList.size())
|
||||
// / 8.00);
|
||||
int numBitsPerDbit = numDigitalSamples;
|
||||
if ((numBitsPerDbit % 8) != 0)
|
||||
numBitsPerDbit += (8 - (numDigitalSamples % 8));
|
||||
const int totalNumBytes = (numBitsPerDbit / 8) * ctbDbitList.size();
|
||||
std::vector<uint8_t> result(totalNumBytes);
|
||||
int totalNumBytes =
|
||||
0; // number of bytes for selected digital data given by dtbDbitList
|
||||
|
||||
// store each selected bit from all samples consecutively
|
||||
if (ctbDbitReorder) {
|
||||
size_t numBitsPerDbit =
|
||||
numDigitalSamples; // num bits per selected digital
|
||||
// Bit for all samples
|
||||
if ((numBitsPerDbit % 8) != 0)
|
||||
numBitsPerDbit += (8 - (numDigitalSamples % 8));
|
||||
totalNumBytes = (numBitsPerDbit / 8) * ctbDbitList.size();
|
||||
}
|
||||
// store all selected bits from one sample consecutively
|
||||
else {
|
||||
size_t numBitsPerSample =
|
||||
ctbDbitList.size(); // num bits for all selected bits per sample
|
||||
if ((numBitsPerSample % 8) != 0)
|
||||
numBitsPerSample += (8 - (numBitsPerSample % 8));
|
||||
totalNumBytes = (numBitsPerSample / 8) * numDigitalSamples;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> result(totalNumBytes, 0);
|
||||
uint8_t *dest = &result[0];
|
||||
|
||||
auto *source = (uint64_t *)(data + nAnalogDataBytes + ctbDbitOffset);
|
||||
|
||||
// loop through digital bit enable vector
|
||||
int bitoffset = 0;
|
||||
for (auto bi : ctbDbitList) {
|
||||
// where numbits * numDigitalSamples is not a multiple of 8
|
||||
if (bitoffset != 0) {
|
||||
bitoffset = 0;
|
||||
++dest;
|
||||
}
|
||||
|
||||
// loop through the frame digital data
|
||||
for (auto *ptr = source; ptr < (source + numDigitalSamples);) {
|
||||
// get selected bit from each 8 bit
|
||||
uint8_t bit = (*ptr++ >> bi) & 1;
|
||||
*dest |= bit << bitoffset;
|
||||
++bitoffset;
|
||||
// extract destination in 8 bit batches
|
||||
if (bitoffset == 8) {
|
||||
if (ctbDbitReorder) {
|
||||
// loop through digital bit enable vector
|
||||
int bitoffset = 0;
|
||||
for (auto bi : ctbDbitList) {
|
||||
// where numbits * numDigitalSamples is not a multiple of 8
|
||||
if (bitoffset != 0) {
|
||||
bitoffset = 0;
|
||||
++dest;
|
||||
}
|
||||
|
||||
uint8_t byte_index = bi / 8;
|
||||
|
||||
// loop through the frame digital data
|
||||
for (auto *ptr = source + byte_index;
|
||||
ptr < (source + 8 * numDigitalSamples); ptr += 8) {
|
||||
// get selected bit from each 8 bit
|
||||
uint8_t bit = (*ptr >> bi % 8) & 1;
|
||||
*dest |= bit << bitoffset; // stored as least significant
|
||||
++bitoffset;
|
||||
// extract destination in 8 bit batches
|
||||
if (bitoffset == 8) {
|
||||
bitoffset = 0;
|
||||
++dest;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// loop through the digital data
|
||||
int bitoffset = 0;
|
||||
for (auto *ptr = source; ptr < (source + 8 * numDigitalSamples);
|
||||
ptr += 8) {
|
||||
// where bit enable vector size is not a multiple of 8
|
||||
if (bitoffset != 0) {
|
||||
bitoffset = 0;
|
||||
++dest;
|
||||
}
|
||||
|
||||
// loop through digital bit enable vector
|
||||
for (auto bi : ctbDbitList) {
|
||||
// get selected bit from each 64 bit
|
||||
uint8_t byte_index = bi / 8;
|
||||
|
||||
uint8_t bit = (*(ptr + byte_index) >> (bi % 8)) & 1;
|
||||
*dest |= bit << bitoffset;
|
||||
++bitoffset;
|
||||
// extract destination in 8 bit batches
|
||||
if (bitoffset == 8) {
|
||||
bitoffset = 0;
|
||||
++dest;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size = totalNumBytes * sizeof(uint8_t) + nAnalogDataBytes +
|
||||
nTransceiverDataBytes;
|
||||
|
||||
// check if size changed, if so move transceiver data to avoid gap in memory
|
||||
if (size != nAnalogDataBytes + nDigitalDataBytes + nTransceiverDataBytes)
|
||||
memmove(data + nAnalogDataBytes + totalNumBytes * sizeof(uint8_t),
|
||||
data + nAnalogDataBytes + nDigitalDataBytes,
|
||||
nTransceiverDataBytes);
|
||||
|
||||
// copy back to memory and update size
|
||||
memcpy(data + nAnalogDataBytes, result.data(),
|
||||
totalNumBytes * sizeof(uint8_t));
|
||||
size = totalNumBytes * sizeof(uint8_t) + nAnalogDataBytes + ctbDbitOffset +
|
||||
nTransceiverDataBytes;
|
||||
|
||||
LOG(logDEBUG1) << "totalNumBytes: " << totalNumBytes
|
||||
<< " nAnalogDataBytes:" << nAnalogDataBytes
|
||||
<< " ctbDbitOffset:" << ctbDbitOffset
|
||||
|
@ -45,8 +45,6 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject {
|
||||
void SetStreamingTimerInMs(uint32_t value);
|
||||
void SetStreamingStartFnum(uint32_t value);
|
||||
void SetFramePadding(bool enable);
|
||||
void SetCtbDbitList(std::vector<int> value);
|
||||
void SetCtbDbitOffset(int value);
|
||||
void SetQuadEnable(bool value);
|
||||
void SetFlipRows(bool fd);
|
||||
void SetNumberofTotalFrames(uint64_t value);
|
||||
@ -91,6 +89,20 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject {
|
||||
size_t &, void *),
|
||||
void *arg);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Align corresponding digital bits together (CTB only if ctbDbitlist is not
|
||||
* empty)
|
||||
* set variable reorder to true if data should be rearranged such that
|
||||
* it groups each signal (0-63) from all the different samples together
|
||||
*/
|
||||
void ArrangeDbitData(size_t &size, char *data);
|
||||
|
||||
/**
|
||||
* remove trailing bits in digital data stream
|
||||
*/
|
||||
void RemoveTrailingBits(size_t &size, char *data);
|
||||
|
||||
private:
|
||||
void RecordFirstIndex(uint64_t fnum);
|
||||
|
||||
@ -137,12 +149,6 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject {
|
||||
|
||||
void PadMissingPackets(sls_receiver_header header, char *data);
|
||||
|
||||
/**
|
||||
* Align corresponding digital bits together (CTB only if ctbDbitlist is not
|
||||
* empty)
|
||||
*/
|
||||
void RearrangeDbitData(size_t &size, char *data);
|
||||
|
||||
void CropImage(size_t &size, char *data);
|
||||
|
||||
static const std::string typeName;
|
||||
@ -162,10 +168,8 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject {
|
||||
uint32_t streamingTimerInMs;
|
||||
uint32_t streamingStartFnum;
|
||||
uint32_t currentFreqCount{0};
|
||||
struct timespec timerbegin {};
|
||||
struct timespec timerbegin{};
|
||||
bool framePadding;
|
||||
std::vector<int> ctbDbitList;
|
||||
int ctbDbitOffset;
|
||||
std::atomic<bool> startedFlag{false};
|
||||
std::atomic<uint64_t> firstIndex{0};
|
||||
bool quadEnable{false};
|
||||
|
@ -10,12 +10,10 @@
|
||||
#include "sls/container_utils.h"
|
||||
#include "sls/logger.h"
|
||||
#include "sls/sls_detector_defs.h"
|
||||
#include "sls/versionAPI.h"
|
||||
|
||||
#include <csignal> //SIGINT
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <getopt.h>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <ostream>
|
||||
@ -88,6 +86,19 @@ void cleanup() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* prints usage of this example program
|
||||
*/
|
||||
std::string getHelpMessage() {
|
||||
std::ostringstream os;
|
||||
os << "\nUsage:\n"
|
||||
"./slsFrameSynchronizer [start tcp port] [num recevers] [print "
|
||||
"callback headers (optional)]\n"
|
||||
<< "\t - tcp port has to be non-zero and 16 bit\n"
|
||||
<< "\t - print callback headers option is 0 (disabled) by default\n";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
void zmq_free(void *data, void *hint) { delete[] static_cast<char *>(data); }
|
||||
|
||||
void print_frames(const PortFrameMap &frame_port_map) {
|
||||
@ -493,115 +504,51 @@ void GetDataCallback(slsDetectorDefs::sls_receiver_header &header,
|
||||
* - Default Start TCP port is 1954
|
||||
*/
|
||||
int main(int argc, char *argv[]) {
|
||||
uint16_t startPort = DEFAULT_TCP_RX_PORTNO;
|
||||
uint16_t numReceivers = 1;
|
||||
|
||||
/** - set default values */
|
||||
int numReceivers = 1;
|
||||
uint16_t startTCPPort = DEFAULT_TCP_RX_PORTNO;
|
||||
bool printHeaders = false;
|
||||
uid_t userid = -1;
|
||||
|
||||
std::string help_message =
|
||||
"\nUsage: " + std::string(argv[0]) + " Options:\n" +
|
||||
"\t-v, --version : Version of " + std::string(argv[0]) + ".\n" +
|
||||
"\t-n, --num-receivers : Number of receivers.\n" +
|
||||
"\t-p, --port : TCP port to communicate with client for "
|
||||
"configuration. Non-zero and 16 bit.\n" +
|
||||
"\t-c, --print-headers : Print callback headers for debugging. "
|
||||
"Disabled by default.\n" +
|
||||
"\t-u, --uid : Set effective user id if receiver started "
|
||||
"with privileges. \n\n";
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"version", no_argument, nullptr, 'v'},
|
||||
{"num-receivers", required_argument, nullptr, 'n'},
|
||||
{"port", required_argument, nullptr, 'p'},
|
||||
{"print-headers", no_argument, nullptr, 'c'},
|
||||
{"uid", required_argument, nullptr, 'u'},
|
||||
{"help", no_argument, nullptr, 'h'},
|
||||
{nullptr, 0, nullptr, 0}};
|
||||
|
||||
int option_index = 0;
|
||||
int opt = 0;
|
||||
while (-1 != (opt = getopt_long(argc, argv, "vn:p:cu:h", long_options,
|
||||
&option_index))) {
|
||||
|
||||
switch (opt) {
|
||||
|
||||
case 'v':
|
||||
std::cout << argv[0] << " Version: " << APIRECEIVER << std::endl;
|
||||
return (EXIT_SUCCESS);
|
||||
|
||||
case 'n':
|
||||
try {
|
||||
numReceivers = sls::StringTo<uint16_t>(optarg);
|
||||
if (numReceivers == 0 || numReceivers > 100) {
|
||||
throw std::runtime_error("Invalid argument.");
|
||||
/** - get number of receivers and start tcp port from command line
|
||||
* arguments */
|
||||
if (argc > 1) {
|
||||
try {
|
||||
if (argc == 3 || argc == 4) {
|
||||
startTCPPort = sls::StringTo<uint16_t>(argv[1]);
|
||||
if (startTCPPort == 0) {
|
||||
throw std::runtime_error("Invalid start tcp port");
|
||||
}
|
||||
} catch (...) {
|
||||
throw sls::RuntimeError("Invalid number of receivers." +
|
||||
help_message);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
try {
|
||||
startPort = sls::StringTo<uint16_t>(optarg);
|
||||
} catch (...) {
|
||||
throw sls::RuntimeError("Could not scan port number." +
|
||||
help_message);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
printHeaders = true;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
try {
|
||||
userid = sls::StringTo<uint32_t>(optarg);
|
||||
} catch (...) {
|
||||
throw sls::RuntimeError("Invalid uid." + help_message);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
std::cout << help_message << std::endl;
|
||||
return (EXIT_SUCCESS);
|
||||
|
||||
default:
|
||||
LOG(sls::logERROR) << help_message;
|
||||
return (EXIT_FAILURE);
|
||||
numReceivers = std::stoi(argv[2]);
|
||||
if (numReceivers > 1024) {
|
||||
cprintf(RED,
|
||||
"Did you mix up the order of the arguments?\n%s\n",
|
||||
getHelpMessage().c_str());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (numReceivers == 0) {
|
||||
cprintf(RED, "Invalid number of receivers.\n%s\n",
|
||||
getHelpMessage().c_str());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (argc == 4) {
|
||||
printHeaders = sls::StringTo<bool>(argv[3]);
|
||||
if (printHeaders) {
|
||||
printHeadersLevel = sls::logINFOBLUE;
|
||||
}
|
||||
}
|
||||
} else
|
||||
throw std::runtime_error("Invalid number of arguments");
|
||||
} catch (const std::exception &e) {
|
||||
cprintf(RED, "Error: %s\n%s\n", e.what(), getHelpMessage().c_str());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
// remaining arguments
|
||||
if (optind < argc) {
|
||||
LOG(sls::logERROR) << "Invalid arguments\n" << help_message;
|
||||
return (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
LOG(sls::logINFOBLUE) << "Current Process [ Tid: " << gettid() << ']';
|
||||
LOG(sls::logINFO) << "Number of Receivers: " << numReceivers;
|
||||
LOG(sls::logINFO) << "Start TCP Port: " << startPort;
|
||||
LOG(sls::logINFO) << "Print Callback Headers: " << printHeaders;
|
||||
|
||||
// set effective id if provided
|
||||
if (userid != static_cast<uid_t>(-1)) {
|
||||
if (geteuid() == userid) {
|
||||
LOG(sls::logINFO)
|
||||
<< "Process already has the same Effective UID " << userid;
|
||||
} else {
|
||||
if (seteuid(userid) != 0) {
|
||||
std::ostringstream oss;
|
||||
oss << "Could not set Effective UID to " << userid;
|
||||
throw sls::RuntimeError(oss.str());
|
||||
}
|
||||
if (geteuid() != userid) {
|
||||
std::ostringstream oss;
|
||||
oss << "Could not set Effective UID to " << userid << ". Got "
|
||||
<< geteuid();
|
||||
throw sls::RuntimeError(oss.str());
|
||||
}
|
||||
LOG(sls::logINFO) << "Process Effective UID changed to " << userid;
|
||||
}
|
||||
}
|
||||
cprintf(RESET, "Number of Receivers: %d\n", numReceivers);
|
||||
cprintf(RESET, "Start TCP Port: %hu\n", startTCPPort);
|
||||
cprintf(RESET, "Print Callback Headers: %s\n\n",
|
||||
(printHeaders ? "Enabled" : "Disabled"));
|
||||
|
||||
/** - Catch signal SIGINT to close files and call destructors properly */
|
||||
struct sigaction sa;
|
||||
@ -638,7 +585,7 @@ int main(int argc, char *argv[]) {
|
||||
sem_init(semaphore, 1, 0);
|
||||
semaphores.push_back(semaphore);
|
||||
|
||||
uint16_t port = startPort + i;
|
||||
uint16_t port = startTCPPort + i;
|
||||
threads.emplace_back([i, semaphore, port, user_data]() {
|
||||
sls::Receiver receiver(port);
|
||||
receiver.registerCallBackStartAcquisition(StartAcquisitionCallback,
|
||||
|
@ -52,6 +52,9 @@ class GeneralData {
|
||||
uint32_t nAnalogSamples{0};
|
||||
uint32_t nDigitalSamples{0};
|
||||
uint32_t nTransceiverSamples{0};
|
||||
std::vector<int> ctbDbitList{};
|
||||
int ctbDbitOffset{0};
|
||||
bool ctbDbitReorder{false};
|
||||
slsDetectorDefs::readoutMode readoutType{slsDetectorDefs::ANALOG_ONLY};
|
||||
uint32_t adcEnableMaskOneGiga{BIT32_MASK};
|
||||
uint32_t adcEnableMaskTenGiga{BIT32_MASK};
|
||||
@ -60,8 +63,8 @@ class GeneralData {
|
||||
slsDetectorDefs::frameDiscardPolicy frameDiscardMode{
|
||||
slsDetectorDefs::NO_DISCARD};
|
||||
|
||||
GeneralData(){};
|
||||
virtual ~GeneralData(){};
|
||||
GeneralData() {};
|
||||
virtual ~GeneralData() {};
|
||||
|
||||
// Returns the pixel depth in byte, 4 bits being 0.5 byte
|
||||
float GetPixelDepth() { return float(dynamicRange) / 8; }
|
||||
@ -148,6 +151,18 @@ class GeneralData {
|
||||
virtual void SetTransceiverEnableMask(int n) {
|
||||
ThrowGenericError("SetTransceiverEnableMask");
|
||||
};
|
||||
|
||||
virtual void SetctbDbitOffset(const int n) {
|
||||
ThrowGenericError("SetctbDbitOffset");
|
||||
};
|
||||
|
||||
virtual void SetctbDbitList(const std::vector<int> &value) {
|
||||
ThrowGenericError("SetctbDbitList");
|
||||
};
|
||||
|
||||
virtual void SetctbDbitReorder(const bool reorder) {
|
||||
ThrowGenericError("SetctbDbitReorder");
|
||||
};
|
||||
};
|
||||
|
||||
class EigerData : public GeneralData {
|
||||
@ -387,6 +402,7 @@ class ChipTestBoardData : public GeneralData {
|
||||
framesPerFile = CTB_MAX_FRAMES_PER_FILE;
|
||||
fifoDepth = 2500;
|
||||
standardheader = true;
|
||||
ctbDbitReorder = true;
|
||||
UpdateImageSize();
|
||||
};
|
||||
|
||||
@ -412,6 +428,12 @@ class ChipTestBoardData : public GeneralData {
|
||||
UpdateImageSize();
|
||||
};
|
||||
|
||||
void SetctbDbitOffset(const int value) { ctbDbitOffset = value; }
|
||||
|
||||
void SetctbDbitList(const std::vector<int> &value) { ctbDbitList = value; }
|
||||
|
||||
void SetctbDbitReorder(const bool value) { ctbDbitReorder = value; }
|
||||
|
||||
void SetOneGigaAdcEnableMask(int n) {
|
||||
adcEnableMaskOneGiga = n;
|
||||
UpdateImageSize();
|
||||
@ -443,6 +465,7 @@ class ChipTestBoardData : public GeneralData {
|
||||
nDigitalBytes = 0;
|
||||
nTransceiverBytes = 0;
|
||||
int nAnalogChans = 0, nDigitalChans = 0, nTransceiverChans = 0;
|
||||
uint64_t digital_bytes_reserved = 0;
|
||||
|
||||
// analog channels (normal, analog/digital readout)
|
||||
if (readoutType == slsDetectorDefs::ANALOG_ONLY ||
|
||||
@ -461,7 +484,12 @@ class ChipTestBoardData : public GeneralData {
|
||||
readoutType == slsDetectorDefs::ANALOG_AND_DIGITAL ||
|
||||
readoutType == slsDetectorDefs::DIGITAL_AND_TRANSCEIVER) {
|
||||
nDigitalChans = NCHAN_DIGITAL;
|
||||
nDigitalBytes = (sizeof(uint64_t) * nDigitalSamples);
|
||||
// allocate enough memory to support reordering of digital bits
|
||||
uint32_t num_bytes_per_bit = (nDigitalSamples % 8 == 0)
|
||||
? nDigitalSamples / 8
|
||||
: nDigitalSamples / 8 + 1;
|
||||
digital_bytes_reserved = 64 * num_bytes_per_bit;
|
||||
nDigitalBytes = sizeof(uint64_t) * nDigitalSamples;
|
||||
LOG(logDEBUG1) << "Number of Digital Channels:" << nDigitalChans
|
||||
<< " Databytes: " << nDigitalBytes;
|
||||
}
|
||||
@ -480,7 +508,7 @@ class ChipTestBoardData : public GeneralData {
|
||||
nPixelsX = nAnalogChans + nDigitalChans + nTransceiverChans;
|
||||
dataSize = tengigaEnable ? 8144 : UDP_PACKET_DATA_BYTES;
|
||||
packetSize = headerSizeinPacket + dataSize;
|
||||
imageSize = nAnalogBytes + nDigitalBytes + nTransceiverBytes;
|
||||
imageSize = nAnalogBytes + digital_bytes_reserved + nTransceiverBytes;
|
||||
packetsPerFrame = ceil((double)imageSize / (double)dataSize);
|
||||
|
||||
LOG(logDEBUG1) << "Total Number of Channels:" << nPixelsX
|
||||
@ -512,6 +540,7 @@ class XilinxChipTestBoardData : public GeneralData {
|
||||
dataSize = 8144;
|
||||
packetSize = headerSizeinPacket + dataSize;
|
||||
tengigaEnable = true;
|
||||
ctbDbitReorder = true;
|
||||
UpdateImageSize();
|
||||
};
|
||||
|
||||
@ -537,6 +566,12 @@ class XilinxChipTestBoardData : public GeneralData {
|
||||
UpdateImageSize();
|
||||
};
|
||||
|
||||
void SetctbDbitOffset(const int value) { ctbDbitOffset = value; }
|
||||
|
||||
void SetctbDbitList(const std::vector<int> &value) { ctbDbitList = value; }
|
||||
|
||||
void SetctbDbitReorder(const bool value) { ctbDbitReorder = value; }
|
||||
|
||||
void SetOneGigaAdcEnableMask(int n) {
|
||||
adcEnableMaskOneGiga = n;
|
||||
UpdateImageSize();
|
||||
@ -563,6 +598,7 @@ class XilinxChipTestBoardData : public GeneralData {
|
||||
nDigitalBytes = 0;
|
||||
nTransceiverBytes = 0;
|
||||
int nAnalogChans = 0, nDigitalChans = 0, nTransceiverChans = 0;
|
||||
uint64_t digital_bytes_reserved = 0;
|
||||
|
||||
// analog channels (normal, analog/digital readout)
|
||||
if (readoutType == slsDetectorDefs::ANALOG_ONLY ||
|
||||
@ -580,7 +616,11 @@ class XilinxChipTestBoardData : public GeneralData {
|
||||
readoutType == slsDetectorDefs::ANALOG_AND_DIGITAL ||
|
||||
readoutType == slsDetectorDefs::DIGITAL_AND_TRANSCEIVER) {
|
||||
nDigitalChans = NCHAN_DIGITAL;
|
||||
nDigitalBytes = (sizeof(uint64_t) * nDigitalSamples);
|
||||
uint32_t num_bytes_per_bit = (nDigitalSamples % 8 == 0)
|
||||
? nDigitalSamples / 8
|
||||
: nDigitalSamples / 8 + 1;
|
||||
digital_bytes_reserved = 64 * num_bytes_per_bit;
|
||||
nDigitalBytes = sizeof(uint64_t) * nDigitalSamples;
|
||||
LOG(logDEBUG1) << "Number of Digital Channels:" << nDigitalChans
|
||||
<< " Databytes: " << nDigitalBytes;
|
||||
}
|
||||
@ -598,7 +638,7 @@ class XilinxChipTestBoardData : public GeneralData {
|
||||
}
|
||||
nPixelsX = nAnalogChans + nDigitalChans + nTransceiverChans;
|
||||
|
||||
imageSize = nAnalogBytes + nDigitalBytes + nTransceiverBytes;
|
||||
imageSize = nAnalogBytes + digital_bytes_reserved + nTransceiverBytes;
|
||||
packetsPerFrame = ceil((double)imageSize / (double)dataSize);
|
||||
|
||||
LOG(logDEBUG1) << "Total Number of Channels:" << nPixelsX
|
||||
|
@ -200,8 +200,6 @@ void Implementation::SetupDataProcessor(int i) {
|
||||
dataProcessor[i]->SetStreamingTimerInMs(streamingTimerInMs);
|
||||
dataProcessor[i]->SetStreamingStartFnum(streamingStartFnum);
|
||||
dataProcessor[i]->SetFramePadding(framePadding);
|
||||
dataProcessor[i]->SetCtbDbitList(ctbDbitList);
|
||||
dataProcessor[i]->SetCtbDbitOffset(ctbDbitOffset);
|
||||
dataProcessor[i]->SetQuadEnable(quadEnable);
|
||||
dataProcessor[i]->SetFlipRows(flipRows);
|
||||
dataProcessor[i]->SetNumberofTotalFrames(numberOfTotalFrames);
|
||||
@ -990,9 +988,11 @@ void Implementation::StartMasterWriter() {
|
||||
? 1
|
||||
: 0;
|
||||
masterAttributes.digitalSamples = generalData->nDigitalSamples;
|
||||
masterAttributes.dbitoffset = ctbDbitOffset;
|
||||
masterAttributes.dbitoffset = generalData->ctbDbitOffset;
|
||||
masterAttributes.dbitreorder = generalData->ctbDbitReorder;
|
||||
masterAttributes.dbitlist = 0;
|
||||
for (auto &i : ctbDbitList) {
|
||||
|
||||
for (auto &i : generalData->ctbDbitList) {
|
||||
masterAttributes.dbitlist |= (static_cast<uint64_t>(1) << i);
|
||||
}
|
||||
masterAttributes.transceiverSamples =
|
||||
@ -1748,22 +1748,29 @@ void Implementation::setTenGigaADCEnableMask(uint32_t mask) {
|
||||
LOG(logINFO) << "Packets per Frame: " << (generalData->packetsPerFrame);
|
||||
}
|
||||
|
||||
std::vector<int> Implementation::getDbitList() const { return ctbDbitList; }
|
||||
|
||||
void Implementation::setDbitList(const std::vector<int> &v) {
|
||||
ctbDbitList = v;
|
||||
for (const auto &it : dataProcessor)
|
||||
it->SetCtbDbitList(ctbDbitList);
|
||||
LOG(logINFO) << "Dbit list: " << ToString(ctbDbitList);
|
||||
std::vector<int> Implementation::getDbitList() const {
|
||||
return generalData->ctbDbitList;
|
||||
}
|
||||
|
||||
int Implementation::getDbitOffset() const { return ctbDbitOffset; }
|
||||
void Implementation::setDbitList(const std::vector<int> &v) {
|
||||
generalData->SetctbDbitList(v);
|
||||
LOG(logINFO) << "Dbit list: " << ToString(v);
|
||||
}
|
||||
|
||||
int Implementation::getDbitOffset() const { return generalData->ctbDbitOffset; }
|
||||
|
||||
void Implementation::setDbitOffset(const int s) {
|
||||
ctbDbitOffset = s;
|
||||
for (const auto &it : dataProcessor)
|
||||
it->SetCtbDbitOffset(ctbDbitOffset);
|
||||
LOG(logINFO) << "Dbit offset: " << ctbDbitOffset;
|
||||
generalData->SetctbDbitOffset(s);
|
||||
LOG(logINFO) << "Dbit offset: " << s;
|
||||
}
|
||||
|
||||
bool Implementation::getDbitReorder() const {
|
||||
return generalData->ctbDbitReorder;
|
||||
}
|
||||
|
||||
void Implementation::setDbitReorder(const bool reorder) {
|
||||
generalData->SetctbDbitReorder(reorder);
|
||||
LOG(logINFO) << "Dbit reorder: " << reorder;
|
||||
}
|
||||
|
||||
uint32_t Implementation::getTransceiverEnableMask() const {
|
||||
|
@ -252,6 +252,10 @@ class Implementation : private virtual slsDetectorDefs {
|
||||
int getDbitOffset() const;
|
||||
/* [Ctb] */
|
||||
void setDbitOffset(const int s);
|
||||
bool getDbitReorder() const;
|
||||
/* [Ctb] */
|
||||
void setDbitReorder(const bool reorder);
|
||||
|
||||
uint32_t getTransceiverEnableMask() const;
|
||||
/* [Ctb] */
|
||||
void setTransceiverEnableMask(const uint32_t mask);
|
||||
@ -366,8 +370,6 @@ class Implementation : private virtual slsDetectorDefs {
|
||||
int thresholdEnergyeV{-1};
|
||||
std::array<int, 3> thresholdAllEnergyeV = {{-1, -1, -1}};
|
||||
std::vector<int64_t> rateCorrections;
|
||||
std::vector<int> ctbDbitList;
|
||||
int ctbDbitOffset{0};
|
||||
|
||||
// callbacks
|
||||
void (*startAcquisitionCallBack)(const startCallbackHeader,
|
||||
|
@ -551,6 +551,13 @@ void MasterAttributes::WriteHDF5DbitOffset(H5::H5File *fd, H5::Group *group) {
|
||||
dataset.write(&dbitoffset, H5::PredType::NATIVE_INT);
|
||||
}
|
||||
|
||||
void MasterAttributes::WriteHDF5DbitReorder(H5::H5File *fd, H5::Group *group) {
|
||||
H5::DataSpace dataspace = H5::DataSpace(H5S_SCALAR);
|
||||
H5::DataSet dataset = group->createDataSet(
|
||||
"Dbit Reorder", H5::PredType::NATIVE_INT, dataspace);
|
||||
dataset.write(&dbitreorder, H5::PredType::NATIVE_INT);
|
||||
}
|
||||
|
||||
void MasterAttributes::WriteHDF5DbitList(H5::H5File *fd, H5::Group *group) {
|
||||
H5::DataSpace dataspace = H5::DataSpace(H5S_SCALAR);
|
||||
H5::DataSet dataset = group->createDataSet(
|
||||
@ -744,6 +751,8 @@ void MasterAttributes::GetCtbBinaryAttributes(
|
||||
w->Uint(digitalSamples);
|
||||
w->Key("Dbit Offset");
|
||||
w->Uint(dbitoffset);
|
||||
w->Key("Dbit Reorder");
|
||||
w->Uint(dbitreorder);
|
||||
w->Key("Dbit Bitset");
|
||||
w->Uint64(dbitlist);
|
||||
w->Key("Transceiver Mask");
|
||||
@ -766,6 +775,7 @@ void MasterAttributes::WriteCtbHDF5Attributes(H5::H5File *fd,
|
||||
MasterAttributes::WriteHDF5DigitalFlag(fd, group);
|
||||
MasterAttributes::WriteHDF5DigitalSamples(fd, group);
|
||||
MasterAttributes::WriteHDF5DbitOffset(fd, group);
|
||||
MasterAttributes::WriteHDF5DbitReorder(fd, group);
|
||||
MasterAttributes::WriteHDF5DbitList(fd, group);
|
||||
MasterAttributes::WriteHDF5TransceiverMask(fd, group);
|
||||
MasterAttributes::WriteHDF5TransceiverFlag(fd, group);
|
||||
@ -791,6 +801,8 @@ void MasterAttributes::GetXilinxCtbBinaryAttributes(
|
||||
w->Uint(digitalSamples);
|
||||
w->Key("Dbit Offset");
|
||||
w->Uint(dbitoffset);
|
||||
w->Key("Dbit Reorder");
|
||||
w->Uint(dbitreorder);
|
||||
w->Key("Dbit Bitset");
|
||||
w->Uint64(dbitlist);
|
||||
w->Key("Transceiver Mask");
|
||||
@ -812,6 +824,7 @@ void MasterAttributes::WriteXilinxCtbHDF5Attributes(H5::H5File *fd,
|
||||
MasterAttributes::WriteHDF5DigitalFlag(fd, group);
|
||||
MasterAttributes::WriteHDF5DigitalSamples(fd, group);
|
||||
MasterAttributes::WriteHDF5DbitOffset(fd, group);
|
||||
MasterAttributes::WriteHDF5DbitReorder(fd, group);
|
||||
MasterAttributes::WriteHDF5DbitList(fd, group);
|
||||
MasterAttributes::WriteHDF5TransceiverMask(fd, group);
|
||||
MasterAttributes::WriteHDF5TransceiverFlag(fd, group);
|
||||
|
@ -51,6 +51,7 @@ class MasterAttributes {
|
||||
uint32_t analogSamples{0};
|
||||
uint32_t digital{0};
|
||||
uint32_t digitalSamples{0};
|
||||
uint32_t dbitreorder{1};
|
||||
uint32_t dbitoffset{0};
|
||||
uint64_t dbitlist{0};
|
||||
uint32_t transceiverMask{0};
|
||||
@ -104,6 +105,7 @@ class MasterAttributes {
|
||||
void WriteHDF5DigitalSamples(H5::H5File *fd, H5::Group *group);
|
||||
void WriteHDF5DbitOffset(H5::H5File *fd, H5::Group *group);
|
||||
void WriteHDF5DbitList(H5::H5File *fd, H5::Group *group);
|
||||
void WriteHDF5DbitReorder(H5::H5File *fd, H5::Group *group);
|
||||
void WriteHDF5TransceiverMask(H5::H5File *fd, H5::Group *group);
|
||||
void WriteHDF5TransceiverFlag(H5::H5File *fd, H5::Group *group);
|
||||
void WriteHDF5TransceiverSamples(H5::H5File *fd, H5::Group *group);
|
||||
|
@ -7,12 +7,9 @@
|
||||
#include "sls/container_utils.h"
|
||||
#include "sls/logger.h"
|
||||
#include "sls/sls_detector_defs.h"
|
||||
#include "sls/sls_detector_exceptions.h"
|
||||
#include "sls/versionAPI.h"
|
||||
|
||||
#include <csignal> //SIGINT
|
||||
#include <cstring>
|
||||
#include <getopt.h>
|
||||
#include <iostream>
|
||||
#include <semaphore.h>
|
||||
#include <sys/wait.h> //wait
|
||||
@ -31,6 +28,26 @@
|
||||
|
||||
sem_t semaphore;
|
||||
|
||||
/**
|
||||
* Control+C Interrupt Handler
|
||||
* to let all the processes know to exit properly
|
||||
*/
|
||||
void sigInterruptHandler(int p) { sem_post(&semaphore); }
|
||||
|
||||
/**
|
||||
* prints usage of this example program
|
||||
*/
|
||||
std::string getHelpMessage() {
|
||||
std::ostringstream os;
|
||||
os << "\nUsage:\n"
|
||||
<< "./slsMultiReceiver [start tcp port] [num recevers] [call back "
|
||||
"option (optional)]\n"
|
||||
<< "\t - tcp port has to be non-zero and 16 bit\n"
|
||||
<< "\t - call back option is 0 (disabled) by default, 1 prints frame "
|
||||
"header for debugging\n";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start Acquisition Call back (slsMultiReceiver writes data if file write
|
||||
* enabled) if registerCallBackRawDataReady or
|
||||
@ -129,63 +146,21 @@ void GetData(slsDetectorDefs::sls_receiver_header &header,
|
||||
// header->packetsMask.to_string().c_str(),
|
||||
((uint8_t)(*((uint8_t *)(dataPointer)))), imageSize);
|
||||
|
||||
// if data is modified, can affect size
|
||||
// only reduction in size allowed, not increase
|
||||
// imageSize = 26000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Control+C Interrupt Handler
|
||||
* to let all the processes know to exit properly
|
||||
*/
|
||||
void sigInterruptHandler(int p) { sem_post(&semaphore); }
|
||||
|
||||
int GetDeprecatedCommandLineOptions(int argc, char *argv[], uint16_t &startPort,
|
||||
uint16_t &numReceivers,
|
||||
bool &callbackEnabled) {
|
||||
std::string deprecatedMessage =
|
||||
"Detected deprecated Options. Please update.\n";
|
||||
if (argc > 1) {
|
||||
try {
|
||||
if (argc == 3 || argc == 4) {
|
||||
startPort = sls::StringTo<uint16_t>(argv[1]);
|
||||
numReceivers = sls::StringTo<uint16_t>(argv[2]);
|
||||
if (numReceivers > 1024) {
|
||||
LOG(sls::logWARNING) << deprecatedMessage;
|
||||
LOG(sls::logERROR)
|
||||
<< "Did you mix up the order of the arguments?";
|
||||
return slsDetectorDefs::FAIL;
|
||||
}
|
||||
if (numReceivers == 0) {
|
||||
LOG(sls::logWARNING) << deprecatedMessage;
|
||||
LOG(sls::logERROR) << "Invalid number of receivers.";
|
||||
return slsDetectorDefs::FAIL;
|
||||
}
|
||||
if (argc == 4) {
|
||||
callbackEnabled = sls::StringTo<bool>(argv[3]);
|
||||
}
|
||||
} else
|
||||
throw std::runtime_error("Invalid number of arguments");
|
||||
} catch (const std::exception &e) {
|
||||
LOG(sls::logWARNING) << deprecatedMessage;
|
||||
LOG(sls::logERROR) << e.what();
|
||||
return slsDetectorDefs::FAIL;
|
||||
}
|
||||
}
|
||||
return slsDetectorDefs::OK;
|
||||
}
|
||||
|
||||
std::string getHelpMessage() {
|
||||
std::string name = "slsMultiReceiver";
|
||||
return "\nUsage: " + name + " Options:\n" +
|
||||
"\t-v, --version : Version of " + name + ".\n" +
|
||||
"\t-n, --num-receivers : Number of receivers.\n" +
|
||||
"\t-p, --port : TCP port to communicate with client for "
|
||||
"configuration. Non-zero and 16 bit.\n" +
|
||||
"\t-c, --callback : Enable dummy callbacks for debugging. "
|
||||
"Disabled by default. \n" +
|
||||
"\t-u, --uid : Set effective user id if receiver started "
|
||||
"with privileges. \n\n";
|
||||
// // example of how to use roi or modify data that is later written to file
|
||||
// slsDetectorDefs::ROI roi{0, 10, 0, 20};
|
||||
// int width = roi.xmax - roi.xmin;
|
||||
// int height = roi.ymax - roi.ymin;
|
||||
// uint8_t *destPtr = (uint8_t *)dataPointer;
|
||||
// for (int irow = roi.ymin; irow < roi.ymax; ++irow) {
|
||||
// memcpy(destPtr,
|
||||
// ((uint8_t *)(dataPointer + irow * callbackHeader.shape.x +
|
||||
// roi.xmin)),
|
||||
// width);
|
||||
// destPtr += width;
|
||||
// }
|
||||
// memcpy((uint8_t*)dataPointer, (uint8_t*)dataPointer
|
||||
// // setting roi for eg. changes size
|
||||
// imageSize = width * height;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -196,114 +171,49 @@ std::string getHelpMessage() {
|
||||
* - Default Start TCP port is 1954
|
||||
*/
|
||||
int main(int argc, char *argv[]) {
|
||||
uint16_t startPort = DEFAULT_TCP_RX_PORTNO;
|
||||
uint16_t numReceivers = 1;
|
||||
bool callbackEnabled = false;
|
||||
uid_t userid = -1;
|
||||
|
||||
std::string help_message = getHelpMessage();
|
||||
/** - set default values */
|
||||
int numReceivers = 1;
|
||||
uint16_t startTCPPort = DEFAULT_TCP_RX_PORTNO;
|
||||
int withCallback = 0;
|
||||
sem_init(&semaphore, 1, 0);
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"version", no_argument, nullptr, 'v'},
|
||||
{"num-receivers", required_argument, nullptr, 'n'},
|
||||
{"rx_tcpport", required_argument, nullptr, 't'},
|
||||
{"port", required_argument, nullptr, 'p'},
|
||||
{"callback", no_argument, nullptr, 'c'},
|
||||
{"uid", required_argument, nullptr, 'u'},
|
||||
{"help", no_argument, nullptr, 'h'},
|
||||
{nullptr, 0, nullptr, 0}};
|
||||
|
||||
int option_index = 0;
|
||||
int opt = 0;
|
||||
while (-1 != (opt = getopt_long(argc, argv, "vn:t:p:cu:h", long_options,
|
||||
&option_index))) {
|
||||
|
||||
switch (opt) {
|
||||
|
||||
case 'v':
|
||||
std::cout << argv[0] << " Version: " << APIRECEIVER << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
case 'n':
|
||||
try {
|
||||
numReceivers = sls::StringTo<uint16_t>(optarg);
|
||||
if (numReceivers == 0 || numReceivers > 100) {
|
||||
throw std::runtime_error("Invalid argument.");
|
||||
/** - get number of receivers and start tcp port from command line
|
||||
* arguments */
|
||||
if (argc > 1) {
|
||||
try {
|
||||
if (argc == 3 || argc == 4) {
|
||||
startTCPPort = sls::StringTo<uint16_t>(argv[1]);
|
||||
if (startTCPPort == 0) {
|
||||
throw std::runtime_error("Invalid start tcp port");
|
||||
}
|
||||
} catch (...) {
|
||||
throw sls::RuntimeError("Invalid number of receivers." +
|
||||
help_message);
|
||||
}
|
||||
break;
|
||||
|
||||
case 't':
|
||||
LOG(sls::logWARNING)
|
||||
<< "Deprecated option. Please use 'p' or '--port'.";
|
||||
//[[fallthrough]]; TODO: for when we update to c++17
|
||||
case 'p':
|
||||
try {
|
||||
startPort = sls::StringTo<uint16_t>(optarg);
|
||||
} catch (...) {
|
||||
throw sls::RuntimeError("Could not scan port number." +
|
||||
help_message);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
callbackEnabled = true;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
try {
|
||||
userid = sls::StringTo<uint32_t>(optarg);
|
||||
} catch (...) {
|
||||
throw sls::RuntimeError("Invalid uid." + help_message);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
std::cout << help_message << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
default:
|
||||
LOG(sls::logERROR) << help_message;
|
||||
numReceivers = std::stoi(argv[2]);
|
||||
if (numReceivers > 1024) {
|
||||
cprintf(RED,
|
||||
"Did you mix up the order of the arguments?\n%s\n",
|
||||
getHelpMessage().c_str());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (numReceivers == 0) {
|
||||
cprintf(RED, "Invalid number of receivers.\n%s\n",
|
||||
getHelpMessage().c_str());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (argc == 4) {
|
||||
withCallback = std::stoi(argv[3]);
|
||||
}
|
||||
} else
|
||||
throw std::runtime_error("Invalid number of arguments");
|
||||
} catch (const std::exception &e) {
|
||||
cprintf(RED, "Error: %s\n%s\n", e.what(), getHelpMessage().c_str());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
// if remaining arguments, maintain backward compatibility of [startport]
|
||||
// [num-receivers] [callback]
|
||||
if (optind < argc) {
|
||||
if (slsDetectorDefs::FAIL ==
|
||||
GetDeprecatedCommandLineOptions(argc, argv, startPort, numReceivers,
|
||||
callbackEnabled))
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
LOG(sls::logINFOBLUE) << "Current Process [ Tid: " << gettid() << ']';
|
||||
LOG(sls::logINFO) << "Number of Receivers: " << numReceivers;
|
||||
LOG(sls::logINFO) << "Start TCP Port: " << startPort;
|
||||
LOG(sls::logINFO) << "Callback Enable: " << callbackEnabled;
|
||||
|
||||
// set effective id if provided
|
||||
if (userid != static_cast<uid_t>(-1)) {
|
||||
if (geteuid() == userid) {
|
||||
LOG(sls::logINFO)
|
||||
<< "Process already has the same Effective UID " << userid;
|
||||
} else {
|
||||
if (seteuid(userid) != 0) {
|
||||
std::ostringstream oss;
|
||||
oss << "Could not set Effective UID to " << userid;
|
||||
throw sls::RuntimeError(oss.str());
|
||||
}
|
||||
if (geteuid() != userid) {
|
||||
std::ostringstream oss;
|
||||
oss << "Could not set Effective UID to " << userid << ". Got "
|
||||
<< geteuid();
|
||||
throw sls::RuntimeError(oss.str());
|
||||
}
|
||||
LOG(sls::logINFO) << "Process Effective UID changed to " << userid;
|
||||
}
|
||||
}
|
||||
cprintf(BLUE, "Parent Process Created [ Tid: %ld ]\n", (long)gettid());
|
||||
cprintf(RESET, "Number of Receivers: %d\n", numReceivers);
|
||||
cprintf(RESET, "Start TCP Port: %hu\n", startTCPPort);
|
||||
cprintf(RESET, "Callback Enable: %d\n", withCallback);
|
||||
|
||||
/** - Catch signal SIGINT to close files and call destructors properly */
|
||||
struct sigaction sa;
|
||||
@ -312,7 +222,7 @@ int main(int argc, char *argv[]) {
|
||||
sigemptyset(&sa.sa_mask); // dont block additional signals during invocation
|
||||
// of handler
|
||||
if (sigaction(SIGINT, &sa, nullptr) == -1) {
|
||||
LOG(sls::logERROR) << "Could not set handler function for SIGINT";
|
||||
cprintf(RED, "Could not set handler function for SIGINT\n");
|
||||
}
|
||||
|
||||
/** - Ignore SIG_PIPE, prevents global signal handler, handle locally,
|
||||
@ -324,11 +234,10 @@ int main(int argc, char *argv[]) {
|
||||
sigemptyset(&asa.sa_mask); // dont block additional signals during
|
||||
// invocation of handler
|
||||
if (sigaction(SIGPIPE, &asa, nullptr) == -1) {
|
||||
LOG(sls::logERROR) << "Could not set handler function for SIGPIPE";
|
||||
cprintf(RED, "Could not set handler function for SIGPIPE\n");
|
||||
}
|
||||
|
||||
/** - loop over number of receivers */
|
||||
sem_init(&semaphore, 1, 0);
|
||||
for (int i = 0; i < numReceivers; ++i) {
|
||||
|
||||
/** - fork process to create child process */
|
||||
@ -337,54 +246,48 @@ int main(int argc, char *argv[]) {
|
||||
/** - if fork failed, raise SIGINT and properly destroy all child
|
||||
* processes */
|
||||
if (pid < 0) {
|
||||
LOG(sls::logERROR)
|
||||
<< "fork() failed. Killing all the receiver objects";
|
||||
cprintf(RED, "fork() failed. Killing all the receiver objects\n");
|
||||
raise(SIGINT);
|
||||
}
|
||||
|
||||
/** - if child process */
|
||||
else if (pid == 0) {
|
||||
LOG(sls::logINFOBLUE)
|
||||
<< "Child process " << i << " [ Tid: " << gettid() << ']';
|
||||
cprintf(BLUE, "Child process %d [ Tid: %ld ]\n", i, (long)gettid());
|
||||
|
||||
std::unique_ptr<sls::Receiver> receiver = nullptr;
|
||||
try {
|
||||
uint16_t port = startPort + i;
|
||||
sls::Receiver receiver(port);
|
||||
|
||||
/** - register callbacks. remember to set file write enable
|
||||
* to 0 (using the client) if we should not write files and you
|
||||
* will write data using the callbacks */
|
||||
if (callbackEnabled) {
|
||||
|
||||
/** - Call back for start acquisition */
|
||||
LOG(sls::logINFOBLUE) << "Registering StartAcq()";
|
||||
receiver.registerCallBackStartAcquisition(StartAcq,
|
||||
nullptr);
|
||||
|
||||
/** - Call back for acquisition finished */
|
||||
LOG(sls::logINFOBLUE)
|
||||
<< "Registering AcquisitionFinished()";
|
||||
receiver.registerCallBackAcquisitionFinished(
|
||||
AcquisitionFinished, nullptr);
|
||||
|
||||
/* - Call back for raw data */
|
||||
LOG(sls::logINFOBLUE) << "Registering GetData()";
|
||||
receiver.registerCallBackRawDataReady(GetData, nullptr);
|
||||
}
|
||||
|
||||
/** - as long as no Ctrl+C */
|
||||
sem_wait(&semaphore);
|
||||
sem_destroy(&semaphore);
|
||||
|
||||
receiver = sls::make_unique<sls::Receiver>(startTCPPort + i);
|
||||
} catch (...) {
|
||||
LOG(sls::logINFOBLUE)
|
||||
<< "Exiting Child Process [ Tid: " << gettid() << " ]";
|
||||
throw;
|
||||
}
|
||||
/** - register callbacks. remember to set file write enable to 0
|
||||
* (using the client) if we should not write files and you will
|
||||
* write data using the callbacks */
|
||||
if (withCallback) {
|
||||
|
||||
LOG(sls::logINFOBLUE)
|
||||
<< "Exiting Child Process [ Tid: " << gettid() << ']';
|
||||
return EXIT_SUCCESS;
|
||||
/** - Call back for start acquisition */
|
||||
cprintf(BLUE, "Registering StartAcq()\n");
|
||||
receiver->registerCallBackStartAcquisition(StartAcq, nullptr);
|
||||
|
||||
/** - Call back for acquisition finished */
|
||||
cprintf(BLUE, "Registering AcquisitionFinished()\n");
|
||||
receiver->registerCallBackAcquisitionFinished(
|
||||
AcquisitionFinished, nullptr);
|
||||
|
||||
/* - Call back for raw data */
|
||||
cprintf(BLUE, "Registering GetData() \n");
|
||||
receiver->registerCallBackRawDataReady(GetData, nullptr);
|
||||
}
|
||||
|
||||
/** - as long as no Ctrl+C */
|
||||
sem_wait(&semaphore);
|
||||
sem_destroy(&semaphore);
|
||||
cprintf(BLUE, "Exiting Child Process [ Tid: %ld ]\n",
|
||||
(long)gettid());
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -395,12 +298,12 @@ int main(int argc, char *argv[]) {
|
||||
sigemptyset(&sa.sa_mask); // dont block additional signals during invocation
|
||||
// of handler
|
||||
if (sigaction(SIGINT, &sa, nullptr) == -1) {
|
||||
LOG(sls::logERROR) << "Could not set handler function for SIGINT";
|
||||
cprintf(RED, "Could not set handler function for SIGINT\n");
|
||||
}
|
||||
|
||||
/** - Print Ready and Instructions how to exit */
|
||||
std::cout << "Ready ... \n";
|
||||
LOG(sls::logINFO) << "\n[ Press \'Ctrl+c\' to exit ]";
|
||||
cprintf(RESET, "\n[ Press \'Ctrl+c\' to exit ]\n");
|
||||
|
||||
/** - Parent process waits for all child processes to exit */
|
||||
for (;;) {
|
||||
@ -409,21 +312,20 @@ int main(int argc, char *argv[]) {
|
||||
// no child closed
|
||||
if (childPid == -1) {
|
||||
if (errno == ECHILD) {
|
||||
LOG(sls::logINFOGREEN)
|
||||
<< "All Child Processes have been closed";
|
||||
cprintf(GREEN, "All Child Processes have been closed\n");
|
||||
break;
|
||||
} else {
|
||||
LOG(sls::logERROR)
|
||||
<< "Unexpected error from waitpid(): " << strerror(errno);
|
||||
cprintf(RED, "Unexpected error from waitpid(): (%s)\n",
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// child closed
|
||||
LOG(sls::logINFOBLUE)
|
||||
<< "Exiting Child Process [ Tid: " << childPid << ']';
|
||||
cprintf(BLUE, "Exiting Child Process [ Tid: %ld ]\n",
|
||||
(long int)childPid);
|
||||
}
|
||||
|
||||
std::cout << "Goodbye!\n";
|
||||
return EXIT_SUCCESS;
|
||||
return 0;
|
||||
}
|
||||
|
@ -27,9 +27,106 @@ namespace sls {
|
||||
|
||||
Receiver::~Receiver() = default;
|
||||
|
||||
Receiver::Receiver(uint16_t port) {
|
||||
validatePortNumber(port);
|
||||
tcpipInterface = make_unique<ClientInterface>(port);
|
||||
Receiver::Receiver(int argc, char *argv[]) : tcpipInterface(nullptr) {
|
||||
|
||||
// options
|
||||
uint16_t tcpip_port_no = 1954;
|
||||
uid_t userid = -1;
|
||||
|
||||
// parse command line for config
|
||||
static struct option long_options[] = {
|
||||
// These options set a flag.
|
||||
//{"verbose", no_argument, &verbose_flag, 1},
|
||||
// These options don’t set a flag. We distinguish them by their indices.
|
||||
{"rx_tcpport", required_argument, nullptr,
|
||||
't'}, // TODO change or backward compatible to "port, p"?
|
||||
{"uid", required_argument, nullptr, 'u'},
|
||||
{"version", no_argument, nullptr, 'v'},
|
||||
{"help", no_argument, nullptr, 'h'},
|
||||
{nullptr, 0, nullptr, 0}};
|
||||
|
||||
// initialize global optind variable (required when instantiating multiple
|
||||
// receivers in the same process)
|
||||
optind = 1;
|
||||
// getopt_long stores the option index here.
|
||||
int option_index = 0;
|
||||
int c = 0;
|
||||
|
||||
std::string help_message =
|
||||
"\nUsage: " + std::string(argv[0]) + " [arguments]\n" +
|
||||
"Possible arguments are:\n" +
|
||||
"\t-t, --rx_tcpport <port> : TCP Communication Port with "
|
||||
"client. Non-zero and 16 bit.\n" +
|
||||
"\t-u, --uid <user id> : Set effective user id if receiver "
|
||||
"\n" +
|
||||
"\t started with privileges. \n\n";
|
||||
|
||||
while (c != -1) {
|
||||
c = getopt_long(argc, argv, "hvf:t:u:", long_options, &option_index);
|
||||
|
||||
// Detect the end of the options.
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
|
||||
case 't':
|
||||
try {
|
||||
tcpip_port_no = sls::StringTo<uint16_t>(optarg);
|
||||
validatePortNumber(tcpip_port_no);
|
||||
} catch (...) {
|
||||
throw RuntimeError("Could not scan TCP port number." +
|
||||
help_message);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
if (sscanf(optarg, "%u", &userid) != 1) {
|
||||
throw RuntimeError("Could not scan uid" + help_message);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
std::cout << "SLS Receiver Version: " << APIRECEIVER << std::endl;
|
||||
LOG(logINFOBLUE) << "Exiting [ Tid: " << gettid() << " ]";
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
case 'h':
|
||||
std::cout << help_message << std::endl;
|
||||
exit(EXIT_SUCCESS);
|
||||
default:
|
||||
throw RuntimeError(help_message);
|
||||
}
|
||||
}
|
||||
|
||||
// set effective id if provided
|
||||
if (userid != static_cast<uid_t>(-1)) {
|
||||
if (geteuid() == userid) {
|
||||
LOG(logINFO) << "Process already has the same Effective UID "
|
||||
<< userid;
|
||||
} else {
|
||||
if (seteuid(userid) != 0) {
|
||||
std::ostringstream oss;
|
||||
oss << "Could not set Effective UID to " << userid;
|
||||
throw RuntimeError(oss.str());
|
||||
}
|
||||
if (geteuid() != userid) {
|
||||
std::ostringstream oss;
|
||||
oss << "Could not set Effective UID to " << userid << ". Got "
|
||||
<< geteuid();
|
||||
throw RuntimeError(oss.str());
|
||||
}
|
||||
LOG(logINFO) << "Process Effective UID changed to " << userid;
|
||||
}
|
||||
}
|
||||
|
||||
// might throw an exception
|
||||
tcpipInterface = make_unique<ClientInterface>(tcpip_port_no);
|
||||
}
|
||||
|
||||
Receiver::Receiver(uint16_t tcpip_port_no) {
|
||||
// might throw an exception
|
||||
tcpipInterface = make_unique<ClientInterface>(tcpip_port_no);
|
||||
}
|
||||
|
||||
std::string Receiver::getReceiverVersion() {
|
||||
|
@ -2,14 +2,11 @@
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
/* slsReceiver */
|
||||
#include "sls/Receiver.h"
|
||||
#include "sls/ToString.h"
|
||||
#include "sls/container_utils.h"
|
||||
#include "sls/logger.h"
|
||||
#include "sls/sls_detector_defs.h"
|
||||
#include "sls/versionAPI.h"
|
||||
|
||||
#include <csignal> //SIGINT
|
||||
#include <getopt.h>
|
||||
#include <semaphore.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@ -25,95 +22,9 @@ void sigInterruptHandler(int p) { sem_post(&semaphore); }
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
uint16_t port = DEFAULT_TCP_RX_PORTNO;
|
||||
uid_t userid = -1;
|
||||
sem_init(&semaphore, 1, 0);
|
||||
|
||||
std::string help_message =
|
||||
"\nUsage: " + std::string(argv[0]) + " Options:\n" +
|
||||
"\t-v, --version : Version of " + std::string(argv[0]) + ".\n" +
|
||||
"\t-p, --port : TCP port to communicate with client for "
|
||||
"configuration. Non-zero and 16 bit.\n" +
|
||||
"\t-u, --uid : Set effective user id if receiver started "
|
||||
"with privileges. \n\n";
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"version", no_argument, nullptr, 'v'},
|
||||
{"rx_tcpport", required_argument, nullptr, 't'},
|
||||
{"port", required_argument, nullptr, 'p'},
|
||||
{"uid", required_argument, nullptr, 'u'},
|
||||
{"help", no_argument, nullptr, 'h'},
|
||||
{nullptr, 0, nullptr, 0}};
|
||||
|
||||
int option_index = 0;
|
||||
int opt = 0;
|
||||
while (-1 != (opt = getopt_long(argc, argv, "vt:p:u:h", long_options,
|
||||
&option_index))) {
|
||||
|
||||
switch (opt) {
|
||||
|
||||
case 'v':
|
||||
std::cout << argv[0] << " Version: " << APIRECEIVER << std::endl;
|
||||
return (EXIT_SUCCESS);
|
||||
|
||||
case 't':
|
||||
LOG(sls::logWARNING)
|
||||
<< "Deprecated option. Please use 'p' or '--port'.";
|
||||
//[[fallthrough]]; TODO: for when we update to c++17
|
||||
case 'p':
|
||||
try {
|
||||
port = sls::StringTo<uint16_t>(optarg);
|
||||
} catch (...) {
|
||||
throw sls::RuntimeError("Could not scan port number." +
|
||||
help_message);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
try {
|
||||
userid = sls::StringTo<uint32_t>(optarg);
|
||||
} catch (...) {
|
||||
throw sls::RuntimeError("Invalid uid." + help_message);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
std::cout << help_message << std::endl;
|
||||
return (EXIT_SUCCESS);
|
||||
|
||||
default:
|
||||
LOG(sls::logERROR) << help_message;
|
||||
return (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
// remaining arguments
|
||||
if (optind < argc) {
|
||||
LOG(sls::logERROR) << "Invalid arguments\n" << help_message;
|
||||
return (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
LOG(sls::logINFOBLUE) << "Current Process [ Tid: " << gettid() << " ]";
|
||||
LOG(sls::logINFO) << "Port: " << port;
|
||||
|
||||
// set effective id if provided
|
||||
if (userid != static_cast<uid_t>(-1)) {
|
||||
if (geteuid() == userid) {
|
||||
LOG(sls::logINFO)
|
||||
<< "Process already has the same Effective UID " << userid;
|
||||
} else {
|
||||
if (seteuid(userid) != 0) {
|
||||
std::ostringstream oss;
|
||||
oss << "Could not set Effective UID to " << userid;
|
||||
throw sls::RuntimeError(oss.str());
|
||||
}
|
||||
if (geteuid() != userid) {
|
||||
std::ostringstream oss;
|
||||
oss << "Could not set Effective UID to " << userid << ". Got "
|
||||
<< geteuid();
|
||||
throw sls::RuntimeError(oss.str());
|
||||
}
|
||||
LOG(sls::logINFO) << "Process Effective UID changed to " << userid;
|
||||
}
|
||||
}
|
||||
LOG(sls::logINFOBLUE) << "Created [ Tid: " << gettid() << " ]";
|
||||
|
||||
// Catch signal SIGINT to close files and call destructors properly
|
||||
struct sigaction sa;
|
||||
@ -136,9 +47,8 @@ int main(int argc, char *argv[]) {
|
||||
LOG(sls::logERROR) << "Could not set handler function for SIGPIPE";
|
||||
}
|
||||
|
||||
sem_init(&semaphore, 1, 0);
|
||||
try {
|
||||
sls::Receiver r(port);
|
||||
sls::Receiver r(argc, argv);
|
||||
LOG(sls::logINFO) << "[ Press \'Ctrl+c\' to exit ]";
|
||||
sem_wait(&semaphore);
|
||||
sem_destroy(&semaphore);
|
||||
@ -147,5 +57,5 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
LOG(sls::logINFOBLUE) << "Exiting [ Tid: " << gettid() << " ]";
|
||||
LOG(sls::logINFO) << "Exiting Receiver";
|
||||
return EXIT_SUCCESS;
|
||||
return 0;
|
||||
}
|
||||
|
@ -19,8 +19,8 @@ namespace sls {
|
||||
// files
|
||||
|
||||
// versions
|
||||
#define HDF5_WRITER_VERSION (6.6) // 1 decimal places
|
||||
#define BINARY_WRITER_VERSION (7.2) // 1 decimal places
|
||||
#define HDF5_WRITER_VERSION (6.7) // 1 decimal places
|
||||
#define BINARY_WRITER_VERSION (7.3) // 1 decimal places
|
||||
|
||||
#define MAX_FRAMES_PER_FILE 20000
|
||||
#define SHORT_MAX_FRAMES_PER_FILE 100000
|
||||
|
@ -3,6 +3,9 @@
|
||||
target_sources(tests PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test-GeneralData.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test-CircularFifo.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test-ArrangeDataBasedOnBitList.cpp
|
||||
)
|
||||
|
||||
target_include_directories(tests PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../src>")
|
||||
|
||||
message(STATUS "Resolved path: ${CMAKE_CURRENT_SOURCE_DIR}/../src")
|
411
slsReceiverSoftware/tests/test-ArrangeDataBasedOnBitList.cpp
Normal file
411
slsReceiverSoftware/tests/test-ArrangeDataBasedOnBitList.cpp
Normal file
@ -0,0 +1,411 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2025 Contributors to the SLS Detector Package
|
||||
/************************************************
|
||||
* @file test-ArrangeDataBasedOnBitList.cpp
|
||||
* @short test case for DataProcessor rearrange functions,
|
||||
***********************************************/
|
||||
|
||||
#include "DataProcessor.h"
|
||||
#include "GeneralData.h"
|
||||
#include "catch.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace sls {
|
||||
|
||||
// dummy GeneralData class for testing
|
||||
class GeneralDataTest : public GeneralData {
|
||||
|
||||
public:
|
||||
GeneralDataTest() { detType = slsDetectorDefs::CHIPTESTBOARD; }
|
||||
|
||||
int GetNumberOfAnalogDatabytes() { return nAnalogBytes; };
|
||||
|
||||
int GetNumberOfDigitalDatabytes() { return nDigitalBytes; };
|
||||
|
||||
int GetNumberOfTransceiverDatabytes() { return nTransceiverBytes; };
|
||||
|
||||
void SetNumberOfAnalogDatabytes(int value) { nAnalogBytes = value; }
|
||||
|
||||
void SetNumberOfDigitalDatabytes(int value) { nDigitalBytes = value; }
|
||||
|
||||
void SetNumberOfTransceiverDatabytes(int value) {
|
||||
nTransceiverBytes = value;
|
||||
}
|
||||
|
||||
void SetCtbDbitOffset(const int value) { ctbDbitOffset = value; }
|
||||
|
||||
void SetCtbDbitList(const std::vector<int> &value) { ctbDbitList = value; }
|
||||
|
||||
void SetCtbDbitReorder(const bool value) { ctbDbitReorder = value; }
|
||||
|
||||
private:
|
||||
int nAnalogBytes{};
|
||||
int nDigitalBytes{};
|
||||
int nTransceiverBytes{};
|
||||
};
|
||||
|
||||
// dummy DataProcessor class for testing
|
||||
class DataProcessorTest : public DataProcessor {
|
||||
public:
|
||||
DataProcessorTest() : DataProcessor(0) {};
|
||||
~DataProcessorTest() {};
|
||||
void ArrangeDbitData(size_t &size, char *data) {
|
||||
DataProcessor::ArrangeDbitData(size, data);
|
||||
}
|
||||
|
||||
void RemoveTrailingBits(size_t &size, char *data) {
|
||||
DataProcessor::RemoveTrailingBits(size, data);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* test fixture for Testing,
|
||||
* num_analog_bytes = 1 byte has a value of 125
|
||||
* num_transceiver_bytes = 2 both bytes have a value of 125
|
||||
* num_digital_bytes is variable and is defined by number of samples
|
||||
* default num sample is 5
|
||||
* all bytes in digital data take a value of 255
|
||||
*/
|
||||
class DataProcessorTestFixture {
|
||||
public:
|
||||
DataProcessorTestFixture() {
|
||||
// setup Test Fixture
|
||||
dataprocessor = new DataProcessorTest;
|
||||
generaldata = new GeneralDataTest;
|
||||
|
||||
generaldata->SetNumberOfAnalogDatabytes(num_analog_bytes);
|
||||
generaldata->SetNumberOfTransceiverDatabytes(num_transceiver_bytes);
|
||||
generaldata->SetNumberOfDigitalDatabytes(num_digital_bytes +
|
||||
num_random_offset_bytes);
|
||||
|
||||
dataprocessor->SetGeneralData(generaldata);
|
||||
}
|
||||
|
||||
~DataProcessorTestFixture() {
|
||||
delete[] data;
|
||||
delete dataprocessor;
|
||||
delete generaldata;
|
||||
}
|
||||
|
||||
size_t get_size() const {
|
||||
return num_analog_bytes + num_digital_bytes + num_transceiver_bytes +
|
||||
num_random_offset_bytes;
|
||||
}
|
||||
|
||||
void set_num_samples(const size_t value) {
|
||||
num_samples = value;
|
||||
num_digital_bytes = num_samples * 8; // 64 (8 bytes) per sample
|
||||
|
||||
generaldata->SetNumberOfDigitalDatabytes(num_digital_bytes +
|
||||
num_random_offset_bytes);
|
||||
}
|
||||
|
||||
void set_random_offset_bytes(const size_t value) {
|
||||
num_random_offset_bytes = value;
|
||||
generaldata->SetNumberOfDigitalDatabytes(num_digital_bytes +
|
||||
num_random_offset_bytes);
|
||||
}
|
||||
|
||||
void set_data() {
|
||||
delete[] data;
|
||||
uint64_t max_bytes_per_bit =
|
||||
num_samples % 8 == 0 ? num_samples / 8 : num_samples / 8 + 1;
|
||||
uint64_t reserved_size =
|
||||
get_size() - num_digital_bytes + max_bytes_per_bit * 64;
|
||||
data = new char[reserved_size];
|
||||
|
||||
// set testing data
|
||||
memset(data, dummy_value, num_analog_bytes); // set to dummy value
|
||||
memset(data + num_analog_bytes, 0,
|
||||
num_random_offset_bytes); // set to zero
|
||||
memset(data + num_analog_bytes + num_random_offset_bytes, 0xFF,
|
||||
num_digital_bytes); // all digital bits are one
|
||||
memset(data + num_digital_bytes + num_analog_bytes +
|
||||
num_random_offset_bytes,
|
||||
dummy_value,
|
||||
num_transceiver_bytes); // set to dummy value
|
||||
}
|
||||
|
||||
DataProcessorTest *dataprocessor;
|
||||
GeneralDataTest *generaldata;
|
||||
const size_t num_analog_bytes = 1;
|
||||
const size_t num_transceiver_bytes = 2;
|
||||
const char dummy_value = static_cast<char>(125);
|
||||
size_t num_digital_bytes = 40; // num_samples * 8 = 5 * 8 = 40
|
||||
size_t num_random_offset_bytes = 0;
|
||||
size_t num_samples = 5;
|
||||
char *data = nullptr;
|
||||
};
|
||||
|
||||
TEST_CASE_METHOD(DataProcessorTestFixture, "Remove Trailing Bits",
|
||||
"[.dataprocessor][.bitoffset]") {
|
||||
|
||||
const size_t num_random_offset_bytes = 3;
|
||||
set_random_offset_bytes(num_random_offset_bytes);
|
||||
set_data();
|
||||
|
||||
generaldata->SetCtbDbitOffset(num_random_offset_bytes);
|
||||
|
||||
size_t expected_size = get_size() - num_random_offset_bytes;
|
||||
|
||||
char *expected_data = new char[expected_size];
|
||||
memset(expected_data, dummy_value, num_analog_bytes); // set to 125
|
||||
memset(expected_data + num_analog_bytes, 0xFF,
|
||||
num_digital_bytes); // set to 1
|
||||
memset(expected_data + num_digital_bytes + num_analog_bytes, dummy_value,
|
||||
num_transceiver_bytes); // set to 125
|
||||
|
||||
size_t size = get_size();
|
||||
dataprocessor->RemoveTrailingBits(size, data);
|
||||
|
||||
CHECK(size == expected_size);
|
||||
|
||||
CHECK(memcmp(data, expected_data, expected_size) == 0);
|
||||
|
||||
delete[] expected_data;
|
||||
}
|
||||
|
||||
// parametric test tested with num_samples = 5, num_samples = 10, num_samples =
|
||||
// 8
|
||||
TEST_CASE_METHOD(DataProcessorTestFixture, "Reorder all",
|
||||
"[.dataprocessor][.reorder]") {
|
||||
// parameters: num_samples, expected_num_digital_bytes,
|
||||
// expected_digital_part
|
||||
auto parameters = GENERATE(
|
||||
std::make_tuple(5, 64, std::vector<uint8_t>{0b00011111}),
|
||||
std::make_tuple(10, 2 * 64, std::vector<uint8_t>{0xFF, 0b00000011}),
|
||||
std::make_tuple(8, 64, std::vector<uint8_t>{0xFF}));
|
||||
|
||||
size_t num_samples, expected_num_digital_bytes;
|
||||
std::vector<uint8_t> expected_digital_part;
|
||||
std::tie(num_samples, expected_num_digital_bytes, expected_digital_part) =
|
||||
parameters;
|
||||
|
||||
// set number of samples for test fixture -> create data
|
||||
set_num_samples(num_samples);
|
||||
set_data();
|
||||
|
||||
std::vector<int> bitlist(64);
|
||||
std::iota(bitlist.begin(), bitlist.end(), 0);
|
||||
generaldata->SetCtbDbitList(bitlist);
|
||||
generaldata->SetCtbDbitReorder(true); // set reorder to true
|
||||
|
||||
const size_t expected_size =
|
||||
num_analog_bytes + num_transceiver_bytes + expected_num_digital_bytes;
|
||||
|
||||
// create expected data
|
||||
char *expected_data = new char[expected_size];
|
||||
|
||||
memset(expected_data, dummy_value, num_analog_bytes); // set to 125
|
||||
for (size_t bit = 0; bit < 64; ++bit) {
|
||||
memcpy(expected_data + num_analog_bytes +
|
||||
expected_digital_part.size() * bit,
|
||||
expected_digital_part.data(), expected_digital_part.size());
|
||||
}
|
||||
memset(expected_data + expected_num_digital_bytes + num_analog_bytes,
|
||||
dummy_value,
|
||||
num_transceiver_bytes); // set to 125
|
||||
|
||||
size_t size = get_size();
|
||||
dataprocessor->ArrangeDbitData(size, data); // call reorder
|
||||
|
||||
CHECK(size == expected_size);
|
||||
CHECK(memcmp(data, expected_data, expected_size) == 0);
|
||||
|
||||
delete[] expected_data;
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(DataProcessorTestFixture,
|
||||
"Reorder all and remove trailing bits",
|
||||
"[.dataprocessor][.reorder]") {
|
||||
|
||||
// set number of samples for test fixture -> create data
|
||||
const size_t num_random_offset_bytes = 3;
|
||||
set_random_offset_bytes(num_random_offset_bytes);
|
||||
set_data();
|
||||
|
||||
std::vector<int> bitlist(64);
|
||||
std::iota(bitlist.begin(), bitlist.end(), 0);
|
||||
generaldata->SetCtbDbitList(bitlist);
|
||||
generaldata->SetCtbDbitOffset(num_random_offset_bytes);
|
||||
generaldata->SetCtbDbitReorder(true); // set reorder to true
|
||||
|
||||
const size_t expected_num_digital_bytes = 64;
|
||||
std::vector<uint8_t> expected_digital_part{0b00011111};
|
||||
|
||||
const size_t expected_size =
|
||||
num_analog_bytes + num_transceiver_bytes + expected_num_digital_bytes;
|
||||
|
||||
// create expected data
|
||||
char *expected_data = new char[expected_size];
|
||||
|
||||
memset(expected_data, dummy_value, num_analog_bytes); // set to 125
|
||||
for (size_t bit = 0; bit < 64; ++bit) {
|
||||
memcpy(expected_data + num_analog_bytes +
|
||||
expected_digital_part.size() * bit,
|
||||
expected_digital_part.data(), expected_digital_part.size());
|
||||
}
|
||||
memset(expected_data + expected_num_digital_bytes + num_analog_bytes,
|
||||
dummy_value,
|
||||
num_transceiver_bytes); // set to 125
|
||||
|
||||
size_t size = get_size();
|
||||
dataprocessor->ArrangeDbitData(size, data); // call reorder
|
||||
|
||||
CHECK(size == expected_size);
|
||||
CHECK(memcmp(data, expected_data, expected_size) == 0);
|
||||
|
||||
delete[] expected_data;
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(DataProcessorTestFixture, "Arrange bitlist with reorder false",
|
||||
"[.dataprocessor][.retrievebitlist]") {
|
||||
// parameters: num_samples, bitlist, expected_num_digital_bytes,
|
||||
// expected_digital_part
|
||||
auto parameters = GENERATE(
|
||||
std::make_tuple(5, std::vector<int>{1, 4, 5}, 5,
|
||||
std::vector<uint8_t>{0b00000111}),
|
||||
std::make_tuple(5, std::vector<int>{1, 5, 3, 7, 8, 50, 42, 60, 39}, 10,
|
||||
std::vector<uint8_t>{0xFF, 0b00000001}),
|
||||
std::make_tuple(5, std::vector<int>{1, 5, 3, 7, 8, 50, 42, 60}, 5,
|
||||
std::vector<uint8_t>{0xFF}));
|
||||
|
||||
size_t num_samples, expected_num_digital_bytes;
|
||||
std::vector<uint8_t> expected_digital_part;
|
||||
std::vector<int> bitlist;
|
||||
std::tie(num_samples, bitlist, expected_num_digital_bytes,
|
||||
expected_digital_part) = parameters;
|
||||
|
||||
generaldata->SetCtbDbitList(bitlist);
|
||||
|
||||
generaldata->SetCtbDbitReorder(false);
|
||||
|
||||
set_num_samples(num_samples);
|
||||
set_data();
|
||||
|
||||
size_t expected_size =
|
||||
num_analog_bytes + num_transceiver_bytes + expected_num_digital_bytes;
|
||||
|
||||
// create expected data
|
||||
char *expected_data = new char[expected_size];
|
||||
|
||||
memset(expected_data, dummy_value, num_analog_bytes);
|
||||
|
||||
for (size_t sample = 0; sample < num_samples; ++sample) {
|
||||
memcpy(expected_data + num_analog_bytes +
|
||||
expected_digital_part.size() * sample,
|
||||
expected_digital_part.data(), expected_digital_part.size());
|
||||
}
|
||||
|
||||
memset(expected_data + expected_num_digital_bytes + num_analog_bytes,
|
||||
dummy_value, num_transceiver_bytes);
|
||||
|
||||
size_t size = get_size();
|
||||
dataprocessor->ArrangeDbitData(size, data);
|
||||
|
||||
CHECK(size == expected_size);
|
||||
|
||||
CHECK(memcmp(data, expected_data, expected_size) == 0);
|
||||
|
||||
delete[] expected_data;
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(DataProcessorTestFixture, "Arrange bitlist with reorder true",
|
||||
"[.dataprocessor][.retrievebitlist]") {
|
||||
// parameters: num_samples, bitlist, expected_num_digital_bytes,
|
||||
// expected_digital_part
|
||||
auto parameters = GENERATE(
|
||||
std::make_tuple(5, std::vector<int>{1, 4, 5}, 3,
|
||||
std::vector<uint8_t>{0b00011111}),
|
||||
std::make_tuple(10, std::vector<int>{1, 4, 5}, 6,
|
||||
std::vector<uint8_t>{0xFF, 0b00000011}),
|
||||
std::make_tuple(8, std::vector<int>{1, 5, 3, 7, 8, 50, 42, 60, 39}, 9,
|
||||
std::vector<uint8_t>{0xFF}));
|
||||
|
||||
size_t num_samples, expected_num_digital_bytes;
|
||||
std::vector<uint8_t> expected_digital_part;
|
||||
std::vector<int> bitlist;
|
||||
std::tie(num_samples, bitlist, expected_num_digital_bytes,
|
||||
expected_digital_part) = parameters;
|
||||
|
||||
generaldata->SetCtbDbitList(bitlist);
|
||||
|
||||
generaldata->SetCtbDbitReorder(true);
|
||||
|
||||
set_num_samples(num_samples);
|
||||
set_data();
|
||||
|
||||
size_t expected_size =
|
||||
num_analog_bytes + num_transceiver_bytes + expected_num_digital_bytes;
|
||||
|
||||
// create expected data
|
||||
char *expected_data = new char[expected_size];
|
||||
|
||||
memset(expected_data, dummy_value, num_analog_bytes);
|
||||
|
||||
for (size_t sample = 0; sample < bitlist.size(); ++sample) {
|
||||
memcpy(expected_data + num_analog_bytes +
|
||||
expected_digital_part.size() * sample,
|
||||
expected_digital_part.data(), expected_digital_part.size());
|
||||
}
|
||||
|
||||
memset(expected_data + expected_num_digital_bytes + num_analog_bytes,
|
||||
dummy_value, num_transceiver_bytes);
|
||||
|
||||
size_t size = get_size();
|
||||
dataprocessor->ArrangeDbitData(size, data);
|
||||
|
||||
CHECK(size == expected_size);
|
||||
|
||||
CHECK(memcmp(data, expected_data, expected_size) == 0);
|
||||
|
||||
delete[] expected_data;
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(DataProcessorTestFixture,
|
||||
"Arrange bitlist and remove trailing bits",
|
||||
"[.dataprocessor][.retrievebitlist]") {
|
||||
|
||||
size_t num_random_offset_bytes = 3;
|
||||
std::vector<int> bitlist{1, 4, 5};
|
||||
|
||||
set_random_offset_bytes(num_random_offset_bytes);
|
||||
set_data();
|
||||
|
||||
generaldata->SetCtbDbitList(bitlist);
|
||||
|
||||
generaldata->SetCtbDbitReorder(false);
|
||||
|
||||
generaldata->SetCtbDbitOffset(num_random_offset_bytes);
|
||||
|
||||
std::vector<uint8_t> expected_digital_part{0b00000111};
|
||||
const size_t expected_num_digital_bytes = 5;
|
||||
|
||||
size_t expected_size =
|
||||
num_analog_bytes + num_transceiver_bytes + expected_num_digital_bytes;
|
||||
|
||||
// create expected data
|
||||
char *expected_data = new char[expected_size];
|
||||
|
||||
memset(expected_data, dummy_value, num_analog_bytes);
|
||||
|
||||
for (size_t sample = 0; sample < num_samples; ++sample) {
|
||||
memcpy(expected_data + num_analog_bytes +
|
||||
expected_digital_part.size() * sample,
|
||||
expected_digital_part.data(), expected_digital_part.size());
|
||||
}
|
||||
|
||||
memset(expected_data + expected_num_digital_bytes + num_analog_bytes,
|
||||
dummy_value, num_transceiver_bytes);
|
||||
|
||||
size_t size = get_size();
|
||||
dataprocessor->ArrangeDbitData(size, data);
|
||||
|
||||
CHECK(size == expected_size);
|
||||
|
||||
CHECK(memcmp(data, expected_data, expected_size) == 0);
|
||||
|
||||
delete[] expected_data;
|
||||
}
|
||||
|
||||
} // namespace sls
|
@ -410,6 +410,8 @@ enum detFuncs {
|
||||
F_RECEIVER_SET_TRANSCEIVER_MASK,
|
||||
F_RECEIVER_SET_ROW,
|
||||
F_RECEIVER_SET_COLUMN,
|
||||
F_GET_RECEIVER_DBIT_REORDER,
|
||||
F_SET_RECEIVER_DBIT_REORDER,
|
||||
|
||||
NUM_REC_FUNCTIONS
|
||||
};
|
||||
@ -816,7 +818,8 @@ const char* getFunctionNameFromEnum(enum detFuncs func) {
|
||||
case F_RECEIVER_SET_TRANSCEIVER_MASK: return "F_RECEIVER_SET_TRANSCEIVER_MASK";
|
||||
case F_RECEIVER_SET_ROW: return "F_RECEIVER_SET_ROW";
|
||||
case F_RECEIVER_SET_COLUMN: return "F_RECEIVER_SET_COLUMN";
|
||||
|
||||
case F_GET_RECEIVER_DBIT_REORDER: return "F_GET_RECEIVER_DBIT_REORDER";
|
||||
case F_SET_RECEIVER_DBIT_REORDER: return "F_SET_RECEIVER_DBIT_REORDER";
|
||||
|
||||
case NUM_REC_FUNCTIONS: return "NUM_REC_FUNCTIONS";
|
||||
default: return "Unknown Function";
|
||||
|
@ -5,8 +5,8 @@
|
||||
#define APIRECEIVER "developer 0x241122"
|
||||
#define APICTB "developer 0x250310"
|
||||
#define APIGOTTHARD2 "developer 0x250310"
|
||||
#define APIMYTHEN3 "developer 0x250310"
|
||||
#define APIMOENCH "developer 0x250310"
|
||||
#define APIEIGER "developer 0x250310"
|
||||
#define APIXILINXCTB "developer 0x250311"
|
||||
#define APIJUNGFRAU "developer 0x250318"
|
||||
#define APIMYTHEN3 "developer 0x250409"
|
||||
|
@ -4,7 +4,7 @@
|
||||
This file is used to start up simulators, receivers and run all the tests on them and finally kill the simulators and receivers.
|
||||
'''
|
||||
import argparse
|
||||
import os, sys, subprocess, time, colorama, signal
|
||||
import os, sys, subprocess, time, colorama
|
||||
|
||||
from colorama import Fore
|
||||
from slsdet import Detector, detectorType, detectorSettings
|
||||
@ -23,23 +23,9 @@ def Log(color, message):
|
||||
|
||||
|
||||
def checkIfProcessRunning(processName):
|
||||
cmd = "ps -ef | grep " + processName
|
||||
print(cmd)
|
||||
res=subprocess.getoutput(cmd)
|
||||
print(res)
|
||||
# eg. of output
|
||||
#l_user 250506 243295 0 14:38 pts/5 00:00:00 /bin/sh -c ps -ef | grep slsReceiver
|
||||
#l_user 250508 250506 0 14:38 pts/5 00:00:00 grep slsReceiver
|
||||
|
||||
print('how many')
|
||||
cmd = "ps -ef | grep " + processName + " | wc -l"
|
||||
print(cmd)
|
||||
res=subprocess.getoutput(cmd)
|
||||
print(res)
|
||||
|
||||
if res == '2':
|
||||
return False
|
||||
return True
|
||||
cmd = f"pgrep -f {processName}"
|
||||
res = subprocess.getoutput(cmd)
|
||||
return bool(res.strip())
|
||||
|
||||
|
||||
def killProcess(name):
|
||||
@ -52,7 +38,7 @@ def killProcess(name):
|
||||
print('process not running : ' + name)
|
||||
|
||||
|
||||
def killAllStaleProcesses():
|
||||
def killAllStaleProcesses(fp):
|
||||
killProcess('eigerDetectorServer_virtual')
|
||||
killProcess('jungfrauDetectorServer_virtual')
|
||||
killProcess('mythen3DetectorServer_virtual')
|
||||
@ -62,9 +48,9 @@ def killAllStaleProcesses():
|
||||
killProcess('xilinx_ctbDetectorServer_virtual')
|
||||
killProcess('slsReceiver')
|
||||
killProcess('slsMultiReceiver')
|
||||
cleanSharedmemory()
|
||||
cleanSharedmemory(fp)
|
||||
|
||||
def cleanup(name):
|
||||
def cleanup(name, fp):
|
||||
'''
|
||||
kill both servers, receivers and clean shared memory
|
||||
'''
|
||||
@ -72,9 +58,9 @@ def cleanup(name):
|
||||
killProcess(name + 'DetectorServer_virtual')
|
||||
killProcess('slsReceiver')
|
||||
killProcess('slsMultiReceiver')
|
||||
cleanSharedmemory()
|
||||
cleanSharedmemory(fp)
|
||||
|
||||
def cleanSharedmemory():
|
||||
def cleanSharedmemory(fp):
|
||||
Log(Fore.GREEN, 'Cleaning up shared memory...')
|
||||
try:
|
||||
p = subprocess.run(['sls_detector_get', 'free'], stdout=fp, stderr=fp)
|
||||
@ -87,8 +73,8 @@ def startProcessInBackground(name):
|
||||
# in background and dont print output
|
||||
p = subprocess.Popen(name.split(), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, restore_signals=False)
|
||||
Log(Fore.GREEN, 'Starting up ' + name + ' ...')
|
||||
except:
|
||||
Log(Fore.RED, 'Could not start ' + name)
|
||||
except Exception as e:
|
||||
Log(Fore.RED, f'Could not start {name}:{e}')
|
||||
raise
|
||||
|
||||
def startServer(name):
|
||||
@ -139,14 +125,19 @@ def loadConfig(name, rx_hostname, settingsdir):
|
||||
def startCmdTests(name, fp, fname):
|
||||
Log(Fore.GREEN, 'Cmd Tests for ' + name)
|
||||
cmd = 'tests --abort [.cmdcall] -s -o ' + fname
|
||||
p = subprocess.run(cmd.split(), stdout=fp, stderr=fp, check=True, text=True)
|
||||
p.check_returncode()
|
||||
try:
|
||||
subprocess.run(cmd.split(), stdout=fp, stderr=fp, check=True, text=True)
|
||||
except subprocess.CalledProcessError as e:
|
||||
pass
|
||||
|
||||
with open (fname, 'r') as f:
|
||||
for line in f:
|
||||
if "FAILED" in line:
|
||||
msg = 'Cmd tests failed for ' + name + '!!!'
|
||||
sys.stdout = original_stdout
|
||||
Log(Fore.RED, msg)
|
||||
Log(Fore.RED, line)
|
||||
sys.stdout = fp
|
||||
raise Exception(msg)
|
||||
|
||||
Log(Fore.GREEN, 'Cmd Tests successful for ' + name)
|
||||
@ -154,14 +145,18 @@ def startCmdTests(name, fp, fname):
|
||||
def startGeneralTests(fp, fname):
|
||||
Log(Fore.GREEN, 'General Tests')
|
||||
cmd = 'tests --abort -s -o ' + fname
|
||||
p = subprocess.run(cmd.split(), stdout=fp, stderr=fp, check=True, text=True)
|
||||
p.check_returncode()
|
||||
try:
|
||||
subprocess.run(cmd.split(), stdout=fp, stderr=fp, check=True, text=True)
|
||||
except subprocess.CalledProcessError as e:
|
||||
pass
|
||||
|
||||
with open (fname, 'r') as f:
|
||||
for line in f:
|
||||
if "FAILED" in line:
|
||||
msg = 'General tests failed !!!'
|
||||
Log(Fore.RED, msg)
|
||||
sys.stdout = original_stdout
|
||||
Log(Fore.RED, msg + '\n' + line)
|
||||
sys.stdout = fp
|
||||
raise Exception(msg)
|
||||
|
||||
Log(Fore.GREEN, 'General Tests successful')
|
||||
@ -170,12 +165,10 @@ def startGeneralTests(fp, fname):
|
||||
|
||||
# parse cmd line for rx_hostname and settingspath using the argparse library
|
||||
parser = argparse.ArgumentParser(description = 'automated tests with the virtual detector servers')
|
||||
parser.add_argument('rx_hostname', help = 'hostname/ip of the current machine')
|
||||
parser.add_argument('settingspath', help = 'Relative or absolut path to the settingspath')
|
||||
parser.add_argument('rx_hostname', nargs='?', default='localhost', help = 'hostname/ip of the current machine')
|
||||
parser.add_argument('settingspath', nargs='?', default='../../settingsdir', help = 'Relative or absolut path to the settingspath')
|
||||
parser.add_argument('-s', '--servers', help='Detector servers to run', nargs='*')
|
||||
args = parser.parse_args()
|
||||
if args.rx_hostname == 'localhost':
|
||||
raise RuntimeException('Cannot use localhost for rx_hostname for the tests (fails for rx_arping for eg.)')
|
||||
|
||||
if args.servers is None:
|
||||
servers = [
|
||||
@ -203,46 +196,59 @@ Log(Fore.BLUE, '\nLog File: ' + fname)
|
||||
|
||||
with open(fname, 'w') as fp:
|
||||
|
||||
|
||||
|
||||
# general tests
|
||||
file_results = prefix_fname + '_results_general.txt'
|
||||
Log(Fore.BLUE, 'General tests (results: ' + file_results + ')')
|
||||
sys.stdout = fp
|
||||
sys.stderr = fp
|
||||
Log(Fore.BLUE, 'General tests (results: ' + file_results + ')')
|
||||
startGeneralTests(fp, file_results)
|
||||
|
||||
killAllStaleProcesses()
|
||||
try:
|
||||
startGeneralTests(fp, file_results)
|
||||
killAllStaleProcesses(fp)
|
||||
|
||||
for server in servers:
|
||||
try:
|
||||
# print to terminal for progress
|
||||
sys.stdout = original_stdout
|
||||
sys.stderr = original_stderr
|
||||
file_results = prefix_fname + '_results_cmd_' + server + '.txt'
|
||||
Log(Fore.BLUE, 'Cmd tests for ' + server + ' (results: ' + file_results + ')')
|
||||
sys.stdout = fp
|
||||
sys.stderr = fp
|
||||
Log(Fore.BLUE, 'Cmd tests for ' + server + ' (results: ' + file_results + ')')
|
||||
|
||||
# cmd tests for det
|
||||
cleanup(server)
|
||||
startServer(server)
|
||||
startReceiver(server)
|
||||
loadConfig(server, args.rx_hostname, args.settingspath)
|
||||
startCmdTests(server, fp, file_results)
|
||||
cleanup(server)
|
||||
except:
|
||||
Log(Fore.RED, 'Exception caught. Cleaning up.')
|
||||
cleanup(server)
|
||||
sys.stdout = original_stdout
|
||||
sys.stderr = original_stderr
|
||||
Log(Fore.RED, 'Cmd tests failed for ' + server + '!!!')
|
||||
raise
|
||||
testError = False
|
||||
for server in servers:
|
||||
try:
|
||||
# print to terminal for progress
|
||||
sys.stdout = original_stdout
|
||||
sys.stderr = original_stderr
|
||||
file_results = prefix_fname + '_results_cmd_' + server + '.txt'
|
||||
Log(Fore.BLUE, 'Cmd tests for ' + server + ' (results: ' + file_results + ')')
|
||||
sys.stdout = fp
|
||||
sys.stderr = fp
|
||||
Log(Fore.BLUE, 'Cmd tests for ' + server + ' (results: ' + file_results + ')')
|
||||
|
||||
# cmd tests for det
|
||||
cleanup(server, fp)
|
||||
startServer(server)
|
||||
startReceiver(server)
|
||||
loadConfig(server, args.rx_hostname, args.settingspath)
|
||||
startCmdTests(server, fp, file_results)
|
||||
cleanup(server, fp)
|
||||
|
||||
except Exception as e:
|
||||
# redirect to terminal
|
||||
sys.stdout = original_stdout
|
||||
sys.stderr = original_stderr
|
||||
Log(Fore.RED, f'Exception caught while testing {server}. Cleaning up...')
|
||||
testError = True
|
||||
break
|
||||
|
||||
# redirect to terminal
|
||||
sys.stdout = original_stdout
|
||||
sys.stderr = original_stderr
|
||||
if not testError:
|
||||
Log(Fore.GREEN, 'Passed all tests for virtual detectors \n' + str(servers))
|
||||
|
||||
|
||||
Log(Fore.GREEN, 'Passed all tests for virtual detectors \n' + str(servers))
|
||||
except Exception as e:
|
||||
# redirect to terminal
|
||||
sys.stdout = original_stdout
|
||||
sys.stderr = original_stderr
|
||||
Log(Fore.RED, f'Exception caught with general testing. Cleaning up...')
|
||||
cleanSharedmemory(sys.stdout)
|
||||
|
||||
|
||||
# redirect to terminal
|
||||
sys.stdout = original_stdout
|
||||
sys.stderr = original_stderr
|
||||
Log(Fore.GREEN, 'Passed all tests for virtual detectors \n' + str(servers) + '\nYayyyy! :) ')
|
@ -5,7 +5,12 @@ Script to update VERSION file with semantic versioning if provided as an argumen
|
||||
"""
|
||||
|
||||
import sys
|
||||
import re
|
||||
import os
|
||||
|
||||
from packaging.version import Version, InvalidVersion
|
||||
|
||||
|
||||
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
def get_version():
|
||||
|
||||
@ -14,23 +19,24 @@ def get_version():
|
||||
return "0.0.0"
|
||||
|
||||
version = sys.argv[1]
|
||||
|
||||
# Validate that the version argument matches semantic versioning format (X.Y.Z)
|
||||
if not re.match(r'^\d+\.\d+\.\d+$', version):
|
||||
print("Error: Version argument must be in semantic versioning format (X.Y.Z)")
|
||||
|
||||
try:
|
||||
v = Version(version) # normalizcheck if version follows PEP 440 specification
|
||||
#replace -
|
||||
return version.replace("-", ".")
|
||||
except InvalidVersion as e:
|
||||
print(f"Invalid version {version}. Version format must follow semantic versioning format of python PEP 440 version identification specification.")
|
||||
sys.exit(1)
|
||||
|
||||
return version
|
||||
|
||||
|
||||
def write_version_to_file(version):
|
||||
with open("VERSION", "w") as version_file:
|
||||
version_file_path = os.path.join(SCRIPT_DIR, "VERSION")
|
||||
with open(version_file_path, "w") as version_file:
|
||||
version_file.write(version)
|
||||
print(f"Version {version} written to VERSION file.")
|
||||
|
||||
|
||||
# Main script
|
||||
if __name__ == "__main__":
|
||||
|
||||
version = get_version()
|
||||
write_version_to_file(version)
|
||||
write_version_to_file(version)
|
||||
|
Reference in New Issue
Block a user