102 lines
4.2 KiB
C++
102 lines
4.2 KiB
C++
// Copyright (2019-2022) Paul Scherrer Institute
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
#include <cstring>
|
|
|
|
#include "ProcessJFPacket.h"
|
|
#include "jf_packet.h"
|
|
#include "../common/JFJochException.h"
|
|
#include "JFConversionFixedPoint.h"
|
|
|
|
ProcessJFPacket::ProcessJFPacket(ThreadSafeFIFO<Completion> &in_c, ThreadSafeFIFO<WorkRequest> &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<std::mutex> 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<JFConversionFixedPoint>();
|
|
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());
|
|
}
|
|
}
|