100 lines
4.1 KiB
C++
100 lines
4.1 KiB
C++
// Copyright (2019-2023) Paul Scherrer Institute
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
#include "FPGAAcquisitionDevice.h"
|
|
|
|
void FPGAAcquisitionDevice::HW_StartAction() {
|
|
FPGA_StartAction();
|
|
read_work_completion_future = std::async(std::launch::async, &FPGAAcquisitionDevice::ReadWorkCompletionThread, this);
|
|
}
|
|
|
|
void FPGAAcquisitionDevice::StartSendingWorkRequests() {
|
|
stop_work_requests = false;
|
|
send_work_request_future = std::async(std::launch::async, &FPGAAcquisitionDevice::SendWorkRequestThread, this);
|
|
}
|
|
|
|
void FPGAAcquisitionDevice::HW_EndAction() {
|
|
read_work_completion_future.get();
|
|
|
|
stop_work_requests = true;
|
|
send_work_request_future.get();
|
|
|
|
FPGA_EndAction();
|
|
}
|
|
|
|
void FPGAAcquisitionDevice::ReadWorkCompletionThread() {
|
|
uint32_t values[12];
|
|
|
|
Completion c{};
|
|
bool quit_loop = false;
|
|
do {
|
|
while (!HW_ReadMailbox(values))
|
|
std::this_thread::sleep_for(std::chrono::microseconds(10));
|
|
|
|
c = parse_hw_completion(values);
|
|
if (c.data_collection_id == data_collection_id) {
|
|
work_completion_queue.PutBlocking(c);
|
|
if (c.type == Completion::Type::End)
|
|
quit_loop = true;
|
|
}
|
|
} while (!quit_loop);
|
|
}
|
|
|
|
void FPGAAcquisitionDevice::SendWorkRequestThread() {
|
|
while (!stop_work_requests) {
|
|
WorkRequest wr{};
|
|
if (work_request_queue.Get(wr)) {
|
|
if ( !HW_SendWorkRequest(wr.handle)) {
|
|
work_request_queue.Put(wr);
|
|
std::this_thread::sleep_for(std::chrono::microseconds(10));
|
|
}
|
|
} else {
|
|
std::this_thread::sleep_for(std::chrono::microseconds(10));
|
|
}
|
|
}
|
|
}
|
|
|
|
void FPGAAcquisitionDevice::InitializeCalibration(const DiffractionExperiment &experiment, const JFCalibration &calib) {
|
|
auto offset = experiment.GetFirstModuleOfDataStream(data_stream);
|
|
|
|
if (calib.GetModulesNum() != experiment.GetModulesNum())
|
|
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
|
|
"Mismatch regarding module count in calibration and experiment description");
|
|
|
|
if (calib.GetStorageCellNum() != experiment.GetStorageCellNumber())
|
|
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
|
|
"Mismatch regarding storage cell count in calibration and experiment description");
|
|
|
|
size_t modules = experiment.GetModulesNum(data_stream);
|
|
|
|
if (1 + modules * (3 + 3 * experiment.GetStorageCellNumber()) > buffer_device.size())
|
|
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
|
|
"Not enough host/FPGA buffers to load all calibration constants");
|
|
|
|
for (int m = 0; m < modules; m++) {
|
|
calib.GainCalibration(m).ExportG0(buffer_device[1 + m]);
|
|
calib.GainCalibration(m).ExportG1(buffer_device[1 + m + modules]);
|
|
calib.GainCalibration(m).ExportG2(buffer_device[1 + m + modules * 2]);
|
|
}
|
|
|
|
for (int s = 0; s < experiment.GetStorageCellNumber(); s++) {
|
|
auto mask = calib.CalculateMask(experiment, s);
|
|
for (int m = 0; m < modules; m++) {
|
|
auto pedestal_g0 = calib.Pedestal(offset + m, 0, s).GetPedestal();
|
|
auto pedestal_g1 = calib.Pedestal(offset + m, 1, s).GetPedestal();
|
|
auto pedestal_g2 = calib.Pedestal(offset + m, 2, s).GetPedestal();
|
|
for (int i = 0; i < RAW_MODULE_SIZE; i++) {
|
|
if (experiment.GetApplyPixelMaskInFPGA() && (mask[(offset + m) * RAW_MODULE_SIZE + i] != 0)) {
|
|
buffer_device[1 + m + (3 + 0 * 16 + s) * modules][i] = 16384;
|
|
buffer_device[1 + m + (3 + 1 * 16 + s) * modules][i] = 16384;
|
|
buffer_device[1 + m + (3 + 2 * 16 + s) * modules][i] = 16384;
|
|
} else {
|
|
buffer_device[1 + m + (3 + 0 * 16 + s) * modules][i] = pedestal_g0[i];
|
|
buffer_device[1 + m + (3 + 1 * 16 + s) * modules][i] = pedestal_g1[i];
|
|
buffer_device[1 + m + (3 + 2 * 16 + s) * modules][i] = pedestal_g2[i];
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
} |