231 lines
10 KiB
C++
231 lines
10 KiB
C++
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#include <thread>
|
|
|
|
#include "AcquisitionCounters.h"
|
|
#include "../common/JFJochException.h"
|
|
|
|
AcquisitionCounters::AcquisitionCounters()
|
|
: curr_frame_number(max_modules, 0), slowest_frame_number(0), fastest_frame_number(0),
|
|
total_packets(0), expected_frames(0), acquisition_finished(false) {}
|
|
|
|
void AcquisitionCounters::Reset(const DiffractionExperiment &experiment, uint16_t data_stream) {
|
|
std::unique_lock ul(m);
|
|
acquisition_finished = false;
|
|
|
|
slowest_frame_number = 0;
|
|
fastest_frame_number = 0;
|
|
|
|
if ((experiment.GetDetectorMode() == DetectorMode::PedestalG0) ||
|
|
(experiment.GetDetectorMode() == DetectorMode::PedestalG1) ||
|
|
(experiment.GetDetectorMode() == DetectorMode::PedestalG2))
|
|
expected_frames = experiment.GetFrameNum();
|
|
else
|
|
expected_frames = experiment.GetFrameNum() / experiment.GetFPGASummation();
|
|
|
|
nmodules = experiment.GetModulesNum(data_stream);
|
|
if (nmodules > max_modules)
|
|
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Acquisition counter cannot support that many modules");
|
|
for (int i = 0; i < max_modules; i++)
|
|
curr_frame_number[i] = 0;
|
|
|
|
handle_for_frame = std::vector<uint64_t>(expected_frames * nmodules, HandleNotFound);
|
|
handle_for_pedestal = std::vector<uint64_t>(nmodules * 16, HandleNotFound); // 16 = storage cells
|
|
packets_collected = std::vector<uint16_t>(expected_frames * nmodules);
|
|
saved_completions = std::vector<Completion>(expected_frames * nmodules);
|
|
packets_per_module = std::vector<uint64_t>(nmodules);
|
|
total_packets = 0;
|
|
expected_packets_per_module = 512 * experiment.GetFPGASummation();
|
|
|
|
if (experiment.GetBitDepthReadout() == 32)
|
|
bytes_per_packet = 4096LU;
|
|
else if (experiment.GetBitDepthReadout() == 8)
|
|
bytes_per_packet = 1024LU; // Need to seriously refactor, to have expected_packets_per_module specific for detector
|
|
else
|
|
bytes_per_packet = 2048LU;
|
|
}
|
|
|
|
void AcquisitionCounters::UpdateCounters(const Completion *c) {
|
|
std::unique_lock ul(m);
|
|
|
|
if (c->module_number >= nmodules)
|
|
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
|
|
"UpdateCounters wrong module number: " + std::to_string(c->module_number) + " for frame " + std::to_string(c->frame_number) +
|
|
" and handle " + std::to_string(c->handle));
|
|
if (c->frame_number >= expected_frames)
|
|
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
|
|
"UpdateCounters frame number is out of bounds");
|
|
else {
|
|
if (curr_frame_number.at(c->module_number) < c->frame_number)
|
|
curr_frame_number.at(c->module_number) = c->frame_number;
|
|
|
|
if (c->frame_number > slowest_frame_number) {
|
|
slowest_frame_number = curr_frame_number[0];
|
|
for (int i = 1; i < nmodules; i++)
|
|
if (curr_frame_number[i] < slowest_frame_number)
|
|
slowest_frame_number = curr_frame_number[i];
|
|
}
|
|
|
|
if (c->frame_number > fastest_frame_number) {
|
|
fastest_frame_number = c->frame_number;
|
|
}
|
|
|
|
if (fastest_frame_number - slowest_frame_number > ThresholdFramesLost)
|
|
slowest_frame_number = fastest_frame_number - ThresholdFramesLost;
|
|
|
|
packets_collected.at(c->frame_number * nmodules + c->module_number) = c->packet_count;
|
|
handle_for_frame.at(c->frame_number * nmodules + c->module_number) = c->handle;
|
|
saved_completions.at(c->frame_number * nmodules + c->module_number) = *c;
|
|
|
|
total_packets += c->packet_count;
|
|
packets_per_module[c->module_number] += c->packet_count;
|
|
}
|
|
|
|
data_updated.notify_all();
|
|
}
|
|
|
|
void AcquisitionCounters::SetAcquisitionFinished() {
|
|
std::unique_lock ul(m);
|
|
acquisition_finished = true;
|
|
data_updated.notify_all();
|
|
}
|
|
|
|
uint64_t AcquisitionCounters::GetBufferHandle(size_t frame, uint16_t module_number) const {
|
|
if (frame >= expected_frames)
|
|
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds,
|
|
"GetBufferHandle Wrong frame number: " + std::to_string(frame));
|
|
if (module_number >= nmodules)
|
|
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds,
|
|
"GetBufferHandle Wrong module number: " + std::to_string(module_number)
|
|
+ " for frame " + std::to_string(frame));
|
|
return handle_for_frame.at(frame * nmodules + module_number);
|
|
}
|
|
|
|
uint64_t AcquisitionCounters::GetBufferHandleAndClear(size_t frame, uint16_t module_number) {
|
|
std::unique_lock ul(m);
|
|
if (frame >= expected_frames)
|
|
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds,
|
|
"GetBufferHandleAndClear Wrong frame number: " + std::to_string(frame));
|
|
if (module_number >= nmodules)
|
|
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds,
|
|
"GetBufferHandleAndClear Wrong module number: " + std::to_string(module_number)
|
|
+ " for frame " + std::to_string(frame));
|
|
uint64_t ret_val = handle_for_frame.at(frame * nmodules + module_number);
|
|
handle_for_frame.at(frame * nmodules + module_number) = HandleNotFound;
|
|
return ret_val;
|
|
}
|
|
|
|
uint64_t AcquisitionCounters::GetPedestalBufferHandle(size_t storage_cell, uint16_t module_number) const {
|
|
std::unique_lock ul(m);
|
|
if (storage_cell >= 16)
|
|
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds,
|
|
"GetBufferHandleAndClear Wrong frame number: " + std::to_string(storage_cell));
|
|
if (module_number >= nmodules)
|
|
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds,
|
|
"GetBufferHandleAndClear Wrong module number: " + std::to_string(module_number)
|
|
+ " for SC " + std::to_string(storage_cell));
|
|
return handle_for_pedestal.at(storage_cell * nmodules + module_number);
|
|
}
|
|
|
|
uint64_t AcquisitionCounters::GetCurrFrameNumber(uint16_t module_number) const {
|
|
if (module_number >= max_modules)
|
|
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds,
|
|
"GetCurrFrameNumber Wrong module number: " + std::to_string(module_number));
|
|
return curr_frame_number[module_number];
|
|
}
|
|
|
|
uint64_t AcquisitionCounters::GetSlowestFrameNumber() const {
|
|
return slowest_frame_number;
|
|
}
|
|
|
|
uint64_t AcquisitionCounters::GetFastestFrameNumber() const {
|
|
return fastest_frame_number;
|
|
}
|
|
|
|
void AcquisitionCounters::WaitForFrame(size_t curr_frame, uint16_t module_number) const {
|
|
uint64_t slowest_head_tmp = (module_number == UINT16_MAX) ? GetSlowestFrameNumber() : GetCurrFrameNumber(module_number);
|
|
if (curr_frame == 0)
|
|
curr_frame = 1; // Cannot wait for frame 0, as this is initial value of slowest frame number, so waiting for frame 1 in this case
|
|
while (!acquisition_finished && (slowest_head_tmp < curr_frame)) {
|
|
std::this_thread::sleep_for(std::chrono::microseconds(100));
|
|
slowest_head_tmp = (module_number == UINT16_MAX) ? GetSlowestFrameNumber() : GetCurrFrameNumber(module_number);
|
|
}
|
|
}
|
|
|
|
int64_t AcquisitionCounters::CalculateDelay(size_t curr_frame, uint16_t module_number) const {
|
|
uint64_t slowest_head_tmp;
|
|
|
|
if (module_number == UINT16_MAX)
|
|
slowest_head_tmp = GetSlowestFrameNumber();
|
|
else
|
|
slowest_head_tmp = GetCurrFrameNumber(module_number);
|
|
if (slowest_head_tmp < curr_frame)
|
|
return 0;
|
|
return slowest_head_tmp - curr_frame;
|
|
}
|
|
|
|
bool AcquisitionCounters::IsAcquisitionFinished() const {
|
|
return acquisition_finished;
|
|
}
|
|
|
|
bool AcquisitionCounters::IsFullModuleCollected(size_t frame, uint16_t module_number) const {
|
|
if (frame >= expected_frames)
|
|
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds,
|
|
"IsFullModuleCollected Wrong frame number: " + std::to_string(frame));
|
|
|
|
if (module_number >= nmodules)
|
|
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds,
|
|
"IsFullModuleCollected Wrong module number: " + std::to_string(module_number)
|
|
+ " for frame " + std::to_string(frame));
|
|
|
|
return packets_collected[frame * nmodules + module_number] == expected_packets_per_module;
|
|
}
|
|
|
|
bool AcquisitionCounters::IsAnyPacketCollected(size_t frame, uint16_t module_number) const {
|
|
if (frame >= expected_frames)
|
|
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds,
|
|
"IsFullModuleCollected Wrong frame number: " + std::to_string(frame));
|
|
|
|
if (module_number >= nmodules)
|
|
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds,
|
|
"IsFullModuleCollected Wrong module number: " + std::to_string(module_number)
|
|
+ " for frame " + std::to_string(frame));
|
|
|
|
return packets_collected[frame * nmodules + module_number] > 0;
|
|
}
|
|
|
|
uint64_t AcquisitionCounters::GetTotalPackets() const {
|
|
return total_packets;
|
|
}
|
|
|
|
uint64_t AcquisitionCounters::GetTotalPackets(uint16_t module_number) const {
|
|
std::unique_lock ul(m);
|
|
|
|
if (module_number >= nmodules)
|
|
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds,
|
|
"GetTotalPackets Wrong module number: " + std::to_string(module_number));
|
|
|
|
return packets_per_module[module_number];
|
|
}
|
|
|
|
uint64_t AcquisitionCounters::GetExpectedPacketsPerImage() const {
|
|
return expected_packets_per_module * nmodules;
|
|
}
|
|
|
|
uint64_t AcquisitionCounters::GetTotalExpectedPackets() const {
|
|
return GetTotalExpectedPacketsPerModule() * nmodules;
|
|
}
|
|
|
|
uint64_t AcquisitionCounters::GetTotalExpectedPacketsPerModule() const {
|
|
return expected_frames * expected_packets_per_module;
|
|
}
|
|
|
|
uint64_t AcquisitionCounters::GetModuleNumber() const {
|
|
return nmodules;
|
|
}
|
|
|
|
uint64_t AcquisitionCounters::GetBytesReceived() const {
|
|
return GetTotalPackets() * bytes_per_packet;
|
|
}
|