Compare commits

..

91 Commits

Author SHA1 Message Date
ab2e290658 Merge branch 'developer' into jf_h5reader
All checks were successful
Build on RHEL8 / build (push) Successful in 4m37s
Build on RHEL9 / build (push) Successful in 5m6s
2025-04-30 16:19:22 +02:00
01d3dc7115 Polish data structure 2025-04-30 11:01:24 +02:00
3e2d34bec7 Merge branch 'developer' into jf_h5reader
Some checks failed
CMake / Configure and build using cmake (push) Failing after 14s
2025-03-18 18:57:21 +01:00
5e8a354194 roll back debug comments 2025-03-18 18:56:01 +01:00
8c35fc16b9 Implement copy constructor in analogDetector
- avoid default shallow copy of pointer members triggered by copy of derived class
- as a result avoid double-free bugs
2025-03-18 18:15:43 +01:00
ac0394e176 extensive debugging 2025-03-18 17:20:12 +01:00
dd6354ff94 Merge branch 'developer' into jf_h5reader 2025-03-17 12:19:48 +01:00
18d781c35a Merge branch 'developer' into jf_h5reader 2025-03-14 12:03:21 +01:00
9c111fbeab deal with EuXFEL hdf5 (frames, 16)-size frame index datasets 2025-03-14 12:02:49 +01:00
222d9e4839 debug 2025-03-13 16:49:55 +01:00
9508dd1adc Debug 2025-03-13 16:14:12 +01:00
cf62f8cae8 Debug 2025-03-13 16:10:32 +01:00
08c10679e6 Debug 2025-03-13 16:06:50 +01:00
2b68b2158b Debug 2025-03-13 16:02:24 +01:00
721d296712 Merge branch 'developer' into jf_h5reader 2025-03-13 11:01:47 +01:00
62dd5c8d4e Enforce compiler support for c++17 standard 2025-03-13 11:01:20 +01:00
35c37998f3 tweak file name 2025-03-11 11:55:53 +01:00
9b13ddf6be Merge branch 'developer' into jf_h5reader 2025-03-10 16:46:42 +01:00
49db2fbee7 Fix tiff filename 2025-03-10 16:46:04 +01:00
670d4dbce4 Merge branch 'developer' into jf_h5reader 2025-03-10 12:24:33 +01:00
a0e5304df6 Modify tiff file name 2025-03-10 12:23:51 +01:00
2b8fbad47d reduce compiler warnings 2025-03-07 22:01:44 +01:00
a095a4ffce Fix double-free 2025-03-07 21:49:05 +01:00
d74da4cf04 Fix implicit conversion float->double compiler warning 2025-03-07 11:48:15 +01:00
9321d6d03a add SC to CMake 2025-03-06 20:32:45 +01:00
45a9a74137 Merge branch 'developer' into jf_h5reader 2025-03-06 17:14:17 +01:00
bede3003b6 Edit default rank 2025-03-06 17:06:45 +01:00
5fd319725e include <mutex> 2025-02-10 20:05:13 +01:00
fb77bc7f1d Rework for mutex safety and RAII compliance 2025-02-10 20:01:36 +01:00
8a5bd21ecc Add constructor printout (debug) 2025-02-10 19:08:13 +01:00
cb99aa40cb Adapt main() for storage cell case 2025-02-10 17:45:05 +01:00
41bb7ca1ed Adapt file pointer setting + pedestal reading 2025-02-10 16:50:09 +01:00
d85d4f94d6 Adapt constructor for multithreaded storage cell use 2025-02-10 16:11:30 +01:00
ea288a1939 Globally implement Copy() function for deep copy of detector objects 2025-02-10 16:10:53 +01:00
be607e8a2e Fix missing includes 2025-02-07 21:49:06 +01:00
7396ceed54 Create copy constructor for singlePhotonDetector that creates a new mutex 2025-02-07 21:09:31 +01:00
243c555798 Remove explicit class member analogDetector<uint16_t>* dd[MAXTHREADS] 2025-02-07 16:32:09 +01:00
7b1e74f4a4 Adapt get and writeImage methods to storage cell data 2025-02-07 15:33:31 +01:00
fcbb87b71a Adapt multithreaded cluster finder to storage cell data - continued (non-functional) 2025-02-06 20:42:36 +01:00
3a1945116a First (unfinished) attempt to adapt multithreaded cluster finding to storage cell data; REVERT BACK TO PREVIOUS COMMIT IF THIS FAILS! 2025-02-05 20:17:46 +01:00
884104156b Minor debugging 2025-02-04 18:15:33 +01:00
830ce66a4c Remove redundant default constructor and destructor of HDF5File reader class 2025-02-03 18:52:39 +01:00
69e1702493 Clear up warnings 2025-02-03 18:36:57 +01:00
027534cc2f comments 2025-02-03 18:01:13 +01:00
633f83f9c7 Minor include cleanup 2025-02-03 17:35:50 +01:00
b73684612b Merge branch 'developer' into jf_h5reader 2025-02-03 17:29:11 +01:00
71ca4e9f0f Generalize HDF5 reader for 3- or 4-dimensional datasets 2025-02-03 17:28:33 +01:00
25854f7736 Init problem fixed, add comments 2024-12-03 16:56:47 +01:00
bc6814ad0b Initialize image for all threads 2024-12-03 16:23:24 +01:00
7608d6392c Merge branch 'developer' into jf_h5reader 2024-12-02 15:06:48 +01:00
adcaf6b3df Debug getImage() 2024-12-02 15:06:09 +01:00
577362f95e Merge branch 'developer' into jf_h5reader 2024-11-21 16:34:08 +01:00
cfa0b003ba include <memory> 2024-11-21 16:33:38 +01:00
266ace44a2 Include fmt a CMake dependency 2024-11-08 16:35:04 +01:00
a8a4cc641e Merge branch 'developer' into jf_h5reader 2024-11-08 12:01:43 +01:00
d2dead070c Revert previous datatype change to int 2024-11-08 12:01:08 +01:00
0583a0703c Datatype change long long int also for moenchZMqProcess; these datatype changes need to be discussed as they could have fruther impact! 2024-10-29 17:51:09 +01:00
19f4c07642 Datatype change long long int also for multiThreadedInterpolatingDetector; note that this change could have further impact on local code 2024-10-29 17:32:21 +01:00
b587e95717 Merge branch 'developer' into jf_h5reader 2024-10-29 12:03:17 +01:00
f3a3fb09bf Merge branch 'developer' into jf_h5reader 2024-10-11 17:15:33 +02:00
f0fc547c6f Fix segmentation fault caused by double delete of threads and resolve memory leaks 2024-10-11 17:14:55 +02:00
3150276bfe Add frame number 2024-10-11 17:12:55 +02:00
7b4740ced2 program runs (fixed detector size in jungfrauLGADStrixelsDataQuadH5.h) 2024-09-05 17:03:31 +02:00
16bfcc17ce Fetch json from remote 2024-09-02 18:16:57 +02:00
a9c366890b add vs code and rhel 8 2024-09-02 12:00:12 +02:00
4ae2edf686 Compiles 2024-08-28 12:10:04 +02:00
69fb5876cb almost compiles, error: undefined reference to vtable for jungfrauLGADStrixelsDataQuadH5 2024-08-26 18:50:56 +02:00
543b311c06 Merge branch 'developer' into jf_h5reader 2024-08-23 11:44:05 +02:00
669e5f3c7a intermediate 2024-08-23 11:43:32 +02:00
a6a4ea7f21 first draft 2024-08-07 11:05:23 +02:00
31f6a6de61 Merge branch 'developer' into jf_singlemodule 2024-08-06 13:58:16 +02:00
9d2d4f49d4 Merge branch 'developer' into jf_singlemodule 2024-07-26 15:56:23 +02:00
76ee52a3ca edit strixel mapping quad 2024-03-14 15:20:58 +01:00
732c54d273 Merge branch 'developer' into jf_singlemodule 2024-02-26 16:44:23 +01:00
c0cbccd7d4 minor 2024-02-26 16:41:58 +01:00
783b95b1f3 Merge branch 'developer' into jf_singlemodule 2024-02-01 16:45:46 +01:00
d8e3e38c33 Compile strixel quad in cluster finder 2024-02-01 16:41:57 +01:00
7a03e56f09 Data structures 2024-02-01 16:38:26 +01:00
9bc20ab9b4 modify RawDataProcess_filetxt 2023-10-06 12:29:48 +02:00
95b7be6842 modify RawDataProcess 2023-10-06 12:18:33 +02:00
51d34063ac create single chip data map 2023-10-06 12:08:26 +02:00
d2fcc1f344 Merge branch 'developer' into jf_json_rxroi 2023-10-06 12:02:16 +02:00
2b93ef4565 minor 2023-10-06 11:55:20 +02:00
78cbe8e660 fix jungfrauModuleData empty if statement 2023-08-04 16:12:27 +02:00
0ee54be252 rx_roi for module data 2023-08-04 15:31:30 +02:00
f90a9b7520 Read rx_ROI from json master 2023-08-03 18:25:43 +02:00
558c2de85c Merge branch 'developer' into jf_json_rxroi 2023-08-03 18:24:08 +02:00
877a648d9e Merge branch 'developer' into jf_json_rxroi 2023-07-28 12:18:29 +02:00
9ea5101299 Merge branch 'developer' into jf_json_rxroi 2023-07-20 16:56:38 +02:00
c57f10c242 Merge branch 'developer' into jf_json_rxroi 2023-07-20 16:40:53 +02:00
6d6b6b98df Fix strixel mapping and interpolation 2023-07-20 11:12:13 +02:00
41 changed files with 4407 additions and 1767 deletions

View File

