mirror of
https://github.com/paulscherrerinstitute/sf_daq_buffer.git
synced 2026-05-06 09:54:14 +02:00
eiger image assemble routine.
This commit is contained in:
@@ -26,7 +26,7 @@ public:
|
||||
size_t meta_n_bytes,
|
||||
size_t data_n_bytes,
|
||||
int n_modules,
|
||||
int n_slots=buffer_config::RAM_BUFFER_N_SLOTS);
|
||||
int n_slots);
|
||||
|
||||
~RamBuffer();
|
||||
|
||||
@@ -43,7 +43,6 @@ public:
|
||||
const uint64_t image_id, const uint64_t module_id) const;
|
||||
char* get_slot_meta(const uint64_t image_id) const;
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define EIGER_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <stdint.h>
|
||||
|
||||
#define N_MODULES 1
|
||||
#define BYTES_PER_PACKET 4144
|
||||
@@ -27,6 +28,9 @@
|
||||
|
||||
|
||||
#define N_BYTES_PER_MODULE_LINE(bit_depth) ((MODULE_X_SIZE * bit_depth) / 8)
|
||||
#define N_BYTES_PER_MODULE_FRAME(bit_depth) ((131072 * bit_depth) / 8)
|
||||
|
||||
|
||||
// #define N_BYTES_PER_IMAGE_LINE(bit_depth, n_submodules) ((n_submodules / 2 * MODULE_X_SIZE * bit_depth) / 8)
|
||||
|
||||
// DR 16
|
||||
|
||||
@@ -17,7 +17,7 @@ using namespace buffer_config;
|
||||
RamBuffer::RamBuffer(const string& buffer_name,
|
||||
const size_t meta_n_bytes,
|
||||
const size_t data_n_bytes,
|
||||
const int n_modules = 1,
|
||||
const int n_modules,
|
||||
const int n_slots) :
|
||||
buffer_name_(buffer_name),
|
||||
n_modules_(n_modules),
|
||||
@@ -66,8 +66,8 @@ RamBuffer::~RamBuffer()
|
||||
char* RamBuffer::_get_meta_buffer(
|
||||
int slot_n,
|
||||
uint64_t module_id) const
|
||||
{
|
||||
return buffer_ + (slot_n * slot_bytes_) +
|
||||
{
|
||||
return buffer_ + (slot_n * slot_bytes_) +
|
||||
(module_id * meta_bytes_);
|
||||
}
|
||||
|
||||
@@ -96,6 +96,7 @@ void RamBuffer::write_frame(
|
||||
cout << " || src_meta.n_recv_packets " << src_meta.n_recv_packets;
|
||||
cout << " || src_meta.daq_rec " << src_meta.daq_rec;
|
||||
cout << " || src_meta.module_id " << src_meta.module_id;
|
||||
cout << " || dst_meta " << &dst_meta;
|
||||
cout << endl;
|
||||
#endif
|
||||
|
||||
@@ -127,4 +128,4 @@ char* RamBuffer::get_frame_data(
|
||||
char* RamBuffer::get_slot_data(const uint64_t image_id) const
|
||||
{
|
||||
return get_frame_data(image_id, 0);
|
||||
}
|
||||
}
|
||||
@@ -2,25 +2,50 @@
|
||||
#ifndef SF_DAQ_BUFFER_EIGERASSEMBLER_HPP
|
||||
#define SF_DAQ_BUFFER_EIGERASSEMBLER_HPP
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <cstddef>
|
||||
|
||||
class EigerAssembler {
|
||||
const int n_modules_;
|
||||
const int bit_depth_;
|
||||
const int n_eiger_modules_;
|
||||
|
||||
const uint32_t n_bytes_per_frame_;
|
||||
const uint32_t n_bytes_per_module_line_;
|
||||
const uint32_t n_packets_per_frame_;
|
||||
const uint32_t n_bytes_per_gap_;
|
||||
const uint32_t n_bytes_per_x_gap_;
|
||||
const uint32_t n_bytes_per_y_gap_;
|
||||
const uint32_t n_bytes_per_eiger_x_gap_;
|
||||
const uint32_t n_bytes_per_eiger_y_gap_;
|
||||
const uint32_t n_bytes_per_image_line_;
|
||||
const int n_lines_per_frame_;
|
||||
const int image_bytes_;
|
||||
|
||||
public:
|
||||
EigerAssembler(const int n_modules, const int bit_depth);
|
||||
void assemble_image(const char* src_meta, const char* src_data,
|
||||
char* dst_meta, char* dst_data) const;
|
||||
size_t get_image_n_bytes();
|
||||
size_t get_image_n_bytes() const;
|
||||
size_t get_module_n_bytes() const;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const EigerAssembler& p)
|
||||
{
|
||||
return os << "( n_bytes_per_frame_"
|
||||
<< p.n_bytes_per_frame_ << ", n_bytes_per_module_line_"
|
||||
<< p.n_bytes_per_module_line_ << ", n_packets_per_frame_"
|
||||
<< p.n_packets_per_frame_ << ", n_bytes_per_x_gap_"
|
||||
<< p.n_bytes_per_x_gap_ << ", n_bytes_per_y_gap_"
|
||||
<< p.n_bytes_per_y_gap_ << ", n_bytes_per_eiger_x_gap_"
|
||||
<< p.n_bytes_per_eiger_x_gap_ << ", n_bytes_per_eiger_y_gap_"
|
||||
<< p.n_bytes_per_eiger_y_gap_ << ", n_bytes_per_image_line_"
|
||||
<< p.n_bytes_per_image_line_ << ", n_lines_per_frame_"
|
||||
<< p.n_lines_per_frame_ << ", image_bytes_"
|
||||
<< p.image_bytes_ << ", n_modules_"
|
||||
<< p.n_modules_ << ", bit_depth_"
|
||||
<< p.bit_depth_ << ""
|
||||
<< ")";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,73 +1,71 @@
|
||||
#include <cstdint>
|
||||
#include "EigerAssembler.hpp"
|
||||
#include "eiger.hpp"
|
||||
#include "date.h"
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <formats.hpp>
|
||||
#include <cstring>
|
||||
|
||||
#include "EigerAssembler.hpp"
|
||||
#include "eiger.hpp"
|
||||
#include "date.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace buffer_config;
|
||||
|
||||
EigerAssembler::EigerAssembler(const int n_modules, const int bit_depth):
|
||||
n_modules_(n_modules),
|
||||
n_modules_(n_modules),
|
||||
n_eiger_modules_(n_modules/4),
|
||||
bit_depth_(bit_depth),
|
||||
n_bytes_per_frame_(MODULE_N_PIXELS * bit_depth / 8),
|
||||
n_bytes_per_module_line_(N_BYTES_PER_MODULE_LINE(bit_depth)),
|
||||
// TODO: Is this correct?
|
||||
n_packets_per_frame_(n_bytes_per_frame_ / DATA_BYTES_PER_PACKET),
|
||||
n_bytes_per_gap_(GAP_X_MODULE_PIXELS * bit_depth / 8),
|
||||
n_bytes_per_image_line_(n_bytes_per_module_line_ * 2 + n_bytes_per_gap_),
|
||||
n_bytes_per_x_gap_(GAP_X_MODULE_PIXELS * bit_depth / 8),
|
||||
n_bytes_per_y_gap_(GAP_Y_MODULE_PIXELS * bit_depth / 8),
|
||||
n_bytes_per_eiger_x_gap_(GAP_X_EIGERMOD_PIXELS * bit_depth / 8),
|
||||
n_bytes_per_eiger_y_gap_(GAP_Y_EIGERMOD_PIXELS * bit_depth / 8),
|
||||
n_bytes_per_image_line_(n_bytes_per_module_line_ * 2 + n_bytes_per_x_gap_),
|
||||
n_lines_per_frame_(DATA_BYTES_PER_PACKET / n_bytes_per_module_line_
|
||||
* n_packets_per_frame_)
|
||||
* n_packets_per_frame_),
|
||||
image_bytes_((n_modules_ * MODULE_N_PIXELS * bit_depth_ / 8) + ((n_eiger_modules_) * (MODULE_Y_SIZE * 2) * bit_depth_ / 8) + ((n_eiger_modules_) * (2 * n_bytes_per_image_line_)))
|
||||
{
|
||||
#ifdef DEBUG_OUTPUT
|
||||
using namespace date;
|
||||
cout << " [" << std::chrono::system_clock::now();
|
||||
cout << "] [EigerAssembler::EigerAssembler] " << endl;
|
||||
cout << " || bit_depth " << bit_depth_ << endl;
|
||||
cout << endl;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
size_t EigerAssembler::get_image_n_bytes()
|
||||
size_t EigerAssembler::get_module_n_bytes() const
|
||||
{
|
||||
// TODO: Calculate the real size.
|
||||
return 0;
|
||||
return n_bytes_per_frame_;
|
||||
}
|
||||
|
||||
void EigerAssembler::assemble_image(
|
||||
const char* src_meta,
|
||||
size_t EigerAssembler::get_image_n_bytes() const
|
||||
{
|
||||
return image_bytes_;
|
||||
}
|
||||
|
||||
void EigerAssembler::assemble_image(const char* src_meta,
|
||||
const char* src_data,
|
||||
char* dst_meta,
|
||||
char* dst_data) const
|
||||
{
|
||||
|
||||
for (int i_module = 0; i_module < n_modules_; i_module++) {
|
||||
// defines from which eiger module this submodule is part
|
||||
// TODO: Deviding with n_modules_ .. is this correct?
|
||||
const int eiger_module_index = i_module / n_modules_;
|
||||
// module frame metadata
|
||||
// TODO: Using i_module.. is this correct?
|
||||
auto *frame_meta =
|
||||
(ModuleFrame *) src_meta + (sizeof(ModuleFrame) * i_module);
|
||||
auto frame_meta = (ModuleFrame *)(src_meta + (sizeof(ModuleFrame)* i_module));
|
||||
// module frame data
|
||||
// TODO: Using i_module.. is this correct?
|
||||
auto *frame_data = src_data + (n_bytes_per_frame_ * i_module);
|
||||
|
||||
// top
|
||||
uint32_t source_offset = 0;
|
||||
uint32_t reverse_factor = 0;
|
||||
uint32_t bottom_offset = 0;
|
||||
uint32_t line_number = 0;
|
||||
uint32_t dest_line_offset = 0;
|
||||
uint32_t dest_offset = 0;
|
||||
|
||||
// If bottom -> reversed
|
||||
const auto reverse = IS_BOTTOM(frame_meta->row);
|
||||
if (reverse == -1) {
|
||||
line_number = MODULE_Y_SIZE + GAP_Y_MODULE_PIXELS;
|
||||
reverse_factor = MODULE_Y_SIZE - 1;
|
||||
dest_line_offset += n_bytes_per_image_line_ *
|
||||
dest_offset += n_bytes_per_image_line_ *
|
||||
(MODULE_Y_SIZE + GAP_Y_MODULE_PIXELS);
|
||||
source_offset = (MODULE_Y_SIZE-1) * n_bytes_per_module_line_;
|
||||
}
|
||||
|
||||
const auto i_module_row = frame_meta->row;
|
||||
@@ -76,30 +74,51 @@ void EigerAssembler::assemble_image(
|
||||
uint32_t dest_module_line = line_number;
|
||||
|
||||
if (i_module_column == 1) {
|
||||
source_offset += MODULE_X_SIZE + GAP_X_MODULE_PIXELS;
|
||||
dest_line_offset += n_bytes_per_module_line_ + n_bytes_per_gap_;
|
||||
dest_offset += n_bytes_per_module_line_ + n_bytes_per_x_gap_;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_OUTPUT
|
||||
using namespace date;
|
||||
// if (i_module == 1){
|
||||
cout << " [" << std::chrono::system_clock::now();
|
||||
cout << "] [MODULE " << i_module;
|
||||
cout << "] (row " << i_module_row;
|
||||
cout << " , column)" << i_module_column;
|
||||
cout << " || reverse_factor" << reverse_factor;
|
||||
cout << " || line_number" << line_number;
|
||||
cout << endl;
|
||||
// }
|
||||
#endif
|
||||
int counter = 0;
|
||||
for (uint32_t frame_line = 0;
|
||||
frame_line < n_lines_per_frame_; frame_line++) {
|
||||
// Copy each chip line individually, to allow a gap of n_bytes_per_chip_gap in the destination memory.
|
||||
// memcpy (
|
||||
// (char*)(dst_data + (image_bytes_ * slot_n)) + dest_line_offset,
|
||||
// // TODO: Using source_offset which has also GAP_X_MODULE in frames buffer -> is this correct?
|
||||
// (char*) frame_data + source_offset,
|
||||
// n_bytes_per_module_line_
|
||||
// );
|
||||
//
|
||||
// memcpy (
|
||||
// (char*)(dst_data + (image_bytes_ * slot_n)) + dest_line_offset + n_bytes_per_module_line,
|
||||
// // TODO: Using source_offset which has also GAP_X_MODULE in frames buffer -> is this correct?
|
||||
// (char*) frame_data + source_offset + n_bytes_per_module_line_,
|
||||
// n_bytes_per_module_line_
|
||||
// );
|
||||
|
||||
source_offset += n_bytes_per_module_line_;
|
||||
dest_line_offset += reverse * n_bytes_per_image_line_;
|
||||
}
|
||||
// void * destination, const void * source, size_t num
|
||||
memcpy (
|
||||
(char*)(dst_data + dest_offset),
|
||||
(char*) (src_data + source_offset),
|
||||
n_bytes_per_module_line_
|
||||
);
|
||||
|
||||
#ifdef DEBUG_OUTPUT
|
||||
using namespace date;
|
||||
// verifies the addresses for
|
||||
// beginning and end of each frame
|
||||
if (counter < 5 || counter > 508){
|
||||
cout << " [" << std::chrono::system_clock::now();
|
||||
cout << "] [MODULE :" << i_module;
|
||||
cout << "] ROW :" << i_module_row;
|
||||
cout << "] COLUMN :" << i_module_column;
|
||||
cout << " || source_offset" << source_offset;
|
||||
cout << " || dest_offset " << dest_offset;
|
||||
cout << " || frame_line " << frame_line;
|
||||
cout << " || COUNTER " << counter;
|
||||
cout << endl;
|
||||
}
|
||||
#endif
|
||||
counter += 1;
|
||||
source_offset += reverse * n_bytes_per_module_line_;
|
||||
dest_offset += reverse * n_bytes_per_image_line_;
|
||||
}
|
||||
line_number += n_lines_per_frame_;
|
||||
dest_module_line = line_number + n_lines_per_frame_ - 1;
|
||||
}
|
||||
|
||||
@@ -47,15 +47,16 @@ PulseAndSync ZmqPulseSyncReceiver::get_next_pulse_id() const
|
||||
for (int i = 0; i < n_modules_; i++) {
|
||||
zmq_recv(sockets_[i], &pulses[i], sizeof(uint64_t), 0);
|
||||
if (pulses[0] != pulses[i]) {
|
||||
|
||||
modules_in_sync = false;
|
||||
}
|
||||
}
|
||||
|
||||
// cout << " modules_in_sync " << modules_in_sync << endl;
|
||||
if (modules_in_sync) {
|
||||
#ifdef DEBUG_OUTPUT
|
||||
using namespace date;
|
||||
cout << " [" << std::chrono::system_clock::now();
|
||||
cout << "] [ZmqPulseSyncReceiver::get_next_pulse_id] ";
|
||||
cout << "] [ZmqPulseSyncReceiver::get_next_pulse_id ";
|
||||
cout << "] (modules_in_sync) Frame index:" << pulses[0];
|
||||
cout << endl;
|
||||
#endif
|
||||
@@ -109,12 +110,6 @@ PulseAndSync ZmqPulseSyncReceiver::get_next_pulse_id() const
|
||||
n_lost_pulses += i_sync_lost_pulses;
|
||||
|
||||
if (modules_in_sync) {
|
||||
#ifdef DEBUG_OUTPUT
|
||||
using namespace date;
|
||||
cout << " [" << std::chrono::system_clock::now();
|
||||
cout << "] [ZmqPulseSyncReceiver::get_next_pulse_id] modules_in_sync false";
|
||||
cout << endl;
|
||||
#endif
|
||||
return {pulses[0], n_lost_pulses};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
#include <BufferUtils.hpp>
|
||||
#include <AssemblerStats.hpp>
|
||||
|
||||
#include "date.h"
|
||||
#include <chrono>
|
||||
#include <EigerAssembler.hpp>
|
||||
|
||||
#include "date.h"
|
||||
#include "EigerAssembler.hpp"
|
||||
#include "assembler_config.hpp"
|
||||
#include "ZmqPulseSyncReceiver.hpp"
|
||||
|
||||
@@ -53,27 +54,38 @@ int main (int argc, char *argv[])
|
||||
cout << endl;
|
||||
#endif
|
||||
|
||||
// TODO: Is n_submodules here correct?
|
||||
EigerAssembler assembler(config.n_submodules, bit_depth);
|
||||
EigerAssembler assembler(n_receivers, bit_depth);
|
||||
|
||||
#ifdef DEBUG_OUTPUT
|
||||
using namespace date;
|
||||
cout << " [" << std::chrono::system_clock::now();
|
||||
cout << "] [EigerAssembler] :";
|
||||
cout << " Eiger details:";
|
||||
cout << assembler;
|
||||
cout << endl;
|
||||
#endif
|
||||
|
||||
RamBuffer frame_buffer(config.detector_name,
|
||||
sizeof(ModuleFrame), MODULE_N_BYTES, config.n_modules);
|
||||
sizeof(ModuleFrame), N_BYTES_PER_MODULE_FRAME(bit_depth), n_receivers,
|
||||
buffer_config::RAM_BUFFER_N_SLOTS);
|
||||
|
||||
|
||||
RamBuffer image_buffer(config.detector_name + "_" + stream_name,
|
||||
sizeof(ImageMetadata), assembler.get_image_n_bytes(), 1);
|
||||
sizeof(ImageMetadata), assembler.get_image_n_bytes(), 1,
|
||||
buffer_config::RAM_BUFFER_N_SLOTS);
|
||||
|
||||
ZmqPulseSyncReceiver receiver(ctx, config.detector_name, n_receivers);
|
||||
AssemblerStats stats(config.detector_name, ASSEMBLER_STATS_MODULO);
|
||||
|
||||
while (true) {
|
||||
auto pulse_and_sync = receiver.get_next_pulse_id();
|
||||
|
||||
// metadata
|
||||
auto* src_meta = frame_buffer.get_slot_meta(pulse_and_sync.pulse_id);
|
||||
auto* src_data = frame_buffer.get_slot_data(pulse_and_sync.pulse_id);
|
||||
|
||||
// data
|
||||
auto* dst_meta = image_buffer.get_slot_meta(pulse_and_sync.pulse_id);
|
||||
auto* dst_data = image_buffer.get_slot_data(pulse_and_sync.pulse_id);
|
||||
|
||||
// assemble
|
||||
assembler.assemble_image(src_meta, src_data, dst_meta, dst_data);
|
||||
|
||||
zmq_send(sender, dst_meta, sizeof(ImageMetadata), 0);
|
||||
|
||||
@@ -84,9 +84,10 @@ inline void FrameUdpReceiver::copy_packet_to_buffers(
|
||||
(void*) (frame_buffer + frame_buffer_offset),
|
||||
packet_buffer_[i_packet].data,
|
||||
DATA_BYTES_PER_PACKET);
|
||||
|
||||
if (i_packet == 0){
|
||||
// cout << " BUFFER LOCATION " << (frame_buffer + frame_buffer_offset) << endl;
|
||||
}
|
||||
metadata.n_recv_packets++;
|
||||
// cout << "[ frame" << metadata.frame_index << "] NUMBER OF RECV PACKETS : " << metadata.n_recv_packets ;
|
||||
}
|
||||
|
||||
inline uint64_t FrameUdpReceiver::process_packets(
|
||||
@@ -122,9 +123,11 @@ inline uint64_t FrameUdpReceiver::process_packets(
|
||||
using namespace date;
|
||||
cout << " [" << std::chrono::system_clock::now();
|
||||
cout << "] [FrameUdpReceiver::process_packets] :";
|
||||
cout << " Frame " << metadata.frame_index << " || ";
|
||||
cout << packet_buffer_[i_packet].packetnum << " packets received.";
|
||||
cout << " PULSE ID "<< metadata.pulse_id;
|
||||
cout << " Frame " << metadata.frame_index;
|
||||
cout << " || N_RECV_PACKETS " << metadata.n_recv_packets;
|
||||
cout << " || PULSE ID "<< metadata.pulse_id;
|
||||
cout << " metadata.row " << metadata.row;
|
||||
cout << " metadata.column " << metadata.column;
|
||||
cout << endl;
|
||||
#endif
|
||||
// Buffer is loaded only if this is not the last message.
|
||||
|
||||
@@ -40,15 +40,15 @@ int main (int argc, char *argv[]) {
|
||||
const auto udp_port = config.start_udp_port + module_id;
|
||||
|
||||
FrameUdpReceiver receiver(module_id, udp_port, n_receivers, config.n_submodules, bit_depth);
|
||||
RamBuffer buffer(config.detector_name, n_receivers, config.n_submodules, bit_depth);
|
||||
RamBuffer buffer(config.detector_name, sizeof(ModuleFrame), N_BYTES_PER_MODULE_FRAME(bit_depth), n_receivers,
|
||||
buffer_config::RAM_BUFFER_N_SLOTS);
|
||||
FrameStats stats(config.detector_name, n_receivers, module_id, bit_depth, STATS_TIME);
|
||||
|
||||
auto ctx = zmq_ctx_new();
|
||||
auto socket = bind_socket(ctx, config.detector_name, to_string(module_id));
|
||||
|
||||
ModuleFrame meta;
|
||||
// TODO: This will not work. Only if Eiger sends in 16 bit. Use MODULE_N_PIXELS * bit_depth / 8
|
||||
char* data = new char[MODULE_N_BYTES];
|
||||
char* data = new char[MODULE_N_PIXELS * bit_depth / 8];
|
||||
|
||||
uint64_t pulse_id_previous = 0;
|
||||
uint64_t frame_index_previous = 0;
|
||||
|
||||
Reference in New Issue
Block a user