// Copyright (2019-2022) Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-or-later #include #include "ProcessJFPacket.h" #include "jf_packet.h" #include "../common/JFJochException.h" #include "JFConversionFixedPoint.h" ProcessJFPacket::ProcessJFPacket(ThreadSafeFIFO &in_c, ThreadSafeFIFO &in_wr, uint32_t nmodules) : m(2 * nmodules), c_fifo(in_c), wr_fifo(in_wr), module_info(2 * nmodules), conv(nmodules) { for (auto &i: module_info) i.c.frame_number = UINT64_MAX; } ProcessJFPacket::~ProcessJFPacket() { for (auto &i: module_info) { if (i.c.frame_number != UINT64_MAX) c_fifo.Put(i.c); } } void ProcessJFPacket::ProcessPacket(jf_udp_payload *datagram) { if (datagram->framenum == 0) throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "Frame number cannot be zero"); uint64_t frame_number = datagram->framenum - 1; uint32_t module_number = (datagram->xCoord % 32) / 2; bool second_half_module = (datagram->xCoord % 2 == 1); uint32_t packetnum = datagram->packetnum | (second_half_module ? 64 : 0); uint64_t module_info_location = (module_number * 2) | (frame_number % 2); if (module_info_location > module_info.size()) throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "Module number out of bounds"); { std::unique_lock ul(m[module_info_location]); if (module_info[module_info_location].c.frame_number != frame_number) { if (module_info[module_info_location].c.frame_number != UINT64_MAX) c_fifo.Put(module_info[module_info_location].c); auto wr = wr_fifo.GetBlocking(); module_info[module_info_location].c.type = Completion::Type::Image; module_info[module_info_location].c.frame_number = frame_number; module_info[module_info_location].c.timestamp = datagram->timestamp; module_info[module_info_location].c.bunchid = datagram->bunchid; module_info[module_info_location].c.exptime = datagram->exptime; module_info[module_info_location].c.debug = datagram->debug; module_info[module_info_location].c.packet_mask[0] = 0; module_info[module_info_location].c.packet_mask[1] = 0; module_info[module_info_location].c.packet_count = 0; module_info[module_info_location].c.module_number = module_number; module_info[module_info_location].c.handle = wr.handle; module_info[module_info_location].ptr = wr.ptr; } module_info[module_info_location].c.packet_count++; module_info[module_info_location].c.packet_mask[packetnum >= 64 ? 1 : 0] |= (1LU << (packetnum % 64)); uint16_t* dst = module_info[module_info_location].ptr + 4096 * packetnum; if (conv[module_number]) conv[module_number]->ConvertPacket((int16_t *) dst, datagram->data, packetnum); else memcpy(dst, datagram->data, 4096 * sizeof(uint16_t)); } packet_counter++; } uint64_t ProcessJFPacket::GetCounter() { return packet_counter; } void ProcessJFPacket::RegisterConversion(const DiffractionExperiment &experiment, const JFCalibration &calib, uint16_t data_stream) { if (data_stream >= experiment.GetDataStreamsNum()) throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "Data stream not found"); if (conv.size() != experiment.GetModulesNum(data_stream)) throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Wrong module count"); auto module0 = experiment.GetFirstModuleOfDataStream(data_stream); for (int i = 0; i < experiment.GetModulesNum(data_stream); i++) { conv[i] = std::make_unique(); conv[i]->Setup(calib.GainCalibration(module0 + i), calib.Pedestal(module0 + i, 0, 0), calib.Pedestal(module0 + i, 1, 0), calib.Pedestal(module0 + i, 2, 0), experiment.GetPhotonEnergy_keV()); } }