171 lines
5.9 KiB
C++
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;
|
|
}
|