Dhanya Thattil 9ac8dab8af
Rxclassmembers (#503)
* gui message doesnt show if it has a '>' symbol in error msg

* minor refactoring for readability (size_t calc fifo size)

* refactoring listening udp socket code: activated and datastream dont create udp sockets anyway, rc<=- should be discarded in any case

* wip

* refactoring memory structure access

* wip: bugfix write header + data to binary

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* portRoi no roi effecto on progress

* fail at receiver progress, wip

* segfaults for char pointer in struct

* reference to header to get header and data

* refactoring

* use const defined for size of header of fifo

* updated release notes

* remove pointer in callback for sls_receiver_header pointer

* rx same name arguments in constructors

* rx: same name arguments in constructor

* rx: removing the '_' suffix in class data members

* merge fix

* merge fix

* review fix refactoring
2022-07-25 14:02:11 +02:00

633 lines
20 KiB
C++

// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
#pragma once
/************************************************
* @file GeneralData.h
* @short abstract for setting/getting properties of detector data
***********************************************/
/**
*@short abstract for setting/getting properties of detector data
*/
#include "receiver_defs.h"
#include "sls/ToString.h"
#include "sls/logger.h"
#include "sls/sls_detector_defs.h"
#include <cmath> //ceil
#include <vector>
namespace sls {
class GeneralData {
public:
slsDetectorDefs::detectorType detType{slsDetectorDefs::GENERIC};
uint32_t nPixelsX{0};
uint32_t nPixelsY{0};
uint32_t headerSizeinPacket{0};
/** Size of just data in 1 packet (in bytes) */
uint32_t dataSize{0};
uint32_t packetSize{0};
/** Number of packets in an image (for each listening UDP port) */
uint32_t packetsPerFrame{0};
/** Image size (in bytes, for each listening UDP port) */
uint32_t imageSize{0};
uint64_t frameIndexMask{0};
uint32_t frameIndexOffset{0};
uint32_t packetIndexMask{0};
uint32_t packetIndexOffset{0};
uint32_t maxFramesPerFile{0};
uint32_t defaultFifoDepth{0};
uint32_t numUDPInterfaces{1};
uint32_t headerPacketSize{0};
/** Streaming (for ROI - mainly short Gotthard) */
uint32_t nPixelsXComplete{0};
/** Streaming (for ROI - mainly short Gotthard) */
uint32_t nPixelsYComplete{0};
/** Streaming (for ROI - mainly short Gotthard) - Image size (in bytes) */
uint32_t imageSizeComplete{0};
/** if standard header implemented in firmware */
bool standardheader{false};
uint32_t defaultUdpSocketBufferSize{RECEIVE_SOCKET_BUFFER_SIZE};
uint32_t vetoDataSize{0};
uint32_t vetoPacketSize{0};
uint32_t vetoImageSize{0};
uint32_t vetoHsize{0};
uint32_t maxRowsPerReadout{0};
uint32_t dynamicRange{16};
bool tengigaEnable{false};
uint32_t nAnalogSamples{0};
uint32_t nDigitalSamples{0};
slsDetectorDefs::readoutMode readoutType{slsDetectorDefs::ANALOG_ONLY};
uint32_t adcEnableMaskOneGiga{BIT32_MASK};
uint32_t adcEnableMaskTenGiga{BIT32_MASK};
slsDetectorDefs::ROI roi{};
uint32_t counterMask{0};
GeneralData(){};
virtual ~GeneralData(){};
// Returns the pixel depth in byte, 4 bits being 0.5 byte
float GetPixelDepth() { return float(dynamicRange) / 8; }
void ThrowGenericError(std::string msg) const {
throw RuntimeError(
msg + std::string("This is a generic function that should be "
"overloaded by a derived class"));
}
/**
* Get Header Infomation (frame number, packet number)
* @param index thread index for debugging purposes
* @param packetData pointer to data
* @param oddStartingPacket odd starting packet (gotthard)
* @param frameNumber frame number
* @param packetNumber packet number
* @param bunchId bunch Id
*/
virtual void GetHeaderInfo(int index, char *packetData,
bool oddStartingPacket, uint64_t &frameNumber,
uint32_t &packetNumber,
uint64_t &bunchId) const {
frameNumber = ((uint32_t)(*((uint32_t *)(packetData))));
frameNumber++;
packetNumber = frameNumber & packetIndexMask;
frameNumber = (frameNumber & frameIndexMask) >> frameIndexOffset;
bunchId = -1;
}
virtual void SetDetectorROI(slsDetectorDefs::ROI i) {
ThrowGenericError("SetDetectorROI");
};
/**@returns adc configured */
virtual int GetAdcConfigured(int index, slsDetectorDefs::ROI i) const {
ThrowGenericError("GetAdcConfigured");
return 0;
};
virtual void SetDynamicRange(int dr) {
ThrowGenericError("SetDynamicRange");
};
virtual void SetTenGigaEnable(bool tgEnable) {
ThrowGenericError("SetTenGigaEnable");
};
virtual bool SetOddStartingPacket(int index, char *packetData) {
ThrowGenericError("SetOddStartingPacket");
return false;
};
virtual void SetNumberofInterfaces(const int n) {
ThrowGenericError("SetNumberofInterfaces");
};
virtual void SetCounterMask(const int n) {
ThrowGenericError("setCounterMask");
};
virtual int GetNumberOfAnalogDatabytes() {
ThrowGenericError("GetNumberOfAnalogDatabytes");
return 0;
};
virtual void SetNumberOfAnalogSamples(int n) {
ThrowGenericError("SetNumberOfAnalogSamples");
};
virtual void SetNumberOfDigitalSamples(int n) {
ThrowGenericError("SetNumberOfDigitalSamples");
};
virtual void SetOneGigaAdcEnableMask(int n) {
ThrowGenericError("SetOneGigaAdcEnableMask");
};
virtual void SetTenGigaAdcEnableMask(int n) {
ThrowGenericError("SetTenGigaAdcEnableMask");
};
virtual void SetReadoutMode(slsDetectorDefs::readoutMode r) {
ThrowGenericError("SetReadoutMode");
};
};
class GotthardData : public GeneralData {
private:
const int nChan = 128;
const int nChipsPerAdc = 2;
public:
GotthardData() {
detType = slsDetectorDefs::GOTTHARD;
nPixelsY = 1;
headerSizeinPacket = 6;
maxFramesPerFile = MAX_FRAMES_PER_FILE;
UpdateImageSize();
};
/**
* Get Header Infomation (frame number, packet number)
* @param index thread index for debugging purposes
* @param packetData pointer to data
* @param oddStartingPacket odd starting packet (gotthard)
* @param frameNumber frame number
* @param packetNumber packet number
* @param bunchId bunch Id
*/
void GetHeaderInfo(int index, char *packetData, bool oddStartingPacket,
uint64_t &frameNumber, uint32_t &packetNumber,
uint64_t &bunchId) const {
if (nPixelsX == 1280) {
frameNumber = *reinterpret_cast<uint32_t *>(packetData);
if (oddStartingPacket)
frameNumber++;
packetNumber = frameNumber & packetIndexMask;
frameNumber = (frameNumber & frameIndexMask) >> frameIndexOffset;
} else {
frameNumber = *reinterpret_cast<uint32_t *>(packetData);
packetNumber = 0;
}
bunchId = -1;
}
/** @returns adc configured */
int GetAdcConfigured(int index, slsDetectorDefs::ROI i) const {
int adc = -1;
// single adc
if (i.xmin != -1) {
// gotthard can have only one adc per detector enabled (or all)
// adc = mid value/numchans also for only 1 roi
adc = ((((i.xmax) + (i.xmin)) / 2) / (nChan * nChipsPerAdc));
if ((adc < 0) || (adc > 4)) {
LOG(logWARNING) << index
<< ": Deleting ROI. "
"Adc value should be between 0 and 4";
adc = -1;
}
}
LOG(logINFO) << "Adc Configured: " << adc;
return adc;
};
/**
* Set odd starting packet (gotthard)
* @param index thread index for debugging purposes
* @param packetData pointer to data
* @returns true or false for odd starting packet number
*/
bool SetOddStartingPacket(int index, char *packetData) {
bool oddStartingPacket = true;
// care only if no roi
if (nPixelsX == 1280) {
uint32_t fnum = ((uint32_t)(*((uint32_t *)(packetData))));
uint32_t firstData = ((uint32_t)(*((uint32_t *)(packetData + 4))));
// first packet
if (firstData == 0xCACACACA) {
// packet number should be 0, but is 1 => so odd starting packet
if (fnum & packetIndexMask) {
oddStartingPacket = true;
} else {
oddStartingPacket = false;
}
}
// second packet
else {
// packet number should be 1, but is 0 => so odd starting packet
if (!(fnum & packetIndexMask)) {
oddStartingPacket = true;
} else {
oddStartingPacket = false;
}
}
}
return oddStartingPacket;
};
void SetDetectorROI(slsDetectorDefs::ROI i) {
roi = i;
UpdateImageSize();
};
private:
void UpdateImageSize() {
// all adcs
if (roi.xmin == -1) {
nPixelsX = 1280;
dataSize = 1280;
packetsPerFrame = 2;
frameIndexMask = 0xFFFFFFFE;
frameIndexOffset = 1;
packetIndexMask = 1;
maxFramesPerFile = MAX_FRAMES_PER_FILE;
nPixelsXComplete = 0;
nPixelsYComplete = 0;
imageSizeComplete = 0;
defaultFifoDepth = 50000;
} else {
nPixelsX = 256;
dataSize = 512;
packetsPerFrame = 1;
frameIndexMask = 0xFFFFFFFF;
frameIndexOffset = 0;
packetIndexMask = 0;
maxFramesPerFile = SHORT_MAX_FRAMES_PER_FILE;
nPixelsXComplete = 1280;
nPixelsYComplete = 1;
imageSizeComplete = 1280 * 2;
defaultFifoDepth = 75000;
}
imageSize = int(nPixelsX * nPixelsY * GetPixelDepth());
packetSize = headerSizeinPacket + dataSize;
packetsPerFrame = imageSize / dataSize;
};
};
class EigerData : public GeneralData {
public:
EigerData() {
detType = slsDetectorDefs::EIGER;
headerSizeinPacket = sizeof(slsDetectorDefs::sls_detector_header);
maxFramesPerFile = EIGER_MAX_FRAMES_PER_FILE;
numUDPInterfaces = 2;
headerPacketSize = 40;
standardheader = true;
maxRowsPerReadout = 256;
UpdateImageSize();
};
void SetDynamicRange(int dr) {
dynamicRange = dr;
UpdateImageSize();
}
void SetTenGigaEnable(bool tgEnable) {
tengigaEnable = tgEnable;
UpdateImageSize();
};
private:
void UpdateImageSize() {
nPixelsX = (256 * 4) / numUDPInterfaces;
nPixelsY = 256;
dataSize = (tengigaEnable ? 4096 : 1024);
packetSize = headerSizeinPacket + dataSize;
imageSize = int(nPixelsX * nPixelsY * GetPixelDepth());
packetsPerFrame = imageSize / dataSize;
defaultFifoDepth = (dynamicRange == 32 ? 100 : 1000);
};
};
class JungfrauData : public GeneralData {
public:
JungfrauData() {
detType = slsDetectorDefs::JUNGFRAU;
headerSizeinPacket = sizeof(slsDetectorDefs::sls_detector_header);
dataSize = 8192;
packetSize = headerSizeinPacket + dataSize;
maxFramesPerFile = JFRAU_MAX_FRAMES_PER_FILE;
defaultFifoDepth = 2500;
standardheader = true;
maxRowsPerReadout = 512;
UpdateImageSize();
};
void SetNumberofInterfaces(const int n) {
numUDPInterfaces = n;
UpdateImageSize();
};
private:
void UpdateImageSize() {
nPixelsX = (256 * 4);
nPixelsY = (256 * 2) / numUDPInterfaces;
imageSize = int(nPixelsX * nPixelsY * GetPixelDepth());
packetsPerFrame = imageSize / dataSize;
defaultUdpSocketBufferSize = (1000 * 1024 * 1024) / numUDPInterfaces;
};
};
class Mythen3Data : public GeneralData {
private:
int ncounters{0};
const int NCHAN = 1280;
public:
Mythen3Data() {
detType = slsDetectorDefs::MYTHEN3;
nPixelsY = 1;
headerSizeinPacket = sizeof(slsDetectorDefs::sls_detector_header);
maxFramesPerFile = MYTHEN3_MAX_FRAMES_PER_FILE;
defaultFifoDepth = 50000;
standardheader = true;
defaultUdpSocketBufferSize = (1000 * 1024 * 1024);
dynamicRange = 32;
tengigaEnable = true;
SetCounterMask(0x7);
UpdateImageSize();
};
void SetDynamicRange(int dr) {
dynamicRange = dr;
UpdateImageSize();
};
void SetTenGigaEnable(bool tg) {
tengigaEnable = tg;
UpdateImageSize();
};
virtual void SetCounterMask(const int mask) {
int n = __builtin_popcount(mask);
if (n < 1 || n > 3) {
throw RuntimeError("Invalid number of counters " +
std::to_string(n) + ". Expected 1-3.");
}
counterMask = mask;
ncounters = n;
UpdateImageSize();
};
private:
void UpdateImageSize() {
nPixelsX = (NCHAN * ncounters); // max 1280 channels x 3 counters
LOG(logINFO) << "nPixelsX: " << nPixelsX;
imageSize = nPixelsX * nPixelsY * GetPixelDepth();
// 10g
if (tengigaEnable) {
if (dynamicRange == 32 && ncounters > 1) {
packetsPerFrame = 2;
} else {
packetsPerFrame = 1;
}
dataSize = imageSize / packetsPerFrame;
}
// 1g
else {
if (ncounters == 3) {
dataSize = 768;
} else {
dataSize = 1280;
}
packetsPerFrame = imageSize / dataSize;
}
LOG(logINFO) << "Packets Per Frame: " << packetsPerFrame;
packetSize = headerSizeinPacket + dataSize;
LOG(logINFO) << "PacketSize: " << packetSize;
};
};
class Gotthard2Data : public GeneralData {
public:
Gotthard2Data() {
detType = slsDetectorDefs::GOTTHARD2;
nPixelsX = 128 * 10;
nPixelsY = 1;
headerSizeinPacket = sizeof(slsDetectorDefs::sls_detector_header);
dataSize = 2560; // 1280 channels * 2 bytes
maxFramesPerFile = GOTTHARD2_MAX_FRAMES_PER_FILE;
defaultFifoDepth = 50000;
standardheader = true;
vetoDataSize = 160;
vetoHsize = 16;
UpdateImageSize();
};
void SetNumberofInterfaces(const int n) {
numUDPInterfaces = n;
UpdateImageSize();
};
/**
* Get Header Infomation (frame number, packet number) for veto packets
* @param index thread index for debugging purposes
* @param packetData pointer to data
* @param oddStartingPacket odd starting packet (gotthard)
* @param frameNumber frame number
* @param packetNumber packet number
* @param bunchId bunch Id
*/
void GetHeaderInfo(int index, char *packetData, bool oddStartingPacket,
uint64_t &frameNumber, uint32_t &packetNumber,
uint64_t &bunchId) const {
frameNumber = *reinterpret_cast<uint64_t *>(packetData);
bunchId = *reinterpret_cast<uint64_t *>(packetData + 8);
packetNumber = 0;
};
private:
void UpdateImageSize() {
packetSize = headerSizeinPacket + dataSize;
imageSize = int(nPixelsX * nPixelsY * GetPixelDepth());
packetsPerFrame = imageSize / dataSize;
vetoPacketSize = vetoHsize + vetoDataSize;
vetoImageSize = vetoDataSize * packetsPerFrame;
defaultUdpSocketBufferSize = (1000 * 1024 * 1024) / numUDPInterfaces;
};
};
class ChipTestBoardData : public GeneralData {
private:
const int NCHAN_DIGITAL = 64;
const int NUM_BYTES_PER_ANALOG_CHANNEL = 2;
int nAnalogBytes = 0;
public:
/** Constructor */
ChipTestBoardData() {
detType = slsDetectorDefs::CHIPTESTBOARD;
nPixelsY = 1; // number of samples
headerSizeinPacket = sizeof(slsDetectorDefs::sls_detector_header);
frameIndexMask = 0xFFFFFF; // 10g
frameIndexOffset = 8; // 10g
packetIndexMask = 0xFF; // 10g
maxFramesPerFile = CTB_MAX_FRAMES_PER_FILE;
defaultFifoDepth = 2500;
standardheader = true;
UpdateImageSize();
};
public:
int GetNumberOfAnalogDatabytes() { return nAnalogBytes; };
void SetNumberOfAnalogSamples(int n) {
nAnalogSamples = n;
UpdateImageSize();
};
void SetNumberOfDigitalSamples(int n) {
nDigitalSamples = n;
UpdateImageSize();
};
void SetOneGigaAdcEnableMask(int n) {
adcEnableMaskOneGiga = n;
UpdateImageSize();
};
void SetTenGigaAdcEnableMask(int n) {
adcEnableMaskTenGiga = n;
UpdateImageSize();
};
void SetReadoutMode(slsDetectorDefs::readoutMode r) {
readoutType = r;
UpdateImageSize();
};
void SetTenGigaEnable(bool tg) {
tengigaEnable = tg;
UpdateImageSize();
};
private:
void UpdateImageSize() {
nAnalogBytes = 0;
int nDigitalBytes = 0;
int nAnalogChans = 0, nDigitalChans = 0;
// analog channels (normal, analog/digital readout)
if (readoutType == slsDetectorDefs::ANALOG_ONLY ||
readoutType == slsDetectorDefs::ANALOG_AND_DIGITAL) {
uint32_t adcEnableMask =
(tengigaEnable ? adcEnableMaskTenGiga : adcEnableMaskOneGiga);
nAnalogChans = __builtin_popcount(adcEnableMask);
nAnalogBytes =
nAnalogChans * NUM_BYTES_PER_ANALOG_CHANNEL * nAnalogSamples;
LOG(logDEBUG1) << " Number of Analog Channels:" << nAnalogChans
<< " Databytes: " << nAnalogBytes;
}
// digital channels
if (readoutType == slsDetectorDefs::DIGITAL_ONLY ||
readoutType == slsDetectorDefs::ANALOG_AND_DIGITAL) {
nDigitalChans = NCHAN_DIGITAL;
nDigitalBytes = (sizeof(uint64_t) * nDigitalSamples);
LOG(logDEBUG1) << "Number of Digital Channels:" << nDigitalChans
<< " Databytes: " << nDigitalBytes;
}
nPixelsX = nAnalogChans + nDigitalChans;
dataSize = tengigaEnable ? 8144 : UDP_PACKET_DATA_BYTES;
packetSize = headerSizeinPacket + dataSize;
imageSize = nAnalogBytes + nDigitalBytes;
packetsPerFrame = ceil((double)imageSize / (double)dataSize);
LOG(logDEBUG1) << "Total Number of Channels:" << nPixelsX
<< " Databytes: " << imageSize;
};
};
class MoenchData : public GeneralData {
private:
const int NUM_BYTES_PER_ANALOG_CHANNEL = 2;
public:
MoenchData() {
detType = slsDetectorDefs::MOENCH;
headerSizeinPacket = sizeof(slsDetectorDefs::sls_detector_header);
frameIndexMask = 0xFFFFFF;
maxFramesPerFile = MOENCH_MAX_FRAMES_PER_FILE;
defaultFifoDepth = 2500;
standardheader = true;
UpdateImageSize();
};
void SetNumberOfAnalogSamples(int n) {
nAnalogSamples = n;
UpdateImageSize();
};
void SetOneGigaAdcEnableMask(int n) {
adcEnableMaskOneGiga = n;
UpdateImageSize();
};
void SetTenGigaAdcEnableMask(int n) {
adcEnableMaskTenGiga = n;
UpdateImageSize();
};
void SetTenGigaEnable(bool tg) {
tengigaEnable = tg;
UpdateImageSize();
};
private:
void UpdateImageSize() {
uint32_t adcEnableMask =
(tengigaEnable ? adcEnableMaskTenGiga : adcEnableMaskOneGiga);
// count number of channels in x, each adc has 25 channels each
int nchanTop = __builtin_popcount(adcEnableMask & 0xF0F0F0F0) * 25;
int nchanBot = __builtin_popcount(adcEnableMask & 0x0F0F0F0F) * 25;
nPixelsX = nchanTop > 0 ? nchanTop : nchanBot;
// if both top and bottom adcs enabled, rows = 2
int nrows = 1;
if (nchanTop > 0 && nchanBot > 0) {
nrows = 2;
}
nPixelsY = nAnalogSamples / 25 * nrows;
LOG(logINFO) << "Number of Pixels: [" << nPixelsX << ", " << nPixelsY
<< "]";
dataSize = tengigaEnable ? 8144 : UDP_PACKET_DATA_BYTES;
packetSize = headerSizeinPacket + dataSize;
imageSize = nPixelsX * nPixelsY * NUM_BYTES_PER_ANALOG_CHANNEL;
packetsPerFrame = ceil((double)imageSize / (double)dataSize);
LOG(logDEBUG) << "Databytes: " << imageSize;
};
};
} // namespace sls