@ -3,14 +3,14 @@
#ifndef ANALOGDETECTOR_H
#define ANALOGDETECTOR_H
//#include <mutex>
#include <mutex>
#include "commonModeSubtractionNew.h"
#include "ghostSummation.h"
#include "pedestalSubtraction.h"
#include "sls/tiffIO.h"
#include "slsDetectorData.h"
#include "slsInterpolation.h"
#include "sls/tiffIO.h"
#include <pthread.h>
#ifdef ROOTSPECTRUM
@ -90,6 +90,8 @@ template <class dataType> class analogDetector {
ymin = 0;
ymax = ny;
fMode = ePedestal;
dMode = eInterpolating;
// std::cout << "dMode " << dMode << std::endl;
thr = 0;
myFile = NULL;
#ifdef ROOTSPECTRUM
@ -111,15 +113,20 @@ template <class dataType> class analogDetector {
destructor. Deletes the pdestalSubtraction array and the image
*/
virtual ~analogDetector() {
// std::cout << "#### Debug: Destructing analogDetector! ####"
// << std::endl;
for (int i = 0; i < ny; i++) {
delete[] stat[i];
if (stat[i]) { delete[] stat[i]; stat[i] = nullptr; }
// delete[] stat[i];
/* delete [] pedMean[i]; */
/* delete [] pedVariance[i]; */
};
}
/* delete [] pedMean; */
/* delete [] pedVariance; */
delete[] stat;
delete[] image;
// delete[] stat;
// delete[] image;
if (stat) { delete[] stat; stat = nullptr; }
if (image) { delete[] image; image = nullptr; }
#ifdef ROOTSPECTRUM
delete hs;
#ifdef ROOTCLUST
@ -137,6 +144,8 @@ template <class dataType> class analogDetector {
*/
analogDetector(analogDetector *orig) {
/* copy construction from orig*/
// std::cout << "#### Debug: Calling analogDetector cloning method! ####"
// << std::endl;
det = orig->det;
nx = orig->nx;
ny = orig->ny;
@ -152,6 +161,8 @@ template <class dataType> class analogDetector {
thr = orig->thr;
// nSigma=orig->nSigma;
fMode = orig->fMode;
dMode = orig->dMode;
// std::cout << "dMode " << dMode << std::endl;
myFile = orig->myFile;
stat = new pedestalSubtraction *[ny];
@ -216,12 +227,75 @@ template <class dataType> class analogDetector {
ghSum = NULL;
}
/**
constructor creating a deep copy of another analog detector
\param other analog Detector structure to be copied
*/
analogDetector(const analogDetector &other)
: det(other.det), nx(other.nx), ny(other.ny), dataSign(other.dataSign),
iframe(other.iframe), gmap(other.gmap), id(other.id),
xmin(other.xmin), xmax(other.xmax), ymin(other.ymin),
ymax(other.ymax), thr(other.thr), fMode(other.fMode),
dMode(other.dMode), myFile(NULL) {
// std::cout << "#### Debug: Calling analogDetector copy constructor! ####"
// << std::endl;
// Deep copy the stat array
stat = new pedestalSubtraction *[ny];
for (int i = 0; i < ny; i++) {
stat[i] = new pedestalSubtraction[nx];
std::copy(other.stat[i], other.stat[i] + nx, stat[i]);
}
// Deep copy image array
image = new int[nx * ny];
std::copy(other.image, other.image + (nx * ny), image);
// Copy common-mode subtraction object (if it exists)
if (other.cmSub) {
cmSub = other.cmSub->Clone();
std::cout << "Copying cmSub" << std::endl;
} else {
cmSub = nullptr;
}
// Copy ghost summation object (if it exists)
if (other.ghSum) {
ghSum = other.ghSum->Clone();
std::cout << "Copying ghSum" << std::endl;
} else {
ghSum = nullptr;
}
// Ensure pedestal values are copied properly
int nped = other.GetNPedestals(0, 0);
for (int iy = 0; iy < ny; ++iy) {
for (int ix = 0; ix < nx; ++ix) {
stat[iy][ix].SetNPedestals(nped);
setPedestal(ix, iy, other.getPedestal(ix, iy),
other.getPedestalRMS(ix, iy),
other.GetNPedestals(ix, iy));
}
}
}
/**
clone. Must be virtual!
\returns a clone of the original analog detector
*/
virtual analogDetector *Clone() = 0;
/**
Deep copy. Must be virtual!
This is a new addition because of multithreaded storage cell data (where
each sc has its own mutex). If the pure virtual function exists here,
EVERY derived class has to overwrite it! That means a Copy() function
must also be implemented in any derived class. \returns a deep copy of
the original analog detector
*/
virtual analogDetector *Copy() = 0;
/**
Gives an id to the structure. For debugging purposes in case of
multithreading. \param i is to be set \returns current id
@ -548,6 +622,11 @@ template <class dataType> class analogDetector {
return ped;
};
// Const version for use in the copy constructor
virtual double getPedestal(int ix, int iy, int cm = 0) const {
return stat[iy][ix].getPedestal();
};
/**
gets pedestal rms (i.e. noise)
\param ix pixel x coordinate
@ -566,6 +645,11 @@ template <class dataType> class analogDetector {
return ped;
};
// Const version for use in the copy constructor
virtual double getPedestalRMS(int ix, int iy) const {
return stat[iy][ix].getPedestalRMS();
};
/**
sets pedestal
\param ix pixel x coordinate
@ -1226,7 +1310,7 @@ template <class dataType> class analogDetector {
/** gets number of samples for moving average pedestal calculation
\returns actual number of samples
*/
int GetNPedestals(int ix, int iy) {
int GetNPedestals(int ix, int iy) const {
if (ix >= 0 && ix < nx && iy >= 0 && iy < ny)
return stat[iy][ix].GetNPedestals();
else

View File

@ -50,6 +50,8 @@ template <typename Element> class CircularFifo {
mutable sem_t data_mutex;
mutable sem_t free_mutex;
unsigned int increment(unsigned int idx_) const;
int id_;
int thread_id_;
};
template <typename Element> int CircularFifo<Element>::getDataValue() const {
@ -74,14 +76,18 @@ template <typename Element> int CircularFifo<Element>::getFreeValue() const {
template <typename Element>
bool CircularFifo<Element>::push(Element *&item_, bool no_block) {
// check for fifo full
if (no_block && isFull())
return false;
if (no_block && isFull()) {
//std::cout << "Full Fifo at push. Returning." << std::endl;
return false; // No space, return immediately
}
sem_wait(&free_mutex);
array[tail] = item_;
tail = increment(tail);
sem_post(&data_mutex);
return true;
//std::cout << "Thread " << thread_id_ <<" Push Fifo " << id_ << " item " << static_cast<void*>(item_) << std::endl;
sem_wait(&free_mutex); // Wait for space
array[tail] = item_; // Add item to the buffer
tail = increment(tail); // Move the tail pointer
sem_post(&data_mutex); // Signal that there is new data
return true; // Success
}
/** Consumer only: Removes and returns item from the queue
@ -94,14 +100,18 @@ bool CircularFifo<Element>::push(Element *&item_, bool no_block) {
template <typename Element>
bool CircularFifo<Element>::pop(Element *&item_, bool no_block) {
// check for fifo empty
if (no_block && isEmpty())
return false;
if (no_block && isEmpty()) {
//std::cout << "Empty Fifo at pop. Returning." << std::endl;
return false; // No data in fifo, return immediately
}
sem_wait(&data_mutex);
item_ = array[head];
head = increment(head);
sem_post(&free_mutex);
return true;
//std::cout << "Thread " << thread_id_ << " Pop Fifo " << id_ << " item " << static_cast<void*>(item_) << std::endl;
sem_wait(&data_mutex); // Wait for data
item_ = array[head]; // Retreive item from the current head of the buffer
head = increment(head); // Move the head pointer (to point to the next item)
sem_post(&free_mutex); // Signal that there is new free space available
return true; //Success
}
/** Useful for testinng and Consumer check of status

View File

@ -0,0 +1,482 @@
#include "HDF5File.h"
#include "ansi.h"
#include <algorithm>
#include <fmt/ranges.h>
/*
* No class member helper functions
*/
std::string vectorToString(std::vector<hsize_t> const& v) {
return fmt::format("({})", fmt::join(v, ", "));
}
/*
* increment frame offset (if s dimension exists, loop through all before incrementing z)
* should also work if file_dims[1] is not s but x (in that case we ignore it)
*/
void conditionalIncrement(std::vector<hsize_t>& vec, hsize_t max_value) {
if (vec.size() < 3) {
throw std::invalid_argument("Vector must have at least 3 elements.");
}
// If vector has 4 elements, increment vec[1] first
if (vec.size() == 4) {
if (++vec[1] >= max_value) { //max_value is never reached!
vec[1] = 0; // Reset and increment vec[0]
++vec[0];
}
}
// If vector has 3 elements, increment vec[0] directly
else if (vec.size() == 3) {
++vec[0];
}
}
void printDatatypeSize(hid_t dataset) {
hid_t datatype = H5Dget_type(dataset);
H5T_class_t class_id = H5Tget_class(datatype);
size_t type_size = H5Tget_size(datatype);
H5Tclose(datatype);
std::cout << " dataset type class: " << class_id
<< ", size: " << type_size << " bytes\n";
//Ensure the read datatype matches a system native type correctly
//hid_t read_type = (type_size == 8) ? H5T_NATIVE_LLONG : H5T_NATIVE_UINT;
//return read_type;
}
/* **********************
* Class member functions
* **********************
*/
// Default constructor
/*
HDF5File::HDF5File () {
//InitializeParameters(); //old
}
*/
/*
HDF5File::~HDF5File () {
if(current_image)
delete [] current_image;
}
*/
void HDF5File::SetImageDataPath (std::string const& name) {
std::cout << "Image dataset path set to " << name << std::endl;
data_datasetname = name;
}
void HDF5File::SetFrameIndexPath (std::string const& name) {
std::cout << "Frame index dataset path set to " << name << std::endl;
index_datasetname = name;
}
void HDF5File::InitializeDimensions () {
rank = H5Sget_simple_extent_ndims(dataspace);
file_dims.resize(rank);
H5Sget_simple_extent_dims(dataspace, file_dims.data(), nullptr);
std::cout << "Dataset dimensions: " << vectorToString(file_dims) << "\n";
}
std::vector<hsize_t> HDF5File::GetDatasetDimensions() {
return file_dims;
}
std::vector<hsize_t> HDF5File::GetChunkDimensions() {
return chunk_dims;
}
hsize_t HDF5File::GetRank() {
return rank;
}
bool HDF5File::ValidateDimensions () {
// validate rank
if(rank != RANK) {
cprintf(RED,"rank found %llu. Expected %d\n", rank, RANK);
std::cerr << "Error: Rank could not be validated\n";
return false;
}
// validate file dimensions of x and y (assuming those are the last two dimensions of the dataset)
if ( (file_dims[file_dims.size()-2] != DEFAULT_X_DIMS) || (file_dims[file_dims.size()-1] != DEFAULT_Y_DIMS) ) {
cprintf(RED,"file dimensions of x found %llu. Expected %d\n", file_dims[file_dims.size()-2], DEFAULT_X_DIMS);
cprintf(RED,"file dimensions of y found %llu. Expected %d\n", file_dims[file_dims.size()-1], DEFAULT_Y_DIMS);
std::cerr << "Error: Dataset dimensions could not be validated\n";
return false;
}
cprintf(GREEN, "File rank & dimensions validated.");
return true;
}
bool HDF5File::ReadChunkDimensions () {
// Get layout
hid_t plist_id = H5Dget_create_plist(dataset);
if (H5Pget_layout (plist_id) != H5D_CHUNKED) {
cprintf(RED,"NOTE: Dataset is not chunked!\n");
std::cerr << "Error: Dataset is not chunked\n";
return false;
}
// Get Chunk Dimensions
int rank_chunk = H5Pget_chunk (plist_id, 0, nullptr);
chunk_dims.resize(rank_chunk);
H5Pget_chunk (plist_id, rank_chunk, chunk_dims.data());
std::cout << "Chunk dimensions: " << vectorToString(chunk_dims) << "\n";
H5Pclose (plist_id);
return true;
}
bool HDF5File::ValidateChunkDimensions () {
// validate rank
if(chunk_dims.size() != rank) {
cprintf(RED,"Chunk rank does not match dataset rank! Found %lu. Expected %llu\n", chunk_dims.size(), rank);
std::cerr << "Error: Chunk rank does not match dataset rank\n";
return false;
}
// validate chunk dimensions of x and y (assuming those are the last two dimensions of the dataset)
if ( (chunk_dims[chunk_dims.size()-2] != DEFAULT_CHUNK_X_DIMS) || (chunk_dims[chunk_dims.size()-1] != DEFAULT_CHUNK_Y_DIMS) ) {
cprintf(RED,"file dimensions of x found %llu. Expected %d\n", chunk_dims[chunk_dims.size()-2], DEFAULT_CHUNK_X_DIMS);
cprintf(RED,"file dimensions of y found %llu. Expected %d\n", chunk_dims[chunk_dims.size()-1], DEFAULT_CHUNK_Y_DIMS);
std::cerr << "Error: Chunk dimensions could not be validated\n";
return false;
}
cprintf(GREEN, "Chunk rank & dimensions validated.");
return true;
}
bool HDF5File::OpenFrameIndexDataset() {
// Get all the frame numbers
// Open frame index dataset
hid_t fi_dataset = H5Dopen2 (file, index_datasetname.c_str(), H5P_DEFAULT);
if (fi_dataset < 0){
cprintf (RED,"Could not open frame index dataset %s\n", index_datasetname.c_str());
std::cerr << "Error: Could not open frame index dataset\n";
return false;
}
hid_t fi_dataspace = H5Dget_space (fi_dataset);
int fi_rank = H5Sget_simple_extent_ndims(fi_dataspace);
std::vector<hsize_t> fi_dims(fi_rank);
H5Sget_simple_extent_dims (fi_dataspace, fi_dims.data(), nullptr);
std::cout << "Frame index dataset dimensions: " << vectorToString(fi_dims) << "\n";
// validate size
if (fi_dims[0] != file_dims[0]) {
cprintf (RED,"Frame index dimensions of z found %llu. Expected %llu\n", fi_dims[0], file_dims[0]);
std::cerr << "Error: Z dimension of frame index dataset does not align with z dimension of image dataset\n";
H5Sclose (fi_dataspace);
H5Dclose (fi_dataset);
return false;
}
// allocate frame index memory
frame_index_list.resize(fi_dims[0]); //file_dims
// read and print datatype size of dataset
std::cout << "Frame index";
printDatatypeSize(fi_dataset);
// make sure we only read the first column of the frame index dataset (not all storage cells)
//NOTE: For XFEL datasets, this may mean that some frame numbers are skipped
//(because they assign a unique frame number to every storage cell)
//Possibly, there is a cleaner fix for this...
std::vector<hsize_t> start(fi_rank,0);
std::vector<hsize_t> count(fi_rank,1);
count[0] = fi_dims[0];
hid_t memspace = H5Screate_simple (fi_rank, count.data(), nullptr);
if (memspace < 0) {
std::cerr << "Error: Failed to create memory space for HDF5 read operation\n";
H5Sclose(memspace);
H5Sclose(fi_dataspace);
H5Dclose(fi_dataset);
return false;
}
// Create hyperslab selection
if (H5Sselect_hyperslab(fi_dataspace, H5S_SELECT_SET, start.data(), nullptr, count.data(), nullptr) < 0 ) {
cprintf (RED,"Could not create hyperslab for %s\n", vectorToString(start).c_str());
std::cerr << "Error: Hyperslab creation failed for " << vectorToString(start) << "\n";
H5Sclose(memspace);
H5Sclose (fi_dataspace);
H5Dclose(fi_dataset);
return false;
}
//read frame index values
//Is u32 correct? I would think not. But I get a segmentation fault if I use u64.
if (H5Dread (fi_dataset, H5T_STD_U64LE, memspace, fi_dataspace, H5P_DEFAULT, frame_index_list.data()) < 0) {
cprintf (RED,"Could not read frame index dataset %s\n", index_datasetname.c_str());
std::cerr << "Error: Could not read frame index dataset\n";
H5Sclose(memspace);
H5Sclose (fi_dataspace);
H5Dclose (fi_dataset);
return false;
}
H5Sclose(memspace);
H5Sclose (fi_dataspace);
H5Dclose(fi_dataset);
return true;
}
int HDF5File::OpenResources (char const*const fname, bool validate) {
std::cout << "Debug HDF5File.cpp: Attempting to open file " << fname << std::endl;
// Open File
file = H5Fopen (fname, H5F_ACC_RDONLY, H5P_DEFAULT);
if (file < 0) {
cprintf(RED,"Could not open hdf5 file\n");
std::cerr << "Error: H5Fopen failed\n";
return 0;
}
cprintf(BLUE, "Opened File: %s\n", fname);
// Open Dataset
dataset = H5Dopen2 (file, data_datasetname.c_str(), H5P_DEFAULT);
if (dataset < 0){
cprintf(RED,"Could not open dataset\n");
std::cerr << "Error: H5Dopen2 failed\n";
CloseResources ();
return 0;
}
cprintf(BLUE, "Opened Dataset: %s\n", data_datasetname.c_str());
// print datatype size of dataset
std::cout << "Image";
printDatatypeSize(dataset);
// Create Dataspace
dataspace = H5Dget_space (dataset);
if (dataspace < 0){
cprintf(RED,"Could not open dataspace\n");
std::cerr << "Error: H5Dget_space failed\n";
CloseResources ();
return 0;
}
// Get Dimensions
InitializeDimensions();
// Get chunk dimensions
if (!ReadChunkDimensions()) {
CloseResources();
return 0;
}
// validate file dimensions
if (validate) {
if ( !ValidateDimensions() || !ValidateChunkDimensions() ) {
CloseResources();
return 0;
}
}
//Read frame indices
if (!OpenFrameIndexDataset()) {
CloseResources();
return 0;
}
return 1;
}
void HDF5File::CloseResources () {
if (dataspace >=0 ) {
H5Sclose(dataspace);
dataspace = -1;
}
if (dataset >=0 ) {
H5Dclose(dataset);
dataset = -1;
}
if (file >=0 ) {
H5Fclose(file);
file = -1;
}
}
/*
* Function takes uint16_t* argument to make explicit that the caller has to handle memory allocation and deallocation.
* This is legacy caused by the structure with which the slsDetectorCalibration cluster finder is written.
* (Best practice for modern C++ would be using smart pointers.)
*
* Originially, this function took uint16_t** which may lead to memory management issues since image gets redirected
* to point to current_image, which is owned by HDF5File.
* (Good practice in classic C-style. HDF5File needs to clean up the resource at destruction.)
*
* \param image pointer to uint16_t, buffer which the image is read into. (Memory handled by caller!)
* \param offset contains iFrame at [0] and storage cell number at [1],
* depending on dimensionality of the dataset, the storage cell number may not be included.
* Note that frame number (as read from file) may (likely) differ from frame index (in the dataset)!
*/
int HDF5File::ReadImage (uint16_t* image, std::vector<hsize_t>& offset ) {
// Validate input arguments
if (!image) {
std::cerr << "Error: image buffer is null.\n";
return -99;
}
if ( offset.size() != rank-2 ) {
cprintf ( RED,"Offset vector must have size %llu. Found %lu\n", rank-2, offset.size() );
std::cerr << "Error: Wrong offset vector size\n";
CloseResources ();
return -99;
}
// Initialize frame_offset
if (frame_offset.empty())
frame_offset.resize(rank,0);
// Check if we reached the end of file
// Compares that the offsets of frame and storage cell (Z and S) have reached the end of file
// Excludes X and Y indices (of the image dataset) from the comparison
// As it is now, this never triggers, because frame_offset[1] is never equals file_dims[1]=16
/*
if( std::equal( frame_offset.cbegin(), frame_offset.cend()-2, file_dims.cbegin() ) ) {
printf("End of file reached\n");
return -1;
}
*/
if (frame_offset[0] == file_dims[0]) {
printf("End of file reached\n");
return -1;
}
/* //old
if (frame_offset[0] == file_dims[0]-1) {
printf("end of file\n");
return -1;
}
*/
// Validate frame_offset index
if (frame_offset[0] >= frame_index_list.size()) {
std::cerr << "Error: frame_offset[0] = " << frame_offset[0] << " of bounds.\n";
return -99;
}
// Check if images exist at the current frame offset
if (frame_index_list[frame_offset[0]] == 0) {
cprintf (RED,"No images at this frame offset %llu\n", frame_offset[0]);
std::cerr << "Error: Framenumber 0 at this frame offset\n";
CloseResources ();
return -99;
}
// Optional: Ensure dataset and dataspace are valid
if (dataset < 0) {
std::cerr << "Error: Invalid dataset ID.\n";
return -99;
}
if (dataspace < 0) {
std::cerr << "Error: Invalid dataspace.\n";
return -99;
}
// Define the size of the hyperslab to read
std::vector<hsize_t> frame_size(rank, 1);
std::copy(file_dims.begin() + rank-2, file_dims.end(), frame_size.begin() + rank-2);
/*
for ( int d=0; d < rank; ++d ) {
if (d < rank-2)
frame_size[d] = 1;
if ( d >= rank-2 )
frame_size[d] = file_dims[d];
}
*/
// Define memory space
hid_t memspace = H5Screate_simple (rank, frame_size.data(), nullptr);
if (memspace < 0) {
std::cerr << "Error: Failed to create memory space for HDF5 read operation\n";
CloseResources();
return -99;
}
// Create hyperslab selection
// This aligns dataspace such that we read the correct frame
if (H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, frame_offset.data(), nullptr, frame_size.data(), nullptr) < 0 ) {
cprintf (RED,"Could not create hyperslab for frame offset %s\n", vectorToString(frame_offset).c_str());
std::cerr << "Error: Hyperslab creation failed for frame offset " << vectorToString(frame_offset) << "\n";
CloseResources();
H5Sclose(memspace);
return -99;
}
// Read dataset into image buffer (previously read to current_image owned by HDF5File)
if (H5Dread(dataset, H5T_STD_U16LE, memspace, dataspace, H5P_DEFAULT, image) < 0 ) {
cprintf (RED,"Could not read dataset for frame offset %s\n", vectorToString(frame_offset).c_str());
std::cerr << "Error: Reading of dataset failed for given start frame offset " << vectorToString(frame_offset) << "\n";
CloseResources ();
H5Sclose(memspace);
return -99;
}
// Clean up memory space
H5Sclose(memspace);
//*image = current_image; //if uint16_t** is passed, HDF5File owns the resource image points to, which is potentially dangerous
// Return frame number
unsigned int retval = frame_index_list[frame_offset[0]];
// Pass updated frame offset value(s) via offset parameter vector
std::copy_n(frame_offset.begin(), offset.size(), offset.begin());
/*
std::transform( offset.begin(), offset.end(), offset.begin(),
[&, i = 0](size_t) mutable { return frame_offset[i++]; } );
*/
// Increment frame offset correctly
conditionalIncrement(frame_offset, file_dims[1]);
//++frame_offset[0]; //old
return retval;
}
void HDF5File::PrintCurrentImage (uint16_t* image) {
printf("\n");
printf("Frame %llu, Image: %llu\n", frame_offset[0]-1, frame_index_list[frame_offset[0]-1]);
hsize_t size = file_dims[rank-1] * file_dims[rank-2];
for (hsize_t i = 0; i < size; ++i){
printf("%u ", image[i]);
if (!((i+1) % file_dims[rank-2] ))
printf("\n\n");
}
printf("\n\n\n\n");
}

View File

@ -0,0 +1,159 @@
#pragma once
/************************************************
* @file HDF5Fle.h
* @short functions to open/close/read HDF5 File
* Adapted for generalization, accepts rank 3 and 4
* Supports control over storage cells
***********************************************/
/**
*@short functions to open/close/read HDF5 File
*/
#include <iostream>
#include <vector>
#include <string>
#include "hdf5.h"
#include "hdf5_hl.h"
//#define MAX_STR_LENGTH 1000
#define RANK 4 // Dimension of the image dataset, only for validation
#define DEFAULT_Z_DIMS 10000 // only for validation
#define DEFAULT_Y_DIMS 1024 // only for validation
#define DEFAULT_X_DIMS 512 // only for validation
//#define DEFAULT_S_DIMS 1 // Storage cells
#define DEFAULT_CHUNK_Z_DIMS 1 // only for validation
#define DEFAULT_CHUNK_Y_DIMS 1024 // only for validation
#define DEFAULT_CHUNK_X_DIMS 512 // only for validation
//#define DEFAULT_CHUNK_S_DIMS 1
#define DATA_DATASETNAME "/data/JF18T01V01/data" //Furka JF
#define INDEX_DATASETNAME "/data/JF18T01V01/frame_index"
//enum{Z,S,X,Y}; //S is the storage cell //enum is not used
class HDF5File {
public:
/**
* Constructor
*/
//HDF5File () = default; //No need to declare if it is default
/**
* Destructor
*/
//~HDF5File () = default; //Since the destructor is default (and copy and move are default too)
std::vector<hsize_t> GetDatasetDimensions ();
std::vector<hsize_t> GetChunkDimensions ();
hsize_t GetRank ();
void SetImageDataPath (std::string const& name);
void SetFrameIndexPath (std::string const& name);
/**
* Open HDF5 file and dataset,
* reads frame index dataset to array
* @param fname file name
* @param validate true if one must validate if file is
* chunked with dims [? x 128 x 512] and chunk dims [1 x 128 x 512]
* @returns 1 if successful, else 0 if fail
*/
int OpenResources (const char* const fname, bool validate);
/**
* Close Open resources
*/
void CloseResources ();
/**
* Read an image into current_image,
* increment Z-offset (frame) and (if rank==4) storage cell
* @returns frame number read from file,
*/
int ReadImage (uint16_t* image, std::vector<hsize_t>& offset);
/**
* Print current image in memory
*/
void PrintCurrentImage (uint16_t* image);
private:
/**
* Initialize dimensions of image dataset for each new file
*/
void InitializeDimensions ();
bool ReadChunkDimensions ();
bool ValidateDimensions ();
bool ValidateChunkDimensions ();
/**
* Open dataset containing the frame numbers
*/
bool OpenFrameIndexDataset ();
/** file name */
std::string file_name{};
/** dataset name for image data */
std::string data_datasetname = DATA_DATASETNAME;
/** dataset name for frame index data */
std::string index_datasetname = INDEX_DATASETNAME;
/** file handle */
hid_t file{};
/** dataspace handle */
hid_t dataspace{};
/** memory space handle */
//hid_t memspace; //old
/** dataset handle */
hid_t dataset{};
/** file dimensions */
std::vector<hsize_t> file_dims{};
//hsize_t file_dims[RANK]{}; //static array (dimensions are known)
/** chunk dimensions
** not necessarily required
** useful for optimization or validation */
std::vector<hsize_t> chunk_dims{};
//hsize_t chunk_dims[RANK]{};
/** Rank of the image dataset */
hsize_t rank{};
/** number of frames */
unsigned int number_of_frames{};
/** frame index list */
std::vector<hsize_t> frame_index_list{};
/** Current image
** dynamic array
** uint16_t pointer format is chosen to support use with slsDetectorCalibration cluster finder */
//uint16_t* current_image{nullptr};
//uint16_t current_chunk[DEFAULT_CHUNK_Z_DIMS][DEFAULT_CHUNK_Y_DIMS][DEFAULT_CHUNK_X_DIMS];
/** Current frame offset
** (Z-offset, S-offset, 0, 0) or (Z-offset, 0, 0), increments automatically with ReadImage */
std::vector<hsize_t> frame_offset{};
//hsize_t frame_offset[RANK]{};
};

View File

@ -0,0 +1,422 @@
// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
#ifndef JUNGFRAULGADSTRIXELSDATAQUAD_H
#define JUNGFRAULGADSTRIXELSDATAQUAD_H
#ifdef CINT
#include "sls/sls_detector_defs_CINT.h"
#else
#include "sls/sls_detector_defs.h"
#endif
#include "slsDetectorData.h"
// #define VERSION_V2
/**
@short structure for a Detector Packet or Image Header
@li frameNumber is the frame number
@li expLength is the subframe number (32 bit eiger) or real time exposure
time in 100ns (others)
@li packetNumber is the packet number
@li bunchId is the bunch id from beamline
@li timestamp is the time stamp with 10 MHz clock
@li modId is the unique module id (unique even for left, right, top, bottom)
@li xCoord is the x coordinate in the complete detector system
@li yCoord is the y coordinate in the complete detector system
@li zCoord is the z coordinate in the complete detector system
@li debug is for debugging purposes
@li roundRNumber is the round robin set number
@li detType is the detector type see :: detectorType
@li version is the version number of this structure format
*/
#include <algorithm>
#include <numeric>
#include <tuple>
namespace strixelQuad {
constexpr int nc_rawimg = 1024; // for full images //256;
constexpr int nc_quad = 512;
constexpr int nr_rawimg = 512;
constexpr int nr_chip = 256;
constexpr int gr = 9;
//shift due to extra pixels
constexpr int shift_x = 2; //left
constexpr int nc_strixel = ( nc_quad - shift_x - 2*gr ) / 3; //164
constexpr int nr_strixel = ( nr_chip - 1 - gr ) * 3; //one half (-1 because double sided pixel) //738
constexpr int nr_center = 12; //double sided pixels to be skipped
// boundaries in ASIC coordinates (pixels at both bounds are included)
constexpr int xstart = 256 + gr; // 265
constexpr int xend = 255 + nc_quad - gr; // 758
constexpr int bottom_ystart = gr; // 9
constexpr int bottom_yend = nr_chip - 2; // 254
constexpr int top_ystart = nr_chip + 1; // 257
constexpr int top_yend = nr_chip*2 - gr - 1; // 502
// x shift because of 2-pixel strixels on one side
constexpr int shift = 2;
} // namespace strixelQuad
//to account for module rotation
enum rotation {
NORMAL = 0,
INVERSE = 1
};
const int rota = NORMAL;
typedef struct {
uint64_t bunchNumber; /**< is the frame number */
uint64_t pre; /**< something */
} jf_header; // Aldo's header
using namespace strixelQuad;
class jungfrauLGADStrixelsDataQuad : public slsDetectorData<uint16_t> {
private:
int iframe;
int x0, y0, x1, y1, shifty;
struct {
uint16_t xmin;
uint16_t xmax;
uint16_t ymin;
uint16_t ymax;
int nc;
} globalROI;
//to account for the inverted routing of the two different quad halfs
enum location {
BOTTOM = 0,
TOP = 1
};
int multiplicator = 3;
std::vector<int> mods{ 0, 1, 2 };
void reverseVector( std::vector<int>& v ) {
std::reverse( v.begin(), v.end() );
std::cout << "mods reversed ";
for ( auto i : v )
std::cout << i << " ";
std::cout << '\n';
}
void setMappingShifts( const int rot, const int half ) {
x0 = xstart;
x1 = xend;
if (rot==NORMAL) {
x0 += shift;
} else {
x1-=shift;
reverseVector(mods);
}
if (half==BOTTOM) {
y0 = bottom_ystart;
y1 = bottom_yend;
shifty = 0;
} else {
y0 = top_ystart;
y1 = top_yend;
reverseVector(mods);
shifty = nr_strixel + nr_center; //double-sided pixels in the center have to be jumped
}
}
void remap( int xmin=0, int xmax=0, int ymin=0, int ymax=0 ) {
int ix, iy = 0;
// remapping loop
for (int ipy = y0; ipy <= y1; ipy++) {
for (int ipx = x0; ipx <= x1; ipx++) {
ix = int((ipx - x0) / multiplicator);
for (int m = 0; m < multiplicator; ++m) {
if ((ipx - x0) % multiplicator == m)
iy = (ipy - y0) * multiplicator + mods[m] + shifty;
}
// if (iy< 40) cout << iy << " " << ix <<endl;
if (xmin < xmax && ymin < ymax) {
if ( ipx>=xmin && ipx<=xmax && ipy>=ymin && ipy <=ymax )
dataMap[iy][ix] =
sizeof(header) + (globalROI.nc * (ipy - globalROI.ymin) + (ipx - globalROI.xmin)) * 2;
} else {
dataMap[iy][ix] = sizeof(header) + (nc_rawimg * ipy + ipx) * 2;
}
}
}
}
void remapQuad(const int rot) {
setMappingShifts( rot, BOTTOM );
remap();
setMappingShifts( rot, TOP );
remap();
}
std::tuple< uint16_t, uint16_t, uint16_t, uint16_t > adjustROItoLimits(uint16_t xmin,
uint16_t xmax,
uint16_t ymin,
uint16_t ymax,
uint16_t lim_roi_xmin,
uint16_t lim_roi_xmax,
uint16_t lim_roi_ymin,
uint16_t lim_roi_ymax) {
uint16_t xmin_roi, xmax_roi, ymin_roi, ymax_roi;
if ( xmin < lim_roi_xmin)
xmin_roi = lim_roi_xmin;
else
xmin_roi = xmin;
if ( xmax > lim_roi_xmax )
xmax_roi = lim_roi_xmax;
else
xmax_roi = xmax;
if ( ymin < lim_roi_ymin )
ymin_roi = lim_roi_ymin;
else
ymin_roi = ymin;
if ( ymax > lim_roi_ymax )
ymax_roi = lim_roi_ymax;
else
ymax_roi = ymax;
return std::make_tuple(xmin_roi, xmax_roi, ymin_roi, ymax_roi);
}
std::vector < std::tuple< int, uint16_t, uint16_t, uint16_t, uint16_t > > mapSubROIs(uint16_t xmin,
uint16_t xmax,
uint16_t ymin,
uint16_t ymax) {
bool bottom = false;
bool top = false;
for ( int x=xmin; x!=xmax+1; ++x ) {
for ( int y=ymin; y!=ymax; ++y ) {
if ( xstart<=x && x<=xend && bottom_ystart<=y && y<=bottom_yend )
bottom = true;
if ( xstart<=x && x<=xend && top_ystart<=y && y<=top_yend )
top = true;
}
}
uint16_t xmin_roi{}, xmax_roi{}, ymin_roi{}, ymax_roi{};
std::vector < std::tuple< int, uint16_t, uint16_t, uint16_t, uint16_t > > rois{};
if (bottom) {
std::tie( xmin_roi, xmax_roi, ymin_roi, ymax_roi ) =
adjustROItoLimits( xmin, xmax, ymin, ymax,
xstart, xend, bottom_ystart, bottom_yend );
rois.push_back( std::make_tuple( BOTTOM, xmin_roi, xmax_roi, ymin_roi, ymax_roi ) );
}
if (top) {
std::tie( xmin_roi, xmax_roi, ymin_roi, ymax_roi ) =
adjustROItoLimits( xmin, xmax, ymin, ymax,
xstart, xend, top_ystart, top_yend );
rois.push_back( std::make_tuple( TOP, xmin_roi, xmax_roi, ymin_roi, ymax_roi ) );
}
return rois;
}
void remapROI(std::tuple< int, uint16_t, uint16_t, uint16_t, uint16_t > roi, const int rot ) {
int half, xmin, xmax, ymin, ymax;
std::tie( half, xmin, xmax, ymin, ymax ) = roi;
setMappingShifts(rot, half);
std::cout << "remapping roi: "
<< ", x0: " << x0 << ", x1: " << x1 << ", y0: " << y0
<< ", y1: " << y1 << std::endl;
std::cout << "Adjusted roi: [" << xmin << ", " << xmax << ", " << ymin << ", " << ymax << "]" << std::endl;
remap( xmin, xmax, ymin, ymax );
}
public:
using header = sls::defs::sls_receiver_header;
jungfrauLGADStrixelsDataQuad(uint16_t xmin = 0, uint16_t xmax = 0,
uint16_t ymin = 0, uint16_t ymax = 0)
: slsDetectorData<uint16_t>(
nc_strixel,
nr_strixel * 2 + nr_center,
nc_strixel * ( nr_strixel * 2 + nr_center ) * 2 + sizeof(header)) {
std::cout << "Jungfrau strixels quad with full module data "
<< std::endl;
// Fill all strixels with dummy values
for (int ix = 0; ix != nc_strixel; ++ix) {
for (int iy = 0; iy != nr_strixel * 2 + nr_center; ++iy) {
dataMap[iy][ix] = sizeof(header);
}
}
globalROI.xmin = xmin;
globalROI.xmax = xmax;
globalROI.ymin = ymin;
globalROI.ymax = ymax;
std::cout << "sizeofheader = " << sizeof(header) << std::endl;
std::cout << "Jungfrau strixels quad with full module data "
<< std::endl;
if (xmin < xmax && ymin < ymax) {
// get ROI raw image number of columns
globalROI.nc = xmax - xmin + 1;
std::cout << "nc_roi = " << globalROI.nc << std::endl;
dataSize =
(xmax - xmin + 1) * (ymax - ymin + 1) * 2 + sizeof(header);
std::cout << "datasize " << dataSize << std::endl;
auto rois = mapSubROIs(xmin, xmax, ymin, ymax);
//function to fill vector of rois from globalROI
for ( auto roi : rois )
remapROI(roi, rota);
} else {
remapQuad( rota );
}
iframe = 0;
std::cout << "data struct created" << std::endl;
};
/**
Returns the value of the selected channel for the given dataset as
double. \param data pointer to the dataset (including headers etc) \param
ix pixel number in the x direction \param iy pixel number in the y
direction \returns data for the selected channel, with inversion if
required as double
*/
virtual double getValue(char *data, int ix, int iy = 0) {
uint16_t val = getChannel(data, ix, iy) & 0x3fff;
return val;
};
/**
Returns the frame number for the given dataset. Purely virtual func.
\param buff pointer to the dataset
\returns frame number
*/
int getFrameNumber(char *buff) {
#ifdef ALDO // VH
return ((jf_header *)buff)->bunchNumber; // VH
#endif // VH
return ((header *)buff)->detHeader.frameNumber;
};
/**
Returns the packet number for the given dataset. purely virtual func
\param buff pointer to the dataset
\returns packet number number
*/
int getPacketNumber(char *buff) {
#ifdef ALDO // VH
// uint32_t fakePacketNumber = 1000;
// return fakePacketNumber; //VH //TODO: Keep in mind in case of bugs!
// //This is definitely bad!
return 1000;
#endif // VH
return ((header *)buff)->detHeader.packetNumber;
};
char *readNextFrame(std::ifstream &filebin) {
int ff = -1, np = -1;
return readNextFrame(filebin, ff, np);
};
char *readNextFrame(std::ifstream &filebin, int &ff) {
int np = -1;
return readNextFrame(filebin, ff, np);
};
char *readNextFrame(std::ifstream &filebin, int &ff, int &np) {
char *data = new char[dataSize];
char *d = readNextFrame(filebin, ff, np, data);
if (d == NULL) {
delete[] data;
data = NULL;
}
return data;
};
char *readNextFrame(std::ifstream &filebin, int &ff, int &np, char *data) {
//char *retval = 0;
//int nd;
//int fnum = -1;
np = 0;
//int pn;
//std::cout << dataSize << std::endl;
//if (ff >= 0) {
// fnum = ff; }
if (filebin.is_open()) {
if (filebin.read(data, dataSize)) {
std::cout << "*";
ff = getFrameNumber(data);
np = getPacketNumber(data);
return data;
}
std::cout << "#";
} else {
std::cout << "File not open" << std::endl;
}
return NULL;
};
/* Loops over a memory slot until a complete frame is found (i.e. all */
/* packets 0 to nPackets, same frame number). purely virtual func \param
*/
/* data pointer to the memory to be analyzed \param ndata reference to
* the */
/* amount of data found for the frame, in case the frame is incomplete at
*/
/* the end of the memory slot \param dsize size of the memory slot to be
*/
/* analyzed \returns pointer to the beginning of the last good frame
* (might */
/* be incomplete if ndata smaller than dataSize), or NULL if no frame is
*/
/* found */
/* *\/ */
virtual char *findNextFrame(char *data, int &ndata, int dsize) {
if (dsize < dataSize)
ndata = dsize;
else
ndata = dataSize;
return data;
};
// int getPacketNumber(int x, int y) {return dataMap[y][x]/packetSize;};
};
#endif

View File

@ -0,0 +1,432 @@
// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
#ifndef JUNGFRAULGADSTRIXELSDATAQUADH5_H
#define JUNGFRAULGADSTRIXELSDATAQUADH5_H
#ifdef CINT
#include "sls/sls_detector_defs_CINT.h"
#else
#include "sls/sls_detector_defs.h"
#endif
#include "slsDetectorData.h"
// This needs to be linked correctly
#include "HDF5File.cpp"
#include "HDF5File.h" //this includes hdf5.h and hdf5_hl.h
// #define VERSION_V2
/**
@short structure for a Detector Packet or Image Header
@li frameNumber is the frame number
@li expLength is the subframe number (32 bit eiger) or real time exposure
time in 100ns (others)
@li packetNumber is the packet number
@li bunchId is the bunch id from beamline
@li timestamp is the time stamp with 10 MHz clock
@li modId is the unique module id (unique even for left, right, top, bottom)
@li xCoord is the x coordinate in the complete detector system
@li yCoord is the y coordinate in the complete detector system
@li zCoord is the z coordinate in the complete detector system
@li debug is for debugging purposes
@li roundRNumber is the round robin set number
@li detType is the detector type see :: detectorType
@li version is the version number of this structure format
*/
// #include <algorithm>
#include <numeric>
#include <tuple>
namespace strixelQuad {
constexpr int nc_rawimg = 1024; // for full images //256;
constexpr int nc_quad = 512;
constexpr int nr_rawimg = 512;
constexpr int nr_chip = 256;
constexpr int gr = 9;
// shift due to extra pixels
constexpr int shift_x = 2; // left
constexpr int nc_strixel = (nc_quad - shift_x - 2 * gr) / 3; // 164
constexpr int nr_strixel =
(nr_chip - 1 - gr) * 3; // one half (-1 because double sided pixel) //738
constexpr int nr_center = 12; // double sided pixels to be skipped
// boundaries in ASIC coordinates (pixels at both bounds are included)
constexpr int xstart = 256 + gr; // 265
constexpr int xend = 255 + nc_quad - gr; // 758
constexpr int bottom_ystart = gr; // 9
constexpr int bottom_yend = nr_chip - 2; // 254
constexpr int top_ystart = nr_chip + 1; // 257
constexpr int top_yend = nr_chip * 2 - gr - 1; // 502
// x shift because of 2-pixel strixels on one side
constexpr int shift = 2;
} // namespace strixelQuad
// to account for module rotation
enum rotation { NORMAL = 0, INVERSE = 1 };
const int rota = NORMAL;
typedef struct {
uint64_t bunchNumber; /**< is the frame number */
uint64_t pre; /**< something */
} jf_header; // Aldo's header
using namespace strixelQuad;
class jungfrauLGADStrixelsDataQuadH5 : public slsDetectorData<uint16_t> {
private:
int iframe;
int x0, y0, x1, y1, shifty;
struct {
uint16_t xmin;
uint16_t xmax;
uint16_t ymin;
uint16_t ymax;
int nc;
} globalROI;
// to account for the inverted routing of the two different quad halfs
enum location { BOTTOM = 0, TOP = 1 };
int multiplicator = 3;
std::vector<int> mods{0, 1, 2};
void reverseVector(std::vector<int> &v) {
std::reverse(v.begin(), v.end());
std::cout << "mods reversed ";
for (auto i : v)
std::cout << i << " ";
std::cout << '\n';
}
void setMappingShifts(const int rot, const int half) {
x0 = xstart;
x1 = xend;
if (rot == NORMAL) {
x0 += shift;
} else {
x1 -= shift;
reverseVector(mods);
}
if (half == BOTTOM) {
y0 = bottom_ystart;
y1 = bottom_yend;
shifty = 0;
} else {
y0 = top_ystart;
y1 = top_yend;
reverseVector(mods);
shifty = nr_strixel + nr_center; // double-sided pixels in the
// center have to be jumped
}
}
void remap(int xmin = 0, int xmax = 0, int ymin = 0, int ymax = 0) {
int ix, iy = 0;
// remapping loop
for (int ipy = y0; ipy <= y1; ++ipy) {
for (int ipx = x0; ipx <= x1; ++ipx) {
ix = int((ipx - x0) / multiplicator);
for (int m = 0; m < multiplicator; ++m) {
if ((ipx - x0) % multiplicator == m)
iy = (ipy - y0) * multiplicator + mods[m] + shifty;
}
// if (iy< 40) cout << iy << " " << ix <<endl;
if (xmin < xmax && ymin < ymax) { // if ROI
if (ipx >= xmin && ipx <= xmax && ipy >= ymin &&
ipy <= ymax)
dataMap[iy][ix] =
(globalROI.nc * (ipy - globalROI.ymin) +
(ipx - globalROI.xmin)) *
2;
} else { // if full Quad
dataMap[iy][ix] = (nc_rawimg * ipy + ipx) * 2;
}
}
}
}
void remapQuad(const int rot) {
setMappingShifts(rot, BOTTOM);
remap();
setMappingShifts(rot, TOP);
remap();
}
std::tuple<uint16_t, uint16_t, uint16_t, uint16_t>
adjustROItoLimits(uint16_t xmin, uint16_t xmax, uint16_t ymin,
uint16_t ymax, uint16_t lim_roi_xmin,
uint16_t lim_roi_xmax, uint16_t lim_roi_ymin,
uint16_t lim_roi_ymax) {
uint16_t xmin_roi, xmax_roi, ymin_roi, ymax_roi;
if (xmin < lim_roi_xmin)
xmin_roi = lim_roi_xmin;
else
xmin_roi = xmin;
if (xmax > lim_roi_xmax)
xmax_roi = lim_roi_xmax;
else
xmax_roi = xmax;
if (ymin < lim_roi_ymin)
ymin_roi = lim_roi_ymin;
else
ymin_roi = ymin;
if (ymax > lim_roi_ymax)
ymax_roi = lim_roi_ymax;
else
ymax_roi = ymax;
return std::make_tuple(xmin_roi, xmax_roi, ymin_roi, ymax_roi);
}
// The strixel Quad has a mirrored symmetry from the center axis
// So we need to distinguish between bottom and top half for remapping
std::vector<std::tuple<int, uint16_t, uint16_t, uint16_t, uint16_t>>
mapSubROIs(uint16_t xmin, uint16_t xmax, uint16_t ymin, uint16_t ymax) {
bool bottom = false;
bool top = false;
for (int x = xmin; x != xmax + 1; ++x) {
for (int y = ymin; y != ymax; ++y) {
if (xstart <= x && x <= xend && bottom_ystart <= y &&
y <= bottom_yend)
bottom = true;
if (xstart <= x && x <= xend && top_ystart <= y &&
y <= top_yend)
top = true;
}
}
uint16_t xmin_roi{}, xmax_roi{}, ymin_roi{}, ymax_roi{};
std::vector<std::tuple<int, uint16_t, uint16_t, uint16_t, uint16_t>>
rois{};
if (bottom) {
std::tie(xmin_roi, xmax_roi, ymin_roi, ymax_roi) =
adjustROItoLimits(xmin, xmax, ymin, ymax, xstart, xend,
bottom_ystart, bottom_yend);
rois.push_back(std::make_tuple(BOTTOM, xmin_roi, xmax_roi, ymin_roi,
ymax_roi));
}
if (top) {
std::tie(xmin_roi, xmax_roi, ymin_roi, ymax_roi) =
adjustROItoLimits(xmin, xmax, ymin, ymax, xstart, xend,
top_ystart, top_yend);
rois.push_back(
std::make_tuple(TOP, xmin_roi, xmax_roi, ymin_roi, ymax_roi));
}
return rois;
}
void remapROI(std::tuple<int, uint16_t, uint16_t, uint16_t, uint16_t> roi,
const int rot) {
int half, xmin, xmax, ymin, ymax;
std::tie(half, xmin, xmax, ymin, ymax) = roi;
setMappingShifts(rot, half);
std::cout << "remapping roi: "
<< ", x0: " << x0 << ", x1: " << x1 << ", y0: " << y0
<< ", y1: " << y1 << std::endl;
std::cout << "Adjusted roi: [" << xmin << ", " << xmax << ", " << ymin
<< ", " << ymax << "]" << std::endl;
remap(xmin, xmax, ymin, ymax);
}
// The following functions are pure virtual in the base class. But I don't
// want them to be accessible here! Implement the functions as private (to
// satisfy the linker) int getFrameNumber(char* buff){return 0;} //This is
// actually needed because the cluster finder writes the framenumber
int getPacketNumber(char *buff) { return 0; } // Not provided
// Mark overwritten functions as override final
char *readNextFrame(std::ifstream &filebin) override final {
return nullptr;
}
public:
using header = sls::defs::sls_receiver_header;
jungfrauLGADStrixelsDataQuadH5(uint16_t xmin = 0, uint16_t xmax = 0,
uint16_t ymin = 0, uint16_t ymax = 0)
: slsDetectorData<uint16_t>(
// nc_strixel,
// nr_strixel * 2 + nr_center,
// nc_strixel * ( nr_strixel * 2 + nr_center ) * 2
512 / 2, 1024 * 2, 512 * 1024 * 2) {
std::cout << "Jungfrau strixels quad with full module data "
<< std::endl;
// Fill all strixels with dummy values
// for (int ix = 0; ix != nc_strixel; ++ix) {
// for (int iy = 0; iy != nr_strixel * 2 + nr_center; ++iy) {
for (int ix = 0; ix != 512 / 2; ++ix) {
for (int iy = 0; iy != 1024 * 2; ++iy) {
// Set everything to dummy value
dataMap[iy][ix] = sizeof(header);
}
}
globalROI.xmin = xmin;
globalROI.xmax = xmax;
globalROI.ymin = ymin;
globalROI.ymax = ymax;
// std::cout << "sizeofheader = " << sizeof(header) << std::endl;
std::cout << "Jungfrau strixels quad with full module data "
<< std::endl;
if (xmin < xmax && ymin < ymax) {
// get ROI raw image number of columns
globalROI.nc = xmax - xmin + 1;
std::cout << "nc_roi = " << globalROI.nc << std::endl;
dataSize = (xmax - xmin + 1) * (ymax - ymin + 1) * 2;
std::cout << "datasize " << dataSize << std::endl;
auto rois = mapSubROIs(xmin, xmax, ymin, ymax);
// function to fill vector of rois from globalROI
for (auto roi : rois)
remapROI(roi, rota);
} else {
remapQuad(rota);
}
iframe = 0;
std::cout << "data struct created" << std::endl;
};
/**
Returns the value of the selected channel for the given dataset as
double. \param data pointer to the dataset (including headers etc) \param
ix pixel number in the x direction \param iy pixel number in the y
direction \returns data for the selected channel, with inversion if
required as double
*/
virtual double getValue(char *data, int ix, int iy = 0) {
uint16_t val = getChannel(data, ix, iy) & 0x3fff;
return val;
};
char *readNextFrame(HDF5File &hfile) {
int fn = 0;
std::vector<hsize_t> h5offset(1);
return readNextFrame(hfile, fn, h5offset);
};
char *readNextFrame(HDF5File &hfile, int &fn) {
std::vector<hsize_t> h5offset(1);
return readNextFrame(hfile, fn, h5offset);
};
char *readNextFrame(HDF5File &hfile, int &fn,
std::vector<hsize_t> &h5offset) {
// Ensure dataSize is a valid size for allocation
if (dataSize <= 0) {
// Handle error case appropriately, e.g., log an error message
return nullptr;
}
char *data = new char[dataSize];
char *readResult = readNextFrame(hfile, fn, h5offset, data);
// Check if reading failed
if (readResult == nullptr) {
delete[] data; // Free allocated memory
data = nullptr; // Set to nullptr to avoid dangling pointer
}
return data; // returning data is equivalent to returning
// reinterpret_cast<char*>(data_ptr) as they both point to
// the same memory
};
/*
* This is the most recent function. This is used in the cluster finder!
* The overloads are legacy!
* Note that caller has to allocate and deallocate memory for data!
* \param hfile object of type HDF5File (reader class)
* \param framenumber frame number as read from the HDF5 file
* \param h5offset vector defining offset parameters for HDF5 hyperslab
* selection (dimensions Z and S), incremented automatially
* \param data pointer to image buffer (converted to hold uint16_t by
* definition of HDF5File)
*/
char *readNextFrame(HDF5File &hfile, int &framenumber,
std::vector<hsize_t> &h5offset, char *data) {
if (framenumber >= 0) {
if (h5offset[0] % 10 == 0)
std::cout << "*";
// Storing the reinterpret_cast in the variable data_ptr ensures
// that I can pass it to a function that expects at uint16_t*
uint16_t *data_ptr = reinterpret_cast<uint16_t *>(
data); // now data_ptr points where data points (thus modifies
// the same memory)
framenumber = hfile.ReadImage(data_ptr, h5offset);
iframe = h5offset[0]; // iframe is a class member!
return data; // return reinterpret_cast<char*>(data_ptr); //
// Equivalent
}
std::cout << "#";
return nullptr;
};
int getFrameNumber(char *buff) {
return iframe;
} // Provided via public method readNextFrame
// It is debatable if one might not instead want to provide the "real" frame
// number as read from the file here For now, this is the frame offset
// counter (that always has to start at 0 for each new file)
/* Loops over a memory slot until a complete frame is found (i.e. all */
/* packets 0 to nPackets, same frame number). purely virtual func \param
*/
/* data pointer to the memory to be analyzed \param ndata reference to
* the */
/* amount of data found for the frame, in case the frame is incomplete at
*/
/* the end of the memory slot \param dsize size of the memory slot to be
*/
/* analyzed \returns pointer to the beginning of the last good frame
* (might */
/* be incomplete if ndata smaller than dataSize), or NULL if no frame is
*/
/* found */
/* *\/ */
virtual char *findNextFrame(char *data, int &ndata, int dsize) {
if (dsize < dataSize)
ndata = dsize;
else
ndata = dataSize;
return data;
};
// int getPacketNumber(int x, int y) {return dataMap[y][x]/packetSize;};
};
#endif

View File

@ -28,6 +28,10 @@
@li version is the version number of this structure format
*/
#include <algorithm>
#include <numeric>
#include <tuple>
namespace strixelSingleChip {
constexpr int nc_rawimg = 1024; // for full images //256;
constexpr int nr_rawimg = 512;
@ -77,7 +81,7 @@ constexpr int c6g1_ystart = c6g2_yend + 1; // 448
constexpr int c6g1_yend = c6g2_yend + 64 - gr; // 502
// y shift due to faulty bonding (relevant for M408)
constexpr int bond_shift_y = 1; // CHANGE IF YOU CHANGE MODULE!
constexpr int bond_shift_y = 0; // CHANGE IF YOU CHANGE MODULE!
} // namespace strixelSingleChip
@ -97,6 +101,13 @@ class jungfrauLGADStrixelsData : public slsDetectorData<uint16_t> {
int chip_x0;
int chip_y0;
int x0, y0, x1, y1, shifty;
struct {
uint16_t xmin;
uint16_t xmax;
uint16_t ymin;
uint16_t ymax;
int nc;
} globalROI;
int getMultiplicator(const int group) {
int multiplicator;
@ -215,9 +226,113 @@ class jungfrauLGADStrixelsData : public slsDetectorData<uint16_t> {
}
}
void remapROI(uint16_t xmin, uint16_t xmax, uint16_t ymin, uint16_t ymax) {
std::tuple< uint16_t, uint16_t, uint16_t, uint16_t > adjustROItoLimits(uint16_t xmin,
uint16_t xmax,
uint16_t ymin,
uint16_t ymax,
uint16_t lim_roi_xmin,
uint16_t lim_roi_xmax,
uint16_t lim_roi_ymin,
uint16_t lim_roi_ymax) {
uint16_t xmin_roi, xmax_roi, ymin_roi, ymax_roi;
if ( xmin < lim_roi_xmin)
xmin_roi = lim_roi_xmin;
else
xmin_roi = xmin;
if ( xmax > lim_roi_xmax )
xmax_roi = lim_roi_xmax;
else
xmax_roi = xmax;
if ( ymin < lim_roi_ymin )
ymin_roi = lim_roi_ymin;
else
ymin_roi = ymin;
if ( ymax > lim_roi_ymax )
ymax_roi = lim_roi_ymax;
else
ymax_roi = ymax;
return std::make_tuple(xmin_roi, xmax_roi, ymin_roi, ymax_roi);
}
std::vector < std::tuple< int, int, uint16_t, uint16_t, uint16_t, uint16_t > > mapSubROIs(uint16_t xmin,
uint16_t xmax,
uint16_t ymin,
uint16_t ymax) {
bool chip_1_1 = false;
bool chip_1_2 = false;
bool chip_1_3 = false;
bool chip_6_1 = false;
bool chip_6_2 = false;
bool chip_6_3 = false;
for ( int x=xmin; x!=xmax+1; ++x ) {
for ( int y=ymin; y!=ymax; ++y ) {
if ( c1g1_xstart<=x && x<=c1_xend && (c1g1_ystart+bond_shift_y)<=y && y<=(c1g1_yend+bond_shift_y) )
chip_1_1 = true;
if ( c1g2_xstart<=x && x<=c1_xend && (c1g2_ystart+bond_shift_y)<=y && y<=(c1g2_yend+bond_shift_y) )
chip_1_2 = true;
if ( c1g3_xstart<=x && x<=c1_xend && (c1g3_ystart+bond_shift_y)<=y && y<=(c1g3_yend+bond_shift_y) )
chip_1_3 = true;
if ( c6_xstart<=x && x<=c6g1_xend && (c6g1_ystart-bond_shift_y)<=y && y<=(c6g1_yend-bond_shift_y) )
chip_6_1 = true;
if ( c6_xstart<=x && x<=c6g2_xend && (c6g2_ystart-bond_shift_y)<=y && y<=(c6g2_yend-bond_shift_y) )
chip_6_2 = true;
if ( c6_xstart<=x && x<=c6g3_xend && (c6g3_ystart-bond_shift_y)<=y && y<=(c6g3_yend-bond_shift_y) )
chip_6_3 = true;
}
}
uint16_t xmin_roi{}, xmax_roi{}, ymin_roi{}, ymax_roi{};
//[ chip, group, xmin, xmax, ymin, ymax ]
std::vector < std::tuple< int, int, uint16_t, uint16_t, uint16_t, uint16_t > > rois{};
if (chip_1_1) {
std::tie( xmin_roi, xmax_roi, ymin_roi, ymax_roi ) =
adjustROItoLimits( xmin, xmax, ymin, ymax,
c1g1_xstart, c1_xend, 0, c1g1_yend+bond_shift_y );
rois.push_back( std::make_tuple( 1, 1, xmin_roi, xmax_roi, ymin_roi, ymax_roi ) );
}
if (chip_1_2) {
std::tie( xmin_roi, xmax_roi, ymin_roi, ymax_roi ) =
adjustROItoLimits( xmin, xmax, ymin, ymax,
c1g2_xstart, c1_xend, c1g2_ystart+bond_shift_y, c1g2_yend+bond_shift_y );
rois.push_back( std::make_tuple( 1, 2, xmin_roi, xmax_roi, ymin_roi, ymax_roi ) );
}
if (chip_1_3) {
std::tie( xmin_roi, xmax_roi, ymin_roi, ymax_roi ) =
adjustROItoLimits( xmin, xmax, ymin, ymax,
c1g3_xstart, c1_xend, c1g3_ystart+bond_shift_y, c1g3_yend+bond_shift_y );
rois.push_back( std::make_tuple( 1, 3, xmin_roi, xmax_roi, ymin_roi, ymax_roi ) );
}
if (chip_6_3) {
std::tie( xmin_roi, xmax_roi, ymin_roi, ymax_roi ) =
adjustROItoLimits( xmin, xmax, ymin, ymax,
c6_xstart, c6g3_xend, c6g3_ystart-bond_shift_y, c6g3_yend-bond_shift_y );
rois.push_back( std::make_tuple( 6, 3, xmin_roi, xmax_roi, ymin_roi, ymax_roi ) );
}
if (chip_6_2) {
std::tie( xmin_roi, xmax_roi, ymin_roi, ymax_roi ) =
adjustROItoLimits( xmin, xmax, ymin, ymax,
c6_xstart, c6g2_xend, c6g2_ystart-bond_shift_y, c6g2_yend-bond_shift_y );
rois.push_back( std::make_tuple( 6, 2, xmin_roi, xmax_roi, ymin_roi, ymax_roi ) );
}
if (chip_6_1) {
std::tie( xmin_roi, xmax_roi, ymin_roi, ymax_roi ) =
adjustROItoLimits( xmin, xmax, ymin, ymax,
c6_xstart, c6g1_xend, c6g1_ystart-bond_shift_y, 511 );
rois.push_back( std::make_tuple( 6, 1, xmin_roi, xmax_roi, ymin_roi, ymax_roi ) );
}
return rois;
}
void remapROI(std::tuple< int, int, uint16_t, uint16_t, uint16_t, uint16_t > roi) {
// determine group and chip selected by ROI
int group;
int group, xmin, xmax, ymin, ymax;
std::tie( mchip, group, xmin, xmax, ymin, ymax ) = roi;
/*
if (ymax <= c1g1_yend + bond_shift_y) {
group = 1;
mchip = 1;
@ -243,18 +358,17 @@ class jungfrauLGADStrixelsData : public slsDetectorData<uint16_t> {
group = -1;
mchip = -1;
}
int multiplicator = getMultiplicator(group);
setMappingShifts(group);
std::cout << "chip: " << mchip << ", group: " << group << ", m: " << multiplicator
<< ", x0: " << x0 << ", x1: " << x1 << ", y0: " << y0
<< ", y1: " << y1 << std::endl;
// get ROI raw image number of columns
int nc_roi = xmax - xmin + 1;
std::cout << "nc_roi = " << nc_roi << std::endl;
*/
int multiplicator = getMultiplicator(group);
setMappingShifts(group);
std::cout << "remapping chip: " << mchip << ", group: " << group << ", m: " << multiplicator
<< ", x0: " << x0 << ", x1: " << x1 << ", y0: " << y0
<< ", y1: " << y1 << std::endl;
std::cout << "Adjusted roi: [" << xmin << ", " << xmax << ", " << ymin << ", " << ymax << "]" << std::endl;
// make sure loop bounds are correct
/*
if (y0 < ymin)
std::cout << "Error ymin" << std::endl;
if (y1 > ymax)
@ -264,24 +378,27 @@ class jungfrauLGADStrixelsData : public slsDetectorData<uint16_t> {
std::cout << "Error xmin" << std::endl;
if (x1 > xmax)
std::cout << "Error xmax" << std::endl;
*/
// remapping loop
int ix, iy = 0;
for (int ipy = y0; ipy <= y1; ++ipy) {
for (int ipx = x0; ipx <= x1; ++ipx) {
int ix, iy = 0;
for (int ipy = y0; ipy <= y1; ++ipy) {
for (int ipx = x0; ipx <= x1; ++ipx) {
ix = int((ipx - x0 /*-xmin*/) / multiplicator);
for (int m = 0; m < multiplicator; m++) {
if ((ipx - x0 /*-xmin*/) % multiplicator == m)
iy = (ipy - y0 /*-ymin*/) * multiplicator + m + shifty;
}
// if (iy< 40) cout << iy << " " << ix <<endl;
dataMap[iy][ix] =
sizeof(header) + (nc_roi * (ipy - ymin) + (ipx - xmin)) * 2;
groupmap[iy][ix] = group - 1;
}
}
ix = int((ipx - x0 /*-xmin*/) / multiplicator);
for (int m = 0; m < multiplicator; m++) {
if ((ipx - x0 /*-xmin*/) % multiplicator == m)
iy = (ipy - y0 /*-ymin*/) * multiplicator + m + shifty;
}
// if (iy< 40) cout << iy << " " << ix <<endl;
if ( ipx>=xmin && ipx<=xmax && ipy>=ymin && ipy <=ymax )
dataMap[iy][ix] =
sizeof(header) + (globalROI.nc * (ipy - globalROI.ymin) + (ipx - globalROI.xmin)) * 2;
else dataMap[iy][ix] = sizeof(header);
groupmap[iy][ix] = group - 1;
}
}
}
public:
@ -307,16 +424,31 @@ class jungfrauLGADStrixelsData : public slsDetectorData<uint16_t> {
}
}
globalROI.xmin = xmin;
globalROI.xmax = xmax;
globalROI.ymin = ymin;
globalROI.ymax = ymax;
std::cout << "sizeofheader = " << sizeof(header) << std::endl;
std::cout << "Jungfrau strixels 2X single chip with full module data "
<< std::endl;
if (xmin < xmax && ymin < ymax) {
dataSize =
(xmax - xmin + 1) * (ymax - ymin + 1) * 2 + sizeof(header);
std::cout << "datasize " << dataSize << std::endl;
remapROI(xmin, xmax, ymin, ymax);
// get ROI raw image number of columns
globalROI.nc = xmax - xmin + 1;
std::cout << "nc_roi = " << globalROI.nc << std::endl;
dataSize =
(xmax - xmin + 1) * (ymax - ymin + 1) * 2 + sizeof(header);
std::cout << "datasize " << dataSize << std::endl;
//[ chip, group, xmin, xmax, ymin, ymax ]
auto rois = mapSubROIs(xmin, xmax, ymin, ymax);
//function to fill vector of rois from globalROI
for ( auto roi : rois )
remapROI(roi);
} else {

View File

@ -3,6 +3,7 @@
#ifndef JUNGFRAUMODULEDATA_H
#define JUNGFRAUMODULEDATA_H
#include <cstdint>
#include "sls/sls_detector_defs.h"
#include "slsDetectorData.h"
//#define VERSION_V2
@ -27,7 +28,7 @@ typedef struct {
uint64_t bunchNumber; /**< is the frame number */
uint64_t pre; /**< something */
} jf_header;
} jf_header; //Aldo's header!
using namespace std;
class jungfrauModuleData : public slsDetectorData<uint16_t> {
@ -42,20 +43,56 @@ class jungfrauModuleData : public slsDetectorData<uint16_t> {
1286 large etc.) \param c crosstalk parameter for the output buffer
*/
#ifdef ALDO
using header = jf_header;
#else
using header = sls::defs::sls_receiver_header;
#endif
#ifndef ZMQ
#define off sizeof(jf_header)
#define off sizeof(header)
#endif
#ifdef ZMQ
#define off 0
#endif
jungfrauModuleData()
jungfrauModuleData(uint16_t xmin=0, uint16_t xmax=0,
uint16_t ymin=0, uint16_t ymax=0)
: slsDetectorData<uint16_t>(1024, 512,
1024* 512 * 2 + off) {
for (int ix = 0; ix < 1024; ix++) {
for (int iy = 0; iy < 512; iy++) {
for (int ix = 0; ix != 1024; ++ix) {
for (int iy = 0; iy != 512; ++iy) {
dataMap[iy][ix] = off;
}
}
if (xmin < xmax && ymin < ymax) {
int nc_roi = xmax - xmin + 1;
int nr_roi = ymax - ymin + 1;
std::cout << "nc_roi = " << nc_roi << std::endl;
std::cout << "nr_roi = " << nr_roi << std::endl;
dataSize =
(xmax - xmin + 1) * (ymax - ymin + 1) * 2 + off;
std::cout << "datasize " << dataSize << std::endl;
for (int ix = xmin; ix < xmax+1; ++ix) {
for (int iy = ymin; iy < ymax+1; ++iy) {
dataMap[iy][ix] = off + (nc_roi * iy + ix) * 2;
#ifdef HIGHZ
dataMask[iy][ix] = 0x3fff;
#endif
}
}
} else {
for (int ix = 0; ix < 1024; ++ix) {
for (int iy = 0; iy < 512; ++iy) {
dataMap[iy][ix] = off + (1024 * iy + ix) * 2;
#ifdef HIGHZ
dataMask[iy][ix] = 0x3fff;
@ -63,7 +100,7 @@ class jungfrauModuleData : public slsDetectorData<uint16_t> {
}
}
}
iframe = 0;
@ -150,7 +187,7 @@ class jungfrauModuleData : public slsDetectorData<uint16_t> {
//int pn;
// cout << dataSize << endl;
if (ff >= 0)
//if (ff >= 0)
//fnum = ff;
if (filebin.is_open()) {

View File

@ -0,0 +1,226 @@
// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
#ifndef JUNGFRAUSINGLECHIPDATA_H
#define JUNGFRAUSINGLECHIPDATA_H
#include <cstdint>
#include "sls/sls_detector_defs.h"
#include "slsDetectorData.h"
//#define VERSION_V2
/**
@short structure for a Detector Packet or Image Header
@li frameNumber is the frame number
@li expLength is the subframe number (32 bit eiger) or real time exposure
time in 100ns (others)
@li packetNumber is the packet number
@li bunchId is the bunch id from beamline
@li timestamp is the time stamp with 10 MHz clock
@li modId is the unique module id (unique even for left, right, top, bottom)
@li xCoord is the x coordinate in the complete detector system
@li yCoord is the y coordinate in the complete detector system
@li zCoord is the z coordinate in the complete detector system
@li debug is for debugging purposes
@li roundRNumber is the round robin set number
@li detType is the detector type see :: detectorType
@li version is the version number of this structure format
*/
typedef struct {
uint64_t bunchNumber; /**< is the frame number */
uint64_t pre; /**< something */
} jf_header; //Aldo's header!
using namespace std;
class jungfrauSingleChipData : public slsDetectorData<uint16_t> {
private:
int iframe;
public:
/**
Implements the slsReceiverData structure for the moench02 prototype read
out by a module i.e. using the slsReceiver (160x160 pixels, 40 packets
1286 large etc.) \param c crosstalk parameter for the output buffer
*/
#ifdef ALDO
using header = jf_header;
#else
using header = sls::defs::sls_receiver_header;
#endif
#ifndef ZMQ
#define off sizeof(header)
#endif
#ifdef ZMQ
#define off 0
#endif
jungfrauSingleChipData(uint16_t xmin=0, uint16_t xmax=0,
uint16_t ymin=0, uint16_t ymax=0)
: slsDetectorData<uint16_t>(256, 256,
256* 256 * 2 + off) {
for (int ix = 0; ix != 256; ++ix) {
for (int iy = 0; iy != 256; ++iy) {
dataMap[iy][ix] = off;
}
}
if (xmin < xmax && ymin < ymax) {
int nc_roi = xmax - xmin + 1;
int nr_roi = ymax - ymin + 1;
std::cout << "nc_roi = " << nc_roi << std::endl;
std::cout << "nr_roi = " << nr_roi << std::endl;
dataSize =
(xmax - xmin + 1) * (ymax - ymin + 1) * 2 + off;
std::cout << "datasize " << dataSize << std::endl;
for (int ix = xmin; ix < xmax+1; ++ix) {
for (int iy = ymin; iy < ymax+1; ++iy) {
dataMap[iy][ix] = off + (nc_roi * iy + ix) * 2;
#ifdef HIGHZ
dataMask[iy][ix] = 0x3fff;
#endif
}
}
} else {
for (int ix = 0; ix < 256; ++ix) {
for (int iy = 0; iy < 256; ++iy) {
dataMap[iy][ix] = off + (256 * iy + ix) * 2;
#ifdef HIGHZ
dataMask[iy][ix] = 0x3fff;
#endif
}
}
}
iframe = 0;
// cout << "data struct created" << endl;
};
/**
Returns the value of the selected channel for the given dataset as
double. \param data pointer to the dataset (including headers etc) \param
ix pixel number in the x direction \param iy pixel number in the y
direction \returns data for the selected channel, with inversion if
required as double
*/
virtual double getValue(char *data, int ix, int iy = 0) {
uint16_t val = getChannel(data, ix, iy) & 0x3fff;
/* if (ix==0 && iy==0) */
/* cout << val << endl; */
return val;
};
/**
Returns the frame number for the given dataset. Purely virtual func.
\param buff pointer to the dataset
\returns frame number
*/
/* class jfrau_packet_header_t { */
/* public: */
/* unsigned char reserved[4]; */
/* unsigned char packetNumber[1]; */
/* unsigned char frameNumber[3]; */
/* unsigned char bunchid[8]; */
/* }; */
int getFrameNumber(char *buff) {
return ((jf_header *)buff)->bunchNumber;
};
/**
Returns the packet number for the given dataset. purely virtual func
\param buff pointer to the dataset
\returns packet number number
*/
int getPacketNumber(char *buff) {
return 0;
};
char *readNextFrame(ifstream &filebin) {
int ff = -1, np = -1;
return readNextFrame(filebin, ff, np);
};
char *readNextFrame(ifstream &filebin, int &ff) {
int np = -1;
return readNextFrame(filebin, ff, np);
};
char *readNextFrame(ifstream &filebin, int &ff, int &np) {
char *data = new char[dataSize];
char *d = readNextFrame(filebin, ff, np, data);
if (d == NULL) {
delete[] data;
data = NULL;
}
return data;
};
char *readNextFrame(ifstream &filebin, int &ff, int &np,char *data) {
//char *retval = 0;
//int nd;
//int fnum = -1;
np = 0;
//int pn;
// cout << dataSize << endl;
//if (ff >= 0)
//fnum = ff;
if (filebin.is_open()) {
if (filebin.read(data, dataSize)) {
ff = getFrameNumber(data);
np = getPacketNumber(data);
return data;
}
}
return NULL;
};
/**
Loops over a memory slot until a complete frame is found (i.e. all
packets 0 to nPackets, same frame number). purely virtual func \param
data pointer to the memory to be analyzed \param ndata reference to the
amount of data found for the frame, in case the frame is incomplete at
the end of the memory slot \param dsize size of the memory slot to be
analyzed \returns pointer to the beginning of the last good frame (might
be incomplete if ndata smaller than dataSize), or NULL if no frame is
found
*/
virtual char *findNextFrame(char *data, int &ndata, int dsize) {
if (dsize < dataSize)
ndata = dsize;
else
ndata = dataSize;
return data;
};
// int getPacketNumber(int x, int y) {return dataMap[y][x]/packetSize;};
};
#endif

View File

@ -54,6 +54,10 @@ class interpolatingDetector : public singlePhotonDetector {
pthread_mutex_init(fi, NULL);
};
/**
pointer-based copy constructor (cloner)
\param orig detector to be copied
*/
interpolatingDetector(interpolatingDetector *orig)
: singlePhotonDetector(orig) {
// if (orig->interp)
@ -66,10 +70,28 @@ class interpolatingDetector : public singlePhotonDetector {
fi = orig->fi;
}
/**
* copy constructor (deep copy)
* stricly, TODO: Implement Rule of Five!
* (copy op=, move ctor, and move op= would need to be defined)
*/
interpolatingDetector(interpolatingDetector const& other)
: singlePhotonDetector(other) {
interp = other.interp;
id = other.id;
fi = other.fi;
}
virtual interpolatingDetector *Clone() {
return new interpolatingDetector(this);
}
virtual interpolatingDetector *Copy() {
return new interpolatingDetector(*this);
}
virtual int setId(int i) {
id = i;
// interp->setId(id);

View File

@ -6,18 +6,86 @@
set(JUNGFRAU_EXECUTABLES)
find_package(fmt REQUIRED)
#find_package(fmt REQUIRED)
#nlohmann_json
#If the library was INSTALLED (i.e. sudo dnf install nlohmann-json3-dev), do stuff described in the repo under CMake -> External
#find_package(nlohmann_json 3.2.0 REQUIRED)
#find_package(nlohmann_json 3.11.2 REQUIRED)
#find_package(nlohmann_json 3.11.3 REQUIRED)
#
#If the library was not installed but just cloned from https://github.com/nlohmann/json.git (possible, because it is a header-only library),
# do stuff described in the repo under CMake -> Embedded
#set(JSON_BuildTests OFF CACHE INTERNAL "")
# If you only include this third party in PRIVATE source files, you do not
# need to install it when your main project gets installed.
# set(JSON_Install OFF CACHE INTERNAL "")
#add_subdirectory(nlohmann_json) #Put the actual path to json
#
#Alternative: Fetch and install it from remote
include(FetchContent)
FetchContent_Declare(
json
GIT_REPOSITORY https://github.com/nlohmann/json.git
GIT_TAG v3.11.3 # Replace with the version you need
)
#FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz) #Alternative (from the repo documentation)
FetchContent_MakeAvailable(json)
FetchContent_Declare(
fmt
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
GIT_TAG master
)
FetchContent_MakeAvailable(fmt)
# HDF5 file writing
if (SLS_USE_HDF5)
find_package(HDF5 1.10 COMPONENTS CXX REQUIRED)
list (APPEND SOURCES
HDF5File.cpp
)
endif (SLS_USE_HDF5)
# jungfrauRawDataProcess
add_executable(jungfrauRawDataProcess jungfrauRawDataProcess.cpp)
target_compile_definitions(jungfrauRawDataProcess PRIVATE MODULE)
list(APPEND JUNGFRAU_EXECUTABLES jungfrauRawDataProcess)
# jungfrauRawDataProcessChipAldo
add_executable(jungfrauRawDataProcessChipAldo jungfrauRawDataProcess_filetxt.cpp)
target_compile_definitions(jungfrauRawDataProcessChipAldo PRIVATE CHIP ALDO)
list(APPEND JUNGFRAU_EXECUTABLES jungfrauRawDataProcessChipAldo)
# jungfrauRawDataProcessStrx
add_executable(jungfrauRawDataProcessStrx jungfrauRawDataProcess_filetxt.cpp)
target_compile_definitions(jungfrauRawDataProcessStrx PRIVATE JFSTRX)
list(APPEND JUNGFRAU_EXECUTABLES jungfrauRawDataProcessStrx)
# jungfrauRawDataProcessStrxQuad
add_executable(jungfrauRawDataProcessStrxQuad jungfrauRawDataProcess_filetxt.cpp)
target_compile_definitions(jungfrauRawDataProcessStrxQuad PRIVATE JFSTRXQ)
list(APPEND JUNGFRAU_EXECUTABLES jungfrauRawDataProcessStrxQuad)
# jungfrauRawDataProcessStrxQuadH5
# HDF5
if (SLS_USE_HDF5)
if (HDF5_FOUND)
add_executable(jungfrauRawDataProcessStrxQuadH5 jungfrauRawDataProcess_filetxtH5.cpp)
#target_compile_definitions(jungfrauRawDataProcessStrxQuadH5 PRIVATE JFSTRXQH5)
list(APPEND JUNGFRAU_EXECUTABLES jungfrauRawDataProcessStrxQuadH5)
target_include_directories(jungfrauRawDataProcessStrxQuadH5 PRIVATE ${HDF5_INCLUDE_DIRS} ${CMAKE_INSTALL_PREFIX}/include)
target_link_libraries(jungfrauRawDataProcessStrxQuadH5 PRIVATE ${HDF5_LIBRARIES})
add_executable(jungfrauRawDataProcessStrxQuadH5SC jungfrauRawDataProcess_filetxtH5_SC.cpp)
#target_compile_definitions(jungfrauRawDataProcessStrxQuadH5 PRIVATE JFSTRXQH5)
list(APPEND JUNGFRAU_EXECUTABLES jungfrauRawDataProcessStrxQuadH5SC)
target_include_directories(jungfrauRawDataProcessStrxQuadH5SC PRIVATE ${HDF5_INCLUDE_DIRS} ${CMAKE_INSTALL_PREFIX}/include)
target_link_libraries(jungfrauRawDataProcessStrxQuadH5SC PRIVATE ${HDF5_LIBRARIES})
endif ()
endif (SLS_USE_HDF5)
# jungfrauRawDataProcessStrxChip1
add_executable(jungfrauRawDataProcessStrxChip1 jungfrauRawDataProcess.cpp)
@ -58,6 +126,22 @@ list(APPEND JUNGFRAU_EXECUTABLES jungfrauRawDataProcessStrxOldAldo)
# others to be added if needed (might already be there in Makefile.cluster_finder TO BE CHECKED)
if (SLS_USE_HDF5)
if (HDF5_FOUND)
target_include_directories(jungfrauRawDataProcessStrxQuadH5 PRIVATE
${HDF5_INCLUDE_DIRS}
${CMAKE_INSTALL_PREFIX}/include
)
target_link_libraries(jungfrauRawDataProcessStrxQuadH5 PRIVATE ${HDF5_LIBRARIES})
target_include_directories(jungfrauRawDataProcessStrxQuadH5SC PRIVATE
${HDF5_INCLUDE_DIRS}
${CMAKE_INSTALL_PREFIX}/include
)
target_link_libraries(jungfrauRawDataProcessStrxQuadH5SC PRIVATE ${HDF5_LIBRARIES})
endif ()
endif (SLS_USE_HDF5)
foreach(exe ${JUNGFRAU_EXECUTABLES})
@ -67,11 +151,16 @@ foreach(exe ${JUNGFRAU_EXECUTABLES})
../interpolations
../dataStructures
../interpolations/etaVEL
../../slsSupportLib/include/
../../slsSupportLib/include/sls/
../../slsReceiverSoftware/include/
../tiffio/include
${fmt_INCLUDE_DIRS}
)
# if (SLS_USE_HDF5)
# if (HDF5_FOUND)
# target_include_directories(${exe} PRIVATE ${HDF5_INCLUDE_DIRS} ${CMAKE_INSTALL_PREFIX}/include)
# endif ()
# endif (SLS_USE_HDF5)
target_link_libraries(${exe}
PUBLIC
@ -79,6 +168,7 @@ foreach(exe ${JUNGFRAU_EXECUTABLES})
pthread
tiffio
fmt::fmt
nlohmann_json::nlohmann_json
#-L/usr/lib64/
#-lm -lstdc++ -lrt
@ -86,7 +176,11 @@ foreach(exe ${JUNGFRAU_EXECUTABLES})
slsProjectWarnings
slsProjectOptions
)
# if (SLS_USE_HDF5)
# if (HDF5_FOUND)
# target_link_libraries(${exe} PRIVATE ${HDF5_LIBRARIES})
# endif ()
# endif (SLS_USE_HDF5)
set_target_properties(${exe} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
@ -98,4 +192,8 @@ foreach(exe ${JUNGFRAU_EXECUTABLES})
endforeach(exe ${JUNGFRAU_EXECUTABLES})
install(TARGETS ${JUNGFRAU_EXECUTABLES} DESTINATION bin)
install(TARGETS ${JUNGFRAU_EXECUTABLES} DESTINATION bin)

View File

@ -11,7 +11,7 @@
#define RAWDATA
#if !defined JFSTRX && !defined JFSTRXOLD && !defined JFSTRXCHIP1 && \
!defined JFSTRXCHIP6
!defined JFSTRXCHIP6 && !defined CHIP
#ifndef MODULE
#include "jungfrauHighZSingleChipData.h"
#endif
@ -20,6 +20,10 @@
#endif
#endif
#ifdef CHIP
#include "jungfrauSingleChipData.h"
#endif
#ifdef JFSTRX
#include "jungfrauLGADStrixelsData_new.h"
#endif
@ -41,6 +45,9 @@
#include <ctime>
#include <fmt/core.h>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
std::string getRootString( const std::string& filepath ) {
size_t pos1 = filepath.find_last_of("/");
@ -61,20 +68,24 @@ std::string getRootString( const std::string& filepath ) {
std::string createFileName( const std::string& dir, const std::string& fprefix="run", const std::string& fsuffix="", const std::string& fext="raw", int aindex=0, int mindex=0, int findex=0, int outfilecounter=-1 ) {
if (outfilecounter >= 0)
return fmt::format("{:s}/{:s}_d{:d}_f{:d}_{:d}_f{:05d}.{:s}", dir, fprefix, mindex, findex, aindex, outfilecounter, fext);
else if (fsuffix.length()!=0)
return fmt::format("{:s}/{:s}_{:s}.{:s}", dir, fprefix, fsuffix, fext);
else if (fsuffix.length()!=0) {
if (fsuffix == "master")
return fmt::format("{:s}/{:s}_master_{:d}.{:s}", dir, fprefix, aindex, fext);
else
return fmt::format("{:s}/{:s}_{:s}.{:s}", dir, fprefix, fsuffix, fext);
}
else
return fmt::format("{:s}/{:s}_d{:d}_f{:d}_{:d}.{:s}", dir, fprefix, mindex, findex, aindex, fext);
}
int main(int argc, char *argv[]) {
if (argc < 5) {
if (argc < 6) {
std::cout
<< "Usage is " << argv[0]
<< "indir outdir fprefix(excluding slsDetector standard suffixes and extension) fextension "
"[runmin] [runmax] [pedfile (raw or tiff)] [threshold] "
"[nframes] [xmin xmax ymin ymax] [gainmap]"
<< "indir outdir [fprefix(excluding slsDetector standard suffixes and extension)] [fextension] "
"[fmin] [fmax] [runmin] [runmax] [pedfile (raw or tiff)] [threshold] "
"[nframes] [xmin xmax ymin ymax] [optional: bool read rxroi from data file header] [gainmap]"
<< std::endl;
std::cout
<< "threshold <0 means analog; threshold=0 means cluster finder; "
@ -106,94 +117,131 @@ int main(int argc, char *argv[]) {
std::string outdir(argv[2]);
std::string fprefix(argv[3]);
std::string fext(argv[4]);
int fmin = 0;
if (argc >= 6)
fmin = atoi(argv[5]);
int fmax = fmin;
if (argc >= 7)
fmax = atoi(argv[6]);
int runmin = 0;
// cout << "argc is " << argc << endl;
if (argc >= 6) {
runmin = atoi(argv[5]);
if (argc >= 8) {
runmin = atoi(argv[7]);
}
int runmax = runmin;
if (argc >= 7) {
runmax = atoi(argv[6]);
if (argc >= 9) {
runmax = atoi(argv[8]);
}
std::string pedfilename{};
if (argc >= 8) {
pedfilename = argv[7];
if (argc >= 10) {
pedfilename = argv[9];
}
double thr = 0;
double thr1 = 1;
if (argc >= 9) {
thr = atof(argv[8]);
if (argc >= 11) {
thr = atof(argv[10]);
}
int nframes = 0;
if (argc >= 10) {
nframes = atoi(argv[9]);
if (argc >= 12) {
nframes = atoi(argv[11]);
}
bool readrxroifromdatafile = false;
if (argc >= 17)
readrxroifromdatafile = atoi(argv[16]);
// Receiver ROI
uint16_t rxroi_xmin = 0;
uint16_t rxroi_xmax = 0;
uint16_t rxroi_ymin = 0;
uint16_t rxroi_ymax = 0;
{ //protective scope so ifstream gets destroyed properly
auto jsonmastername = createFileName( indir, fprefix, "master", "json", runmin );
std::cout << "json master file " << jsonmastername << std::endl;
std::ifstream masterfile(jsonmastername); //, ios::in | ios::binary);
if (masterfile.is_open()) {
json j;
masterfile >> j;
rxroi_xmin = j["Receiver Roi"]["xmin"];
rxroi_xmax = j["Receiver Roi"]["xmax"];
rxroi_ymin = j["Receiver Roi"]["ymin"];
rxroi_ymax = j["Receiver Roi"]["ymax"];
masterfile.close();
std::cout << "Read Receiver ROI [" << rxroi_xmin << ", " << rxroi_xmax << ", "
<< rxroi_ymin << ", " << rxroi_ymax << "] from json master file" << std::endl;
} else
std::cout << "Could not open master file " << jsonmastername << std::endl;
}
// Define decoders...
#if !defined JFSTRX && !defined JFSTRXOLD && !defined JFSTRXCHIP1 && \
!defined JFSTRXCHIP6
!defined JFSTRXCHIP6 && !defined CHIP
#ifndef MODULE
jungfrauHighZSingleChipData *decoder = new jungfrauHighZSingleChipData();
int nx = 256, ny = 256;
#endif
#ifdef MODULE
jungfrauModuleData *decoder = new jungfrauModuleData();
jungfrauModuleData *decoder = new jungfrauModuleData(rxroi_xmin, rxroi_xmax, rxroi_ymin, rxroi_ymax);
int nx = 1024, ny = 512;
#endif
#endif
#ifdef CHIP
std::cout << "Jungfrau pixel module single chip readout" << std::endl;
jungfrauSingleChipData *decoder = new jungfrauSingleChipData();
int nx = 256, ny = 256;
#endif
#ifdef JFSTRX
cout << "Jungfrau strixel full module readout" << endl;
// ROI
uint16_t xxmin = 0;
uint16_t xxmax = 0;
uint16_t yymin = 0;
uint16_t yymax = 0;
std::cout << "Jungfrau strixel full module readout" << std::endl;
#ifndef ALDO
{ //THIS SCOPE IS IMPORTANT! (To ensure proper destruction of ifstream)
using header = sls::defs::sls_receiver_header;
// check if there is a roi in the header
typedef struct {
uint16_t xmin;
uint16_t xmax;
uint16_t ymin;
uint16_t ymax;
} receiverRoi_compact;
receiverRoi_compact croi;
std::string fsuffix{};
auto filename = createFileName( indir, fprefix, fsuffix, fext, runmin );
std::cout << "Reading header of file " << filename << " to check for ROI "
<< std::endl;
ifstream firstfile(filename, ios::in | ios::binary);
if (firstfile.is_open()) {
header hbuffer;
std::cout << "sizeof(header) = " << sizeof(header) << std::endl;
if (firstfile.read((char *)&hbuffer, sizeof(header))) {
memcpy(&croi, &hbuffer.detHeader.detSpec1, 8);
std::cout << "Read ROI [" << croi.xmin << ", " << croi.xmax << ", "
<< croi.ymin << ", " << croi.ymax << "]" << std::endl;
xxmin = croi.xmin;
xxmax = croi.xmax;
yymin = croi.ymin;
yymax = croi.ymax;
} else
std::cout << "reading error" << std::endl;
firstfile.close();
} else
std::cout << "Could not open " << filename << " for reading " << std::endl;
} //end of protective scope
if (readrxroifromdatafile)
{ //THIS SCOPE IS IMPORTANT! (To ensure proper destruction of ifstream)
using header = sls::defs::sls_receiver_header;
// check if there is a roi in the header
typedef struct {
uint16_t xmin;
uint16_t xmax;
uint16_t ymin;
uint16_t ymax;
} receiverRoi_compact;
receiverRoi_compact croi;
std::string fsuffix{};
auto filename = createFileName( indir, fprefix, fsuffix, fext, runmin );
std::cout << "Reading header of file " << filename << " to check for ROI "
<< std::endl;
ifstream firstfile(filename, ios::in | ios::binary);
if (firstfile.is_open()) {
header hbuffer;
std::cout << "sizeof(header) = " << sizeof(header) << std::endl;
if (firstfile.read((char *)&hbuffer, sizeof(header))) {
memcpy(&croi, &hbuffer.detHeader.detSpec1, 8);
std::cout << "Read ROI [" << croi.xmin << ", " << croi.xmax << ", "
<< croi.ymin << ", " << croi.ymax << "]" << std::endl;
rxroi_xmin = croi.xmin;
rxroi_xmax = croi.xmax;
rxroi_ymin = croi.ymin;
rxroi_ymax = croi.ymax;
} else
std::cout << "reading error" << std::endl;
firstfile.close();
} else
std::cout << "Could not open " << filename << " for reading " << std::endl;
} //end of protective scope
#endif
jungfrauLGADStrixelsData *decoder =
new jungfrauLGADStrixelsData(xxmin, xxmax, yymin, yymax);
new jungfrauLGADStrixelsData(rxroi_xmin, rxroi_xmax, rxroi_ymin, rxroi_ymax);
int nx = 1024 / 3, ny = 512 * 5;
#endif
#ifdef JFSTRXCHIP1
@ -218,19 +266,20 @@ int main(int argc, char *argv[]) {
decoder->getDetectorSize(nx, ny);
std::cout << "Detector size is " << nx << " " << ny << std::endl;
int xmin = 0, xmax = nx, ymin = 0, ymax = ny;
if (argc >= 14) {
xmin = atoi(argv[10]);
xmax = atoi(argv[11]);
ymin = atoi(argv[12]);
ymax = atoi(argv[13]);
//Cluster finder ROI
int xmin = 0, xmax = nx-1, ymin = 0, ymax = ny-1;
if (argc >= 16) {
xmin = atoi(argv[12]);
xmax = atoi(argv[13]);
ymin = atoi(argv[14]);
ymax = atoi(argv[15]);
}
std::cout << xmin << " " << xmax << " " << ymin << " " << ymax << " "
std::cout << "Cluster finder ROI: [" << xmin << ", " << xmax << ", " << ymin << ", " << ymax << "]"
<< std::endl;
char *gainfname = NULL;
if (argc > 14) {
gainfname = argv[14];
if (argc > 17) {
gainfname = argv[17];
std::cout << "Gain map file name is: " << gainfname << std::endl;
}
@ -239,6 +288,8 @@ int main(int argc, char *argv[]) {
std::cout << "input directory is " << indir << std::endl;
std::cout << "output directory is " << outdir << std::endl;
std::cout << "input file prefix is " << fprefix << std::endl;
std::cout << "fmin is " << fmin << std::endl;
std::cout << "fmax is " << fmax << std::endl;
std::cout << "runmin is " << runmin << std::endl;
std::cout << "runmax is " << runmax << std::endl;
if (pedfilename.length()!=0)
@ -319,7 +370,7 @@ int main(int argc, char *argv[]) {
mt->setFrameMode(ePedestal);
ifstream pedefile(fname, ios::in | ios::binary);
std::ifstream pedefile(fname, ios::in | ios::binary);
// //open file
if (pedefile.is_open()) {
std::cout << "bbbb " << std::ctime(&end_time) << std::endl;
@ -380,26 +431,27 @@ int main(int argc, char *argv[]) {
}
ifr = 0;
int ifile = 0;
int ioutfile = 0;
mt->setFrameMode(eFrame);
FILE *of = NULL;
for (int irun = runmin; irun <= runmax; irun++) {
for (int irun = runmin; irun <= runmax; ++irun) {
for (int ifile = fmin; ifile <= fmax; ++ifile) {
std::cout << "DATA ";
std::string fsuffix{};
auto fname = createFileName( indir, fprefix, fsuffix, fext, irun );
auto imgfname = createFileName( outdir, fprefix, fsuffix, "tiff", irun );
auto cfname = createFileName( outdir, fprefix, fsuffix, "clust", irun );
auto fname = createFileName( indir, fprefix, fsuffix, fext, irun, 0, ifile );
auto imgfname = createFileName( outdir, fprefix, fsuffix, "tiff", irun, 0, ifile );
auto cfname = createFileName( outdir, fprefix, fsuffix, "clust", irun, 0, ifile );
std::cout << fname << " ";
std::cout << imgfname << std::endl;
std::time(&end_time);
std::cout << std::ctime(&end_time) << std::endl;
// std::cout << fname << " " << outfname << " " << imgfname << std::endl;
ifstream filebin(fname, ios::in | ios::binary);
std::ifstream filebin(fname, ios::in | ios::binary);
// //open file
ifile = 0;
ioutfile = 0;
if (filebin.is_open()) {
if (thr <= 0 && cf != 0) { // cluster finder
if (of == NULL) {
@ -436,10 +488,10 @@ int main(int argc, char *argv[]) {
std::cout << " " << ifr << " " << ff << std::endl;
if (nframes > 0) {
if (ifr % nframes == 0) {
imgfname = createFileName( outdir, fprefix, fsuffix, "tiff", irun, 0, 0, ifile );
imgfname = createFileName( outdir, fprefix, fsuffix, "tiff", irun, 0, 0, ioutfile );
mt->writeImage(imgfname.c_str(), thr1);
mt->clearImage();
ifile++;
ioutfile++;
}
}
// } else
@ -453,7 +505,7 @@ int main(int argc, char *argv[]) {
}
if (nframes >= 0) {
if (nframes > 0)
imgfname = createFileName( outdir, fprefix, fsuffix, "tiff", irun, 0, 0, ifile );
imgfname = createFileName( outdir, fprefix, fsuffix, "tiff", irun, 0, 0, ioutfile );
std::cout << "Writing tiff to " << imgfname << " " << thr1
<< std::endl;
mt->writeImage(imgfname.c_str(), thr1);
@ -469,9 +521,10 @@ int main(int argc, char *argv[]) {
} else
std::cout << "Could not open " << fname << " for reading "
<< std::endl;
}
}
if (nframes < 0) {
auto imgfname = createFileName( outdir, fprefix, "sum", "tiff", -1, 0, 0, -1 );
auto imgfname = createFileName( outdir, fprefix, "sum", "tiff", runmin, 0, fmin, -1 );
std::cout << "Writing tiff to " << imgfname << " " << thr1 << std::endl;
mt->writeImage(imgfname.c_str(), thr1);
}

View File

@ -10,8 +10,8 @@
#define RAWDATA
#if !defined JFSTRX && !defined JFSTRXOLD && !defined JFSTRXCHIP1 && \
!defined JFSTRXCHIP6
#if !defined JFSTRX && !defined JFSTRXQ && !defined JFSTRXOLD && !defined JFSTRXCHIP1 && \
!defined JFSTRXCHIP6 && !defined CHIP
#ifndef MODULE
#include "jungfrauHighZSingleChipData.h"
#endif
@ -20,9 +20,16 @@
#endif
#endif
#ifdef CHIP
#include "jungfrauSingleChipData.h"
#endif
#ifdef JFSTRX
#include "jungfrauLGADStrixelsData_new.h"
#endif
#ifdef JFSTRXQ
#include "jungfrauLGADStrixelsDataQuad.h"
#endif
#if defined JFSTRXCHIP1 || defined JFSTRXCHIP6
#include "jungfrauLGADStrixelsDataSingleChip.h"
#endif
@ -41,6 +48,9 @@
#include <ctime>
#include <fmt/core.h>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
std::string getRootString( const std::string& filepath ) {
size_t pos1;
@ -71,11 +81,11 @@ std::string createFileName( const std::string& dir, const std::string& fprefix="
//NOTE THAT THE DATA FILES HAVE TO BE IN THE RIGHT ORDER SO THAT PEDESTAL TRACKING WORKS!
int main(int argc, char *argv[]) {
if (argc < 10) {
if (argc < 11) {
std::cout
<< "Usage is " << argv[0]
<< " filestxt outdir [pedfile (raw or tiff)] [xmin xmax ymin ymax] "
"[threshold] [nframes] "
<< " filestxt outdir [json master] [pedfile (raw or tiff)] [xmin xmax ymin ymax] "
"[threshold] [nframes] [optional: bool read rxroi from data file header]"
"NOTE THAT THE DATA FILES HAVE TO BE IN THE RIGHT ORDER SO THAT PEDESTAL TRACKING WORKS! "
<< std::endl;
std::cout
@ -105,19 +115,19 @@ int main(int argc, char *argv[]) {
const std::string txtfilename(argv[1]);
const std::string outdir(argv[2]);
const std::string pedfilename(argv[3]);
int xmin = atoi(argv[4]);
int xmax = atoi(argv[5]);
int ymin = atoi(argv[6]);
int ymax = atoi(argv[7]);
const std::string jsonmastername(argv[3]);
const std::string pedfilename(argv[4]);
double thr = 0;
double thr1 = 1;
thr = atof(argv[8]);
thr = atof(argv[9]);
int nframes = 0;
nframes = atoi(argv[9]);
nframes = atoi(argv[10]);
bool readrxroifromdatafile = false;
if (argc > 11)
readrxroifromdatafile = atoi(argv[11]);
//Get vector of filenames from input txt-file
std::vector<std::string> filenames{};
@ -146,10 +156,34 @@ int main(int argc, char *argv[]) {
}
std::cout << "###############" << std::endl;
// Receiver ROI
uint16_t rxroi_xmin = 0;
uint16_t rxroi_xmax = 0;
uint16_t rxroi_ymin = 0;
uint16_t rxroi_ymax = 0;
{ //protective scope so ifstream gets destroyed properly
std::ifstream masterfile(jsonmastername); //, ios::in | ios::binary);
if (masterfile.is_open()) {
json j;
masterfile >> j;
rxroi_xmin = j["Receiver Roi"]["xmin"];
rxroi_xmax = j["Receiver Roi"]["xmax"];
rxroi_ymin = j["Receiver Roi"]["ymin"];
rxroi_ymax = j["Receiver Roi"]["ymax"];
masterfile.close();
std::cout << "Read rxROI [" << rxroi_xmin << ", " << rxroi_xmax << ", "
<< rxroi_ymin << ", " << rxroi_ymax << "]" << std::endl;
} else
std::cout << "Could not open master file " << jsonmastername << std::endl;
}
// Define decoders...
#if !defined JFSTRX && !defined JFSTRXOLD && !defined JFSTRXCHIP1 && \
!defined JFSTRXCHIP6
#if !defined JFSTRX && !defined JFSTRXQ && !defined JFSTRXOLD && !defined JFSTRXCHIP1 && \
!defined JFSTRXCHIP6 && !defined CHIP
#ifndef MODULE
jungfrauHighZSingleChipData *decoder = new jungfrauHighZSingleChipData();
int nx = 256, ny = 256;
@ -160,52 +194,60 @@ int main(int argc, char *argv[]) {
#endif
#endif
#ifdef CHIP
std::cout << "Jungfrau pixel module single chip readout" << std::endl;
jungfrauSingleChipData *decoder = new jungfrauSingleChipData();
int nx = 256, ny = 256;
#endif
#ifdef JFSTRX
cout << "Jungfrau strixel full module readout" << endl;
// ROI
uint16_t xxmin = 0;
uint16_t xxmax = 0;
uint16_t yymin = 0;
uint16_t yymax = 0;
std::cout << "Jungfrau strixel full module readout" << std::endl;
#ifndef ALDO
{ //THIS SCOPE IS IMPORTANT! (To ensure proper destruction of ifstream)
using header = sls::defs::sls_receiver_header;
// check if there is a roi in the header
typedef struct {
uint16_t xmin;
uint16_t xmax;
uint16_t ymin;
uint16_t ymax;
} receiverRoi_compact;
receiverRoi_compact croi;
//std::string filepath(argv[9]); //This is a problem if the input files have different ROIs!
std::cout << "Reading header of file " << filenames[0] << " to check for ROI "
<< std::endl;
ifstream firstfile(filenames[0], ios::in | ios::binary);
if (firstfile.is_open()) {
header hbuffer;
std::cout << "sizeof(header) = " << sizeof(header) << std::endl;
if (firstfile.read((char *)&hbuffer, sizeof(header))) {
memcpy(&croi, &hbuffer.detHeader.detSpec1, 8);
std::cout << "Read ROI [" << croi.xmin << ", " << croi.xmax << ", "
<< croi.ymin << ", " << croi.ymax << "]" << std::endl;
xxmin = croi.xmin;
xxmax = croi.xmax;
yymin = croi.ymin;
yymax = croi.ymax;
} else
std::cout << "reading error" << std::endl;
firstfile.close();
} else
std::cout << "Could not open " << filenames[0] << " for reading " << std::endl;
} //end of protective scope
if (readrxroifromdatafile)
{ //THIS SCOPE IS IMPORTANT! (To ensure proper destruction of ifstream)
using header = sls::defs::sls_receiver_header;
// check if there is a roi in the header
typedef struct {
uint16_t xmin;
uint16_t xmax;
uint16_t ymin;
uint16_t ymax;
} receiverRoi_compact;
receiverRoi_compact croi;
//std::string filepath(argv[9]); //This is a problem if the input files have different ROIs!
std::cout << "Reading header of file " << filenames[0] << " to check for ROI "
<< std::endl;
std::ifstream firstfile( filenames[0], ios::in | ios::binary);
if (firstfile.is_open()) {
header hbuffer;
std::cout << "sizeof(header) = " << sizeof(header) << std::endl;
if (firstfile.read((char *)&hbuffer, sizeof(header))) {
memcpy(&croi, &hbuffer.detHeader.detSpec1, 8);
std::cout << "Read ROI [" << croi.xmin << ", " << croi.xmax << ", "
<< croi.ymin << ", " << croi.ymax << "]" << std::endl;
rxroi_xmin = croi.xmin;
rxroi_xmax = croi.xmax;
rxroi_ymin = croi.ymin;
rxroi_ymax = croi.ymax;
} else
std::cout << "reading error" << std::endl;
firstfile.close();
} else
std::cout << "Could not open " << filenames[0] << " for reading " << std::endl;
} //end of protective scope
#endif
jungfrauLGADStrixelsData *decoder =
new jungfrauLGADStrixelsData(xxmin, xxmax, yymin, yymax);
new jungfrauLGADStrixelsData(rxroi_xmin, rxroi_xmax, rxroi_ymin, rxroi_ymax);
int nx = 1024 / 3, ny = 512 * 5;
#endif
#ifdef JFSTRXQ
std::cout << "Jungfrau strixel quad" << std::endl;
jungfrauLGADStrixelsDataQuad *decoder =
new jungfrauLGADStrixelsDataQuad(rxroi_xmin, rxroi_xmax, rxroi_ymin, rxroi_ymax);
int nx = 1024 / 3, ny = 512 * 3;
#endif
#ifdef JFSTRXCHIP1
std::cout << "Jungfrau strixel LGAD single chip 1" << std::endl;
jungfrauLGADStrixelsDataSingleChip *decoder =
@ -228,7 +270,16 @@ int main(int argc, char *argv[]) {
decoder->getDetectorSize(nx, ny);
std::cout << "Detector size is " << nx << " " << ny << std::endl;
//Cluster finder ROI
int xmin = 0, xmax = nx-1, ymin = 0, ymax = ny-1;
xmin = atoi(argv[5]);
xmax = atoi(argv[6]);
ymin = atoi(argv[7]);
ymax = atoi(argv[8]);
std::cout << "Cluster finder ROI: [" << xmin << ", " << xmax << ", " << ymin << ", " << ymax << "]"
<< std::endl;
/* old
if ( xmin == xmax ) {
xmin = 0;
xmax = nx;
@ -239,6 +290,7 @@ int main(int argc, char *argv[]) {
}
std::cout << xmin << " " << xmax << " " << ymin << " " << ymax << " "
<< std::endl;
*/
/*
char *gainfname = NULL;
@ -410,7 +462,7 @@ int main(int argc, char *argv[]) {
std::time(&end_time);
std::cout << std::ctime(&end_time) << std::endl;
ifstream filebin(filenames[ifile], ios::in | ios::binary);
std::ifstream filebin(filenames[ifile], ios::in | ios::binary);
// //open file
ioutfile = 0;
if (filebin.is_open()) {

View File

@ -0,0 +1,457 @@
// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
// #include "sls/ansi.h"
//#include <iostream>
#undef CORR
#define C_GHOST 0.0004
#define CM_ROWS 50
#define RAWDATA
#include "jungfrauLGADStrixelsDataQuadH5.h"
#include "multiThreadedCountingDetector.h"
#include "singlePhotonDetector.h"
#include <fstream>
#include <map>
#include <memory>
#include <stdio.h>
#include <sys/stat.h>
#include <ctime>
#include <fmt/core.h>
/*
#include <nlohmann/json.hpp>
using json = nlohmann::json;
*/
/*Dataset paths according to different beamlines*/
std::string const data_datasetname_furka("/data/JF18T01V01/data");
std::string const index_datasetname_furka("/data/JF18T01V01/frame_index");
std::string const data_datasetname_xfelSCS("/INSTRUMENT/SCS_HRIXS_JUNGF/DET/JNGFR01:daqOutput/data/adc");
std::string const index_datasetname_xfelSCS("/INSTRUMENT/SCS_HRIXS_JUNGF/DET/JNGFR01:daqOutput/data/frameNumber");
std::string getRootString( std::string const& filepath ) {
size_t pos1;
if (filepath.find("/") == std::string::npos )
pos1 = 0;
else
pos1 = filepath.find_last_of("/")+1;
size_t pos2 = filepath.find_last_of(".");
//std::cout << "pos1 " << pos1 << " pos2 " << pos2 << " size " << filepath.length() << std::endl;
return filepath.substr( pos1, pos2-pos1 );
}
//Create file name string
// dir: directory
// fprefix: fileprefix (without extension)
// fsuffix: filesuffix (for output files, e.g. "ped")
// fext: file extension (e.g. "raw")
std::string createFileName( std::string const& dir, std::string const& fprefix="run",
std::string const& fsuffix="", std::string const& fext="raw", int const outfilecounter=-1 ) {
std::string return_string;
if (outfilecounter >= 0)
return_string = fmt::format("{:s}/{:s}_{:s}_f{:05d}", dir, fprefix, fsuffix, outfilecounter);
else if (fsuffix.length()!=0)
return_string = fmt::format("{:s}/{:s}_{:s}", dir, fprefix, fsuffix);
else
return_string = fmt::format("{:s}/{:s}", dir, fprefix);
if (fext.length()!=0)
return_string += "." + fext;
return return_string;
}
//NOTE THAT THE DATA FILES HAVE TO BE IN THE RIGHT ORDER SO THAT PEDESTAL TRACKING WORKS!
int main(int argc, char *argv[]) {
if (argc < 4) {
std::cout
<< "Usage is " << argv[0]
<< " filestxt outdir [pedfile (h5)] "
" optional: [int dataset path; 0 means Furka, 1 means XFEL; overwrites default given in HDF5File.h] "
" [bool validate h5 rank] "
" [xmin xmax ymin ymax] [threshold] [nframes] "
" NOTE THAT THE DATA FILES HAVE TO BE IN THE RIGHT ORDER SO THAT PEDESTAL TRACKING WORKS! "
<< std::endl;
std::cout
<< "threshold <0 means analog; threshold=0 means cluster finder; "
"threshold>0 means photon counting"
<< std::endl;
std::cout
<< "nframes <0 means sum everything; nframes=0 means one file per "
"run; nframes>0 means one file every nframes"
<< std::endl;
return 1;
}
int const fifosize = 100; //1000;
int const nthreads = 10;
int const csize = 3; // 3
int const nsigma = 5;
int const nped = 10000;
int cf = 0;
std::string const txtfilename(argv[1]);
std::string const outdir(argv[2]);
std::string const pedfilename(argv[3]);
std::string datasetpath{};
std::string frameindexpath{};
if (argc > 4) {
switch (atoi(argv[4])) {
case 0:
datasetpath = data_datasetname_furka;
frameindexpath = index_datasetname_furka;
break;
case 1:
datasetpath = data_datasetname_xfelSCS;
frameindexpath = index_datasetname_xfelSCS;
break;
default:
break;
}
}
bool validate_rank=true;
if (argc > 5)
validate_rank = atoi(argv[5]);
double thr = 0;
double thr1 = 1;
if (argc > 9)
thr = atof(argv[9]);
int nframes = 0;
if (argc > 10)
nframes = atoi(argv[10]);
//Get vector of filenames from input txt-file
std::vector<std::string> filenames{};
//filenames.reserve(512);
{ //Safety scope for ifstream
ifstream inputs( txtfilename, std::ios::in );
if (inputs.is_open()) {
std::cout << "Reading imput filenames from txt-file ..." << std::endl;
std::string line{};
while (!inputs.eof()) {
std::getline(inputs, line);
if(line.find(".h5") != std::string::npos) {
filenames.emplace_back(line);
std::cout << line << std::endl; //" line.max_size() " << line.max_size() << " filenames.capacity() " << filenames.capacity() << '\n';
}
}
inputs.close();
std::cout << "---- Reached end of txt-file. ----" << std::endl;
} else
std::cout << "Could not open " << txtfilename << std::endl;
if (filenames.size()>0) {
std::cout << filenames.size() << " filenames found in " << txtfilename << std::endl;
std::cout << "The files will be processed in the same order as found in the txt-file." << std::endl;
} else {
std::cout << "No files found in txt-file!" << std::endl;
return 1;
}
}
std::cout << "###############" << std::endl;
// Define decoder
std::cout << "Jungfrau strixel quad h5" << std::endl;
jungfrauLGADStrixelsDataQuadH5* decoder = new jungfrauLGADStrixelsDataQuadH5();
//auto decoder = std::make_unique<jungfrauLGADStrixelsDataQuadH5>();
int nx = 1024 / 3, ny = 512 * 3;
//Cluster finder ROI
int xmin = 0, xmax = nx-1, ymin = 0, ymax = ny-1;
if (argc > 9) {
xmin = atoi(argv[6]);
xmax = atoi(argv[7]);
ymin = atoi(argv[8]);
ymax = atoi(argv[9]);
}
std::cout << "Cluster finder ROI: [" << xmin << ", " << xmax << ", " << ymin << ", " << ymax << "]"
<< std::endl;
decoder->getDetectorSize(nx, ny);
std::cout << "Detector size is " << nx << " " << ny << std::endl;
std::time_t end_time;
std::cout << "output directory is " << outdir << std::endl;
if (pedfilename.length()!=0)
std::cout << "pedestal file is " << pedfilename << std::endl;
if (thr > 0)
std::cout << "threshold is " << thr << std::endl;
std::cout << "Nframes is " << nframes << std::endl;
uint32_t nnx, nny;
singlePhotonDetector* filter =
new singlePhotonDetector(decoder, 3, nsigma, 1, NULL, nped, 200, -1, -1, NULL, NULL);
//auto filter = std::make_unique<singlePhotonDetector>(decoder.get(), 3, nsigma, 1, nullptr, nped, 200, -1, -1, nullptr, nullptr);
thr = 0.15 * thr;
//filter->newDataSet(); //This only initializes the dataset for the first thread (the other threads are created via cloning)
// int dsize = decoder->getDataSize();
if (thr > 0) {
std::cout << "threshold is " << thr << std::endl;
filter->setThreshold(thr);
cf = 0;
} else
cf = 1;
filter->setROI(xmin, xmax, ymin, ymax);
std::time(&end_time);
std::cout << std::ctime(&end_time) << std::endl;
char* buff;
multiThreadedCountingDetector* mt =
new multiThreadedCountingDetector(filter, nthreads, fifosize);
//auto mt = std::make_unique<multiThreadedCountingDetector>(filter.get(), nthreads, fifosize);
mt->setClusterSize(csize, csize);
mt->newDataSet(); //Initialize new dataset for each thread
#ifndef ANALOG
mt->setDetectorMode(ePhotonCounting);
std::cout << "Counting!" << std::endl;
if (thr > 0) {
cf = 0;
}
#endif
//{
#ifdef ANALOG
mt->setDetectorMode(eAnalog);
std::cout << "Analog!" << std::endl;
cf = 0;
// thr1=thr;
#endif
// }
mt->StartThreads();
mt->popFree(buff);
int ifr = 0; //frame counter of while loop
int framenumber = 0; //framenumber as read from file (detector)
std::vector<hsize_t> h5offset(1,0); //frame counter internal to HDF5File::ReadImage (provided for sanity check/debugging)
if (pedfilename.length()>1) {
std::cout << "PEDESTAL " << std::endl;
if (pedfilename.find(".tif") == std::string::npos) { //not a tiff file
std::string const fname(pedfilename);
std::cout << fname << std::endl;
std::time(&end_time);
std::cout << "aaa " << std::ctime(&end_time) << std::endl;
mt->setFrameMode(ePedestal);
//HDF5File pedefile;
auto pedefile = std::make_unique<HDF5File>();
pedefile->SetFrameIndexPath(frameindexpath);
pedefile->SetImageDataPath(datasetpath);
// //open file
if ( pedefile->OpenResources(fname.c_str(),validate_rank) ) {
std::cout << "bbbb " << std::ctime(&end_time) << std::endl;
framenumber = 0;
while ( decoder->readNextFrame(*pedefile, framenumber, h5offset, buff) ) {
if ((ifr + 1) % 100 == 0) {
std::cout
<< " ****"
<< decoder->getValue(buff, 20, 20); // << std::endl;
}
mt->pushData(buff);
mt->nextThread();
mt->popFree(buff);
++ifr;
if (ifr % 100 == 0) {
std::cout << " ****" << ifr << " " << framenumber << " " << h5offset[0]
<< std::endl;
} // else
if (ifr >= 1000)
break;
//framenumber = 0;
}
pedefile->CloseResources();
while (mt->isBusy()) {
;
}
std::cout << "Writing pedestal to " << getRootString(pedfilename) << "_ped.tiff" << std::endl;
auto imgfname = createFileName( outdir, getRootString(pedfilename), "ped", "");
mt->writePedestal(imgfname.c_str());
std::cout << "Writing pedestal rms to " << getRootString(pedfilename) << "_rms.tiff" << std::endl;
imgfname = createFileName( outdir, getRootString(pedfilename), "rms", "");
mt->writePedestalRMS(imgfname.c_str());
} else
std::cout << "Could not open pedestal file " << fname
<< " for reading " << std::endl;
} else { //is a tiff file
std::vector<double> ped(nx * ny);
float* pp = ReadFromTiff(pedfilename.c_str(), nny, nnx);
if (pp && (int)nnx == nx && (int)nny == ny) {
for (int i = 0; i < nx * ny; i++) {
ped[i] = pp[i];
}
delete[] pp;
mt->setPedestal(ped.data());
std::cout << "Pedestal set from tiff file " << pedfilename
<< std::endl;
} else {
std::cout << "Could not open pedestal tiff file " << pedfilename
<< " for reading " << std::endl;
}
}
std::time(&end_time);
std::cout << std::ctime(&end_time) << std::endl;
}
ifr = 0;
int ioutfile = 0;
mt->setFrameMode(eFrame);
FILE* of = nullptr;
//NOTE THAT THE DATA FILES HAVE TO BE IN THE RIGHT ORDER SO THAT PEDESTAL TRACKING WORKS!
for (unsigned int ifile = 0; ifile != filenames.size(); ++ifile) {
std::cout << "DATA " << filenames[ifile] << " " << std::endl;
auto imgfname( createFileName( outdir, getRootString(filenames[ifile]), "", "" ) );
std::string const cfname( createFileName( outdir, getRootString(filenames[ifile]), "", "clust" ) );
std::time(&end_time);
std::cout << std::ctime(&end_time) << std::endl;
//HDF5File fileh5;
auto fileh5 = std::make_unique<HDF5File>();
fileh5->SetFrameIndexPath(frameindexpath);
fileh5->SetImageDataPath(datasetpath);
// //open file
ioutfile = 0;
if ( fileh5->OpenResources(filenames[ifile].c_str(), validate_rank) ) {
if (thr <= 0 && cf != 0) { // cluster finder
if (of == nullptr) {
of = fopen(cfname.c_str(), "w");
if (of) {
if (mt) {
mt->setFilePointer(of);
std::cout << "file pointer set " << std::endl;
} else {
std::cerr << "Error: mt is null." << std::endl;
return 1;
}
//mt->setFilePointer(of);
//std::cout << "file pointer set " << std::endl;
//std::cout << "Here! " << framenumber << " ";
} else {
std::cout << "Could not open " << cfname
<< " for writing " << std::endl;
mt->setFilePointer(nullptr);
return 1;
}
}
}
// //while read frame
framenumber = 0;
h5offset[0] = 0;
ifr = 0;
//std::cout << "Here! " << framenumber << " ";
while ( decoder->readNextFrame(*fileh5, framenumber, h5offset, buff) ) {
//std::cout << "Here! " << framenumber << " ";
// //push
if ((ifr + 1) % 1000 == 0) {
std::cout << " ****"
<< decoder->getValue(buff, 20, 20); // << std::endl;
}
mt->pushData(buff);
// // //pop
mt->nextThread();
mt->popFree(buff); /* In the last execution of the loop,
* this leaves buff outside of the Fifo!
* Free explicitely at the end! */
++ifr;
if (ifr % 1000 == 0)
std::cout << " " << ifr << " " << framenumber << " " << h5offset[0]
<< std::endl;
if (nframes > 0) {
if (ifr % nframes == 0) {
imgfname = createFileName( outdir, getRootString(filenames[ifile]), "", "", ioutfile );
mt->writeImage(imgfname.c_str(), thr1);
mt->clearImage();
++ioutfile;
}
}
//framenumber = 0;
}
//std::cout << "aa --" << std::endl;
fileh5->CloseResources();
//std::cout << "bb --" << std::endl;
while (mt->isBusy()) {
;
}
//std::cout << "cc --" << std::endl;
if (nframes >= 0) {
if (nframes > 0)
imgfname = createFileName( outdir, getRootString(filenames[ifile]), "", "", ioutfile );
std::cout << "Writing tiff to " << imgfname << " " << thr1 << ".tiff"
<< std::endl;
mt->writeImage(imgfname.c_str(), thr1);
mt->clearImage();
if (of) {
fclose(of);
of = nullptr;
mt->setFilePointer(nullptr);
}
}
std::time(&end_time);
std::cout << std::ctime(&end_time) << std::endl;
} else
std::cout << "Could not open " << filenames[ifile] << " for reading "
<< std::endl;
}
if (nframes < 0) {
//std::string fprefix( getRootString(filenames[0]) ); //Possibly, non-ideal name choice for file
auto imgfname( createFileName( outdir, getRootString(filenames[0]), "sum", "" ) );
std::cout << "Writing tiff to " << imgfname << " " << thr1 << ".tiff" << std::endl;
mt->writeImage(imgfname.c_str(), thr1);
}
//std::cout << "Calling delete..." << std::endl;
/* Info: Previously, 'delete mt' caused crash
(double calls of StopThread() in both destructors of
multiThreadedAnalogDetector and threadedAnalogDetector)
Now fixed! */
delete mt; // triggers cleanup of all threads and singlePhotonDetector instances (delete filter is obsolete)
delete decoder;
free(buff); // Free explicitly as it gets popped out of the Fifo at termination of while(readNextFrame)
return 0;
}

View File

@ -0,0 +1,468 @@
// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
// #include "sls/ansi.h"
//#include <iostream>
#undef CORR
#define RAWDATA
#include "jungfrauLGADStrixelsDataQuadH5.h"
#include "multiThreadedCountingDetector.h"
#include "singlePhotonDetector.h"
#include <fstream>
#include <csignal>
#include <map>
#include <memory>
#include <stdio.h>
#include <sys/stat.h>
#include <ctime>
#include <fmt/core.h>
/*Dataset paths according to different beamlines*/
std::string const data_datasetname_furka("/data/JF18T01V01/data");
std::string const index_datasetname_furka("/data/JF18T01V01/frame_index");
std::string const data_datasetname_xfelSCS("/INSTRUMENT/SCS_HRIXS_JUNGF/DET/JNGFR01:daqOutput/data/adc");
std::string const index_datasetname_xfelSCS("/INSTRUMENT/SCS_HRIXS_JUNGF/DET/JNGFR01:daqOutput/data/frameNumber");
std::string getRootString( std::string const& filepath ) {
size_t pos1;
if (filepath.find("/") == std::string::npos )
pos1 = 0;
else
pos1 = filepath.find_last_of("/")+1;
size_t pos2 = filepath.find_last_of(".");
//std::cout << "pos1 " << pos1 << " pos2 " << pos2 << " size " << filepath.length() << std::endl;
return filepath.substr( pos1, pos2-pos1 );
}
/* Create file name string
* \param dir directory
* \param fprefix fileprefix (without extension)
* \param fsuffix filesuffix (for output files, e.g. "ped")
* \param fext file extension (e.g. "raw")
*/
std::string createFileName( std::string const& dir, std::string const& fprefix="run",
std::string const& fsuffix="", std::string const& fext="raw", int const outfilecounter=-1 ) {
std::string return_string;
if (outfilecounter >= 0)
return_string = fmt::format("{:s}/{:s}_{:s}_f{:05d}", dir, fprefix, fsuffix, outfilecounter);
else if (fsuffix.length()!=0)
return_string = fmt::format("{:s}/{:s}_{:s}", dir, fprefix, fsuffix);
else
return_string = fmt::format("{:s}/{:s}", dir, fprefix);
if (fext.length()!=0)
return_string += "." + fext;
return return_string;
}
/* Adjusts number of threads to be a multiple of number of storage cells
* \param requestedThreads number of threads requested by the user
* \param nSC number of storage cells
*/
int adjustThreads(int requestedThreads, int nSC) {
if (nSC <= 0) {
std::cerr << "Error: Number of S values must be greater than zero!" << std::endl;
return requestedThreads; // Return the original value as a fallback
}
// Calculate the remainder
int remainder = requestedThreads % nSC;
// If remainder is non-zero, round up by adding the difference
int adjustedThreads = (remainder == 0) ? requestedThreads : requestedThreads + (nSC - remainder);
// Ensure at least `nSC` threads are used
if (adjustedThreads < nSC) {
adjustedThreads = nSC;
}
std::cout << "Adjusted thread count (rounded up): " << adjustedThreads << " (nearest multiple of "
<< nSC << ")" << std::endl;
return adjustedThreads;
}
// Signal handler for segmentation faults
void signal_handler(int signum) {
std::cerr << "Caught signal " << signum << ": Segmentation fault (core dump)" << std::endl;
// Handle the error (e.g., clean up, abort, etc.)
exit(signum); // Exit program with the signal code
}
int main(int argc, char *argv[]) {
if (argc < 4) {
std::cout
<< "Usage is " << argv[0]
<< " filestxt outdir [pedfile (h5)] "
" optional: [int dataset path; 0 means Furka, 1 means XFEL; overwrites default given in HDF5File.h] "
" [bool validate h5 rank] "
" [xmin xmax ymin ymax] [nframes] "
" NOTE THAT THE DATA FILES HAVE TO BE IN THE RIGHT ORDER SO THAT PEDESTAL TRACKING WORKS! "
<< std::endl;
return 1;
}
// Set up the signal handler for segmentation faults
signal(SIGSEGV, signal_handler);
int const fifosize = 100; //1000;
int const nthreads = 10;
int const csize = 3; // 3
int const nsigma = 5;
int const nped = 10000;
//int cf = 0;
std::string const txtfilename(argv[1]);
std::string const outdir(argv[2]);
std::string const pedfilename(argv[3]);
std::string datasetpath{};
std::string frameindexpath{};
if (argc > 4) {
switch (atoi(argv[4])) {
case 0:
datasetpath = data_datasetname_furka;
frameindexpath = index_datasetname_furka;
break;
case 1:
datasetpath = data_datasetname_xfelSCS;
frameindexpath = index_datasetname_xfelSCS;
break;
default:
break;
}
}
bool validate_rank=true;
if (argc > 5)
validate_rank = atoi(argv[5]);
//Get vector of filenames from input txt-file
std::vector<std::string> filenames{};
{ //Safety scope for ifstream
ifstream inputs( txtfilename, std::ios::in );
if (inputs.is_open()) {
std::cout << "Reading imput filenames from txt-file ..." << std::endl;
std::string line{};
while (!inputs.eof()) {
std::getline(inputs, line);
if(line.find(".h5") != std::string::npos) {
filenames.emplace_back(line);
std::cout << line << std::endl;
}
}
inputs.close();
std::cout << "---- Reached end of txt-file. ----" << std::endl;
} else
std::cout << "Could not open " << txtfilename << std::endl;
if (filenames.size()>0) {
std::cout << filenames.size() << " filenames found in " << txtfilename << std::endl;
std::cout << "The files will be processed in the same order as found in the txt-file." << std::endl;
} else {
std::cout << "No files found in txt-file!" << std::endl;
return 1;
}
}
std::cout << "###############" << std::endl;
// Define decoder
std::cout << "Jungfrau strixel quad h5" << std::endl;
jungfrauLGADStrixelsDataQuadH5* decoder = new jungfrauLGADStrixelsDataQuadH5();
//auto decoder = std::make_unique<jungfrauLGADStrixelsDataQuadH5>();
int nx = 1024 / 3, ny = 512 * 3;
//Cluster finder ROI
int xmin = 0, xmax = nx-1, ymin = 0, ymax = ny-1;
if (argc > 9) {
xmin = atoi(argv[6]);
xmax = atoi(argv[7]);
ymin = atoi(argv[8]);
ymax = atoi(argv[9]);
}
std::cout << "Cluster finder ROI: [" << xmin << ", " << xmax << ", " << ymin << ", " << ymax << "]"
<< std::endl;
decoder->getDetectorSize(nx, ny);
std::cout << "Detector size is " << nx << " " << ny << std::endl;
std::time_t end_time;
std::cout << "Output directory is " << outdir << std::endl;
if (pedfilename.length()!=0)
std::cout << "Pedestal file is " << pedfilename << std::endl;
//uint32_t nnx, nny;
singlePhotonDetector* filter =
new singlePhotonDetector(decoder, 3, nsigma, 1, NULL, nped, 200, -1, -1, NULL, NULL);
//auto filter = std::make_unique<singlePhotonDetector>(decoder.get(), 3, nsigma, 1, nullptr, nped, 200, -1, -1, nullptr, nullptr);
filter->setROI(xmin, xmax, ymin, ymax);
std::time(&end_time);
std::cout << std::ctime(&end_time) << std::endl;
// Validate number of threads for number of storage cells (if applicable)
int nThreads = nthreads;
int nSC = 1;
// Determine the dimensions of the dataset from the first datafile
auto firstfileh5 = std::make_unique<HDF5File>();
firstfileh5->SetFrameIndexPath(frameindexpath);
firstfileh5->SetImageDataPath(datasetpath);
//std::cout << "Debug: Attempting to open file " << filenames[0].c_str() << std::endl;
if ( firstfileh5->OpenResources(filenames[0].c_str(), validate_rank) ) {
// Validate number of threads
if( firstfileh5->GetRank() == 4 ) {
auto h5dims = firstfileh5->GetDatasetDimensions();
nSC = h5dims[1];
nThreads = adjustThreads(nthreads,nSC);
}
firstfileh5->CloseResources();
} else {
std::cerr << "Error: Could not open data file " << filenames[0]
<< " for validating rank " << std::endl;
}
multiThreadedCountingDetector* mt =
new multiThreadedCountingDetector(filter, nThreads, fifosize, nSC);
//auto mt = std::make_unique<multiThreadedCountingDetector>(filter.get(), nthreads, fifosize);
mt->setClusterSize(csize, csize);
mt->newDataSet(); //Initialize new dataset for each thread
mt->setDetectorMode(ePhotonCounting);
char* buff;
mt->StartThreads();
mt->popFree(buff); // Get the first pointer to write image to
size_t ifr = 0; //frame counter of while loop
int framenumber = 0; //framenumber as read from file (detector)
std::vector<hsize_t> h5offset; //hyperslab offset internal to HDF5File::ReadImage
hsize_t h5rank;
if (pedfilename.length()>1) {
std::string froot = getRootString(pedfilename);
std::cout << "PEDESTAL " << pedfilename << std::endl;
std::time(&end_time);
std::cout << "aaa " << std::ctime(&end_time) << std::endl;
mt->setFrameMode(ePedestal);
//HDF5File pedefile;
auto pedefile = std::make_unique<HDF5File>();
pedefile->SetFrameIndexPath(frameindexpath);
pedefile->SetImageDataPath(datasetpath);
// //open file
if ( pedefile->OpenResources(pedfilename.c_str(),validate_rank) ) {
// Initialize offset vector to 0
h5rank = pedefile->GetRank();
h5offset.resize(h5rank-2, 0);
framenumber = 0;
while ( decoder->readNextFrame(*pedefile, framenumber, h5offset, buff) ) {
if ((ifr + 1) % 100 == 0) {
std::cout
<< " ****"
<< decoder->getValue(buff, 20, 20); // << std::endl;
}
int storageCell = 0;
hsize_t n_storageCells = 1;
if (h5rank == 4) {
storageCell = h5offset[1];
n_storageCells = pedefile->GetDatasetDimensions()[1];
}
// push buff into fifoData for a thread corresponding to the active storage cell
mt->pushData(buff, storageCell);
// increment (round-robin) the internal thread counter for that storage cell
mt->nextThread(storageCell);
// get a free memory address from fifoFree of the active storage cell for the next read operation
mt->popFree(buff, storageCell);
/* NOTE: the buff that was popped free from the current thread, will be (likely) pushed into
* the fifoData of a different thread in the next iteration of the loop! */
++ifr;
if (ifr % 100 == 0) {
std::cout << " ****" << ifr << " " << framenumber << " " << h5offset[0];
if (n_storageCells>1)
std::cout << " sc " << storageCell;
std::cout << "\n";
} // else
if (ifr >= 1000*n_storageCells)
break;
//framenumber = 0;
}
pedefile->CloseResources();
while (mt->isBusy()) {
;
}
std::cout << "Writing pedestal to " << getRootString(pedfilename) << "_ped_SCxx.tiff" << std::endl;
auto imgfname = createFileName( outdir, getRootString(pedfilename), "ped", "" );
mt->writePedestal(imgfname.c_str());
std::cout << "Writing pedestal rms to " << getRootString(pedfilename) << "_rms_SCxx.tiff" << std::endl;
imgfname = createFileName( outdir, getRootString(pedfilename), "rms", "");
mt->writePedestalRMS(imgfname.c_str());
} else {
std::cerr << "Error: Could not open pedestal file " << pedfilename
<< " for reading " << std::endl;
}
std::time(&end_time);
std::cout << std::ctime(&end_time) << std::endl;
}
ifr = 0;
//int ioutfile = 0;
mt->setFrameMode(eFrame);
std::vector<FILE*> of(nSC, nullptr);
for (unsigned int ifile = 0; ifile != filenames.size(); ++ifile) {
std::cout << "DATA " << filenames[ifile] << " " << std::endl;
std::time(&end_time);
std::cout << std::ctime(&end_time) << std::endl;
//HDF5File fileh5;
auto fileh5 = std::make_unique<HDF5File>();
fileh5->SetFrameIndexPath(frameindexpath);
fileh5->SetImageDataPath(datasetpath);
// Open HDF5 file
if ( fileh5->OpenResources(filenames[ifile].c_str(), validate_rank) ) {
std::vector<std::string> cfnames(nSC);
for ( int s = 0; s < nSC; ++s ) {
std::string fsuffix = "SC" + std::to_string(s);
cfnames[s] = createFileName( outdir, getRootString(filenames[ifile]), fsuffix, "clust" );
}
//Open output files and set file pointers according to storage cells
for ( size_t f = 0; f < of.size(); ++f ) {
if (!of[f]) {
of[f] = fopen(cfnames[f].c_str(), "w");
if (of[f])
{
if (mt) {
mt->setFilePointer(of[f],f); // assumes f == sc
std::cout << "File pointer set for storage cell " << f << std::endl;
} else {
std::cerr << "Error: mt is null." << std::endl;
return 1;
}
} else {
std::cerr << "Error: could not open " << cfnames[f]
<< " for writing " << std::endl;
mt->setFilePointer(nullptr,f);
return 1;
}
}
}
// Read frames
framenumber = 0;
std::fill(h5offset.begin(), h5offset.end(), 0);
ifr = 0;
while ( decoder->readNextFrame(*fileh5, framenumber, h5offset, buff) ) {
if ((ifr + 1) % 1000 == 0) {
std::cout << " ****"
<< decoder->getValue(buff, 20, 20); // << std::endl;
}
int storageCell = 0;
hsize_t n_storageCells = 1;
if (h5rank == 4) {
storageCell = h5offset[1];
n_storageCells = fileh5->GetDatasetDimensions()[1];
}
// push buff into fifoData for a thread corresponding to the active storage cell
mt->pushData(buff, storageCell);
// increment (round-robin) the internal thread counter for that storage cell
mt->nextThread(storageCell);
// get a free memory address from fifoFree of the active storage cell for the next read operation
mt->popFree(buff, storageCell); /* In the last execution of the loop,
* this leaves buff outside of the Fifo!
* Free explicitely at the end! */
++ifr;
if (ifr % 1000 == 0) {
std::cout << " " << ifr << " " << framenumber << " " << h5offset[0];
if (n_storageCells>1) std::cout << " sc " << storageCell;
std::cout << "\n";
}
//framenumber = 0;
}
//std::cout << "aa --" << std::endl;
fileh5->CloseResources();
//std::cout << "bb --" << std::endl;
while (mt->isBusy()) {
;
}
//std::cout << "cc --" << std::endl;
auto imgfname = createFileName( outdir, getRootString(filenames[ifile]), "", "" );
std::cout << "Writing tiff to " << imgfname << "_SCxx.tiff" << std::endl;
mt->writeImage(imgfname.c_str());
mt->clearImage();
// Close output files
for ( size_t f = 0; f < of.size(); ++f ) {
if (of[f]) {
fclose(of[f]);
mt->setFilePointer(nullptr,f);
of[f] = nullptr;
}
}
std::time(&end_time);
std::cout << std::ctime(&end_time) << std::endl;
} else {
std::cerr << "Error: Could not open " << filenames[ifile] << " for reading "
<< std::endl;
}
}
//std::cout << "Calling delete..." << std::endl;
/* Info: Previously, 'delete mt' caused crash
(double calls of StopThread() in both destructors of
multiThreadedAnalogDetector and threadedAnalogDetector)
Now fixed! */
delete mt; // triggers cleanup of all threads and singlePhotonDetector instances (delete filter is obsolete)
delete decoder;
free(buff); // Free explicitly as it gets popped out of the Fifo at termination of while(readNextFrame)
return 0;
}

View File

@ -336,7 +336,7 @@ int main(int argc, char *argv[]) {
string fname;
// int length;
int *detimage = NULL;
int *detimage = nullptr;
int nnx, nny, nnsx, nnsy;
// uint32_t imageSize = 0, nPixelsX = 0, nPixelsY = 0,
// uint32_t dynamicRange = 0;

View File

@ -23,7 +23,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//#include <mutex>
#include <mutex>
#include <algorithm>
#include<unordered_map>
using namespace std;
@ -47,12 +49,20 @@ class threadedAnalogDetector {
if (mm) {
// memset(mm,0, det->getDataSize());
/*
if (i == 0) { // debug
first_mm = mm;
}
*/
fifoFree->push(mm);
//std::cout << "Allocated memory at: " << static_cast<void*>(mm) << " (fifoslot " << i << ")" << std::endl;
} else
break;
}
if (i < fs)
cout << "Could allocate only " << i << " frames";
std::cout << "Could allocate only " << i << " frames";
busy = 0;
stop = 1;
@ -102,24 +112,50 @@ class threadedAnalogDetector {
};
virtual ~threadedAnalogDetector() {
// std::cout << "#### Debug: Destructing threadedAnalogDetector! ####" << std::endl;
StopThread();
delete fifoFree;
delete fifoData;
if (fifoFree) { delete fifoFree; fifoFree = nullptr; }
if (fifoData) { delete fifoData; fifoData = nullptr; }
if (det) {
delete det; // Call destructor for singlePhotonDetector
det = nullptr;
}
}
/** Returns true if the thread was successfully started, false if there was
* an error starting the thread */
virtual bool StartThread() {
stop = 0;
cout << "Detector number " << det->getId() << endl;
cout << "common mode is " << det->getCommonModeSubtraction() << endl;
cout << "ghos summation is " << det->getGhostSummation() << endl;
std::cout << "Detector number " << det->getId() << std::endl;
std::cout << "common mode is " << det->getCommonModeSubtraction() << std::endl;
std::cout << "ghos summation is " << det->getGhostSummation() << std::endl;
return (pthread_create(&_thread, NULL, processData, this) == 0);
}
virtual void StopThread() {
stop = 1;
(void)pthread_join(_thread, NULL);
//std::cout << "Attempting to stop thread..." << std::endl;
// Free all remaining allocated memory in fifoFree
char *mm = nullptr;
while (fifoFree->pop(mm, true)) { // Use no_block to avoid waiting
//std::cout << "fifo Free: Freeing memory at: " << static_cast<void*>(mm) << std::endl;
free(mm); // Free the allocated memory
}
if (_thread) {
//(void)pthread_join(_thread, NULL);
//std::cout << "Calling pthread_join for thread: " << det->getId() << std::endl;
pthread_join(_thread, NULL);
_thread = 0;
std::cout << "Thread " << det->getId() << " stopped and joined." << std::endl;
} else {
std::cout << "No thread to join." << std::endl;
}
}
virtual bool pushData(char *&ptr) { return fifoData->push(ptr); }
@ -266,6 +302,8 @@ class threadedAnalogDetector {
char *data;
int *ff;
//char* first_mm = nullptr; // For debug; to track first allocated block
static void *processData(void *ptr) {
threadedAnalogDetector *This = ((threadedAnalogDetector *)ptr);
return This->processData();
@ -278,55 +316,118 @@ class threadedAnalogDetector {
usleep(100);
if (fifoData->isEmpty()) {
busy = 0;
} else
} else {
busy = 1;
} else
}
} else {
busy = 1;
}
if (busy == 1) {
// Check stop flag before making a blocking call
//if (stop) {
// break;
//}
// Blocking call
fifoData->pop(data); // blocking!
// Process data if not stopping
//if (!stop) {
det->processData(data);
fifoFree->push(data);
//}
// busy=0;
}
}
return NULL;
}
};
class multiThreadedAnalogDetector {
public:
multiThreadedAnalogDetector(analogDetector<uint16_t> *d, int n,
int fs = 1000)
: stop(0), nThreads(n), ithread(0) {
multiThreadedAnalogDetector(analogDetector<uint16_t> *d, int num_threads,
int fs = 1000, int num_sc = 1)
: stop(0), nThreads(num_threads), nSC(num_sc) {
/*
dd[0] = d;
if (nThreads == 1)
dd[0]->setId(100);
else
dd[0]->setId(0);
for (int i = 1; i < nThreads; i++) {
dd[i] = d->Clone();
dd[i]->setId(i);
*/
// Create separate detectorObjects for each SC (each owns its mutex)
std::vector< analogDetector<uint16_t>* > sc_detectors(nSC, nullptr);
sc_detectors[0] = d; // First storage cell uses the given detector
// std::cout << "#### Debug: Copied analogDetector object for storage cell 0! ####" << std::endl;
for (int sc = 1; sc < nSC; ++sc) {
sc_detectors[sc] = d->Copy(); // Ensure unique mutex for each SC
// std::cout << "#### Debug: Copied analogDetector object for storage cell " << sc << "! ####" << std::endl;
}
// Distribute threads among storage cells
int threads_per_sc = nThreads / nSC;
int remaining_threads = nThreads % nSC; // additional safety measure if nThreads is not divisible by nSC
sc_to_threads.clear();
for (int s = 0, thread_idx = 0; s < nSC; ++s) {
// Remaining threads (if any) are assigned to the first storage cells
int current_sc_threads = threads_per_sc + (s < remaining_threads ? 1 : 0);
for (int t = 0; t < current_sc_threads; ++t, ++thread_idx) {
if (t == 0) {
dd[thread_idx] = sc_detectors[s]; // First thread gets main SC detector
} else {
dd[thread_idx] = sc_detectors[s]->Clone(); // Other threads get clones
}
std::cout << "Assigned thread " << thread_idx << " to storage cell " << s << std::endl;
dd[thread_idx]->setId(thread_idx);
// Store which threads belong to which SC
sc_to_threads[s].push_back(thread_idx);
}
}
if (nSC == 1 && nThreads == 1) {
dd[0]->setId(100);
}
// Initialize threadedAnalogDetector objects
for (int i = 0; i < nThreads; i++) {
cout << "**" << i << endl;
dets[i] = new threadedAnalogDetector(dd[i], fs);
}
image = NULL;
// Set all thread counters to zero for each storage cell
thread_counters_by_sc.resize(nSC,0);
image = nullptr;
ff = NULL;
ped = NULL;
cout << "Ithread is " << ithread << endl;
//std::cout << "Ithread is " << ithread << std::endl;
}
virtual ~multiThreadedAnalogDetector() {
StopThreads();
for (int i = 0; i < nThreads; i++)
delete dets[i];
/* for (int i=1; i<nThreads; i++) */
/* delete dd[i]; */
// delete [] image;
// std::cout << "#### Debug: Destructing multiThreadedAnalogDetector! ####" << std::endl;
//StopThreads(); // Superfluous, leads to double delete
/* Reverse loop for destruction.
* Deletes clones first, then root object, which owns the mutex
* (ensure shared mutex is deleted last).
* Optional solution: reference counting (safer but more complex) */
for (int i = nThreads - 1; i >= 0; --i) {
delete dets[i]; //StopThread() called by each ~threadedAnalogDetector()
dets[i] = nullptr;
}
}
virtual int setFrameMode(int fm) {
@ -359,36 +460,52 @@ class multiThreadedAnalogDetector {
dets[i]->newDataSet();
};
virtual int *getImage(int &nnx, int &nny, int &ns, int &nsy) {
int *img;
// Storage cell sensitive
virtual int *getImage(int &nnx, int &nny, int &ns, int &nsy, int sc = 0) {
//int *img;
// int nnx, nny, ns;
// int nnx, nny, ns;
int nn = dets[0]->getImageSize(nnx, nny, ns, nsy);
if (image) {
delete[] image;
image = NULL;
if (sc_images[sc]) {
delete[] sc_images[sc];
sc_images[sc] = nullptr;
}
image = new int[nn];
// Allocate memory for image and zero-initialize
sc_images[sc] = new int[nn]();
// int nn=dets[0]->getImageSize(nnx, nny, ns);
// for (i=0; i<nn; i++) image[i]=0;
for (int ii = 0; ii < nThreads; ii++) {
// cout << ii << " " << nn << " " << nnx << " " << nny << " " << ns
// << endl;
img = dets[ii]->getImage();
// Get the threads assigned to this storage cell
auto const& assigned_threads = sc_to_threads[sc];
// Only iterate over threads assigned to this storage cell
for (int thread_id : assigned_threads) {
int* tmp_img = dets[thread_id]->getImage();
if (!tmp_img) continue; // Skip if null
/* std::cout << "## Thread " << ii
<< " # image size " << nn
<< " # nnx " << nnx
<< " # nny " << nny
<< " # ns " << ns; */
// Sum images across threads
for (int i = 0; i < nn; i++) {
if (ii == 0)
// if (img[i]>0)
image[i] = img[i];
// else
// image[i]=0;
else // if (img[i]>0)
image[i] += img[i];
/* std::cout << " # pixel " << i
<< " # value " << tmp_img[i]
<< " ## " << std::endl; */
sc_images[sc][i] += tmp_img[i];
// if (img[i]) cout << "det " << ii << " pix " << i << " val
// " << img[i] << " " << image[i] << endl;
}
}
return image;
return sc_images[sc];
}
virtual void clearImage() {
@ -398,7 +515,7 @@ class multiThreadedAnalogDetector {
}
}
virtual void *writeImage(const char *imgname, double t = 1) {
virtual void *writeImage(char const* base_imgname, double t = 1) {
/* #ifdef SAVE_ALL */
/* for (int ii=0; ii<nThreads; ii++) { */
/* char tit[10000];cout << "m" <<endl; */
@ -407,11 +524,30 @@ class multiThreadedAnalogDetector {
/* } */
/* #endif */
int nnx, nny, ns, nsy;
getImage(nnx, nny, ns, nsy);
// int nnx, nny, ns;
int nn = dets[0]->getImageSize(nnx, nny, ns, nsy);
float *gm = new float[nn];
if (gm) {
// Allocate teporary float buffer and zero-initialize
std::vector<float> gm(nn);
// Lambda for pixel conversion
auto convert_pixel = [t](int pixel) -> float {
return (t > 0) ? static_cast<float>(std::max(0, pixel)) / static_cast<float>(t) : pixel;
}; // t ... threshold
// Loop over each storage cell
for (auto const& [sc, _] : sc_to_threads) { // structured bindings [sc, _] only available with -std=c++17
std::string imgname(base_imgname);
if (nSC > 1) imgname += "_SC" + std::to_string(sc);
imgname += ".tiff";
//Retrieve the image for this storage cell
int *image = getImage(nnx, nny, ns, nsy, sc);
if (!image) continue; // Skip if null
// Convert image data to float
std::transform(image, image + nn, gm.begin(), convert_pixel);
/* old loop implementing same logic as convert_pixel
for (int ix = 0; ix < nn; ix++) {
if (t) {
if (image[ix] < 0)
@ -424,11 +560,18 @@ class multiThreadedAnalogDetector {
// if (image[ix]>0 && ix/nnx<350) cout << ix/nnx << " " <<
// ix%nnx << " " << image[ix]<< " " << gm[ix] << endl;
}
// cout << "image " << nnx << " " << nny << endl;
WriteToTiff(gm, imgname, nnx, nny);
delete[] gm;
} else
cout << "Could not allocate float image " << endl;
*/
WriteToTiff(gm.data(), imgname.c_str(), nnx, nny);
// Clean up memory for this storage cell
if (sc_images[sc]) {
delete[] sc_images[sc];
sc_images[sc] = nullptr;
}
}
return NULL;
}
@ -439,6 +582,7 @@ class multiThreadedAnalogDetector {
}
virtual void StopThreads() {
std::cout << "Stopping all threads ..." << std::endl;
for (int i = 0; i < nThreads; i++)
dets[i]->StopThread();
}
@ -453,76 +597,133 @@ class multiThreadedAnalogDetector {
return ret;
}
virtual bool pushData(char *&ptr) { return dets[ithread]->pushData(ptr); }
/*
virtual std::vector<int> getThreadsForSc(int sc) {
return sc_to_threads[sc];
}
*/
virtual bool pushData(char *&ptr, int sc=0) {
//Additional logic implemented to accommodate storage cells
virtual bool popFree(char *&ptr) {
// cout << ithread << endl;
return dets[ithread]->popFree(ptr);
std::unique_lock<std::mutex> lock(map_mutex);
// Get assigned threads for this storage cell
auto& assigned_threads = sc_to_threads[sc];
auto& counter = thread_counters_by_sc[sc];
// Distribute workload among threads using round-robin
int selected_thread = assigned_threads[counter % assigned_threads.size()];
return dets[selected_thread]->pushData(ptr);
}
virtual int nextThread() {
ithread++;
if (ithread == nThreads)
ithread = 0;
return ithread;
virtual bool popFree(char *&ptr, int sc=0) {
//Additional logic implemented to accommodate storage cells
std::unique_lock<std::mutex> lock(map_mutex);
// Get assigned threads for this storage cell
auto& assigned_threads = sc_to_threads[sc];
auto& counter = thread_counters_by_sc[sc];
// Distribute workload among threads using round-robin
int selected_thread = assigned_threads[counter % assigned_threads.size()];
return dets[selected_thread]->popFree(ptr);
}
virtual double *getPedestal() {
virtual int nextThread(int sc=0) {
//Additional logic implemented to accommodate storage cells
auto& counter = thread_counters_by_sc[sc];
//counter++;
if (++counter == nThreads/nSC)
counter = 0;
return counter;
}
// Storage cell sensitive
virtual double *getPedestal(int sc = 0) {
int nx, ny;
dets[0]->getDetectorSize(nx, ny);
if (ped)
delete[] ped;
ped = new double[nx * ny];
if (sc_pedestals.count(sc) && sc_pedestals[sc]) {
delete[] sc_pedestals[sc];
sc_pedestals[sc] = nullptr;
}
// allocate memory and initialize all values to zero
sc_pedestals[sc] = new double[nx * ny](); // parentheses initialize elements to zero
//std::fill(sc_pedestals[sc], sc_pedestals[sc] + (nx * ny), 0.0); // explicit zero initialization
double *p0 = new double[nx * ny];
for (int i = 0; i < nThreads; i++) {
// Get the threads assigned to this storage cell
auto const& assigned_threads = sc_to_threads[sc];
int num_threads = assigned_threads.size();
// Only iterate over threads assigned to this storage cell
for ( int thread_id : assigned_threads ) {
// inte=(slsInterpolation*)dets[i]->getInterpolation(nb,emi,ema);
// cout << i << endl;
p0 = dets[i]->getPedestal(p0);
if (p0) {
if (i == 0) {
//p0 = dets[thread_id]->getPedestal(p0);
dets[thread_id]->getPedestal(p0);
if (p0) { /*
if (i == 0) {
// If first thread, initialize ped with first thread's values
for (int ib = 0; ib < nx * ny; ib++) {
ped[ib] = p0[ib] / ((double)nThreads);
// cout << p0[ib] << " ";
}
} else {
for (int ib = 0; ib < nx * ny; ib++) {
ped[ib] += p0[ib] / ((double)nThreads);
// cout << p0[ib] << " ";
}
*/
// For subsequent threads, accumulate pedestal values
// if ( i == 0 ) becomes superfluous if we zero-initialize earlier
for (int ib = 0; ib < nx * ny; ib++) {
sc_pedestals[sc][ib] += p0[ib] / ((double)num_threads);
// cout << p0[ib] << " ";
}
//}
}
}
delete[] p0;
return ped;
return sc_pedestals[sc];
};
virtual double *getPedestalRMS() {
// Storage cell sensitive
virtual double *getPedestalRMS(int sc = 0) {
int nx, ny;
dets[0]->getDetectorSize(nx, ny);
// if (ped) delete [] ped;
double *rms = new double[nx * ny];
if (sc_pedestals_rms.count(sc) && sc_pedestals_rms[sc]) {
delete[] sc_pedestals_rms[sc];
sc_pedestals_rms[sc] = nullptr;
}
// allocate memory and initialize all values to zero
sc_pedestals_rms[sc] = new double[nx * ny](); // Zero-initialize
//std::fill(sc_pedestals_rms[sc], sc_pedestals_rms[sc] + (nx * ny), 0.0); // explicit zero initialization
//double *rms = sc_pedestals_rms[sc];
double *p0 = new double[nx * ny];
for (int i = 0; i < nThreads; i++) {
// Get the threads assigned to this storage cell
auto const& assigned_threads = sc_to_threads[sc];
int num_threads = assigned_threads.size();
// Only iterate over threads assigned to this storage cell
for (int thread_id : assigned_threads) {
// inte=(slsInterpolation*)dets[i]->getInterpolation(nb,emi,ema);
// cout << i << endl;
p0 = dets[i]->getPedestalRMS(p0);
if (p0) {
if (i == 0) {
//p0 = dets[thread_id]->getPedestalRMS(p0);
dets[thread_id]->getPedestalRMS(p0);
for (int ib = 0; ib < nx * ny; ib++) {
rms[ib] = p0[ib] * p0[ib] / ((double)nThreads);
if (p0) {
for (int ib = 0; ib < nx * ny; ib++) {
sc_pedestals_rms[sc][ib] += (p0[ib] * p0[ib]) / ((double)num_threads);
// cout << p0[ib] << " ";
}
} else {
for (int ib = 0; ib < nx * ny; ib++) {
rms[ib] += p0[ib] * p0[ib] / ((double)nThreads);
// cout << p0[ib] << " ";
}
}
}
}
delete[] p0;
@ -533,64 +734,117 @@ class multiThreadedAnalogDetector {
/* rms[ib]=0; */
/* } */
return rms;
return sc_pedestals_rms[sc];
};
virtual double *setPedestal(double *h = NULL) {
/**
* Sets pedestal for given storage cell
* \param h pedestal
* \param sc storage cell
* \returns NULL
*/
virtual double *setPedestal(double *h = NULL, int sc = 0) {
// int nb=0;
int nx, ny;
dets[0]->getDetectorSize(nx, ny);
if (h == NULL)
h = ped;
for (int i = 0; i < nThreads; i++) {
for (auto i : sc_to_threads[sc]) {
dets[i]->setPedestal(h);
}
return NULL;
};
virtual void *writePedestal(const char *imgname) {
// Storage cell sensitive
virtual void *writePedestal(char const* base_imgname) {
int nx, ny;
dets[0]->getDetectorSize(nx, ny);
getPedestal();
float *gm = new float[nx * ny];
if (gm) {
//float *gm = new float[nx * ny];
// Loop over each storage cell
for ( auto const& entry : sc_to_threads ) {
int sc = entry.first;
std::string imgname = std::string(base_imgname);
if (nSC>1)
imgname += "_SC" + std::to_string(sc);
imgname += ".tiff";
getPedestal(sc); // Compute pedestal for this storage cell
std::vector<float> gm(nx * ny);
// Copy pedestal data into the float array
/*
for (int ix = 0; ix < nx * ny; ix++) {
gm[ix] = ped[ix];
gm[ix] = sc_pedestals[sc][ix];
}
WriteToTiff(gm, imgname, nx, ny);
delete[] gm;
} else
cout << "Could not allocate float image " << endl;
*/
std::copy(sc_pedestals[sc], sc_pedestals[sc] + (nx * ny), gm.data());
WriteToTiff(gm.data(), imgname.c_str(), nx, ny);
// Clean up memory
if(sc_pedestals[sc]) {
delete[] sc_pedestals[sc];
sc_pedestals[sc] = nullptr;
}
}
return NULL;
};
virtual void *writePedestalRMS(const char *imgname) {
// Storage cell sensitive
virtual void *writePedestalRMS(char const* base_imgname) {
int nx, ny;
dets[0]->getDetectorSize(nx, ny);
double *rms = getPedestalRMS();
float *gm = new float[nx * ny];
if (gm) {
//float *gm = new float[nx * ny];
// Loop over each stoarge cell
for ( auto const& entry : sc_to_threads ) {
int sc = entry.first;
std::string imgname = std::string(base_imgname);
if (nSC>1)
imgname += "_SC" + std::to_string(sc);
imgname += ".tiff";
double *rms = getPedestalRMS(sc); // Compute pedestal RMS for this storage cell
std::vector<float> gm(nx * ny);
// Copy rms data into the float array
/*
for (int ix = 0; ix < nx * ny; ix++) {
gm[ix] = rms[ix];
gm[ix] = rms[ix];
}
WriteToTiff(gm, imgname, nx, ny);
delete[] gm;
delete[] rms;
} else
cout << "Could not allocate float image " << endl;
*/
std::copy(rms, rms + (nx * ny), gm.data());
WriteToTiff(gm.data(), imgname.c_str(), nx, ny);
// Clean up memory
//delete[] rms; //This would cause double-free since the pointer is already handled by sc_pedestals_rms[sc]
if(sc_pedestals_rms[sc]) {
delete[] sc_pedestals_rms[sc];
sc_pedestals_rms[sc] = nullptr;
}
}
return NULL;
};
/**
* Reads pedestal and sets it for given storage cell
* \param imgname name of pedestal file
* \param nb obsolete
* \param emin obsolete
* \param emax obsolete
* \param sc storage cell
* \returns setPedestal(NULL, sc)
* */
virtual void *readPedestal(const char *imgname, int nb = -1,
double emin = 1, double emax = 0) {
double emin = 1, double emax = 0, int sc = 0) {
int nx, ny;
dets[0]->getDetectorSize(nx, ny);
@ -610,36 +864,68 @@ class multiThreadedAnalogDetector {
}
delete[] gm;
return setPedestal();
return setPedestal(NULL, sc);
};
/** sets file pointer where to write the clusters to
/** Sets file pointer where to write the clusters to
\param f file pointer
\returns current file pointer
\param sc storage cell index
\returns current file pointer, or nullptr if invalid
*/
virtual FILE *setFilePointer(FILE *f) {
for (int i = 0; i < nThreads; i++) {
dets[i]->setFilePointer(f);
// dets[i]->setMutex(&fmutex);
virtual FILE *setFilePointer(FILE *f, int sc = 0) {
// Check if the storage cell exists
if (sc_to_threads.find(sc) == sc_to_threads.end() || sc_to_threads[sc].empty()) {
std::cerr << "Error: Invalid storage cell index " << sc << std::endl;
return nullptr;
}
return dets[0]->getFilePointer();
// Assign file pointer to all threads belonging to this storage cell
for (auto i : sc_to_threads[sc]) {
if(dets[i]) {
dets[i]->setFilePointer(f);
// dets[i]->setMutex(&fmutex);
} else {
std::cerr << "Warning: dets[" << i << "] is null, skipping file pointer set." << std::endl;
}
}
// Return file pointer of the first thread in this storage cell
return dets[sc_to_threads[sc][0]] ? dets[sc_to_threads[sc][0]]->getFilePointer() : nullptr;
};
/** gets file pointer where to write the clusters to
\returns current file pointer
/** Gets file pointer where to write the clusters to
\param sc storage cell index
\returns current file pointer, or nullptr if invalid
*/
virtual FILE *getFilePointer() { return dets[0]->getFilePointer(); };
virtual FILE *getFilePointer(int sc = 0) {
// Ensure storage cell index is valid
if (sc_to_threads.find(sc) == sc_to_threads.end() || sc_to_threads[sc].empty()) {
std::cerr << "Error: Invalid storage cell index " << sc << std::endl;
return nullptr;
}
// Return file pointer of the first thread in this storage cell
return dets[sc_to_threads[sc][0]] ? dets[sc_to_threads[sc][0]]->getFilePointer() : nullptr;
};
protected:
bool stop;
const int nThreads;
threadedAnalogDetector *dets[MAXTHREADS];
analogDetector<uint16_t> *dd[MAXTHREADS];
int ithread;
int *image;
int *ff;
double *ped;
pthread_mutex_t fmutex;
//int ithread{0}; // Thread index
std::vector<int> thread_counters_by_sc{}; // Counters for threads for each storage cell
int* image;
int* ff;
double* ped;
//pthread_mutex_t fmutex; //unused
std::unordered_map<int,std::vector<int>> sc_to_threads; // Maps storage cell -> vector of assigned thread ids
std::mutex map_mutex; // Ensure thread-safe access to the map
int nSC{1}; // Number of storage cells
std::unordered_map<int,int*> sc_images; // Store images per storage cell
std::unordered_map<int,double*> sc_pedestals; // Store pedestal arrays per storage cell
std::unordered_map<int,double*> sc_pedestals_rms; // Store pedestal RMS arrays per storage cell
// at the moment, these maps could be avoided, but this implementation is more robust in allowing future changes
};
#endif

View File

@ -19,8 +19,8 @@ using namespace std;
class multiThreadedCountingDetector : public multiThreadedAnalogDetector {
public:
multiThreadedCountingDetector(singlePhotonDetector *d, int n, int fs = 1000)
: multiThreadedAnalogDetector(d, n, fs){};
multiThreadedCountingDetector(singlePhotonDetector *d, int num_threads, int fs = 1000, int num_sc = 1)
: multiThreadedAnalogDetector(d, num_threads, fs, num_sc){};
// virtual
// ~multiThreadedCountingDetector{multiThreadedAnalogDetector::~multiThreadedAnalogDetector();};
virtual double setNSigma(double n) {

View File

@ -70,7 +70,6 @@ class multiThreadedInterpolatingDetector
if (getInterpolation() == NULL)
return multiThreadedAnalogDetector::getImage(nnx, nny, nsx, nsy);
// if one interpolates, the whole image is stored in detector 0;
int *img;
// int nnx, nny, ns;
// int nnx, nny, ns;
int nn = dets[0]->getImageSize(nnx, nny, nsx, nsy);
@ -79,9 +78,9 @@ class multiThreadedInterpolatingDetector
image = NULL;
}
image = new int[nn];
img = dets[0]->getImage();
int* tmp_img = dets[0]->getImage();
for (int i = 0; i < nn; i++) {
image[i] = img[i];
image[i] = tmp_img[i];
}
return image;
};

View File

@ -51,7 +51,6 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
*/
singlePhotonDetector(slsDetectorData<uint16_t> *d, int csize = 3,
double nsigma = 5, int sign = 1,
commonModeSubtraction *cm = NULL, int nped = 1000,
@ -60,10 +59,11 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
: analogDetector<uint16_t>(d, sign, cm, nped, nnx, nny, gm, gs),
nDark(nd), eventMask(NULL), nSigma(nsigma), eMin(-1), eMax(-1),
clusterSize(csize), clusterSizeY(csize), c2(1), c3(1), clusters(NULL),
quad(UNDEFINED_QUADRANT), tot(0), quadTot(0) {
quad(UNDEFINED_QUADRANT), tot(0), quadTot(0), ownsMutex(true) { // The original object owns the mutex {
fm = new pthread_mutex_t;
pthread_mutex_init(fm, NULL);
//fm = new pthread_mutex_t;
//pthread_mutex_init(fm, NULL);
fm = new std::mutex();
eventMask = new eventType *[ny];
// val=new double*[ny];
@ -86,24 +86,31 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
nphFrame = 0;
};
/**
destructor. Deletes the cluster structure, the pdestalSubtraction and the
image array
Destructor. Deletes the cluster structure, event mask, and destroys the mutex.
*/
virtual ~singlePhotonDetector() {
delete[] clusters;
for (int i = 0; i < ny; i++)
delete[] eventMask[i];
delete[] eventMask;
// std::cout << "#### Debug: Destructing singlePhotonDetector! ####" << std::endl;
if (clusters) { delete[] clusters; clusters = nullptr; }
for (int i = 0; i < ny; i++) {
if (eventMask[i]) { delete[] eventMask[i]; eventMask[i] = nullptr; }
}
if (eventMask) { delete[] eventMask; eventMask = nullptr; }
if (ownsMutex) {
if (fm) {
//pthread_mutex_destroy(fm); // Destroy the mutex (not necessary with std::mutex)
delete fm; // Free the memory allocated for the mutex
fm = nullptr; // Set the pointer to nullptr to avoid dangling pointer
}
}
};
/**
copy constructor
pointer-based copy constructor (cloner)
\param orig detector to be copied
*/
singlePhotonDetector(singlePhotonDetector *orig)
: analogDetector<uint16_t>(orig) {
: analogDetector<uint16_t>(orig), fm(orig->fm), ownsMutex(false) {
nDark = orig->nDark;
myFile = orig->myFile;
@ -126,11 +133,12 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
c3 = sqrt(clusterSizeY * clusterSize);
clusters = new single_photon_hit[nx * ny];
//std::copy(orig->clusters, orig->clusters + (nx * ny), clusters); //possibly superfluous
// cluster=clusters;
setClusterSize(clusterSize);
fm = orig->fm;
//fm = orig->fm;
quad = UNDEFINED_QUADRANT;
tot = 0;
@ -143,13 +151,67 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
}
/**
duplicates the detector structure
\returns new single photon detector with same parameters
* copy constructor (deep copy), creates a new mutex
* stricly, TODO: Implement Rule of Five!
* (copy op=, move ctor, and move op= would need to be defined)
*/
virtual singlePhotonDetector *Clone() {
singlePhotonDetector(singlePhotonDetector const& other)
: analogDetector<uint16_t>(other), ownsMutex(true) {
//fm = new pthread_mutex_t; // create a new mutex
//pthread_mutex_init(fm, NULL);
fm = new std::mutex(); // New unique mutex per copy
nDark = other.nDark;
myFile = other.myFile;
eventMask = new eventType *[ny];
for (int i = 0; i < ny; i++) {
eventMask[i] = new eventType[nx];
//std::copy(other.eventMask[i], other.eventMask[i] + nx, eventMask[i]);
}
eMin = other.eMin;
eMax = other.eMax;
nSigma = other.nSigma;
clusterSize = other.clusterSize;
clusterSizeY = other.clusterSizeY;
c2 = sqrt((clusterSizeY + 1) / 2 * (clusterSize + 1) / 2);
c3 = sqrt(clusterSizeY * clusterSize);
clusters = new single_photon_hit[nx * ny];
//std::copy(other.clusters, other.clusters + (nx * ny), clusters);
setClusterSize(clusterSize);
quad = other.quad;
tot = other.tot;
quadTot = other.quadTot;
gmap = other.gmap;
nphTot = other.nphTot;
nphFrame = other.nphFrame;
}
/**
Clones the detector structure
\returns new single photon detector with same parameters
that shares the mutex of the original
*/
virtual singlePhotonDetector* Clone() {
return new singlePhotonDetector(this);
}
/**
Copies the detector structure
\returns new single photon detector with same parameters
that owns a new mutex
*/
virtual singlePhotonDetector* Copy() {
return new singlePhotonDetector(*this); // Calls the copy constructor
}
/** sets/gets number of rms threshold to detect photons
\param n number of sigma to be set (0 or negative gets)
\returns actual number of sigma parameter
@ -381,7 +443,7 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
// int ir, ic;
eventType ee;
double max = 0, tl = 0, tr = 0, bl = 0, br = 0, *v;
double max = 0, tl = 0, tr = 0, bl = 0, br = 0, v = 0;//, *v;
int cm = 0;
int good = 1;
int ir, ic;
@ -403,7 +465,8 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
cm = 1;
}
double *val = new double[ny * nx];
//double *val = new double[ny * nx];
std::vector<double> val( ny * nx );
for (int iy = ymin; iy < ymax; ++iy) {
for (int ix = xmin; ix < xmax; ++ix) {
@ -435,26 +498,34 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
(ix + ic) >= 0 && (ix + ic) < nx) {
if ((iy + ir) > iy && (ix + ic) > ix ) {
if ((iy + ir) > iy && (ix + ic) > ix ) {
val[(iy + ir) * nx + ix + ic] =
subtractPedestal(data, ix + ic, iy + ir, cm);
val[(iy + ir) * nx + ix + ic] =
subtractPedestal(data, ix + ic, iy + ir, cm);
}
v = &(val[(iy + ir) * nx + ix + ic]);
tot += *v;
if (ir <= 0 && ic <= 0)
bl += *v;
if (ir <= 0 && ic >= 0)
br += *v;
if (ir >= 0 && ic <= 0)
tl += *v;
if (ir >= 0 && ic >= 0)
tr += *v;
if (*v > max) //{
max = *v;
//}
}
//v = &(val[(iy + ir) * nx + ix + ic]);
v = val[(iy + ir) * nx + ix + ic];
//tot += *v;
tot += v;
if (ir <= 0 && ic <= 0)
bl += v;
//bl += *v;
if (ir <= 0 && ic >= 0)
br += v;
//br += *v;
if (ir >= 0 && ic <= 0)
tl += v;
//tl += *v;
if (ir >= 0 && ic >= 0)
tr += v;
//tr += *v;
//if (*v > max) //{
//max = *v;
if (v > max)
max = v;
//}
}
}
}
@ -524,19 +595,19 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
ic < (clusterSize / 2) + 1; ic++) {
if ((iy + ir) >= 0 && (iy + ir) < ny &&
(ix + ic) >= 0 && (ix + ic) < nx) {
(clusters + nph)
(clusters + nph)
->set_data(val[(iy + ir) * nx + ix + ic],
ic, ir);
if (val[(iy + ir) * nx + ix + ic]>max)
good=0;
}
if (val[(iy + ir) * nx + ix + ic]>max)
good=0;
}
}
}
if (good==0) {
(clusters + nph)->print();
cout << max << " " << val[iy * nx + ix] << endl;
}
//else (clusters + nph)->print();
if (good==0) {
(clusters + nph)->print();
cout << max << " " << val[iy * nx + ix] << endl;
}
//else (clusters + nph)->print();
if (eMin > 0 && tot < eMin)
good = 0;
if (eMax > 0 && tot > eMax)
@ -561,7 +632,7 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
// cout <<id << " **********************************"<< iframe << " " <<
// det->getFrameNumber(data) << " " << nphFrame << endl;
writeClusters(det->getFrameNumber(data));
delete[] val;
//delete[] val;
return image;
};
@ -667,13 +738,14 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
void writeClusters(int fn) {
if (myFile) {
// cout << "++" << endl;
pthread_mutex_lock(fm);
//pthread_mutex_lock(fm); // This is dangerous! What if writeClusters() throws? Then the mutex is never unlocked!
std::lock_guard<std::mutex> lock(*fm); // safer, RAII-based locking
// cout <<"**********************************"<< fn << " " <<
// nphFrame << endl;
writeClusters(myFile, clusters, nphFrame, fn);
// for (int i=0; i<nphFrame; i++)
// (clusters+i)->write(myFile);
pthread_mutex_unlock(fm);
//pthread_mutex_unlock(fm); // unsafe
// cout << "--" << endl;
}
};
@ -711,7 +783,14 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
ema = eMax;
};
void setMutex(pthread_mutex_t *m) { fm = m; };
//void setMutex(pthread_mutex_t *m) { fm = m; };
void setMutex(std::mutex* m) {
if (ownsMutex && fm) {
delete fm; // Cleanup old mutex
}
fm = m;
ownsMutex = false;
};
protected:
int nDark; /**< number of frames to be used at the beginning of the dataset
@ -733,7 +812,9 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
int nphFrame;
// double **val;
pthread_mutex_t *fm;
//pthread_mutex_t* fm; // Pointer to the shared mutex
std::mutex* fm; // Pointer to the shared (or unique) mutex (safer version)
bool ownsMutex; // Flag to indicate ownership
};
#endif

View File

@ -65,8 +65,8 @@
(0x000000FF << STATUS_PT_CNTRL_STTS_OFF_OFST)
#define STATUS_IDLE_MSK (0x677FF)
/* Register containing the git hash of the FPGA firmware */
#define FIRMWARE_GIT_HASH_REG (0x03 << MEM_MAP_SHIFT)
/* Look at me RO register TODO */
#define LOOK_AT_ME_REG (0x03 << MEM_MAP_SHIFT)
/* System Status RO register */
#define SYSTEM_STATUS_REG (0x04 << MEM_MAP_SHIFT)
@ -119,7 +119,7 @@
#define MOD_SERIAL_NUMBER_VRSN_MSK (0x0000003F << MOD_SERIAL_NUMBER_VRSN_OFST)
/* API Version RO register */
#define API_VERSION_REG (0x0B << MEM_MAP_SHIFT)
#define API_VERSION_REG (0x0F << MEM_MAP_SHIFT)
#define API_VERSION_OFST (0)
#define API_VERSION_MSK (0x00FFFFFF << API_VERSION_OFST)
@ -128,24 +128,24 @@
/* Time from Start 64 bit RO register. t = GCLK x 50 ns. Reset using
* CONTROL_CRST. TODO */
#define TIME_FROM_START_LSB_REG (0x97 << MEM_MAP_SHIFT)
#define TIME_FROM_START_MSB_REG (0x98 << MEM_MAP_SHIFT)
#define TIME_FROM_START_LSB_REG (0x10 << MEM_MAP_SHIFT)
#define TIME_FROM_START_MSB_REG (0x11 << MEM_MAP_SHIFT)
/* Delay Left 64 bit RO register. t = DLY x 50 ns. TODO */
#define DELAY_LEFT_LSB_REG (0x8D << MEM_MAP_SHIFT)
#define DELAY_LEFT_MSB_REG (0x8E << MEM_MAP_SHIFT)
#define DELAY_LEFT_LSB_REG (0x12 << MEM_MAP_SHIFT)
#define DELAY_LEFT_MSB_REG (0x13 << MEM_MAP_SHIFT)
/* Triggers Left 64 bit RO register TODO */
#define CYCLES_LEFT_LSB_REG (0x8F << MEM_MAP_SHIFT)
#define CYCLES_LEFT_MSB_REG (0x90 << MEM_MAP_SHIFT)
#define CYCLES_LEFT_LSB_REG (0x14 << MEM_MAP_SHIFT)
#define CYCLES_LEFT_MSB_REG (0x15 << MEM_MAP_SHIFT)
/* Frames Left 64 bit RO register TODO */
#define FRAMES_LEFT_LSB_REG (0x91 << MEM_MAP_SHIFT)
#define FRAMES_LEFT_MSB_REG (0x92 << MEM_MAP_SHIFT)
#define FRAMES_LEFT_LSB_REG (0x16 << MEM_MAP_SHIFT)
#define FRAMES_LEFT_MSB_REG (0x17 << MEM_MAP_SHIFT)
/* Period Left 64 bit RO register. t = T x 50 ns. TODO */
#define PERIOD_LEFT_LSB_REG (0x93 << MEM_MAP_SHIFT)
#define PERIOD_LEFT_MSB_REG (0x94 << MEM_MAP_SHIFT)
#define PERIOD_LEFT_LSB_REG (0x18 << MEM_MAP_SHIFT)
#define PERIOD_LEFT_MSB_REG (0x19 << MEM_MAP_SHIFT)
/* Exposure Time Left 64 bit RO register */
// #define EXPTIME_LEFT_LSB_REG (0x1A << MEM_MAP_SHIFT) // Not
@ -160,34 +160,34 @@
//// Not used in FW
/* Data In 64 bit RO register TODO */
#define DATA_IN_LSB_REG (0x10 << MEM_MAP_SHIFT)
#define DATA_IN_MSB_REG (0x11 << MEM_MAP_SHIFT)
#define DATA_IN_LSB_REG (0x1E << MEM_MAP_SHIFT)
#define DATA_IN_MSB_REG (0x1F << MEM_MAP_SHIFT)
/* Pattern Out 64 bit RO register */
#define PATTERN_OUT_LSB_REG (0x80 << MEM_MAP_SHIFT)
#define PATTERN_OUT_MSB_REG (0x81 << MEM_MAP_SHIFT)
#define PATTERN_OUT_LSB_REG (0x20 << MEM_MAP_SHIFT)
#define PATTERN_OUT_MSB_REG (0x21 << MEM_MAP_SHIFT)
/* Frame number of next acquisition register (64 bit register) */
#define NEXT_FRAME_NUMB_LOCAL_LSB_REG (0x12 << MEM_MAP_SHIFT)
#define NEXT_FRAME_NUMB_LOCAL_MSB_REG (0x13 << MEM_MAP_SHIFT)
#define NEXT_FRAME_NUMB_LOCAL_LSB_REG (0x22 << MEM_MAP_SHIFT)
#define NEXT_FRAME_NUMB_LOCAL_MSB_REG (0x23 << MEM_MAP_SHIFT)
/* Frames From Start PG 64 bit RO register. Reset using CONTROL_CRST. TODO */
#define FRAMES_FROM_START_PG_LSB_REG (0x99 << MEM_MAP_SHIFT)
#define FRAMES_FROM_START_PG_MSB_REG (0x9A << MEM_MAP_SHIFT)
#define FRAMES_FROM_START_PG_LSB_REG (0x24 << MEM_MAP_SHIFT)
#define FRAMES_FROM_START_PG_MSB_REG (0x25 << MEM_MAP_SHIFT)
/* Start Frame Time (Measurement Time) 64 bit register (timestamp at a frame
* start until reset) TODO */
#define START_FRAME_TIME_LSB_REG (0x9B << MEM_MAP_SHIFT)
#define START_FRAME_TIME_MSB_REG (0x9C << MEM_MAP_SHIFT)
#define START_FRAME_TIME_LSB_REG (0x26 << MEM_MAP_SHIFT)
#define START_FRAME_TIME_MSB_REG (0x27 << MEM_MAP_SHIFT)
/* Power Status RO register */
#define POWER_STATUS_REG (0x18 << MEM_MAP_SHIFT)
#define POWER_STATUS_REG (0x29 << MEM_MAP_SHIFT)
#define POWER_STATUS_ALRT_OFST (27)
#define POWER_STATUS_ALRT_MSK (0x0000001F << POWER_STATUS_ALRT_OFST)
/* FIFO Transceiver In Status RO register */
#define FIFO_TIN_STATUS_REG (0x1A << MEM_MAP_SHIFT)
#define FIFO_TIN_STATUS_REG (0x30 << MEM_MAP_SHIFT)
#define FIFO_TIN_STATUS_FIFO_EMPTY_1_OFST (4)
#define FIFO_TIN_STATUS_FIFO_EMPTY_1_MSK (0x00000001 << FIFO_TIN_STATUS_FIFO_EMPTY_1_OFST)
#define FIFO_TIN_STATUS_FIFO_EMPTY_2_OFST (5)
@ -198,54 +198,23 @@
#define FIFO_TIN_STATUS_FIFO_EMPTY_4_MSK (0x00000001 << FIFO_TIN_STATUS_FIFO_EMPTY_4_OFST)
#define FIFO_TIN_STATUS_FIFO_EMPTY_ALL_MSK (0x0000000F << FIFO_TIN_STATUS_FIFO_EMPTY_1_OFST)
/* FIFO Transceiver Fill level RO register */
#define FIFO_TIN_FILL_REG (0x25 << MEM_MAP_SHIFT)
#define FIFO_TIN_FILL_FIFO_1_OFST (0)
#define FIFO_TIN_FILL_FIFO_1_MSK (0x00003FFF << FIFO_TIN_FILL_FIFO__1_OFST)
#define FIFO_TIN_FILL_FIFO_2_OFST (16)
#define FIFO_TIN_FILL_FIFO_2_MSK (0x00003FFF << FIFO_TIN_FILL_FIFO__2_OFST)
/* FIFO ADC Fill level RO register */
#define FIFO_ADC_FILL_REG (0x26 << MEM_MAP_SHIFT)
#define FIFO_ADC_FILL_FIFO_OFST (0)
#define FIFO_ADC_FILL_FIFO_MSK (0x00003FFF << FIFO_ADC_FILL_FIFO_OFST)
/* Enable continuos readout register */
#define CONTINUOUS_RO_ENABLE_REG (0x27 << MEM_MAP_SHIFT)
#define CONTINUOUS_RO_ADC_ENABLE_OFST (0)
#define CONTINUOUS_RO_TIN_ENABLE_OFST (1)
#define CONTINUOUS_RO_DBIT_ENABLE_OFST (2)
#define CONTINUOUS_RO_ADC_ENABLE_MSK (0x00000001 << CONTINUOUS_RO_ADC_ENABLE_OFST)
#define CONTINUOUS_RO_TIN_ENABLE_MSK (0x00000001 << CONTINUOUS_RO_TIN_ENABLE_OFST)
#define CONTINUOUS_RO_DBIT_ENABLE_MSK (0x00000001 << CONTINUOUS_RO_DBIT_ENABLE_OFST)
#define DBIT_INJECT_COUNTER_ENA_OFST (3) // continuously injects fake-data into the dbit fifo when enabled.
#define DBIT_INJECT_COUNTER_ENA_MSK (0x00000001 << DBIT_INJECT_COUNTER_ENA_OFST)
#define DBIT_INJECT_COUNTER_CLKDIV_OFST (8) // Additional clock divider for fake-data injection
#define DBIT_INJECT_COUNTER_CLKDIV_MSK (0x000000FF << DBIT_INJECT_COUNTER_CLKDIV_OFST)
/* 64-bit FPGA chip ID. Unique for every device. read-only */
#define FPGA_chipID_0_REG (0x28 << MEM_MAP_SHIFT)
#define FPGA_chipID_1_REG (0x29 << MEM_MAP_SHIFT)
/* FIFO Transceiver In 64 bit RO register */
#define FIFO_TIN_LSB_REG (0x1B << MEM_MAP_SHIFT)
#define FIFO_TIN_MSB_REG (0x1C << MEM_MAP_SHIFT)
#define FIFO_TIN_LSB_REG (0x31 << MEM_MAP_SHIFT)
#define FIFO_TIN_MSB_REG (0x32 << MEM_MAP_SHIFT)
/* FIFO Digital In Status RO register */
#define FIFO_DIN_STATUS_REG (0x1D << MEM_MAP_SHIFT)
#define FIFO_DIN_STATUS_FIFO_FILL_OFST (0)
#define FIFO_DIN_STATUS_FIFO_FILL_MSK (0x00003FFF)
#define FIFO_DIN_STATUS_REG (0x3B << MEM_MAP_SHIFT)
#define FIFO_DIN_STATUS_FIFO_FULL_OFST (30)
#define FIFO_DIN_STATUS_FIFO_FULL_MSK (0x00000001 << FIFO_DIN_STATUS_FIFO_FULL_OFST)
#define FIFO_DIN_STATUS_FIFO_EMPTY_OFST (31)
#define FIFO_DIN_STATUS_FIFO_EMPTY_MSK (0x00000001 << FIFO_DIN_STATUS_FIFO_EMPTY_OFST)
/* FIFO Digital In 64 bit RO register */
#define FIFO_DIN_LSB_REG (0x1E << MEM_MAP_SHIFT)
#define FIFO_DIN_MSB_REG (0x1F << MEM_MAP_SHIFT)
#define FIFO_DIN_LSB_REG (0x3C << MEM_MAP_SHIFT)
#define FIFO_DIN_MSB_REG (0x3D << MEM_MAP_SHIFT)
/* SPI (Serial Peripheral Interface) DAC, HV RW register */
#define SPI_REG (0x20 << MEM_MAP_SHIFT)
#define SPI_REG (0x40 << MEM_MAP_SHIFT)
#define SPI_DAC_SRL_DGTL_OTPT_OFST (0)
#define SPI_DAC_SRL_DGTL_OTPT_MSK (0x00000001 << SPI_DAC_SRL_DGTL_OTPT_OFST)
@ -261,7 +230,7 @@
#define SPI_HV_SRL_CS_OTPT_MSK (0x00000001 << SPI_HV_SRL_CS_OTPT_OFST)
/* ADC SPI (Serial Peripheral Interface) RW register */
#define ADC_SPI_REG (0x21 << MEM_MAP_SHIFT)
#define ADC_SPI_REG (0x41 << MEM_MAP_SHIFT)
#define ADC_SPI_SRL_CLK_OTPT_OFST (0)
#define ADC_SPI_SRL_CLK_OTPT_MSK (0x00000001 << ADC_SPI_SRL_CLK_OTPT_OFST)
@ -271,7 +240,7 @@
#define ADC_SPI_SRL_CS_OTPT_MSK (0x0000000F << ADC_SPI_SRL_CS_OTPT_OFST)
/* ADC Offset RW register */
#define ADC_OFFSET_REG (0x22 << MEM_MAP_SHIFT)
#define ADC_OFFSET_REG (0x42 << MEM_MAP_SHIFT)
#define ADC_OFFSET_ADC_PPLN_OFST (0)
#define ADC_OFFSET_ADC_PPLN_MSK (0x000000FF << ADC_OFFSET_ADC_PPLN_OFST)
@ -279,7 +248,7 @@
#define ADC_OFFSET_DBT_PPLN_MSK (0x000000FF << ADC_OFFSET_DBT_PPLN_OFST)
/* ADC Port Invert RW register */
#define ADC_PORT_INVERT_REG (0x23 << MEM_MAP_SHIFT)
#define ADC_PORT_INVERT_REG (0x43 << MEM_MAP_SHIFT)
#define ADC_PORT_INVERT_0_INPT_OFST (0)
#define ADC_PORT_INVERT_0_INPT_MSK (0x000000FF << ADC_PORT_INVERT_0_INPT_OFST)
@ -291,7 +260,7 @@
#define ADC_PORT_INVERT_3_INPT_MSK (0x000000FF << ADC_PORT_INVERT_3_INPT_OFST)
/* Dummy RW register */
#define DUMMY_REG (0x24 << MEM_MAP_SHIFT)
#define DUMMY_REG (0x44 << MEM_MAP_SHIFT)
#define DUMMY_FIFO_CHNNL_SLCT_OFST (0)
#define DUMMY_FIFO_CHNNL_SLCT_MSK (0x0000003F << DUMMY_FIFO_CHNNL_SLCT_OFST)
@ -304,8 +273,46 @@
#define DUMMY_TRNSCVR_FIFO_RD_STRBE_OFST (14)
#define DUMMY_TRNSCVR_FIFO_RD_STRBE_MSK (0x00000001 << DUMMY_TRNSCVR_FIFO_RD_STRBE_OFST)
/* Receiver IP Address RW register */
#define RX_IP_REG (0x45 << MEM_MAP_SHIFT)
/* UDP Port RW register */
#define UDP_PORT_REG (0x46 << MEM_MAP_SHIFT)
#define UDP_PORT_RX_OFST (0)
#define UDP_PORT_RX_MSK (0x0000FFFF << UDP_PORT_RX_OFST)
#define UDP_PORT_TX_OFST (16)
#define UDP_PORT_TX_MSK (0x0000FFFF << UDP_PORT_TX_OFST)
/* Receiver Mac Address 64 bit RW register */
#define RX_MAC_LSB_REG (0x47 << MEM_MAP_SHIFT)
#define RX_MAC_MSB_REG (0x48 << MEM_MAP_SHIFT)
#define RX_MAC_LSB_OFST (0)
#define RX_MAC_LSB_MSK (0xFFFFFFFF << RX_MAC_LSB_OFST)
#define RX_MAC_MSB_OFST (0)
#define RX_MAC_MSB_MSK (0x0000FFFF << RX_MAC_MSB_OFST)
/* Detector/ Transmitter Mac Address 64 bit RW register */
#define TX_MAC_LSB_REG (0x49 << MEM_MAP_SHIFT)
#define TX_MAC_MSB_REG (0x4A << MEM_MAP_SHIFT)
#define TX_MAC_LSB_OFST (0)
#define TX_MAC_LSB_MSK (0xFFFFFFFF << TX_MAC_LSB_OFST)
#define TX_MAC_MSB_OFST (0)
#define TX_MAC_MSB_MSK (0x0000FFFF << TX_MAC_MSB_OFST)
/* Detector/ Transmitter IP Address RW register */
#define TX_IP_REG (0x4B << MEM_MAP_SHIFT)
/* Detector/ Transmitter IP Checksum RW register */
#define TX_IP_CHECKSUM_REG (0x4C << MEM_MAP_SHIFT)
#define TX_IP_CHECKSUM_OFST (0)
#define TX_IP_CHECKSUM_MSK (0x0000FFFF << TX_IP_CHECKSUM_OFST)
/* Configuration RW register */
#define CONFIG_REG (0x2D << MEM_MAP_SHIFT)
#define CONFIG_REG (0x4D << MEM_MAP_SHIFT)
#define CONFIG_LED_DSBL_OFST (0)
#define CONFIG_LED_DSBL_MSK (0x00000001 << CONFIG_LED_DSBL_OFST)
@ -320,7 +327,7 @@
#define CONFIG_GB10_SND_UDP_MSK (0x00000001 << CONFIG_GB10_SND_UDP_OFST)
/* External Signal RW register */
#define EXT_SIGNAL_REG (0x2E << MEM_MAP_SHIFT)
#define EXT_SIGNAL_REG (0x4E << MEM_MAP_SHIFT)
#define EXT_SIGNAL_OFST (0)
#define EXT_SIGNAL_MSK (0x00000001 << EXT_SIGNAL_OFST)
@ -328,7 +335,7 @@
#define EXT_SIGNAL_TRGGR_VAL ((0x1 << EXT_SIGNAL_OFST) & EXT_SIGNAL_MSK)
/* Control RW register */
#define CONTROL_REG (0x2F << MEM_MAP_SHIFT)
#define CONTROL_REG (0x4F << MEM_MAP_SHIFT)
#define CONTROL_STRT_ACQSTN_OFST (0)
#define CONTROL_STRT_ACQSTN_MSK (0x00000001 << CONTROL_STRT_ACQSTN_OFST)
@ -368,10 +375,10 @@
#define CONTROL_CLR_ACQSTN_FIFO_MSK (0x00000001 << CONTROL_CLR_ACQSTN_FIFO_OFST)
/* Reconfiguratble PLL Paramater RW register */
#define PLL_PARAM_REG (0x30 << MEM_MAP_SHIFT)
#define PLL_PARAM_REG (0x50 << MEM_MAP_SHIFT)
/* Reconfiguratble PLL Control RW regiser */
#define PLL_CNTRL_REG (0x31 << MEM_MAP_SHIFT)
#define PLL_CNTRL_REG (0x51 << MEM_MAP_SHIFT)
#define PLL_CNTRL_RCNFG_PRMTR_RST_OFST (0)
#define PLL_CNTRL_RCNFG_PRMTR_RST_MSK \
@ -384,7 +391,7 @@
#define PLL_CNTRL_ADDR_MSK (0x0000003F << PLL_CNTRL_ADDR_OFST)
/* Pattern Control RW register */
#define PATTERN_CNTRL_REG (0x88 << MEM_MAP_SHIFT)
#define PATTERN_CNTRL_REG (0x52 << MEM_MAP_SHIFT)
#define PATTERN_CNTRL_WR_OFST (0)
#define PATTERN_CNTRL_WR_MSK (0x00000001 << PATTERN_CNTRL_WR_OFST)
@ -394,7 +401,7 @@
#define PATTERN_CNTRL_ADDR_MSK (0x00001FFF << PATTERN_CNTRL_ADDR_OFST)
/* Pattern Limit RW regiser */
#define PATTERN_LIMIT_REG (0x89 << MEM_MAP_SHIFT)
#define PATTERN_LIMIT_REG (0x53 << MEM_MAP_SHIFT)
#define PATTERN_LIMIT_STRT_OFST (0)
#define PATTERN_LIMIT_STRT_MSK (0x00001FFF << PATTERN_LIMIT_STRT_OFST)
@ -402,7 +409,7 @@
#define PATTERN_LIMIT_STP_MSK (0x00001FFF << PATTERN_LIMIT_STP_OFST)
/* Pattern Loop 0 Address RW regiser */
#define PATTERN_LOOP_0_ADDR_REG (0xA0 << MEM_MAP_SHIFT)
#define PATTERN_LOOP_0_ADDR_REG (0x54 << MEM_MAP_SHIFT)
#define PATTERN_LOOP_0_ADDR_STRT_OFST (0)
#define PATTERN_LOOP_0_ADDR_STRT_MSK \
@ -411,10 +418,10 @@
#define PATTERN_LOOP_0_ADDR_STP_MSK (0x00001FFF << PATTERN_LOOP_0_ADDR_STP_OFST)
/* Pattern Loop 0 Iteration RW regiser */
#define PATTERN_LOOP_0_ITERATION_REG (0xA1 << MEM_MAP_SHIFT)
#define PATTERN_LOOP_0_ITERATION_REG (0x55 << MEM_MAP_SHIFT)
/* Pattern Loop 1 Address RW regiser */
#define PATTERN_LOOP_1_ADDR_REG (0xA5 << MEM_MAP_SHIFT)
#define PATTERN_LOOP_1_ADDR_REG (0x56 << MEM_MAP_SHIFT)
#define PATTERN_LOOP_1_ADDR_STRT_OFST (0)
#define PATTERN_LOOP_1_ADDR_STRT_MSK \
@ -423,10 +430,10 @@
#define PATTERN_LOOP_1_ADDR_STP_MSK (0x00001FFF << PATTERN_LOOP_1_ADDR_STP_OFST)
/* Pattern Loop 1 Iteration RW regiser */
#define PATTERN_LOOP_1_ITERATION_REG (0xA6 << MEM_MAP_SHIFT)
#define PATTERN_LOOP_1_ITERATION_REG (0x57 << MEM_MAP_SHIFT)
/* Pattern Loop 2 Address RW regiser */
#define PATTERN_LOOP_2_ADDR_REG (0xAA << MEM_MAP_SHIFT)
#define PATTERN_LOOP_2_ADDR_REG (0x58 << MEM_MAP_SHIFT)
#define PATTERN_LOOP_2_ADDR_STRT_OFST (0)
#define PATTERN_LOOP_2_ADDR_STRT_MSK \
@ -435,29 +442,29 @@
#define PATTERN_LOOP_2_ADDR_STP_MSK (0x00001FFF << PATTERN_LOOP_2_ADDR_STP_OFST)
/* Pattern Loop 2 Iteration RW regiser */
#define PATTERN_LOOP_2_ITERATION_REG (0xAB << MEM_MAP_SHIFT)
#define PATTERN_LOOP_2_ITERATION_REG (0x59 << MEM_MAP_SHIFT)
/* Pattern Wait 0 RW regiser */
#define PATTERN_WAIT_0_ADDR_REG (0xA2 << MEM_MAP_SHIFT)
#define PATTERN_WAIT_0_ADDR_REG (0x5A << MEM_MAP_SHIFT)
#define PATTERN_WAIT_0_ADDR_OFST (0)
#define PATTERN_WAIT_0_ADDR_MSK (0x00001FFF << PATTERN_WAIT_0_ADDR_OFST)
// FIXME: is mask 3FF
/* Pattern Wait 1 RW regiser */
#define PATTERN_WAIT_1_ADDR_REG (0xA7 << MEM_MAP_SHIFT)
#define PATTERN_WAIT_1_ADDR_REG (0x5B << MEM_MAP_SHIFT)
#define PATTERN_WAIT_1_ADDR_OFST (0)
#define PATTERN_WAIT_1_ADDR_MSK (0x00001FFF << PATTERN_WAIT_1_ADDR_OFST)
/* Pattern Wait 2 RW regiser */
#define PATTERN_WAIT_2_ADDR_REG (0xAC << MEM_MAP_SHIFT)
#define PATTERN_WAIT_2_ADDR_REG (0x5C << MEM_MAP_SHIFT)
#define PATTERN_WAIT_2_ADDR_OFST (0)
#define PATTERN_WAIT_2_ADDR_MSK (0x00001FFF << PATTERN_WAIT_2_ADDR_OFST)
/* Samples RW register */
#define SAMPLES_REG (0x32 << MEM_MAP_SHIFT)
#define SAMPLES_REG (0x5D << MEM_MAP_SHIFT)
#define SAMPLES_DIGITAL_OFST (0)
#define SAMPLES_DIGITAL_MSK (0x0000FFFF << SAMPLES_DIGITAL_OFST)
@ -465,7 +472,7 @@
#define SAMPLES_ANALOG_MSK (0x0000FFFF << SAMPLES_ANALOG_OFST)
/** Power RW register */
#define POWER_REG (0x33 << MEM_MAP_SHIFT)
#define POWER_REG (0x5E << MEM_MAP_SHIFT)
#define POWER_ENBL_VLTG_RGLTR_OFST (16)
#define POWER_ENBL_VLTG_RGLTR_MSK (0x0000001F << POWER_ENBL_VLTG_RGLTR_OFST)
@ -473,25 +480,25 @@
#define POWER_HV_INTERNAL_SLCT_MSK (0x00000001 << POWER_HV_INTERNAL_SLCT_OFST)
/* Number of samples from transceiver RW register */
#define SAMPLES_TRANSCEIVER_REG (0x34 << MEM_MAP_SHIFT)
#define SAMPLES_TRANSCEIVER_REG (0x5F << MEM_MAP_SHIFT)
#define SAMPLES_TRANSCEIVER_OFST (0)
#define SAMPLES_TRANSCEIVER_MSK (0x0000FFFF << SAMPLES_TRANSCEIVER_OFST)
/* Delay 64 bit RW register. t = DLY x 50 ns. */
#define DELAY_LSB_REG (0x8D << MEM_MAP_SHIFT)
#define DELAY_MSB_REG (0x8E << MEM_MAP_SHIFT)
#define DELAY_LSB_REG (0x60 << MEM_MAP_SHIFT)
#define DELAY_MSB_REG (0x61 << MEM_MAP_SHIFT)
/* Triggers 64 bit RW register */
#define CYCLES_LSB_REG (0x8F << MEM_MAP_SHIFT)
#define CYCLES_MSB_REG (0x90 << MEM_MAP_SHIFT)
#define CYCLES_LSB_REG (0x62 << MEM_MAP_SHIFT)
#define CYCLES_MSB_REG (0x63 << MEM_MAP_SHIFT)
/* Frames 64 bit RW register */
#define FRAMES_LSB_REG (0x91 << MEM_MAP_SHIFT)
#define FRAMES_MSB_REG (0x92 << MEM_MAP_SHIFT)
#define FRAMES_LSB_REG (0x64 << MEM_MAP_SHIFT)
#define FRAMES_MSB_REG (0x65 << MEM_MAP_SHIFT)
/* Period 64 bit RW register */
#define PERIOD_LSB_REG (0x93 << MEM_MAP_SHIFT)
#define PERIOD_MSB_REG (0x94 << MEM_MAP_SHIFT)
#define PERIOD_LSB_REG (0x66 << MEM_MAP_SHIFT)
#define PERIOD_MSB_REG (0x67 << MEM_MAP_SHIFT)
/* Period 64 bit RW register */
// #define EXPTIME_LSB_REG (0x68 << MEM_MAP_SHIFT) //
@ -506,27 +513,33 @@
/* Pattern IO Control 64 bit RW regiser
* Each bit configured as output(1)/ input(0) */
#define PATTERN_IO_CNTRL_LSB_REG (0x8A << MEM_MAP_SHIFT)
#define PATTERN_IO_CNTRL_MSB_REG (0x8B << MEM_MAP_SHIFT)
#define PATTERN_IO_CNTRL_LSB_REG (0x6C << MEM_MAP_SHIFT)
#define PATTERN_IO_CNTRL_MSB_REG (0x6D << MEM_MAP_SHIFT)
/* Pattern IO Clock Control 64 bit RW regiser
* When bit n enabled (1), clocked output for DIO[n] (T run clock)
* When bit n disabled (0), Dio[n] driven by its pattern output */
#define PATTERN_IO_CLK_CNTRL_LSB_REG (0x6E << MEM_MAP_SHIFT)
#define PATTERN_IO_CLK_CNTRL_MSB_REG (0x6F << MEM_MAP_SHIFT)
/* Pattern In 64 bit RW register */
#define PATTERN_IN_LSB_REG (0x82 << MEM_MAP_SHIFT)
#define PATTERN_IN_MSB_REG (0x83 << MEM_MAP_SHIFT)
#define PATTERN_IN_LSB_REG (0x70 << MEM_MAP_SHIFT)
#define PATTERN_IN_MSB_REG (0x71 << MEM_MAP_SHIFT)
/* Pattern Wait Timer 0 64 bit RW register. t = PWT1 x T run clock */
#define PATTERN_WAIT_TIMER_0_LSB_REG (0xA3 << MEM_MAP_SHIFT)
#define PATTERN_WAIT_TIMER_0_MSB_REG (0xA4 << MEM_MAP_SHIFT)
#define PATTERN_WAIT_TIMER_0_LSB_REG (0x72 << MEM_MAP_SHIFT)
#define PATTERN_WAIT_TIMER_0_MSB_REG (0x73 << MEM_MAP_SHIFT)
/* Pattern Wait Timer 1 64 bit RW register. t = PWT2 x T run clock */
#define PATTERN_WAIT_TIMER_1_LSB_REG (0xA8 << MEM_MAP_SHIFT)
#define PATTERN_WAIT_TIMER_1_MSB_REG (0xA9 << MEM_MAP_SHIFT)
#define PATTERN_WAIT_TIMER_1_LSB_REG (0x74 << MEM_MAP_SHIFT)
#define PATTERN_WAIT_TIMER_1_MSB_REG (0x75 << MEM_MAP_SHIFT)
/* Pattern Wait Timer 2 64 bit RW register. t = PWT3 x T run clock */
#define PATTERN_WAIT_TIMER_2_LSB_REG (0xAD << MEM_MAP_SHIFT)
#define PATTERN_WAIT_TIMER_2_MSB_REG (0xAE << MEM_MAP_SHIFT)
#define PATTERN_WAIT_TIMER_2_LSB_REG (0x76 << MEM_MAP_SHIFT)
#define PATTERN_WAIT_TIMER_2_MSB_REG (0x77 << MEM_MAP_SHIFT)
/* Readout enable RW register */
#define READOUT_10G_ENABLE_REG (0x3C << MEM_MAP_SHIFT)
#define READOUT_10G_ENABLE_REG (0x79 << MEM_MAP_SHIFT)
#define READOUT_10G_ENABLE_ANLG_OFST (0)
#define READOUT_10G_ENABLE_ANLG_MSK (0x000000FF << READOUT_10G_ENABLE_ANLG_OFST)
@ -537,7 +550,7 @@
(0x0000000F << READOUT_10G_ENABLE_TRNSCVR_OFST)
/* Digital Bit External Trigger RW register */
#define DBIT_EXT_TRG_REG (0x3E << MEM_MAP_SHIFT)
#define DBIT_EXT_TRG_REG (0x7B << MEM_MAP_SHIFT)
#define DBIT_EXT_TRG_SRC_OFST (0)
#define DBIT_EXT_TRG_SRC_MSK (0x0000003F << DBIT_EXT_TRG_SRC_OFST)
@ -545,7 +558,7 @@
#define DBIT_EXT_TRG_OPRTN_MD_MSK (0x00000001 << DBIT_EXT_TRG_OPRTN_MD_OFST)
/* Pin Delay 0 RW register */
#define OUTPUT_DELAY_0_REG (0x3F << MEM_MAP_SHIFT)
#define OUTPUT_DELAY_0_REG (0x7C << MEM_MAP_SHIFT)
#define OUTPUT_DELAY_0_OTPT_STTNG_STEPS (25)
#define OUTPUT_DELAY_0_OTPT_STTNG_OFST \
(0) // t = OTPT_STTNG * 25 ps, max for Cyclone V = 775 ps
@ -561,18 +574,18 @@
/* Pin Delay 1 RW register
* Each bit configured as enable for dynamic output delay configuration */
#define PIN_DELAY_1_REG (0x40 << MEM_MAP_SHIFT)
#define PIN_DELAY_1_REG (0x7D << MEM_MAP_SHIFT)
/** Pattern Mask 64 bit RW regiser */
#define PATTERN_MASK_LSB_REG (0x84 << MEM_MAP_SHIFT)
#define PATTERN_MASK_MSB_REG (0x85 << MEM_MAP_SHIFT)
#define PATTERN_MASK_LSB_REG (0x80 << MEM_MAP_SHIFT)
#define PATTERN_MASK_MSB_REG (0x81 << MEM_MAP_SHIFT)
/** Pattern Set 64 bit RW regiser */
#define PATTERN_SET_LSB_REG (0x86 << MEM_MAP_SHIFT)
#define PATTERN_SET_MSB_REG (0x87 << MEM_MAP_SHIFT)
#define PATTERN_SET_LSB_REG (0x82 << MEM_MAP_SHIFT)
#define PATTERN_SET_MSB_REG (0x83 << MEM_MAP_SHIFT)
/* Pattern Loop 3 Address RW regiser */
#define PATTERN_LOOP_3_ADDR_REG (0xAF << MEM_MAP_SHIFT)
#define PATTERN_LOOP_3_ADDR_REG (0x84 << MEM_MAP_SHIFT)
#define PATTERN_LOOP_3_ADDR_STRT_OFST (0)
#define PATTERN_LOOP_3_ADDR_STRT_MSK \
@ -581,10 +594,10 @@
#define PATTERN_LOOP_3_ADDR_STP_MSK (0x00001FFF << PATTERN_LOOP_3_ADDR_STP_OFST)
/* Pattern Loop 3 Iteration RW regiser */
#define PATTERN_LOOP_3_ITERATION_REG (0xB0 << MEM_MAP_SHIFT)
#define PATTERN_LOOP_3_ITERATION_REG (0x85 << MEM_MAP_SHIFT)
/* Pattern Loop 4 Address RW regiser */
#define PATTERN_LOOP_4_ADDR_REG (0xB4 << MEM_MAP_SHIFT)
#define PATTERN_LOOP_4_ADDR_REG (0x86 << MEM_MAP_SHIFT)
#define PATTERN_LOOP_4_ADDR_STRT_OFST (0)
#define PATTERN_LOOP_4_ADDR_STRT_MSK \
@ -593,10 +606,10 @@
#define PATTERN_LOOP_4_ADDR_STP_MSK (0x00001FFF << PATTERN_LOOP_4_ADDR_STP_OFST)
/* Pattern Loop 4 Iteration RW regiser */
#define PATTERN_LOOP_4_ITERATION_REG (0xB5 << MEM_MAP_SHIFT)
#define PATTERN_LOOP_4_ITERATION_REG (0x87 << MEM_MAP_SHIFT)
/* Pattern Loop 5 Address RW regiser */
#define PATTERN_LOOP_5_ADDR_REG (0xB9 << MEM_MAP_SHIFT)
#define PATTERN_LOOP_5_ADDR_REG (0x88 << MEM_MAP_SHIFT)
#define PATTERN_LOOP_5_ADDR_STRT_OFST (0)
#define PATTERN_LOOP_5_ADDR_STRT_MSK \
@ -605,43 +618,43 @@
#define PATTERN_LOOP_5_ADDR_STP_MSK (0x00001FFF << PATTERN_LOOP_5_ADDR_STP_OFST)
/* Pattern Loop 5 Iteration RW regiser */
#define PATTERN_LOOP_5_ITERATION_REG (0xBA << MEM_MAP_SHIFT)
#define PATTERN_LOOP_5_ITERATION_REG (0x89 << MEM_MAP_SHIFT)
/* Pattern Wait 3 RW regiser */
#define PATTERN_WAIT_3_ADDR_REG (0xB1 << MEM_MAP_SHIFT)
#define PATTERN_WAIT_3_ADDR_REG (0x8A << MEM_MAP_SHIFT)
#define PATTERN_WAIT_3_ADDR_OFST (0)
#define PATTERN_WAIT_3_ADDR_MSK (0x00001FFF << PATTERN_WAIT_3_ADDR_OFST)
/* Pattern Wait 4 RW regiser */
#define PATTERN_WAIT_4_ADDR_REG (0xB6 << MEM_MAP_SHIFT)
#define PATTERN_WAIT_4_ADDR_REG (0x8B << MEM_MAP_SHIFT)
#define PATTERN_WAIT_4_ADDR_OFST (0)
#define PATTERN_WAIT_4_ADDR_MSK (0x00001FFF << PATTERN_WAIT_4_ADDR_OFST)
/* Pattern Wait 5 RW regiser */
#define PATTERN_WAIT_5_ADDR_REG (0xBB << MEM_MAP_SHIFT)
#define PATTERN_WAIT_5_ADDR_REG (0x8C << MEM_MAP_SHIFT)
#define PATTERN_WAIT_5_ADDR_OFST (0)
#define PATTERN_WAIT_5_ADDR_MSK (0x00001FFF << PATTERN_WAIT_5_ADDR_OFST)
/* Pattern Wait Timer 3 64 bit RW register. t = PWT1 x T run clock */
#define PATTERN_WAIT_TIMER_3_LSB_REG (0xB2 << MEM_MAP_SHIFT)
#define PATTERN_WAIT_TIMER_3_MSB_REG (0xB3 << MEM_MAP_SHIFT)
#define PATTERN_WAIT_TIMER_3_LSB_REG (0x8D << MEM_MAP_SHIFT)
#define PATTERN_WAIT_TIMER_3_MSB_REG (0x8E << MEM_MAP_SHIFT)
/* Pattern Wait Timer 4 64 bit RW register. t = PWT1 x T run clock */
#define PATTERN_WAIT_TIMER_4_LSB_REG (0xB7 << MEM_MAP_SHIFT)
#define PATTERN_WAIT_TIMER_4_MSB_REG (0xB8 << MEM_MAP_SHIFT)
#define PATTERN_WAIT_TIMER_4_LSB_REG (0x8F << MEM_MAP_SHIFT)
#define PATTERN_WAIT_TIMER_4_MSB_REG (0x90 << MEM_MAP_SHIFT)
/* Pattern Wait Timer 5 64 bit RW register. t = PWT1 x T run clock */
#define PATTERN_WAIT_TIMER_5_LSB_REG (0xBC << MEM_MAP_SHIFT)
#define PATTERN_WAIT_TIMER_5_MSB_REG (0xBD << MEM_MAP_SHIFT)
#define PATTERN_WAIT_TIMER_5_LSB_REG (0x91 << MEM_MAP_SHIFT)
#define PATTERN_WAIT_TIMER_5_MSB_REG (0x92 << MEM_MAP_SHIFT)
/* Slow ADC SPI Value RO register */
#define ADC_SLOW_DATA_REG (0x41 << MEM_MAP_SHIFT)
#define ADC_SLOW_DATA_REG (0x93 << MEM_MAP_SHIFT)
/* Slow ADC SPI Value Config register */
#define ADC_SLOW_CFG_REG (0x42 << MEM_MAP_SHIFT)
#define ADC_SLOW_CFG_REG (0x94 << MEM_MAP_SHIFT)
/** Read back CFG Register */
#define ADC_SLOW_CFG_RB_OFST (2)
#define ADC_SLOW_CFG_RB_MSK (0x00000001 << ADC_SLOW_CFG_RB_OFST)
@ -720,7 +733,7 @@
((0x1 << ADC_SLOW_CFG_CFG_OFST) & ADC_SLOW_CFG_CFG_MSK)
/* Slow ADC SPI Value Control register */
#define ADC_SLOW_CTRL_REG (0x43 << MEM_MAP_SHIFT)
#define ADC_SLOW_CTRL_REG (0x95 << MEM_MAP_SHIFT)
#define ADC_SLOW_CTRL_STRT_OFST (0)
#define ADC_SLOW_CTRL_STRT_MSK (0x00000001 << ADC_SLOW_CTRL_STRT_OFST)

View File

@ -15,7 +15,6 @@
#include "loadPattern.h"
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> // usleep
@ -94,7 +93,6 @@ void basictests() {
LOG(logINFOBLUE, ("********* Chip Test Board Virtual Server *********\n"));
#else
LOG(logINFOBLUE, ("************* Chip Test Board Server *************\n"));
enableBlackfinAMCExternalAccessExtension();
initError = defineGPIOpins(initErrorMessage);
if (initError == FAIL) {
return;
@ -440,33 +438,6 @@ uint32_t getDetectorIP() {
return res;
}
void enableBlackfinAMCExternalAccessExtension() {
unsigned int value;
const char *file_path = "/sys/kernel/debug/blackfin/ebiu_amc/EBIU_AMBCTL1";
FILE *file = fopen(file_path, "r");
if (!file) {
LOG(logERROR, ("Failed to read EBIU_AMBCTL1\n"));
return;
}
fscanf(file, "%x", &value);
fclose(file);
// enable support for ARDY signal on interface to FPGA
// needed to properly translate avalon_mm_waitrequest in the CTB firmware
// https://www.analog.com/media/en/dsp-documentation/processor-manuals/bf537_hwr_Rev3.2.pdf
// page 274
value |= 0x3;
file = fopen(file_path, "w");
if (!file) {
LOG(logERROR, ("Failed to enable blackfin AMC access extension\n"));
return;
}
fprintf(file, "0x%x", value);
fclose(file);
}
/* initialization */
void initControlServer() {

View File

@ -135,7 +135,6 @@ void setupDetector();
#if defined(CHIPTESTBOARDD)
int updateDatabytesandAllocateRAM();
void updateDataBytes();
void enableBlackfinAMCExternalAccessExtension();
#endif
#if !defined(CHIPTESTBOARDD) && !defined(XILINX_CHIPTESTBOARDD)

View File

@ -44,6 +44,5 @@ install(TARGETS xilinx_ctbDetectorServer_virtual
configure_file(chip_config_xilinx.txt ${CMAKE_BINARY_DIR}/bin/chip_config_xilinx.txt COPYONLY)
configure_file(reset_chip_xilinx.txt ${CMAKE_BINARY_DIR}/bin/reset_chip_xilinx.txt COPYONLY)
configure_file(enable_clock_pattern.pyat ${CMAKE_BINARY_DIR}/bin/enable_clock_pattern.pyat COPYONLY)
configure_file(put_trimbits_zero.pyat ${CMAKE_BINARY_DIR}/bin/put_trimbits_zero.pyat COPYONLY)
configure_file(readout_pattern.pyat ${CMAKE_BINARY_DIR}/bin/readout_pattern.pyat COPYONLY)

View File

@ -51,7 +51,6 @@ $(PROGS): $(OBJS)
cp chip_config_xilinx.txt $(DESTDIR)
cp reset_chip_xilinx.txt $(DESTDIR)
cp enable_clock_pattern.pyat $(DESTDIR)
cp put_trimbits_zero.pyat $(DESTDIR)
cp readout_pattern.pyat $(DESTDIR)
rm $(main_src)*.o $(md5_dir)*.o
clean:

View File

@ -2,12 +2,10 @@
// Copyright (C) 2021 Contributors to the SLS Detector Package
#pragma once
#define PATTERN_RAM_BASE_ADDR (0x0000)
#define CTRL_REG (0x8000)
#define POWER_VIO_OFST (0)
#define POWER_VIO_MSK (0x00000001 << POWER_VIO_OFST)
#define POWER_VIO_OFST (0)
#define POWER_VIO_MSK (0x00000001 << POWER_VIO_OFST)
#define POWER_VCC_A_OFST (1)
#define POWER_VCC_A_MSK (0x00000001 << POWER_VCC_A_OFST)
#define POWER_VCC_B_OFST (2)
@ -19,20 +17,20 @@
#define STATUS_REG (0x8004)
#define PATTERN_RUNNING_OFST (0)
#define PATTERN_RUNNING_MSK (0x00000001 << PATTERN_RUNNING_OFST)
#define RX_BUSY_OFST (1)
#define RX_BUSY_MSK (0x00000001 << RX_BUSY_OFST)
#define PROCESSING_BUSY_OFST (2)
#define PROCESSING_BUSY_MSK (0x00000001 << PROCESSING_BUSY_OFST)
#define UDP_GEN_BUSY_OFST (3)
#define UDP_GEN_BUSY_MSK (0x00000001 << UDP_GEN_BUSY_OFST)
#define NETWORK_BUSY_OFST (4)
#define NETWORK_BUSY_MSK (0x00000001 << NETWORK_BUSY_OFST)
#define PATTERN_RUNNING_OFST (0)
#define PATTERN_RUNNING_MSK (0x00000001 << PATTERN_RUNNING_OFST)
#define RX_BUSY_OFST (1)
#define RX_BUSY_MSK (0x00000001 << RX_BUSY_OFST)
#define PROCESSING_BUSY_OFST (2)
#define PROCESSING_BUSY_MSK (0x00000001 << PROCESSING_BUSY_OFST)
#define UDP_GEN_BUSY_OFST (3)
#define UDP_GEN_BUSY_MSK (0x00000001 << UDP_GEN_BUSY_OFST)
#define NETWORK_BUSY_OFST (4)
#define NETWORK_BUSY_MSK (0x00000001 << NETWORK_BUSY_OFST)
#define WAIT_FOR_TRIGGER_OFST (5)
#define WAIT_FOR_TRIGGER_MSK (0x00000001 << WAIT_FOR_TRIGGER_OFST)
#define RX_NOT_GOOD_OFST (6)
#define RX_NOT_GOOD_MSK (0x00000001 << RX_NOT_GOOD_OFST)
#define RX_NOT_GOOD_OFST (6)
#define RX_NOT_GOOD_MSK (0x00000001 << RX_NOT_GOOD_OFST)
#define STATUS_REG2 (0x8008)
@ -40,8 +38,8 @@
#define FPGACOMPDATE_OFST (0)
#define FPGACOMPDATE_MSK (0x00ffffff << FPGACOMPDATE_OFST)
#define FPGADETTYPE_OFST (24)
#define FPGADETTYPE_MSK (0x000000ff << FPGADETTYPE_OFST)
#define FPGADETTYPE_OFST (24)
#define FPGADETTYPE_MSK (0x000000ff << FPGADETTYPE_OFST)
#define FPGA_GIT_HEAD (0x8010)
@ -52,8 +50,8 @@
#define APICOMPDATE_OFST (0)
#define APICOMPDATE_MSK (0x00ffffff << APICOMPDATE_OFST)
#define APIDETTYPE_OFST (24)
#define APIDETTYPE_MSK (0x000000ff << APIDETTYPE_OFST)
#define APIDETTYPE_OFST (24)
#define APIDETTYPE_MSK (0x000000ff << APIDETTYPE_OFST)
#define A_FIFO_OVERFLOW_STATUS_REG (0x9000)
@ -105,22 +103,23 @@
#define FIFO_TO_GB_CONTROL_REG (0xA000)
#define ENABLED_CHANNELS_ADC_OFST (0)
#define ENABLED_CHANNELS_ADC_MSK (0x000000ff << ENABLED_CHANNELS_ADC_OFST)
#define ENABLED_CHANNELS_D_OFST (8)
#define ENABLED_CHANNELS_D_MSK (0x00000001 << ENABLED_CHANNELS_D_OFST)
#define ENABLED_CHANNELS_X_OFST (9)
#define ENABLED_CHANNELS_X_MSK (0x0000000f << ENABLED_CHANNELS_X_OFST)
#define RO_MODE_ADC_OFST (13)
#define RO_MODE_ADC_MSK (0x00000001 << RO_MODE_ADC_OFST)
#define RO_MODE_D_OFST (14)
#define RO_MODE_D_MSK (0x00000001 << RO_MODE_D_OFST)
#define RO_MODE_X_OFST (15)
#define RO_MODE_X_MSK (0x00000001 << RO_MODE_X_OFST)
#define ENABLED_CHANNELS_ADC_OFST (0)
#define ENABLED_CHANNELS_ADC_MSK (0x000000ff << ENABLED_CHANNELS_ADC_OFST)
#define ENABLED_CHANNELS_D_OFST (8)
#define ENABLED_CHANNELS_D_MSK (0x00000001 << ENABLED_CHANNELS_D_OFST)
#define ENABLED_CHANNELS_X_OFST (9)
#define ENABLED_CHANNELS_X_MSK (0x0000000f << ENABLED_CHANNELS_X_OFST)
#define RO_MODE_ADC_OFST (13)
#define RO_MODE_ADC_MSK (0x00000001 << RO_MODE_ADC_OFST)
#define RO_MODE_D_OFST (14)
#define RO_MODE_D_MSK (0x00000001 << RO_MODE_D_OFST)
#define RO_MODE_X_OFST (15)
#define RO_MODE_X_MSK (0x00000001 << RO_MODE_X_OFST)
#define COUNT_FRAMES_FROM_UPDATE_OFST (16)
#define COUNT_FRAMES_FROM_UPDATE_MSK (0x00000001 << COUNT_FRAMES_FROM_UPDATE_OFST)
#define START_STREAMING_P_OFST (17)
#define START_STREAMING_P_MSK (0x00000001 << START_STREAMING_P_OFST)
#define COUNT_FRAMES_FROM_UPDATE_MSK \
(0x00000001 << COUNT_FRAMES_FROM_UPDATE_OFST)
#define START_STREAMING_P_OFST (17)
#define START_STREAMING_P_MSK (0x00000001 << START_STREAMING_P_OFST)
#define STREAM_BUFFER_CLEAR_OFST (18)
#define STREAM_BUFFER_CLEAR_MSK (0x00000001 << STREAM_BUFFER_CLEAR_OFST)
@ -149,26 +148,26 @@
#define PKTPACKETLENGTHREG (0xA020)
#define PACKETLENGTH1G_OFST (0)
#define PACKETLENGTH1G_MSK (0x0000ffff << PACKETLENGTH1G_OFST)
#define PACKETLENGTH1G_OFST (0)
#define PACKETLENGTH1G_MSK (0x0000ffff << PACKETLENGTH1G_OFST)
#define PACKETLENGTH10G_OFST (16)
#define PACKETLENGTH10G_MSK (0x0000ffff << PACKETLENGTH10G_OFST)
#define PKTNOPACKETSREG (0xA024)
#define NOPACKETS1G_OFST (0)
#define NOPACKETS1G_MSK (0x0000003f << NOPACKETS1G_OFST)
#define NOPACKETS1G_OFST (0)
#define NOPACKETS1G_MSK (0x0000003f << NOPACKETS1G_OFST)
#define NOPACKETS10G_OFST (16)
#define NOPACKETS10G_MSK (0x0000003f << NOPACKETS10G_OFST)
#define PKTCTRLREG (0xA028)
#define NOSERVERS_OFST (0)
#define NOSERVERS_MSK (0x0000003f << NOSERVERS_OFST)
#define NOSERVERS_OFST (0)
#define NOSERVERS_MSK (0x0000003f << NOSERVERS_OFST)
#define SERVERSTART_OFST (8)
#define SERVERSTART_MSK (0x0000001f << SERVERSTART_OFST)
#define ETHINTERF_OFST (16)
#define ETHINTERF_MSK (0x00000001 << ETHINTERF_OFST)
#define ETHINTERF_OFST (16)
#define ETHINTERF_MSK (0x00000001 << ETHINTERF_OFST)
#define PKTCOORDREG1 (0xA02C)
@ -182,306 +181,124 @@
#define COORDZ_OFST (0)
#define COORDZ_MSK (0x0000ffff << COORDZ_OFST)
#define PATTERN_OUT_LSB_REG (0xB000)
#define FLOW_STATUS_REG (0xB000)
#define PATTERN_OUT_MSB_REG (0xB004)
#define RSM_BUSY_OFST (0)
#define RSM_BUSY_MSK (0x00000001 << RSM_BUSY_OFST)
#define RSM_TRG_WAIT_OFST (3)
#define RSM_TRG_WAIT_MSK (0x00000001 << RSM_TRG_WAIT_OFST)
#define CSM_BUSY_OFST (17)
#define CSM_BUSY_MSK (0x00000001 << CSM_BUSY_OFST)
#define PATTERN_IN_LSB_REG (0xB008)
#define FLOW_CONTROL_REG (0xB004)
#define PATTERN_IN_MSB_REG (0xB00C)
#define START_F_OFST (0)
#define START_F_MSK (0x00000001 << START_F_OFST)
#define STOP_F_OFST (1)
#define STOP_F_MSK (0x00000001 << STOP_F_OFST)
#define RST_F_OFST (2)
#define RST_F_MSK (0x00000001 << RST_F_OFST)
#define SW_TRIGGER_F_OFST (3)
#define SW_TRIGGER_F_MSK (0x00000001 << SW_TRIGGER_F_OFST)
#define TRIGGER_ENABLE_OFST (4)
#define TRIGGER_ENABLE_MSK (0x00000001 << TRIGGER_ENABLE_OFST)
#define PATTERN_MASK_LSB_REG (0xB010)
#define TIME_FROM_START_OUT_REG_1 (0xB008)
#define PATTERN_MASK_MSB_REG (0xB014)
#define TIME_FROM_START_OUT_REG_2 (0xB00C)
#define PATTERN_SET_LSB_REG (0xB018)
#define FRAMES_FROM_START_OUT_REG_1 (0xB010)
#define PATTERN_SET_MSB_REG (0xB01C)
#define FRAMES_FROM_START_OUT_REG_2 (0xB014)
#define PATTERN_CNTRL_REG (0xB020)
#define FRAME_TIME_OUT_REG_1 (0xB018)
#define PATTERN_CNTRL_WR_OFST (0)
#define PATTERN_CNTRL_WR_MSK (0x00000001 << PATTERN_CNTRL_WR_OFST)
#define PATTERN_CNTRL_RD_OFST (1)
#define PATTERN_CNTRL_RD_MSK (0x00000001 << PATTERN_CNTRL_RD_OFST)
#define FRAME_TIME_OUT_REG_2 (0xB01C)
#define DELAY_OUT_REG_1 (0xB020)
#define DELAY_OUT_REG_2 (0xB024)
#define CYCLES_OUT_REG_1 (0xB028)
#define CYCLES_OUT_REG_2 (0xB02C)
#define FRAMES_OUT_REG_1 (0xB030)
#define FRAMES_OUT_REG_2 (0xB034)
#define PERIOD_OUT_REG_1 (0xB038)
#define PERIOD_OUT_REG_2 (0xB03C)
#define DELAY_IN_REG_1 (0xB040)
#define DELAY_IN_REG_2 (0xB044)
#define CYCLES_IN_REG_1 (0xB048)
#define CYCLES_IN_REG_2 (0xB04C)
#define FRAMES_IN_REG_1 (0xB050)
#define FRAMES_IN_REG_2 (0xB054)
#define PERIOD_IN_REG_1 (0xB058)
#define PERIOD_IN_REG_2 (0xB05C)
#define PATTERN_OUT_LSB_REG (0xB100)
#define PATTERN_OUT_MSB_REG (0xB104)
#define PATTERN_IN_LSB_REG (0xB108)
#define PATTERN_IN_MSB_REG (0xB10C)
#define PATTERN_MASK_LSB_REG (0xB110)
#define PATTERN_MASK_MSB_REG (0xB114)
#define PATTERN_SET_LSB_REG (0xB118)
#define PATTERN_SET_MSB_REG (0xB11C)
#define PATTERN_CNTRL_REG (0xB120)
#define PATTERN_CNTRL_WR_OFST (0)
#define PATTERN_CNTRL_WR_MSK (0x00000001 << PATTERN_CNTRL_WR_OFST)
#define PATTERN_CNTRL_RD_OFST (1)
#define PATTERN_CNTRL_RD_MSK (0x00000001 << PATTERN_CNTRL_RD_OFST)
#define PATTERN_CNTRL_ADDR_OFST (16)
#define PATTERN_CNTRL_ADDR_MSK (0x00001fff << PATTERN_CNTRL_ADDR_OFST)
#define PATTERN_LIMIT_REG (0xB024)
#define PATTERN_LIMIT_REG (0xB124)
#define PATTERN_LIMIT_STRT_OFST (0)
#define PATTERN_LIMIT_STRT_MSK (0x00001fff << PATTERN_LIMIT_STRT_OFST)
#define PATTERN_LIMIT_STP_OFST (16)
#define PATTERN_LIMIT_STP_MSK (0x00001fff << PATTERN_LIMIT_STP_OFST)
#define PATTERN_LIMIT_STP_OFST (16)
#define PATTERN_LIMIT_STP_MSK (0x00001fff << PATTERN_LIMIT_STP_OFST)
#define PATTERN_IO_CNTRL_LSB_REG (0xB028)
#define PATTERN_LOOP_0_ADDR_REG (0xB128)
#define PATTERN_IO_CNTRL_MSB_REG (0xB02C)
#define FLOW_CONTROL_REG (0xB030)
#define START_F_OFST (0)
#define START_F_MSK (0x00000001 << START_F_OFST)
#define STOP_F_OFST (1)
#define STOP_F_MSK (0x00000001 << STOP_F_OFST)
#define RST_F_OFST (2)
#define RST_F_MSK (0x00000001 << RST_F_OFST)
#define SW_TRIGGER_F_OFST (3)
#define SW_TRIGGER_F_MSK (0x00000001 << SW_TRIGGER_F_OFST)
#define TRIGGER_ENABLE_OFST (4)
#define TRIGGER_ENABLE_MSK (0x00000001 << TRIGGER_ENABLE_OFST)
#define RSM_BUSY_OFST (5)
#define RSM_BUSY_MSK (0x00000001 << RSM_BUSY_OFST)
#define RSM_TRG_WAIT_OFST (6)
#define RSM_TRG_WAIT_MSK (0x00000001 << RSM_TRG_WAIT_OFST)
#define CSM_BUSY_OFST (7)
#define CSM_BUSY_MSK (0x00000001 << CSM_BUSY_OFST)
#define DELAY_IN_REG_1 (0xB034)
#define DELAY_IN_REG_2 (0xB038)
#define CYCLES_IN_REG_1 (0xB03C)
#define CYCLES_IN_REG_2 (0xB040)
#define FRAMES_IN_REG_1 (0xB044)
#define FRAMES_IN_REG_2 (0xB048)
#define PERIOD_IN_REG_1 (0xB04C)
#define PERIOD_IN_REG_2 (0xB050)
#define DELAY_OUT_REG_1 (0xB054)
#define DELAY_OUT_REG_2 (0xB058)
#define CYCLES_OUT_REG_1 (0xB05C)
#define CYCLES_OUT_REG_2 (0xB060)
#define FRAMES_OUT_REG_1 (0xB064)
#define FRAMES_OUT_REG_2 (0xB068)
#define PERIOD_OUT_REG_1 (0xB06C)
#define PERIOD_OUT_REG_2 (0xB070)
#define PATTERN_TEST_REG (0xB074)
#define PATTERN_FIRMWARE_REG (0xB078)
#define PATTERN_WIDTH_OFST (0)
#define PATTERN_WIDTH_MSK (0x000000ff << PATTERN_WIDTH_OFST)
#define PATTERN_ADDR_WIDTH_OFST (8)
#define PATTERN_ADDR_WIDTH_MSK (0x000000ff << PATTERN_ADDR_WIDTH_OFST)
#define PATTERN_NLOOPS_NWAITS_OFST (16)
#define PATTERN_NLOOPS_NWAITS_MSK (0x000000ff << PATTERN_NLOOPS_NWAITS_OFST)
#define DIRECT_PATTERN_RAM_OFST (24)
#define DIRECT_PATTERN_RAM_MSK (0x00000001 << DIRECT_PATTERN_RAM_OFST)
#define TIME_FROM_START_OUT_REG_1 (0xB07C)
#define TIME_FROM_START_OUT_REG_2 (0xB080)
#define FRAMES_FROM_START_OUT_REG_1 (0xB084)
#define FRAMES_FROM_START_OUT_REG_2 (0xB088)
#define FRAME_TIME_OUT_REG_1 (0xB08C)
#define FRAME_TIME_OUT_REG_2 (0xB090)
#define PATTERN_LOOPDEF_START_REG (0xB080)
#define PATTERN_LOOPDEF_LOOP_ADDR_OFST (0)
#define PATTERN_LOOPDEF_LOOP_ADDR_MSK (0x00000001 << PATTERN_LOOPDEF_LOOP_ADDR_OFST)
#define PATTERN_LOOPDEF_LOOP_ITERATION_OFST (1)
#define PATTERN_LOOPDEF_LOOP_ITERATION_MSK (0x00000001 << PATTERN_LOOPDEF_LOOP_ITERATION_OFST)
#define PATTERN_LOOPDEF_WAIT_ADDR_OFST (2)
#define PATTERN_LOOPDEF_WAIT_ADDR_MSK (0x00000001 << PATTERN_LOOPDEF_WAIT_ADDR_OFST)
#define PATTERN_LOOPDEF_WAIT_TIME_LSB_OFST (3)
#define PATTERN_LOOPDEF_WAIT_TIME_LSB_MSK (0x00000001 << PATTERN_LOOPDEF_WAIT_TIME_LSB_OFST)
#define PATTERN_LOOPDEF_WAIT_TIME_MSB_OFST (4)
#define PATTERN_LOOPDEF_WAIT_TIME_MSB_MSK (0x00000001 << PATTERN_LOOPDEF_WAIT_TIME_MSB_OFST)
#define DBITFIFOCTRLREG (0xC000)
#define DBITRD_OFST (0)
#define DBITRD_MSK (0x00000001 << DBITRD_OFST)
#define DBITRST_OFST (1)
#define DBITRST_MSK (0x00000001 << DBITRST_OFST)
#define DBITFULL_OFST (2)
#define DBITFULL_MSK (0x00000001 << DBITFULL_OFST)
#define DBITEMPTY_OFST (3)
#define DBITEMPTY_MSK (0x00000001 << DBITEMPTY_OFST)
#define DBITUNDERFLOW_OFST (4)
#define DBITUNDERFLOW_MSK (0x00000001 << DBITUNDERFLOW_OFST)
#define DBITOVERFLOW_OFST (5)
#define DBITOVERFLOW_MSK (0x00000001 << DBITOVERFLOW_OFST)
#define DBITFIFODATAREG1 (0xC004)
#define DBITFIFODATAREG2 (0xC008)
#define MATTERHORNSPIREG1 (0xC00C)
#define MATTERHORNSPIREG2 (0xC010)
#define MATTERHORNSPICTRL (0xC014)
#define CONFIGSTART_P_OFST (0)
#define CONFIGSTART_P_MSK (0x00000001 << CONFIGSTART_P_OFST)
#define PERIPHERYRST_P_OFST (1)
#define PERIPHERYRST_P_MSK (0x00000001 << PERIPHERYRST_P_OFST)
#define STARTREAD_P_OFST (2)
#define STARTREAD_P_MSK (0x00000001 << STARTREAD_P_OFST)
#define BUSY_OFST (3)
#define BUSY_MSK (0x00000001 << BUSY_OFST)
#define READOUTFROMASIC_OFST (4)
#define READOUTFROMASIC_MSK (0x00000001 << READOUTFROMASIC_OFST)
#define TRANSCEIVERRXCTRL0REG1 (0xC100)
#define TRANSCEIVERRXCTRL0REG2 (0xC104)
#define TRANSCEIVERRXCTRL1REG1 (0xC108)
#define TRANSCEIVERRXCTRL1REG2 (0xC10C)
#define TRANSCEIVERRXCTRL2REG (0xC110)
#define TRANSCEIVERRXCTRL3REG (0xC114)
#define TRANSCEIVERSTATUS (0xC118)
#define LINKDOWNLATCHEDOUT_OFST (0)
#define LINKDOWNLATCHEDOUT_MSK (0x00000001 << LINKDOWNLATCHEDOUT_OFST)
#define TXUSERCLKACTIVE_OFST (1)
#define TXUSERCLKACTIVE_MSK (0x00000001 << TXUSERCLKACTIVE_OFST)
#define RXUSERCLKACTIVE_OFST (2)
#define RXUSERCLKACTIVE_MSK (0x00000001 << RXUSERCLKACTIVE_OFST)
#define RXCOMMADET_OFST (3)
#define RXCOMMADET_MSK (0x0000000f << RXCOMMADET_OFST)
#define RXBYTEREALIGN_OFST (7)
#define RXBYTEREALIGN_MSK (0x0000000f << RXBYTEREALIGN_OFST)
#define RXBYTEISALIGNED_OFST (11)
#define RXBYTEISALIGNED_MSK (0x0000000f << RXBYTEISALIGNED_OFST)
#define GTWIZRXCDRSTABLE_OFST (15)
#define GTWIZRXCDRSTABLE_MSK (0x00000001 << GTWIZRXCDRSTABLE_OFST)
#define RESETTXDONE_OFST (16)
#define RESETTXDONE_MSK (0x00000001 << RESETTXDONE_OFST)
#define RESETRXDONE_OFST (17)
#define RESETRXDONE_MSK (0x00000001 << RESETRXDONE_OFST)
#define RXPMARESETDONE_OFST (18)
#define RXPMARESETDONE_MSK (0x0000000f << RXPMARESETDONE_OFST)
#define TXPMARESETDONE_OFST (22)
#define TXPMARESETDONE_MSK (0x0000000f << TXPMARESETDONE_OFST)
#define GTTPOWERGOOD_OFST (26)
#define GTTPOWERGOOD_MSK (0x0000000f << GTTPOWERGOOD_OFST)
#define TRANSCEIVERSTATUS2 (0xC11C)
#define RXLOCKED_OFST (0)
#define RXLOCKED_MSK (0x0000000f << RXLOCKED_OFST)
#define TRANSCEIVERCONTROL (0xC120)
#define GTWIZRESETALL_OFST (0)
#define GTWIZRESETALL_MSK (0x00000001 << GTWIZRESETALL_OFST)
#define RESETTXPLLANDDATAPATH_OFST (1)
#define RESETTXPLLANDDATAPATH_MSK (0x00000001 << RESETTXPLLANDDATAPATH_OFST)
#define RESETTXDATAPATHIN_OFST (2)
#define RESETTXDATAPATHIN_MSK (0x00000001 << RESETTXDATAPATHIN_OFST)
#define RESETRXPLLANDDATAPATH_OFST (3)
#define RESETRXPLLANDDATAPATH_MSK (0x00000001 << RESETRXPLLANDDATAPATH_OFST)
#define RESETRXDATAPATHIN_OFST (4)
#define RESETRXDATAPATHIN_MSK (0x00000001 << RESETRXDATAPATHIN_OFST)
#define RXPOLARITY_OFST (5)
#define RXPOLARITY_MSK (0x0000000f << RXPOLARITY_OFST)
#define RXERRORCNTRESET_OFST (9)
#define RXERRORCNTRESET_MSK (0x0000000f << RXERRORCNTRESET_OFST)
#define RXMSBLSBINVERT_OFST (13)
#define RXMSBLSBINVERT_MSK (0x0000000f << RXMSBLSBINVERT_OFST)
#define TRANSCEIVERERRCNT_REG0 (0xC124)
#define TRANSCEIVERERRCNT_REG1 (0xC128)
#define TRANSCEIVERERRCNT_REG2 (0xC12C)
#define TRANSCEIVERERRCNT_REG3 (0xC130)
#define TRANSCEIVERALIGNCNT_REG0 (0xC134)
#define RXALIGNCNTCH0_OFST (0)
#define RXALIGNCNTCH0_MSK (0x0000ffff << RXALIGNCNTCH0_OFST)
#define TRANSCEIVERALIGNCNT_REG1 (0xC138)
#define RXALIGNCNTCH1_OFST (0)
#define RXALIGNCNTCH1_MSK (0x0000ffff << RXALIGNCNTCH1_OFST)
#define TRANSCEIVERALIGNCNT_REG2 (0xC13C)
#define RXALIGNCNTCH2_OFST (0)
#define RXALIGNCNTCH2_MSK (0x0000ffff << RXALIGNCNTCH2_OFST)
#define TRANSCEIVERALIGNCNT_REG3 (0xC140)
#define RXALIGNCNTCH3_OFST (0)
#define RXALIGNCNTCH3_MSK (0x0000ffff << RXALIGNCNTCH3_OFST)
#define TRANSCEIVERLASTWORD_REG0 (0xC144)
#define RXDATACH0_OFST (0)
#define RXDATACH0_MSK (0x0000ffff << RXDATACH0_OFST)
#define TRANSCEIVERLASTWORD_REG1 (0xC148)
#define RXDATACH1_OFST (0)
#define RXDATACH1_MSK (0x0000ffff << RXDATACH1_OFST)
#define TRANSCEIVERLASTWORD_REG2 (0xC14C)
#define RXDATACH2_OFST (0)
#define RXDATACH2_MSK (0x0000ffff << RXDATACH2_OFST)
#define TRANSCEIVERLASTWORD_REG3 (0xC150)
#define RXDATACH3_OFST (0)
#define RXDATACH3_MSK (0x0000ffff << RXDATACH3_OFST)
// ----------------------------------------------------
// TODO: remove these:
//-----------------------------------
#define PINIOCTRLREG (0xB028)
#define PATTERN_LOOP_0_ADDR_REG (0xB080)
#define PATTERN_LOOP_0_ADDR_STRT_OFST (0)
#define PATTERN_LOOP_0_ADDR_STRT_MSK \
(0x00001fff << PATTERN_LOOP_0_ADDR_STRT_OFST)
#define PATTERN_LOOP_0_ADDR_STP_OFST (16)
#define PATTERN_LOOP_0_ADDR_STP_MSK (0x00001fff << PATTERN_LOOP_0_ADDR_STP_OFST)
#define PATTERN_LOOP_0_ITERATION_REG (0xB084)
#define PATTERN_WAIT_0_ADDR_REG (0xB088)
#define PATTERN_LOOP_0_ITERATION_REG (0xB12C)
#define PATTERN_WAIT_0_ADDR_REG (0xB130)
#define PATTERN_WAIT_0_ADDR_OFST (0)
#define PATTERN_WAIT_0_ADDR_MSK (0x00001fff << PATTERN_WAIT_0_ADDR_OFST)
#define PATTERN_WAIT_TIMER_0_LSB_REG (0xB08C)
#define PATTERN_WAIT_TIMER_0_LSB_REG (0xB134)
#define PATTERN_WAIT_TIMER_0_MSB_REG (0xB090)
#define PATTERN_WAIT_TIMER_0_MSB_REG (0xB138)
#define PATTERN_LOOP_1_ADDR_REG (0xB094)
#define PATTERN_LOOP_1_ADDR_REG (0xB13C)
#define PATTERN_LOOP_1_ADDR_STRT_OFST (0)
#define PATTERN_LOOP_1_ADDR_STRT_MSK \
@ -489,18 +306,18 @@
#define PATTERN_LOOP_1_ADDR_STP_OFST (16)
#define PATTERN_LOOP_1_ADDR_STP_MSK (0x00001fff << PATTERN_LOOP_1_ADDR_STP_OFST)
#define PATTERN_LOOP_1_ITERATION_REG (0xB098)
#define PATTERN_LOOP_1_ITERATION_REG (0xB140)
#define PATTERN_WAIT_1_ADDR_REG (0xB09C)
#define PATTERN_WAIT_1_ADDR_REG (0xB144)
#define PATTERN_WAIT_1_ADDR_OFST (0)
#define PATTERN_WAIT_1_ADDR_MSK (0x00001fff << PATTERN_WAIT_1_ADDR_OFST)
#define PATTERN_WAIT_TIMER_1_LSB_REG (0xB0A0)
#define PATTERN_WAIT_TIMER_1_LSB_REG (0xB148)
#define PATTERN_WAIT_TIMER_1_MSB_REG (0xB0A4)
#define PATTERN_WAIT_TIMER_1_MSB_REG (0xB14C)
#define PATTERN_LOOP_2_ADDR_REG (0xB0A8)
#define PATTERN_LOOP_2_ADDR_REG (0xB150)
#define PATTERN_LOOP_2_ADDR_STRT_OFST (0)
#define PATTERN_LOOP_2_ADDR_STRT_MSK \
@ -508,18 +325,18 @@
#define PATTERN_LOOP_2_ADDR_STP_OFST (16)
#define PATTERN_LOOP_2_ADDR_STP_MSK (0x00001fff << PATTERN_LOOP_2_ADDR_STP_OFST)
#define PATTERN_LOOP_2_ITERATION_REG (0xB0AC)
#define PATTERN_LOOP_2_ITERATION_REG (0xB154)
#define PATTERN_WAIT_2_ADDR_REG (0xB0B0)
#define PATTERN_WAIT_2_ADDR_REG (0xB158)
#define PATTERN_WAIT_2_ADDR_OFST (0)
#define PATTERN_WAIT_2_ADDR_MSK (0x00001fff << PATTERN_WAIT_2_ADDR_OFST)
#define PATTERN_WAIT_TIMER_2_LSB_REG (0xB0B4)
#define PATTERN_WAIT_TIMER_2_LSB_REG (0xB15C)
#define PATTERN_WAIT_TIMER_2_MSB_REG (0xB0B8)
#define PATTERN_WAIT_TIMER_2_MSB_REG (0xB160)
#define PATTERN_LOOP_3_ADDR_REG (0xB0BC)
#define PATTERN_LOOP_3_ADDR_REG (0xB164)
#define PATTERN_LOOP_3_ADDR_STRT_OFST (0)
#define PATTERN_LOOP_3_ADDR_STRT_MSK \
@ -527,18 +344,18 @@
#define PATTERN_LOOP_3_ADDR_STP_OFST (16)
#define PATTERN_LOOP_3_ADDR_STP_MSK (0x00001fff << PATTERN_LOOP_3_ADDR_STP_OFST)
#define PATTERN_LOOP_3_ITERATION_REG (0xB0C0)
#define PATTERN_LOOP_3_ITERATION_REG (0xB168)
#define PATTERN_WAIT_3_ADDR_REG (0xB0C4)
#define PATTERN_WAIT_3_ADDR_REG (0xB16C)
#define PATTERN_WAIT_3_ADDR_OFST (0)
#define PATTERN_WAIT_3_ADDR_MSK (0x00001fff << PATTERN_WAIT_3_ADDR_OFST)
#define PATTERN_WAIT_TIMER_3_LSB_REG (0xB0C8)
#define PATTERN_WAIT_TIMER_3_LSB_REG (0xB170)
#define PATTERN_WAIT_TIMER_3_MSB_REG (0xB0CC)
#define PATTERN_WAIT_TIMER_3_MSB_REG (0xB174)
#define PATTERN_LOOP_4_ADDR_REG (0xB0D0)
#define PATTERN_LOOP_4_ADDR_REG (0xB178)
#define PATTERN_LOOP_4_ADDR_STRT_OFST (0)
#define PATTERN_LOOP_4_ADDR_STRT_MSK \
@ -546,18 +363,18 @@
#define PATTERN_LOOP_4_ADDR_STP_OFST (16)
#define PATTERN_LOOP_4_ADDR_STP_MSK (0x00001fff << PATTERN_LOOP_4_ADDR_STP_OFST)
#define PATTERN_LOOP_4_ITERATION_REG (0xB0D4)
#define PATTERN_LOOP_4_ITERATION_REG (0xB17C)
#define PATTERN_WAIT_4_ADDR_REG (0xB0D8)
#define PATTERN_WAIT_4_ADDR_REG (0xB180)
#define PATTERN_WAIT_4_ADDR_OFST (0)
#define PATTERN_WAIT_4_ADDR_MSK (0x00001fff << PATTERN_WAIT_4_ADDR_OFST)
#define PATTERN_WAIT_TIMER_4_LSB_REG (0xB0DC)
#define PATTERN_WAIT_TIMER_4_LSB_REG (0xB184)
#define PATTERN_WAIT_TIMER_4_MSB_REG (0xB0E0)
#define PATTERN_WAIT_TIMER_4_MSB_REG (0xB188)
#define PATTERN_LOOP_5_ADDR_REG (0xB0E4)
#define PATTERN_LOOP_5_ADDR_REG (0xB18C)
#define PATTERN_LOOP_5_ADDR_STRT_OFST (0)
#define PATTERN_LOOP_5_ADDR_STRT_MSK \
@ -565,10 +382,162 @@
#define PATTERN_LOOP_5_ADDR_STP_OFST (16)
#define PATTERN_LOOP_5_ADDR_STP_MSK (0x00001fff << PATTERN_LOOP_5_ADDR_STP_OFST)
#define PATTERN_LOOP_5_ITERATION_REG (0xB0E8)
#define PATTERN_LOOP_5_ITERATION_REG (0xB190)
#define PATTERN_WAIT_5_ADDR_REG (0xB194)
#define PATTERN_WAIT_5_ADDR_REG (0xB0EC)
#define PATTERN_WAIT_5_ADDR_OFST (0)
#define PATTERN_WAIT_5_ADDR_MSK (0x00001fff << PATTERN_WAIT_5_ADDR_OFST)
#define PATTERN_WAIT_TIMER_5_LSB_REG (0xB0F0)
#define PATTERN_WAIT_TIMER_5_MSB_REG (0xB0F4)
#define PATTERN_WAIT_TIMER_5_LSB_REG (0xB198)
#define PATTERN_WAIT_TIMER_5_MSB_REG (0xB19C)
#define PINIOCTRLREG (0xB1A0)
#define DBITFIFOCTRLREG (0xB1A4)
#define DBITRD_OFST (0)
#define DBITRD_MSK (0x00000001 << DBITRD_OFST)
#define DBITRST_OFST (1)
#define DBITRST_MSK (0x00000001 << DBITRST_OFST)
#define DBITFULL_OFST (2)
#define DBITFULL_MSK (0x00000001 << DBITFULL_OFST)
#define DBITEMPTY_OFST (3)
#define DBITEMPTY_MSK (0x00000001 << DBITEMPTY_OFST)
#define DBITUNDERFLOW_OFST (4)
#define DBITUNDERFLOW_MSK (0x00000001 << DBITUNDERFLOW_OFST)
#define DBITOVERFLOW_OFST (5)
#define DBITOVERFLOW_MSK (0x00000001 << DBITOVERFLOW_OFST)
#define DBITFIFODATAREG1 (0xB1A8)
#define DBITFIFODATAREG2 (0xB1AC)
#define MATTERHORNSPIREG1 (0xB1B0)
#define MATTERHORNSPIREG2 (0xB1B4)
#define MATTERHORNSPICTRL (0xB1B8)
#define CONFIGSTART_P_OFST (0)
#define CONFIGSTART_P_MSK (0x00000001 << CONFIGSTART_P_OFST)
#define PERIPHERYRST_P_OFST (1)
#define PERIPHERYRST_P_MSK (0x00000001 << PERIPHERYRST_P_OFST)
#define STARTREAD_P_OFST (2)
#define STARTREAD_P_MSK (0x00000001 << STARTREAD_P_OFST)
#define BUSY_OFST (3)
#define BUSY_MSK (0x00000001 << BUSY_OFST)
#define READOUTFROMASIC_OFST (4)
#define READOUTFROMASIC_MSK (0x00000001 << READOUTFROMASIC_OFST)
#define TRANSCEIVERRXCTRL0REG1 (0xB800)
#define TRANSCEIVERRXCTRL0REG2 (0xB804)
#define TRANSCEIVERRXCTRL1REG1 (0xB808)
#define TRANSCEIVERRXCTRL1REG2 (0xB80C)
#define TRANSCEIVERRXCTRL2REG (0xB810)
#define TRANSCEIVERRXCTRL3REG (0xB814)
#define TRANSCEIVERSTATUS (0xB818)
#define LINKDOWNLATCHEDOUT_OFST (0)
#define LINKDOWNLATCHEDOUT_MSK (0x00000001 << LINKDOWNLATCHEDOUT_OFST)
#define TXUSERCLKACTIVE_OFST (1)
#define TXUSERCLKACTIVE_MSK (0x00000001 << TXUSERCLKACTIVE_OFST)
#define RXUSERCLKACTIVE_OFST (2)
#define RXUSERCLKACTIVE_MSK (0x00000001 << RXUSERCLKACTIVE_OFST)
#define RXCOMMADET_OFST (3)
#define RXCOMMADET_MSK (0x0000000f << RXCOMMADET_OFST)
#define RXBYTEREALIGN_OFST (7)
#define RXBYTEREALIGN_MSK (0x0000000f << RXBYTEREALIGN_OFST)
#define RXBYTEISALIGNED_OFST (11)
#define RXBYTEISALIGNED_MSK (0x0000000f << RXBYTEISALIGNED_OFST)
#define GTWIZRXCDRSTABLE_OFST (15)
#define GTWIZRXCDRSTABLE_MSK (0x00000001 << GTWIZRXCDRSTABLE_OFST)
#define RESETTXDONE_OFST (16)
#define RESETTXDONE_MSK (0x00000001 << RESETTXDONE_OFST)
#define RESETRXDONE_OFST (17)
#define RESETRXDONE_MSK (0x00000001 << RESETRXDONE_OFST)
#define RXPMARESETDONE_OFST (18)
#define RXPMARESETDONE_MSK (0x0000000f << RXPMARESETDONE_OFST)
#define TXPMARESETDONE_OFST (22)
#define TXPMARESETDONE_MSK (0x0000000f << TXPMARESETDONE_OFST)
#define GTTPOWERGOOD_OFST (26)
#define GTTPOWERGOOD_MSK (0x0000000f << GTTPOWERGOOD_OFST)
#define TRANSCEIVERSTATUS2 (0xB81C)
#define RXLOCKED_OFST (0)
#define RXLOCKED_MSK (0x0000000f << RXLOCKED_OFST)
#define TRANSCEIVERCONTROL (0xB820)
#define GTWIZRESETALL_OFST (0)
#define GTWIZRESETALL_MSK (0x00000001 << GTWIZRESETALL_OFST)
#define RESETTXPLLANDDATAPATH_OFST (1)
#define RESETTXPLLANDDATAPATH_MSK (0x00000001 << RESETTXPLLANDDATAPATH_OFST)
#define RESETTXDATAPATHIN_OFST (2)
#define RESETTXDATAPATHIN_MSK (0x00000001 << RESETTXDATAPATHIN_OFST)
#define RESETRXPLLANDDATAPATH_OFST (3)
#define RESETRXPLLANDDATAPATH_MSK (0x00000001 << RESETRXPLLANDDATAPATH_OFST)
#define RESETRXDATAPATHIN_OFST (4)
#define RESETRXDATAPATHIN_MSK (0x00000001 << RESETRXDATAPATHIN_OFST)
#define RXPOLARITY_OFST (5)
#define RXPOLARITY_MSK (0x0000000f << RXPOLARITY_OFST)
#define RXERRORCNTRESET_OFST (9)
#define RXERRORCNTRESET_MSK (0x0000000f << RXERRORCNTRESET_OFST)
#define RXMSBLSBINVERT_OFST (13)
#define RXMSBLSBINVERT_MSK (0x0000000f << RXMSBLSBINVERT_OFST)
#define TRANSCEIVERERRCNT_REG0 (0xB824)
#define TRANSCEIVERERRCNT_REG1 (0xB828)
#define TRANSCEIVERERRCNT_REG2 (0xB82C)
#define TRANSCEIVERERRCNT_REG3 (0xB830)
#define TRANSCEIVERALIGNCNT_REG0 (0xB834)
#define RXALIGNCNTCH0_OFST (0)
#define RXALIGNCNTCH0_MSK (0x0000ffff << RXALIGNCNTCH0_OFST)
#define TRANSCEIVERALIGNCNT_REG1 (0xB838)
#define RXALIGNCNTCH1_OFST (0)
#define RXALIGNCNTCH1_MSK (0x0000ffff << RXALIGNCNTCH1_OFST)
#define TRANSCEIVERALIGNCNT_REG2 (0xB83C)
#define RXALIGNCNTCH2_OFST (0)
#define RXALIGNCNTCH2_MSK (0x0000ffff << RXALIGNCNTCH2_OFST)
#define TRANSCEIVERALIGNCNT_REG3 (0xB840)
#define RXALIGNCNTCH3_OFST (0)
#define RXALIGNCNTCH3_MSK (0x0000ffff << RXALIGNCNTCH3_OFST)
#define TRANSCEIVERLASTWORD_REG0 (0xB844)
#define RXDATACH0_OFST (0)
#define RXDATACH0_MSK (0x0000ffff << RXDATACH0_OFST)
#define TRANSCEIVERLASTWORD_REG1 (0xB848)
#define RXDATACH1_OFST (0)
#define RXDATACH1_MSK (0x0000ffff << RXDATACH1_OFST)
#define TRANSCEIVERLASTWORD_REG2 (0xB84C)
#define RXDATACH2_OFST (0)
#define RXDATACH2_MSK (0x0000ffff << RXDATACH2_OFST)
#define TRANSCEIVERLASTWORD_REG3 (0xB850)
#define RXDATACH3_OFST (0)
#define RXDATACH3_MSK (0x0000ffff << RXDATACH3_OFST)

View File

@ -1,37 +1,24 @@
# Prepare MH02 configuration
reg 0xC00C 0x00000041
reg 0xC010 0x01200004
# turn on external CLKSEL for trimbit upload
setbit 0xC00C 17
reg 0xB1B0 0x00000041
reg 0xB1B4 0x01200004
# configure Matterhorn SPI
setbit 0xC014 0
setbit 0xB1B8 0
# wait till config is done
pollbit 0xC014 3 0
# set trimbits to 0
pattern put_trimbits_zero.pyat
setbit 0xB030 0
clearbit 0xB030 0
sleep 1
pollbit 0xB004 0 0
clearbit 0xC00C 17
setbit 0xC014 0
pollbit 0xC014 3 0
pollbit 0xB1B8 3 0
# reset transceiver
reg 0xC120 0x0
reg 0xC120 0x1
reg 0xC120 0x0
reg 0xB820 0x0
reg 0xB820 0x1
reg 0xB820 0x0
# set MSB LSB inversions and polarity for transceiver
reg 0xC120 0x61e0
reg 0xB820 0x61e0
# Enable MH02 PLL clock
pattern enable_clock_pattern.pyat
# start the flow
setbit 0xB030 0
clearbit 0xB030 0
setbit 0xB004 0
clearbit 0xB004 0
sleep 1

View File

@ -1,82 +0,0 @@
patword 0x0000 0x0000000000000000
patword 0x0001 0x0000000000000000
patword 0x0002 0x0000000000000000
patword 0x0003 0x0000000000000000
patword 0x0004 0x0000000000000000
patword 0x0005 0x0000000000000000
patword 0x0006 0x0000000000000000
patword 0x0007 0x0000000000000000
patword 0x0008 0x0000000000000000
patword 0x0009 0x0000000000000000
patword 0x000a 0x0000000000000000
patword 0x000b 0x0000000000000000
patword 0x000c 0x0000000000000000
patword 0x000d 0x0000000000001000
patword 0x000e 0x0000000000001000
patword 0x000f 0x0000000000001000
patword 0x0010 0x0000000000001000
patword 0x0011 0x0000000000001000
patword 0x0012 0x0000000000000000
patword 0x0013 0x0000000000000000
patword 0x0014 0x0000000000000000
patword 0x0015 0x0000000000000000
patword 0x0016 0x0000000000000000
patword 0x0017 0x0000000000000400
patword 0x0018 0x0000000000000400
patword 0x0019 0x0000000000000400
patword 0x001a 0x0000000000000400
patword 0x001b 0x0000000001000400
patword 0x001c 0x0000000001000400
patword 0x001d 0x0000000001000400
patword 0x001e 0x0000000001000400
patword 0x001f 0x0000000000000400
patword 0x0020 0x0000000000000400
patword 0x0021 0x0000000000000400
patword 0x0022 0x0000000000000400
patword 0x0023 0x0000000000001400
patword 0x0024 0x0000000000001400
patword 0x0025 0x0000000000001400
patword 0x0026 0x0000000000001400
patword 0x0027 0x0000000001001400
patword 0x0028 0x0000000001001400
patword 0x0029 0x0000000001001400
patword 0x002a 0x0000000001001400
patword 0x002b 0x0000000000001400
patword 0x002c 0x0000000000001400
patword 0x002d 0x0000000000001400
patword 0x002e 0x0000000000001400
patword 0x002f 0x0000000000000400
patword 0x0030 0x0000000000000400
patword 0x0031 0x0000000000000400
patword 0x0032 0x0000000000000400
patword 0x0033 0x0000000000000400
patword 0x0034 0x0000000000000400
patword 0x0035 0x0000000000000400
patword 0x0036 0x0000000000000400
patword 0x0037 0x0000000000000000
patioctrl 0x0000000001b3ffff
patlimits 0x0000 0x0037
patloop 0 0x0018 0x0036
patnloop 0 192
patloop 1 0x0400 0x0400
patnloop 1 0
patloop 2 0x0400 0x0400
patnloop 2 0
patloop 3 0x0400 0x0400
patnloop 3 0
patloop 4 0x0400 0x0400
patnloop 4 0
patloop 5 0x0400 0x0400
patnloop 5 0
patwait 0 0x0400
patwaittime 0 0
patwait 1 0x0400
patwaittime 1 0
patwait 2 0x0400
patwaittime 2 0
patwait 3 0x0400
patwaittime 3 0
patwait 4 0x0400
patwaittime 4 0
patwait 5 0x0400
patwaittime 5 0

View File

@ -1,30 +1,30 @@
# turn off clock
setbit 0xC00C 16
setbit 0xC014 0
setbit 0xB1B0 16
setbit 0xB1B8 0
sleep 1
# reset Matterhorn periphery
setbit 0xC014 1
setbit 0xB1B8 1
sleep 1
# turn on clock
clearbit 0xC00C 16
setbit 0xC014 0
clearbit 0xB1B0 16
setbit 0xB1B8 0
sleep 1
# reset rx transceiver datapath
setbit 0xC120 4
setbit 0xB820 4
sleep 1
# reset 8b10b counters
setbit 0xC120 9
setbit 0xC120 10
setbit 0xC120 11
setbit 0xC120 12
setbit 0xB820 9
setbit 0xB820 10
setbit 0xB820 11
setbit 0xB820 12
sleep 1
clearbit 0xC120 9
clearbit 0xC120 10
clearbit 0xB820 9
clearbit 0xB820 10
# reset buffer fifos
reg 0x9024 0xFFFFFFFF

View File

@ -1537,12 +1537,8 @@ void *start_timer(void *arg) {
packetSize, packetsPerFrame));
// Generate Data
char *imageData = (char *)malloc(imageSize);
char imageData[imageSize];
memset(imageData, 0, imageSize);
if (imageData == NULL) {
LOG(logERROR, ("Can not allocate image.\n"));
return NULL;
}
for (int i = 0; i < imageSize; i += sizeof(uint16_t)) {
*((uint16_t *)(imageData + i)) = i;
}
@ -1565,7 +1561,6 @@ void *start_timer(void *arg) {
usleep(expUs);
int srcOffset = 0;
int dataSent = 0;
// loop packet
for (int i = 0; i != packetsPerFrame; ++i) {
@ -1582,12 +1577,10 @@ void *start_timer(void *arg) {
header->column = detPos[X];
// fill data
int remaining = imageSize - dataSent;
int dataSize = remaining < maxDataSize ? remaining : maxDataSize;
memcpy(packetData + sizeof(sls_detector_header),
imageData + srcOffset, dataSize);
srcOffset += dataSize;
dataSent += dataSize;
imageData + srcOffset,
(imageSize < maxDataSize ? imageSize : maxDataSize));
srcOffset += maxDataSize;
sendUDPPacket(0, 0, packetData, packetSize);
}

View File

@ -17,119 +17,6 @@ namespace sls {
using test::GET;
using test::PUT;
TEST_CASE("ctb_acquire_check_file_size", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type =
det.getDetectorType().tsquash("Inconsistent detector types to test");
if (det_type == defs::CHIPTESTBOARD ||
det_type == defs::XILINX_CHIPTESTBOARD) {
int num_frames_to_acquire = 2;
// all the test cases
{
testCtbAcquireInfo test_ctb_config;
test_ctb_config.readout_mode = defs::ANALOG_AND_DIGITAL;
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
test_ctb_config, num_frames_to_acquire, det, caller));
}
{
testCtbAcquireInfo test_ctb_config;
test_ctb_config.readout_mode = defs::ANALOG_AND_DIGITAL;
test_ctb_config.dbit_offset = 16;
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
test_ctb_config, num_frames_to_acquire, det, caller));
}
{
testCtbAcquireInfo test_ctb_config;
test_ctb_config.readout_mode = defs::ANALOG_AND_DIGITAL;
test_ctb_config.dbit_reorder = true;
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
test_ctb_config, num_frames_to_acquire, det, caller));
}
{
testCtbAcquireInfo test_ctb_config;
test_ctb_config.readout_mode = defs::ANALOG_AND_DIGITAL;
test_ctb_config.dbit_offset = 16;
test_ctb_config.dbit_reorder = true;
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
test_ctb_config, num_frames_to_acquire, det, caller));
}
{
testCtbAcquireInfo test_ctb_config;
test_ctb_config.readout_mode = defs::ANALOG_AND_DIGITAL;
test_ctb_config.dbit_offset = 16;
test_ctb_config.dbit_list.clear();
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
test_ctb_config, num_frames_to_acquire, det, caller));
}
{
testCtbAcquireInfo test_ctb_config;
test_ctb_config.readout_mode = defs::ANALOG_AND_DIGITAL;
test_ctb_config.dbit_offset = 16;
test_ctb_config.dbit_list.clear();
test_ctb_config.dbit_reorder = true;
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
test_ctb_config, num_frames_to_acquire, det, caller));
}
{
testCtbAcquireInfo test_ctb_config;
test_ctb_config.readout_mode = defs::DIGITAL_AND_TRANSCEIVER;
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
test_ctb_config, num_frames_to_acquire, det, caller));
}
{
testCtbAcquireInfo test_ctb_config;
test_ctb_config.readout_mode = defs::DIGITAL_AND_TRANSCEIVER;
test_ctb_config.dbit_offset = 16;
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
test_ctb_config, num_frames_to_acquire, det, caller));
}
{
testCtbAcquireInfo test_ctb_config;
test_ctb_config.readout_mode = defs::DIGITAL_AND_TRANSCEIVER;
test_ctb_config.dbit_list.clear();
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
test_ctb_config, num_frames_to_acquire, det, caller));
}
{
testCtbAcquireInfo test_ctb_config;
test_ctb_config.readout_mode = defs::DIGITAL_AND_TRANSCEIVER;
test_ctb_config.dbit_offset = 16;
test_ctb_config.dbit_list.clear();
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
test_ctb_config, num_frames_to_acquire, det, caller));
}
{
testCtbAcquireInfo test_ctb_config;
test_ctb_config.readout_mode = defs::DIGITAL_AND_TRANSCEIVER;
test_ctb_config.dbit_offset = 16;
test_ctb_config.dbit_list.clear();
test_ctb_config.dbit_reorder = true;
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
test_ctb_config, num_frames_to_acquire, det, caller));
}
{
testCtbAcquireInfo test_ctb_config;
test_ctb_config.readout_mode = defs::TRANSCEIVER_ONLY;
test_ctb_config.dbit_offset = 16;
test_ctb_config.dbit_list.clear();
test_ctb_config.dbit_reorder = true;
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
test_ctb_config, num_frames_to_acquire, det, caller));
}
{
testCtbAcquireInfo test_ctb_config;
test_ctb_config.readout_mode = defs::ANALOG_ONLY;
test_ctb_config.dbit_offset = 16;
test_ctb_config.dbit_list.clear();
test_ctb_config.dbit_reorder = true;
REQUIRE_NOTHROW(test_ctb_acquire_with_receiver(
test_ctb_config, num_frames_to_acquire, det, caller));
}
}
}
/* dacs */
TEST_CASE("dacname", "[.cmdcall]") {

View File

@ -17,70 +17,6 @@ namespace sls {
using test::GET;
using test::PUT;
TEST_CASE("eiger_acquire_check_file_size", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type =
det.getDetectorType().tsquash("Inconsistent detector types to test");
if (det_type == defs::EIGER) {
// save previous state
testFileInfo prev_file_info = get_file_state(det);
testCommonDetAcquireInfo prev_det_config_info =
get_common_acquire_config_state(det);
// save previous specific det type config
auto exptime = det.getExptime().tsquash("inconsistent exptime to test");
auto n_rows =
det.getReadNRows().tsquash("inconsistent number of rows to test");
auto dynamic_range =
det.getDynamicRange().tsquash("inconsistent dynamic range to test");
REQUIRE(false ==
det.getTenGiga().tsquash("inconsistent 10Giga to test"));
// defaults
int num_frames_to_acquire = 2;
testFileInfo test_file_info;
set_file_state(det, test_file_info);
testCommonDetAcquireInfo det_config;
det_config.num_frames_to_acquire = num_frames_to_acquire;
set_common_acquire_config_state(det, det_config);
// set default specific det type config
det.setExptime(std::chrono::microseconds{200});
det.setReadNRows(256);
det.setDynamicRange(16);
// acquire
test_acquire_with_receiver(caller, det);
// check frames caught
test_frames_caught(det, num_frames_to_acquire);
// check file size (assuming local pc)
{
detParameters par(det_type);
// data split into half due to 2 udp interfaces per half module
int num_chips = (par.nChipX / 2);
int bytes_per_pixel = (dynamic_range / 8);
size_t expected_image_size =
par.nChanX * par.nChanY * num_chips * bytes_per_pixel;
test_acquire_binary_file_size(test_file_info, num_frames_to_acquire,
expected_image_size);
}
// restore previous state
set_file_state(det, prev_file_info);
set_common_acquire_config_state(det, prev_det_config_info);
// restore previous specific det type config
det.setExptime(exptime);
det.setReadNRows(n_rows);
det.setDynamicRange(dynamic_range);
}
}
/** temperature */
TEST_CASE("temp_fpgaext", "[.cmdcall]") {

View File

@ -4,7 +4,6 @@
#include "Caller.h"
#include "catch.hpp"
#include "sls/Detector.h"
#include "sls/logger.h"
#include "tests/globals.h"
namespace sls {
@ -89,227 +88,4 @@ void test_onchip_dac_caller(defs::dacIndex index, const std::string &dacname,
}
}
testFileInfo get_file_state(const Detector &det) {
return testFileInfo{
det.getFilePath().tsquash("Inconsistent file path"),
det.getFileNamePrefix().tsquash("Inconsistent file prefix"),
det.getAcquisitionIndex().tsquash(
"Inconsistent file acquisition index"),
det.getFileWrite().tsquash("Inconsistent file write state"),
det.getFileOverWrite().tsquash("Inconsistent file overwrite state"),
det.getFileFormat().tsquash("Inconsistent file format")};
}
void set_file_state(Detector &det, const testFileInfo &file_info) {
if (!file_info.file_path.empty())
det.setFilePath(file_info.file_path);
det.setFileNamePrefix(file_info.file_prefix);
det.setAcquisitionIndex(file_info.file_acq_index);
det.setFileWrite(file_info.file_write);
det.setFileOverWrite(file_info.file_overwrite);
det.setFileFormat(file_info.file_format);
}
void test_acquire_binary_file_size(const testFileInfo &file_info,
uint64_t num_frames_to_acquire,
uint64_t expected_image_size) {
assert(file_info.file_format == defs::BINARY);
std::string fname = file_info.file_path + "/" + file_info.file_prefix +
"_d0_f0_" + std::to_string(file_info.file_acq_index) +
".raw";
uint64_t expected_file_size =
num_frames_to_acquire *
(expected_image_size + sizeof(defs::sls_receiver_header));
auto actual_file_size = std::filesystem::file_size(fname);
REQUIRE(actual_file_size == expected_file_size);
}
void test_frames_caught(const Detector &det, int num_frames_to_acquire) {
auto frames_caught = det.getFramesCaught().tsquash(
"Inconsistent number of frames caught")[0];
REQUIRE(frames_caught == num_frames_to_acquire);
}
void test_acquire_with_receiver(Caller &caller, const Detector &det) {
REQUIRE_NOTHROW(caller.call("rx_start", {}, -1, PUT));
REQUIRE_NOTHROW(caller.call("start", {}, -1, PUT));
bool idle = false;
while (!idle) {
std::ostringstream oss;
REQUIRE_NOTHROW(caller.call("status", {}, -1, GET));
auto statusList = det.getDetectorStatus();
if (statusList.any(defs::ERROR)) {
throw std::runtime_error("error status while acquiring");
}
if (statusList.contains_only(defs::IDLE, defs::STOPPED)) {
idle = true;
}
}
REQUIRE_NOTHROW(caller.call("rx_stop", {}, -1, PUT));
}
testCommonDetAcquireInfo get_common_acquire_config_state(const Detector &det) {
return testCommonDetAcquireInfo{
det.getTimingMode().tsquash("Inconsistent timing mode"),
det.getNumberOfFrames().tsquash("Inconsistent number of frames"),
det.getNumberOfTriggers().tsquash("Inconsistent number of triggers"),
det.getPeriod().tsquash("Inconsistent period")};
}
void set_common_acquire_config_state(
Detector &det, const testCommonDetAcquireInfo &det_config_info) {
det.setTimingMode(det_config_info.timing_mode);
det.setNumberOfFrames(det_config_info.num_frames_to_acquire);
det.setNumberOfTriggers(det_config_info.num_triggers);
det.setPeriod(det_config_info.period);
}
testCtbAcquireInfo get_ctb_config_state(const Detector &det) {
testCtbAcquireInfo ctb_config_info{
det.getReadoutMode().tsquash("inconsistent readout mode to test"),
true,
det.getNumberOfAnalogSamples().tsquash(
"inconsistent number of analog samples to test"),
det.getNumberOfDigitalSamples().tsquash(
"inconsistent number of digital samples to test"),
det.getNumberOfTransceiverSamples().tsquash(
"inconsistent number of transceiver samples to test"),
0,
det.getTenGigaADCEnableMask().tsquash(
"inconsistent ten giga adc enable mask to test"),
det.getRxDbitOffset().tsquash("inconsistent rx dbit offset to test"),
det.getRxDbitList().tsquash("inconsistent rx dbit list to test"),
det.getRxDbitReorder().tsquash("inconsistent rx dbit reorder to test"),
det.getTransceiverEnableMask().tsquash(
"inconsistent transceiver mask to test")};
if (det.getDetectorType().tsquash("inconsistent detector type to test") ==
slsDetectorDefs::CHIPTESTBOARD) {
ctb_config_info.ten_giga =
det.getTenGiga().tsquash("inconsistent ten giga enable to test");
ctb_config_info.adc_enable_1g = det.getADCEnableMask().tsquash(
"inconsistent adc enable mask to test");
}
return ctb_config_info;
}
void set_ctb_config_state(Detector &det,
const testCtbAcquireInfo &ctb_config_info) {
det.setReadoutMode(ctb_config_info.readout_mode);
if (det.getDetectorType().tsquash("inconsistent detector type to test") ==
slsDetectorDefs::CHIPTESTBOARD) {
det.setTenGiga(ctb_config_info.ten_giga);
det.setADCEnableMask(ctb_config_info.adc_enable_1g);
}
det.setNumberOfAnalogSamples(ctb_config_info.num_adc_samples);
det.setNumberOfDigitalSamples(ctb_config_info.num_dbit_samples);
det.setNumberOfTransceiverSamples(ctb_config_info.num_trans_samples);
det.setTenGigaADCEnableMask(ctb_config_info.adc_enable_10g);
det.setRxDbitOffset(ctb_config_info.dbit_offset);
det.setRxDbitList(ctb_config_info.dbit_list);
det.setRxDbitReorder(ctb_config_info.dbit_reorder);
det.setTransceiverEnableMask(ctb_config_info.transceiver_mask);
}
uint64_t calculate_ctb_image_size(const testCtbAcquireInfo &test_info) {
uint64_t num_analog_bytes = 0, num_digital_bytes = 0,
num_transceiver_bytes = 0;
if (test_info.readout_mode == defs::ANALOG_ONLY ||
test_info.readout_mode == defs::ANALOG_AND_DIGITAL) {
uint32_t adc_enable_mask =
(test_info.ten_giga ? test_info.adc_enable_10g
: test_info.adc_enable_1g);
int num_analog_chans = __builtin_popcount(adc_enable_mask);
const int num_bytes_per_sample = 2;
num_analog_bytes =
num_analog_chans * num_bytes_per_sample * test_info.num_adc_samples;
LOG(logDEBUG1) << "[Analog Databytes: " << num_analog_bytes << ']';
}
// digital channels
if (test_info.readout_mode == defs::DIGITAL_ONLY ||
test_info.readout_mode == defs::ANALOG_AND_DIGITAL ||
test_info.readout_mode == defs::DIGITAL_AND_TRANSCEIVER) {
int num_digital_samples = test_info.num_dbit_samples;
if (test_info.dbit_offset > 0) {
uint64_t num_digital_bytes_reserved =
num_digital_samples * sizeof(uint64_t);
num_digital_bytes_reserved -= test_info.dbit_offset;
num_digital_samples = num_digital_bytes_reserved / sizeof(uint64_t);
}
int num_digital_chans = test_info.dbit_list.size();
if (num_digital_chans == 0) {
num_digital_chans = 64;
}
if (!test_info.dbit_reorder) {
uint32_t num_bits_per_sample = num_digital_chans;
if (num_bits_per_sample % 8 != 0) {
num_bits_per_sample += (8 - (num_bits_per_sample % 8));
}
num_digital_bytes = (num_bits_per_sample / 8) * num_digital_samples;
} else {
uint32_t num_bits_per_bit = num_digital_samples;
if (num_bits_per_bit % 8 != 0) {
num_bits_per_bit += (8 - (num_bits_per_bit % 8));
}
num_digital_bytes = num_digital_chans * (num_bits_per_bit / 8);
}
LOG(logDEBUG1) << "[Digital Databytes: " << num_digital_bytes << ']';
}
// transceiver channels
if (test_info.readout_mode == defs::TRANSCEIVER_ONLY ||
test_info.readout_mode == defs::DIGITAL_AND_TRANSCEIVER) {
int num_transceiver_chans =
__builtin_popcount(test_info.transceiver_mask);
const int num_bytes_per_channel = 8;
num_transceiver_bytes = num_transceiver_chans * num_bytes_per_channel *
test_info.num_trans_samples;
LOG(logDEBUG1) << "[Transceiver Databytes: " << num_transceiver_bytes
<< ']';
}
uint64_t image_size =
num_analog_bytes + num_digital_bytes + num_transceiver_bytes;
LOG(logDEBUG1) << "Expected image size: " << image_size;
return image_size;
}
void test_ctb_acquire_with_receiver(const testCtbAcquireInfo &test_info,
int64_t num_frames_to_acquire,
Detector &det, Caller &caller) {
// save previous state
testFileInfo prev_file_info = get_file_state(det);
testCommonDetAcquireInfo prev_det_config_info =
// overwrite exptime if not using virtual ctb server
get_common_acquire_config_state(det);
testCtbAcquireInfo prev_ctb_config_info = get_ctb_config_state(det);
// defaults
testFileInfo test_file_info;
set_file_state(det, test_file_info);
testCommonDetAcquireInfo det_config;
det_config.num_frames_to_acquire = num_frames_to_acquire;
set_common_acquire_config_state(det, det_config);
// set ctb config
set_ctb_config_state(det, test_info);
// acquire
REQUIRE_NOTHROW(test_acquire_with_receiver(caller, det));
// check frames caught
REQUIRE_NOTHROW(test_frames_caught(det, num_frames_to_acquire));
// check file size (assuming local pc)
uint64_t expected_image_size = calculate_ctb_image_size(test_info);
REQUIRE_NOTHROW(test_acquire_binary_file_size(
test_file_info, num_frames_to_acquire, expected_image_size));
// restore previous state
set_file_state(det, prev_file_info);
set_common_acquire_config_state(det, prev_det_config_info);
set_ctb_config_state(det, prev_ctb_config_info);
}
} // namespace sls

View File

@ -1,46 +1,9 @@
// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
#pragma once
class Caller;
#include "sls/Detector.h"
#include "sls/sls_detector_defs.h"
#include <chrono>
#include <filesystem>
#include <thread>
namespace sls {
struct testFileInfo {
std::string file_path{"/tmp"};
std::string file_prefix{"sls_test"};
int64_t file_acq_index{0};
bool file_write{true};
bool file_overwrite{true};
slsDetectorDefs::fileFormat file_format{slsDetectorDefs::BINARY};
};
struct testCommonDetAcquireInfo {
slsDetectorDefs::timingMode timing_mode{slsDetectorDefs::AUTO_TIMING};
int64_t num_frames_to_acquire{2};
int64_t num_triggers{1};
std::chrono::nanoseconds period{std::chrono::milliseconds{2}};
};
struct testCtbAcquireInfo {
defs::readoutMode readout_mode{defs::ANALOG_AND_DIGITAL};
bool ten_giga{false};
int num_adc_samples{5000};
int num_dbit_samples{6000};
int num_trans_samples{288};
uint32_t adc_enable_1g{0xFFFFFF00};
uint32_t adc_enable_10g{0xFF00FFFF};
int dbit_offset{0};
std::vector<int> dbit_list{0, 12, 2, 43};
bool dbit_reorder{false};
uint32_t transceiver_mask{0x3};
};
void test_valid_port_caller(const std::string &command,
const std::vector<std::string> &arguments,
int detector_id, int action);
@ -50,26 +13,4 @@ void test_dac_caller(slsDetectorDefs::dacIndex index,
void test_onchip_dac_caller(slsDetectorDefs::dacIndex index,
const std::string &dacname, int dacvalue);
testFileInfo get_file_state(const Detector &det);
void set_file_state(Detector &det, const testFileInfo &file_info);
void test_acquire_binary_file_size(const testFileInfo &file_info,
uint64_t num_frames_to_acquire,
uint64_t expected_image_size);
void test_frames_caught(const Detector &det, int num_frames_to_acquire);
void test_acquire_with_receiver(Caller &caller, const Detector &det);
testCommonDetAcquireInfo get_common_acquire_config_state(const Detector &det);
void set_common_acquire_config_state(
Detector &det, const testCommonDetAcquireInfo &det_config_info);
testCtbAcquireInfo get_ctb_config_state(const Detector &det);
void set_ctb_config_state(Detector &det,
const testCtbAcquireInfo &ctb_config_info);
uint64_t calculate_ctb_image_size(const testCtbAcquireInfo &test_info);
void test_ctb_acquire_with_receiver(const testCtbAcquireInfo &test_info,
int64_t num_frames_to_acquire,
Detector &det, Caller &caller);
} // namespace sls

View File

@ -17,69 +17,6 @@ namespace sls {
using test::GET;
using test::PUT;
TEST_CASE("gotthard2_acquire_check_file_size", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type =
det.getDetectorType().tsquash("Inconsistent detector types to test");
if (det_type == defs::GOTTHARD2) {
// save previous state
testFileInfo prev_file_info = get_file_state(det);
testCommonDetAcquireInfo prev_det_config_info =
get_common_acquire_config_state(det);
// save previous specific det type config
auto exptime = det.getExptime().tsquash("inconsistent exptime to test");
auto burst_mode =
det.getBurstMode().tsquash("inconsistent burst mode to test");
auto number_of_bursts = det.getNumberOfBursts().tsquash(
"inconsistent number of bursts to test");
auto burst_period =
det.getBurstPeriod().tsquash("inconsistent burst period to test");
// defaults
int num_frames_to_acquire = 2;
testFileInfo test_file_info;
set_file_state(det, test_file_info);
testCommonDetAcquireInfo det_config;
det_config.num_frames_to_acquire = num_frames_to_acquire;
set_common_acquire_config_state(det, det_config);
// set default specific det type config
det.setExptime(std::chrono::microseconds{200});
det.setBurstMode(defs::CONTINUOUS_EXTERNAL);
det.setNumberOfBursts(1);
det.setBurstPeriod(std::chrono::milliseconds{0});
// acquire
test_acquire_with_receiver(caller, det);
// check frames caught
test_frames_caught(det, num_frames_to_acquire);
// check file size (assuming local pc)
{
detParameters par(det_type);
int bytes_per_pixel = det.getDynamicRange().squash() / 8;
size_t expected_image_size =
par.nChanX * par.nChipX * bytes_per_pixel;
test_acquire_binary_file_size(test_file_info, num_frames_to_acquire,
expected_image_size);
}
// restore previous state
set_file_state(det, prev_file_info);
set_common_acquire_config_state(det, prev_det_config_info);
// restore previous specific det type config
det.setExptime(exptime);
det.setBurstMode(burst_mode);
det.setNumberOfBursts(number_of_bursts);
det.setBurstPeriod(burst_period);
}
}
// time specific measurements for gotthard2
TEST_CASE("timegotthard2", "[.cmdcall]") {
Detector det;

View File

@ -15,65 +15,6 @@ namespace sls {
using test::GET;
using test::PUT;
TEST_CASE("jungfrau_acquire_check_file_size", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type =
det.getDetectorType().tsquash("Inconsistent detector types to test");
if (det_type == defs::JUNGFRAU) {
// save previous state
testFileInfo prev_file_info = get_file_state(det);
testCommonDetAcquireInfo prev_det_config_info =
get_common_acquire_config_state(det);
// save previous specific det type config
auto exptime = det.getExptime().tsquash("inconsistent exptime to test");
auto num_udp_interfaces = det.getNumberofUDPInterfaces().tsquash(
"inconsistent number of udp interfaces");
auto n_rows =
det.getReadNRows().tsquash("inconsistent number of rows to test");
// defaults
int num_frames_to_acquire = 2;
testFileInfo test_file_info;
set_file_state(det, test_file_info);
testCommonDetAcquireInfo det_config;
det_config.num_frames_to_acquire = num_frames_to_acquire;
set_common_acquire_config_state(det, det_config);
// set default specific det type config
det.setExptime(std::chrono::microseconds{200});
det.setReadNRows(512);
// acquire
test_acquire_with_receiver(caller, det);
// check frames caught
test_frames_caught(det, num_frames_to_acquire);
// check file size (assuming local pc)
{
detParameters par(det_type);
int bytes_per_pixel = det.getDynamicRange().squash() / 8;
// if 2 udp interfaces, data split into half
size_t expected_image_size = (par.nChanX * par.nChanY * par.nChipX *
par.nChipY * bytes_per_pixel) /
num_udp_interfaces;
test_acquire_binary_file_size(test_file_info, num_frames_to_acquire,
expected_image_size);
}
// restore previous state
set_file_state(det, prev_file_info);
set_common_acquire_config_state(det, prev_det_config_info);
// restore previous specific det type config
det.setExptime(exptime);
det.setReadNRows(n_rows);
}
}
/* dacs */
TEST_CASE("Setting and reading back Jungfrau dacs", "[.cmdcall][.dacs]") {

View File

@ -15,66 +15,6 @@ namespace sls {
using test::GET;
using test::PUT;
TEST_CASE("moench_acquire_check_file_size", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type =
det.getDetectorType().tsquash("Inconsistent detector types to test");
if (det_type == defs::MOENCH) {
// save previous state
testFileInfo prev_file_info = get_file_state(det);
testCommonDetAcquireInfo prev_det_config_info =
get_common_acquire_config_state(det);
// save previous specific det type config
auto exptime = det.getExptime().tsquash("inconsistent exptime to test");
auto num_udp_interfaces = det.getNumberofUDPInterfaces().tsquash(
"inconsistent number of udp interfaces");
auto n_rows =
det.getReadNRows().tsquash("inconsistent number of rows to test");
// defaults
int num_frames_to_acquire = 2;
testFileInfo test_file_info;
set_file_state(det, test_file_info);
testCommonDetAcquireInfo det_config;
det_config.num_frames_to_acquire = num_frames_to_acquire;
set_common_acquire_config_state(det, det_config);
// set default specific det type config
det.setExptime(std::chrono::microseconds{200});
det.setReadNRows(400);
// acquire
test_acquire_with_receiver(caller, det);
// check frames caught
test_frames_caught(det, num_frames_to_acquire);
// check file size (assuming local pc)
{
detParameters par(det_type);
int bytes_per_pixel = det.getDynamicRange().squash() / 8;
// if 2 udp interfaces, data split into half
size_t expected_image_size = (par.nChanX * par.nChanY * par.nChipX *
par.nChipY * bytes_per_pixel) /
num_udp_interfaces;
test_acquire_binary_file_size(test_file_info, num_frames_to_acquire,
expected_image_size);
}
// restore previous state
set_file_state(det, prev_file_info);
set_common_acquire_config_state(det, prev_det_config_info);
// restore previous specific det type config
det.setExptime(exptime);
det.setReadNRows(n_rows);
}
}
/* dacs */
TEST_CASE("Setting and reading back moench dacs", "[.cmdcall][.dacs]") {

View File

@ -17,74 +17,6 @@ namespace sls {
using test::GET;
using test::PUT;
TEST_CASE("mythen3_acquire_check_file_size", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type =
det.getDetectorType().tsquash("Inconsistent detector types to test");
if (det_type == defs::MYTHEN3) {
// save previous state
testFileInfo prev_file_info = get_file_state(det);
testCommonDetAcquireInfo prev_det_config_info =
get_common_acquire_config_state(det);
// save previous specific det type config
auto exptime =
det.getExptimeForAllGates().tsquash("inconsistent exptime to test");
auto dynamic_range =
det.getDynamicRange().tsquash("inconsistent dynamic range to test");
uint32_t counter_mask =
det.getCounterMask().tsquash("inconsistent counter mask to test");
// defaults
int num_frames_to_acquire = 2;
testFileInfo test_file_info;
set_file_state(det, test_file_info);
testCommonDetAcquireInfo det_config;
det_config.num_frames_to_acquire = num_frames_to_acquire;
set_common_acquire_config_state(det, det_config);
// set default specific det type config
det.setExptime(-1, std::chrono::microseconds{200});
int test_dynamic_range = 16;
det.setDynamicRange(test_dynamic_range);
int test_counter_mask = 0x3;
int num_counters = __builtin_popcount(test_counter_mask);
det.setCounterMask(test_counter_mask);
// acquire
test_acquire_with_receiver(caller, det);
// check frames caught
test_frames_caught(det, num_frames_to_acquire);
// check file size (assuming local pc)
{
detParameters par(det_type);
int bytes_per_pixel = test_dynamic_range / 8;
int num_channels_per_counter = par.nChanX / 3;
size_t expected_image_size = num_channels_per_counter *
num_counters * par.nChipX *
bytes_per_pixel;
test_acquire_binary_file_size(test_file_info, num_frames_to_acquire,
expected_image_size);
}
// restore previous state
set_file_state(det, prev_file_info);
set_common_acquire_config_state(det, prev_det_config_info);
// restore previous specific det type config
for (int iGate = 0; iGate < 3; ++iGate) {
det.setExptime(iGate, exptime[iGate]);
}
det.setDynamicRange(dynamic_range);
det.setCounterMask(counter_mask);
}
}
/* dacs */
TEST_CASE("Setting and reading back MYTHEN3 dacs", "[.cmdcall][.dacs]") {

View File

@ -12,7 +12,6 @@
#include <thread>
#include "tests/globals.h"
#include <filesystem>
namespace sls {

View File

@ -352,20 +352,16 @@ void DataProcessor::ProcessAnImage(sls_receiver_header &header, size_t &size,
if (framePadding && nump < generalData->packetsPerFrame)
PadMissingPackets(header, data);
if (generalData->readoutType == slsDetectorDefs::DIGITAL_ONLY ||
generalData->readoutType == slsDetectorDefs::ANALOG_AND_DIGITAL ||
generalData->readoutType == slsDetectorDefs::DIGITAL_AND_TRANSCEIVER) {
// rearrange ctb digital bits
if (!generalData->ctbDbitList.empty()) {
ArrangeDbitData(size, data);
} else if (generalData->ctbDbitReorder) {
std::vector<int> ctbDbitList(64);
std::iota(ctbDbitList.begin(), ctbDbitList.end(), 0);
generalData->SetctbDbitList(ctbDbitList);
ArrangeDbitData(size, data);
} else if (generalData->ctbDbitOffset > 0) {
RemoveTrailingBits(size, data);
}
// rearrange ctb digital bits
if (!generalData->ctbDbitList.empty()) {
ArrangeDbitData(size, data);
} else if (generalData->ctbDbitReorder) {
std::vector<int> ctbDbitList(64);
std::iota(ctbDbitList.begin(), ctbDbitList.end(), 0);
generalData->SetctbDbitList(ctbDbitList);
ArrangeDbitData(size, data);
} else if (generalData->ctbDbitOffset > 0) {
RemoveTrailingBits(size, data);
}
// 'stream Image' check has to be done here before crop image
@ -679,11 +675,11 @@ void DataProcessor::ArrangeDbitData(size_t &size, char *data) {
memcpy(data + nAnalogDataBytes, result.data(),
totalNumBytes * sizeof(uint8_t));
LOG(logDEBUG1) << "nDigitalDataBytes: " << totalNumBytes
LOG(logDEBUG1) << "totalNumBytes: " << totalNumBytes
<< " nAnalogDataBytes:" << nAnalogDataBytes
<< " ctbDbitOffset:" << ctbDbitOffset
<< " nTransceiverDataBytes:" << nTransceiverDataBytes
<< " toal size:" << size;
<< " size:" << size;
}
void DataProcessor::CropImage(size_t &size, char *data) {

View File

@ -6,7 +6,7 @@ This file is used to start up simulators, receivers and run all the tests on the
import argparse
import os, sys, subprocess, time, colorama
from colorama import Fore, Style
from colorama import Fore
from slsdet import Detector, detectorType, detectorSettings
from slsdet.defines import DEFAULT_TCP_CNTRL_PORTNO, DEFAULT_TCP_RX_PORTNO, DEFAULT_UDP_DST_PORTNO
HALFMOD2_TCP_CNTRL_PORTNO=1955
@ -14,41 +14,48 @@ HALFMOD2_TCP_RX_PORTNO=1957
colorama.init(autoreset=True)
def Log(color, message):
print(f"{color}{message}{Style.RESET_ALL}", flush=True)
class RuntimeException (Exception):
def __init__ (self, message):
super().__init__(Log(Fore.RED, message))
super().__init__(Fore.RED + message)
def Log(color, message):
print('\n' + color + message, flush=True)
def checkIfProcessRunning(processName):
cmd = f"pgrep -f {processName}"
res = subprocess.getoutput(cmd)
return res.strip().splitlines()
return bool(res.strip())
def killProcess(name):
pids = checkIfProcessRunning(name)
if pids:
Log(Fore.GREEN, f"Killing '{name}' processes with PIDs: {', '.join(pids)}")
for pid in pids:
try:
p = subprocess.run(['kill', pid])
if p.returncode != 0 and bool(checkIfProcessRunning(name)):
raise RuntimeException(f"Could not kill {name} with pid {pid}")
except Exception as e:
Log(Fore.RED, f"Failed to kill process {name} pid:{pid}. Exception occured: [code:{e}, msg:{e.stderr}]")
raise
#else:
# Log(Fore.WHITE, 'process not running : ' + name)
if checkIfProcessRunning(name):
Log(Fore.GREEN, 'killing ' + name)
p = subprocess.run(['killall', name])
if p.returncode != 0:
raise RuntimeException('killall failed for ' + name)
else:
print('process not running : ' + name)
def cleanup(fp):
def killAllStaleProcesses(fp):
killProcess('eigerDetectorServer_virtual')
killProcess('jungfrauDetectorServer_virtual')
killProcess('mythen3DetectorServer_virtual')
killProcess('gotthard2DetectorServer_virtual')
killProcess('ctbDetectorServer_virtual')
killProcess('moenchDetectorServer_virtual')
killProcess('xilinx_ctbDetectorServer_virtual')
killProcess('slsReceiver')
killProcess('slsMultiReceiver')
cleanSharedmemory(fp)
def cleanup(name, fp):
'''
kill both servers, receivers and clean shared memory
'''
Log(Fore.GREEN, 'Cleaning up...')
killProcess('DetectorServer_virtual')
killProcess(name + 'DetectorServer_virtual')
killProcess('slsReceiver')
killProcess('slsMultiReceiver')
cleanSharedmemory(fp)
@ -177,7 +184,7 @@ else:
servers = args.servers
Log(Fore.WHITE, 'Arguments:\nrx_hostname: ' + args.rx_hostname + '\nsettingspath: \'' + args.settingspath + '\nservers: \'' + ' '.join(servers) + '\'')
Log(Fore.WHITE, 'Arguments:\nrx_hostname: ' + args.rx_hostname + '\nsettingspath: \'' + args.settingspath + '\'')
# redirect to file
@ -200,7 +207,7 @@ with open(fname, 'w') as fp:
try:
startGeneralTests(fp, file_results)
cleanup(fp)
killAllStaleProcesses(fp)
testError = False
for server in servers:
@ -215,12 +222,12 @@ with open(fname, 'w') as fp:
Log(Fore.BLUE, 'Cmd tests for ' + server + ' (results: ' + file_results + ')')
# cmd tests for det
cleanup(fp)
cleanup(server, fp)
startServer(server)
startReceiver(server)
loadConfig(server, args.rx_hostname, args.settingspath)
startCmdTests(server, fp, file_results)
cleanup(fp)
cleanup(server, fp)
except Exception as e:
# redirect to terminal