// Copyright (2019-2022) Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-or-later #include "MockAcquisitionDevice.h" #include "../common/JFJochException.h" #include #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 &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 MockAcquisitionDevice::GetInternalGeneratorFrame() const { return internal_pkt_gen_frame; }