Files
Jungfraujoch/receiver/MockAcquisitionDevice.cpp

171 lines
5.9 KiB
C++

// Copyright (2019-2023) Paul Scherrer Institute
#include "MockAcquisitionDevice.h"
#include "../common/JFJochException.h"
#include <bitset>
#include "../jungfrau/JFConversionFloatingPoint.h"
void MockAcquisitionDevice::Start(const DiffractionExperiment& experiment) {
idle = false;
cancel = false;
if (experiment.IsUsingInternalPacketGen()) {
if (experiment.GetConversionOnFPGA() && (experiment.GetDetectorMode() == DetectorMode::Conversion)) {
for (auto &i: buffer_device)
memcpy(i, internal_pkt_gen_frame_conv.data(), RAW_MODULE_SIZE * sizeof(uint16_t));
} else {
for (auto &i: buffer_device)
memcpy(i, internal_pkt_gen_frame.data(), RAW_MODULE_SIZE * sizeof(uint16_t));
}
measure = std::async(std::launch::async, &MockAcquisitionDevice::InternalPacketGeneratorThread, this,
experiment.GetModulesNum(data_stream), experiment.GetFrameNum());
} else {
measure = std::async(std::launch::async, &MockAcquisitionDevice::MeasureThread, this);
}
}
void MockAcquisitionDevice::Cancel() {
if (!idle) {
if (logger)
logger->Info("MockAcquisitionDevice cancelling " + std::to_string(data_stream));
cancel = true;
}
}
MockAcquisitionDevice::MockAcquisitionDevice(uint16_t data_stream, size_t in_frame_buffer_size_modules,
int16_t in_numa_node)
: AcquisitionDevice(data_stream), internal_pkt_gen_frame(RAW_MODULE_SIZE), internal_pkt_gen_frame_conv(RAW_MODULE_SIZE) {
max_modules = 16;
MapBuffersStandard(in_frame_buffer_size_modules, 1, in_numa_node);
max_handle = in_frame_buffer_size_modules;
for (int i = 0; i < RAW_MODULE_SIZE; i++) {
internal_pkt_gen_frame[i] = i % 65536;
internal_pkt_gen_frame_conv[i] = i % 65536;
}
}
void MockAcquisitionDevice::SendCompletion(uint32_t handle, uint16_t module_number, uint64_t frame_number) {
Completion c;
c.handle = handle;
c.module_number = module_number;
c.frame_number = frame_number - 1;
c.type = Completion::Type::Image;
c.packet_mask[0] = UINT64_MAX;
c.packet_mask[1] = UINT64_MAX;
c.packet_count = 128;
mock_completions.Put(c);
}
void MockAcquisitionDevice::AddModule(uint64_t frame_number, uint16_t module_number, const uint16_t *data) {
if (module_number >= max_modules)
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds,
"Module number exceeding limit");
if (current_handle < max_handle) {
memcpy(buffer_device.at(current_handle), data, RAW_MODULE_SIZE * sizeof(uint16_t));
SendCompletion(current_handle, module_number, frame_number);
current_handle++;
} else {
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "No buffer handles left");
}
}
void MockAcquisitionDevice::MeasureThread() {
work_completion_queue.Put(Completion{.type = Completion::Type::Start});
while (!cancel) {
Completion c{};
if (mock_completions.Get(c)) {
if (c.type == Completion::Type::Image)
work_completion_queue.Put(c);
else
cancel = true;
} else
std::this_thread::sleep_for(std::chrono::microseconds(100));
}
work_completion_queue.Put(Completion{
.type = Completion::Type::End
});
idle = true;
}
void MockAcquisitionDevice::InternalPacketGeneratorThread(uint32_t nmodules, uint32_t nframes) {
work_completion_queue.Put(Completion{.type = Completion::Type::Start});
uint32_t curr_module = 0;
uint32_t curr_frame = 0;
while ((!cancel) && (curr_frame < nframes)) {
WorkRequest wr{};
if (work_request_queue.Get(wr)) {
Completion c{};
c.handle = wr.handle;
c.module_number = curr_module;
c.frame_number = curr_frame;
c.type = Completion::Type::Image;
c.packet_mask[0] = UINT64_MAX;
c.packet_mask[1] = UINT64_MAX;
c.packet_count = 128;
work_completion_queue.Put(c);
curr_module++;
if (curr_module == nmodules) {
curr_module = 0;
curr_frame++;
}
} else
std::this_thread::sleep_for(std::chrono::microseconds(100));
}
work_completion_queue.Put(Completion{
.type = Completion::Type::End
});
idle = true;
}
void MockAcquisitionDevice::Terminate() {
mock_completions.Put(Completion{
.type = Completion::Type::End
});
}
std::string MockAcquisitionDevice::GetMACAddress() const {
return "00:00:00:00:00:00";
}
std::string MockAcquisitionDevice::GetIPv4Address() const {
return "127.0.0.1";
}
void MockAcquisitionDevice::Finalize() {
if (measure.valid())
measure.get();
}
void MockAcquisitionDevice::SetCustomInternalGeneratorFrame(const std::vector<uint16_t> &v) {
if (v.size() != RAW_MODULE_SIZE)
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Error in size of custom internal generator frame");
internal_pkt_gen_frame = v;
internal_pkt_gen_frame_conv = v;
}
void MockAcquisitionDevice::InitializeCalibration(const DiffractionExperiment &experiment, const JFCalibration &calib) {
JFConversionFloatingPoint conv;
conv.Setup(calib.GainCalibration(experiment.GetFirstModuleOfDataStream(data_stream)),
calib.Pedestal(experiment.GetFirstModuleOfDataStream(data_stream),0),
calib.Pedestal(experiment.GetFirstModuleOfDataStream(data_stream),1),
calib.Pedestal(experiment.GetFirstModuleOfDataStream(data_stream),2),
experiment.GetPhotonEnergy_keV());
conv.ConvertModule((int16_t *) internal_pkt_gen_frame_conv.data(), internal_pkt_gen_frame.data());
}
std::vector<uint16_t> MockAcquisitionDevice::GetInternalGeneratorFrame() const {
return internal_pkt_gen_frame;
}