From 3a8c7c6e2aa201c7750e985de61017bbd2aa9ffc Mon Sep 17 00:00:00 2001 From: Samuel Debionne Date: Mon, 13 May 2019 10:58:54 +0200 Subject: [PATCH 01/76] Fix typo in conda install instructions --- manual/manual-main/slsDetectorInstall.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manual/manual-main/slsDetectorInstall.tex b/manual/manual-main/slsDetectorInstall.tex index dcf7fc84e..542935881 100755 --- a/manual/manual-main/slsDetectorInstall.tex +++ b/manual/manual-main/slsDetectorInstall.tex @@ -127,7 +127,7 @@ conda install sls_detector_gui=4.0.0 \begin{verbatim} #Add conda channels conda config --add channels conda-forge -conda config --add channels sls_detector +conda config --add channels slsdetectorgroup #Install latest version conda install sls_detector From fbada2e81a68681091d74d8fc3f7ca46f9a11966 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Tue, 14 May 2019 10:13:24 +0200 Subject: [PATCH 02/76] commented qwt for now --- conda-recepie/meta.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conda-recepie/meta.yaml b/conda-recepie/meta.yaml index f8fe035c4..c929d0122 100755 --- a/conda-recepie/meta.yaml +++ b/conda-recepie/meta.yaml @@ -16,8 +16,8 @@ requirements: - {{ compiler('c') }} - {{compiler('cxx')}} - cmake - - qwt 6.* - - qt=4.8.7=7 + # - qwt 6.* #require qt5 investigate befor activating gui + # - qt=4.8.7=7 - zeromq=4.2.5=hfc679d8_5 - pyzmq - xorg-libx11 From 0224dccd2e1ad71a3257c8dc1a536cb0860fd737 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Fr=C3=B6jdh?= Date: Tue, 14 May 2019 11:08:25 +0200 Subject: [PATCH 03/76] Added noexcept and constexpr (#21) * noexcept and constexpr * check size --- .../include/FixedCapacityContainer.h | 78 ++++++++++++------- .../tests/test-FixedCapacityContainer.cpp | 14 +++- .../tests/test-sls_detector_defs.cpp | 1 - tests/CMakeLists.txt | 15 +++- 4 files changed, 75 insertions(+), 33 deletions(-) diff --git a/slsSupportLib/include/FixedCapacityContainer.h b/slsSupportLib/include/FixedCapacityContainer.h index 046f5b1f3..4b39d52db 100644 --- a/slsSupportLib/include/FixedCapacityContainer.h +++ b/slsSupportLib/include/FixedCapacityContainer.h @@ -1,4 +1,3 @@ - #pragma once #include #include @@ -12,39 +11,43 @@ template class FixedCapacityContainer { explicit FixedCapacityContainer(std::initializer_list l); explicit FixedCapacityContainer(const std::vector &v); + template + explicit FixedCapacityContainer( + const FixedCapacityContainer &other) noexcept; + FixedCapacityContainer &operator=(const std::vector &other); - bool operator==(const std::vector &other) const; - bool operator!=(const std::vector &other) const; + bool operator==(const std::vector &other) const noexcept; + bool operator!=(const std::vector &other) const noexcept; template - bool - operator==(const FixedCapacityContainer &other) const; + bool operator==(const FixedCapacityContainer &other) const + noexcept; template - bool - operator!=(const FixedCapacityContainer &other) const; + bool operator!=(const FixedCapacityContainer &other) const + noexcept; T &operator[](size_t i) { return data_[i]; } const T &operator[](size_t i) const { return data_[i]; } - size_t size() const { return size_; } - bool empty() const{ return size_ == 0;} - size_t capacity() const { return Capacity; } + constexpr size_t size() const noexcept { return size_; } + bool empty() const noexcept { return size_ == 0; } + constexpr size_t capacity() const noexcept { return Capacity; } void push_back(const T &value); void resize(size_t new_size); void erase(T *ptr); - T &front() { return data_.front(); } - T &back() { return data_[size_ - 1]; } - const T &front() const { return data_.front(); } - const T &back() const { return data_[size_ - 1]; } + T &front() noexcept { return data_.front(); } + T &back() noexcept { return data_[size_ - 1]; } + constexpr const T &front() const noexcept { return data_.front(); } + constexpr const T &back() const noexcept { return data_[size_ - 1]; } // iterators - T *begin() { return &data_[0]; } - T *end() { return &data_[size_]; } - const T *cbegin() const { return &data_[0]; } - const T *cend() const { return &data_[size_]; } + T *begin() noexcept { return &data_[0]; } + T *end() noexcept { return &data_[size_]; } + const T *cbegin() const noexcept { return &data_[0]; } + const T *cend() const noexcept { return &data_[size_]; } private: size_t size_{0}; @@ -62,10 +65,24 @@ FixedCapacityContainer::FixedCapacityContainer( template FixedCapacityContainer::FixedCapacityContainer( const std::vector &v) { + if (v.size() > Capacity) { + throw std::runtime_error( + "Capacity needs to be same size or larger than vector"); + } size_ = v.size(); std::copy(v.begin(), v.end(), data_.begin()); } +template +template +FixedCapacityContainer::FixedCapacityContainer( + const FixedCapacityContainer &other) noexcept { + static_assert(Capacity >= OtherCapacity, + "Container needs to be same size or larger"); + size_ = other.size(); + std::copy(other.cbegin(), other.cend(), data_.begin()); +} + template void FixedCapacityContainer::push_back(const T &value) { if (size_ == Capacity) { @@ -94,7 +111,7 @@ operator=(const std::vector &other) { template bool FixedCapacityContainer:: -operator==(const std::vector &other) const { +operator==(const std::vector &other) const noexcept { if (size_ != other.size()) { return false; } else { @@ -109,14 +126,15 @@ operator==(const std::vector &other) const { template bool FixedCapacityContainer:: -operator!=(const std::vector &other) const { +operator!=(const std::vector &other) const noexcept { return !(*this == other); } template template bool FixedCapacityContainer:: -operator==(const FixedCapacityContainer &other) const { +operator==(const FixedCapacityContainer &other) const + noexcept { if (size_ != other.size()) { return false; } else { @@ -132,7 +150,8 @@ operator==(const FixedCapacityContainer &other) const { template template bool FixedCapacityContainer:: -operator!=(const FixedCapacityContainer &other) const { +operator!=(const FixedCapacityContainer &other) const + noexcept { return !(*this == other); } @@ -146,26 +165,27 @@ void FixedCapacityContainer::erase(T *ptr) { } /* Free function concerning FixedCapacityContainer */ - template -T *begin(FixedCapacityContainer &container) { +constexpr T *begin(FixedCapacityContainer &container) noexcept { return container.begin(); } template -T *end(FixedCapacityContainer &container) { +constexpr T *end(FixedCapacityContainer &container) noexcept { return container.end(); } template -bool operator==(const std::vector &vec, - const FixedCapacityContainer &fixed_container) { +bool operator==( + const std::vector &vec, + const FixedCapacityContainer &fixed_container) noexcept { return fixed_container == vec; } template -bool operator!=(const std::vector &vec, - const FixedCapacityContainer &fixed_container) { +bool operator!=( + const std::vector &vec, + const FixedCapacityContainer &fixed_container) noexcept { return fixed_container != vec; } diff --git a/slsSupportLib/tests/test-FixedCapacityContainer.cpp b/slsSupportLib/tests/test-FixedCapacityContainer.cpp index 78215d336..a5c931a12 100644 --- a/slsSupportLib/tests/test-FixedCapacityContainer.cpp +++ b/slsSupportLib/tests/test-FixedCapacityContainer.cpp @@ -201,5 +201,17 @@ SCENARIO("Assigning containers to each other", "[support]") { REQUIRE(c[2] == 3); } } + WHEN("We create a const FixedCapacityContainer"){ + const FixedCapacityContainer c(a); + THEN("The values are still the same using const operators"){ + REQUIRE(c[0] == 1); + REQUIRE(c[1] == 2); + REQUIRE(c[2] == 3); + REQUIRE(c.front() == 1); + REQUIRE(c.back() == 3); + + } + } } -} \ No newline at end of file +} + diff --git a/slsSupportLib/tests/test-sls_detector_defs.cpp b/slsSupportLib/tests/test-sls_detector_defs.cpp index 9b745a29e..dd5ab366d 100644 --- a/slsSupportLib/tests/test-sls_detector_defs.cpp +++ b/slsSupportLib/tests/test-sls_detector_defs.cpp @@ -1,5 +1,4 @@ #include "catch.hpp" -#include "slsDetector.h" #include "sls_detector_defs.h" using dt = slsDetectorDefs::detectorType; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b8366739e..39607890c 100755 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -12,11 +12,22 @@ target_link_libraries(tests slsProjectOptions slsProjectWarnings slsSupportLib - slsDetectorShared - slsReceiverShared pthread rt ) + +if (SLS_USE_TEXTCLIENT) + target_link_libraries(tests + slsDetectorShared + ) +endif (SLS_USE_TEXTCLIENT) + +if (SLS_USE_RECEIVER) + target_link_libraries(tests + slsReceiverShared + ) +endif (SLS_USE_RECEIVER) + set_target_properties(tests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) From aff6e30b65d1940dab914df8d5985d0704cd507a Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Tue, 14 May 2019 11:41:39 +0200 Subject: [PATCH 04/76] short sleep in socket test --- slsSupportLib/tests/test-Sockets.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/slsSupportLib/tests/test-Sockets.cpp b/slsSupportLib/tests/test-Sockets.cpp index 184cbc71e..8726c2515 100644 --- a/slsSupportLib/tests/test-Sockets.cpp +++ b/slsSupportLib/tests/test-Sockets.cpp @@ -29,6 +29,7 @@ TEST_CASE("The server recive the same message as we send", "[support]") { std::copy(std::begin(m), std::end(m), sent_message.data()); auto s = std::async(std::launch::async, server); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); auto client = sls::DetectorSocket("localhost", 1950); client.sendData(sent_message.data(), sent_message.size()); client.receiveData(received_message.data(), received_message.size()); From d114f8db908154ec60f2aa2f165c01498764a0ab Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Tue, 14 May 2019 11:43:45 +0200 Subject: [PATCH 05/76] receiver bug fix: ctb extractng bits source pointer bug --- slsReceiverSoftware/src/DataProcessor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slsReceiverSoftware/src/DataProcessor.cpp b/slsReceiverSoftware/src/DataProcessor.cpp index 21d3163d9..9a39a79ed 100755 --- a/slsReceiverSoftware/src/DataProcessor.cpp +++ b/slsReceiverSoftware/src/DataProcessor.cpp @@ -537,7 +537,7 @@ void DataProcessor::RearrangeDbitData(char* buf) { } // copy back to buf and update size - memcpy(source + digOffset, result.data(), result.size() * sizeof(uint64_t)); + memcpy(buf + digOffset - (*ctbDbitOffset), result.data(), result.size() * sizeof(uint64_t)); (*((uint32_t*)buf)) = result.size() * sizeof(uint64_t); } From 1029ce97051dec76f6e62c6188a12efb7e95f4f8 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Tue, 14 May 2019 14:53:59 +0200 Subject: [PATCH 06/76] minor --- .clang-tidy | 8 ++++---- slsDetectorSoftware/src/multiSlsDetector.cpp | 2 +- slsSupportLib/tests/test-FixedCapacityContainer.cpp | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index c70b40d30..ed80138ee 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -23,10 +23,10 @@ AnalyzeTemporaryDtors: false FormatStyle: none CheckOptions: - { key: readability-identifier-naming.NamespaceCase, value: lower_case } - - { key: readability-identifier-naming.FunctionCase, value: lower_case } + # - { key: readability-identifier-naming.FunctionCase, value: lower_case } - { key: readability-identifier-naming.ClassCase, value: CamelCase } - - { key: readability-identifier-naming.MethodCase, value: CamelCase } - - { key: readability-identifier-naming.StructCase, value: CamelCase } - - { key: readability-identifier-naming.VariableCase, value: lower_case } + # - { key: readability-identifier-naming.MethodCase, value: CamelCase } + # - { key: readability-identifier-naming.StructCase, value: CamelCase } + # - { key: readability-identifier-naming.VariableCase, value: lower_case } - { key: readability-identifier-naming.GlobalConstantCase, value: UPPER_CASE } ... diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index 231151328..a227fb1eb 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -421,7 +421,7 @@ void multiSlsDetector::addSlsDetector(const std::string &hostname) { } // get type by connecting - detectorType type = slsDetector::getTypeFromDetector(hostname.c_str(), DEFAULT_PORTNO); + detectorType type = slsDetector::getTypeFromDetector(hostname, DEFAULT_PORTNO); int pos = (int)detectors.size(); detectors.push_back(sls::make_unique(type, multiId, pos, false)); multi_shm()->numberOfDetectors = detectors.size(); diff --git a/slsSupportLib/tests/test-FixedCapacityContainer.cpp b/slsSupportLib/tests/test-FixedCapacityContainer.cpp index a5c931a12..9277df258 100644 --- a/slsSupportLib/tests/test-FixedCapacityContainer.cpp +++ b/slsSupportLib/tests/test-FixedCapacityContainer.cpp @@ -10,7 +10,7 @@ SCENARIO("FixedCapacityContainers can be sized and resized", "[support]") { FixedCapacityContainer vec; REQUIRE(vec.empty()); - REQUIRE(vec.size() == 0); + REQUIRE(vec.size() == 0); //NOLINT REQUIRE(vec.capacity() == n_elem); REQUIRE(sizeof(vec) == sizeof(int) * n_elem + sizeof(size_t)); From 3e654977ca8b9d4db2288c0416b44c2234b30858 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Tue, 14 May 2019 16:41:25 +0200 Subject: [PATCH 07/76] slsReceiver bug fix in ctb extracting digital bits --- slsReceiverSoftware/src/DataProcessor.cpp | 43 ++++++++++++++--------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/slsReceiverSoftware/src/DataProcessor.cpp b/slsReceiverSoftware/src/DataProcessor.cpp index 9a39a79ed..e8cf7c276 100755 --- a/slsReceiverSoftware/src/DataProcessor.cpp +++ b/slsReceiverSoftware/src/DataProcessor.cpp @@ -513,32 +513,43 @@ void DataProcessor::RearrangeDbitData(char* buf) { } const int numSamples = (ctbDigitalDataBytes / sizeof(uint64_t)); + const int digOffset = FIFO_HEADER_NUMBYTES + sizeof(sls_receiver_header) + (*ctbAnalogDataBytes); - // ceil as numResult64Bytes could be decimal - const int numResult64Bytes = ceil((double)(numSamples * (*ctbDbitList).size()) / 64.00); - std::vector result(numResult64Bytes, 0); + // ceil as numResult32Bits could be decimal + const int numResult32Bits = ceil((double)(numSamples * (*ctbDbitList).size()) / 32.00); + uint32_t result[numResult32Bits]; + memset(result, 0, numResult32Bits * sizeof(uint32_t)); - auto dest = result.data(); - const int digOffset = FIFO_HEADER_NUMBYTES + sizeof(sls_receiver_header) + (*ctbAnalogDataBytes) + (*ctbDbitOffset); - auto source = (uint64_t*)(buf + digOffset); + uint32_t* dest = result; + uint64_t* source = (uint64_t*)(buf + digOffset + (*ctbDbitOffset)); // loop through digital bit enable vector + int bitoffset = 0; for (auto bi : (*ctbDbitList)) { + // where numbits * numsamples is not a multiple of 32 + if (bitoffset != 0) { + bitoffset = 0; + ++dest; + } + // loop through the frame digital data for (auto ptr = source; ptr < (source + numSamples);) { - // extract destination in 64 bit batches - for (int i = 0; i != 64; ++i) { - // get selected bit from each 64 bit - int bit = (*ptr++ >> bi) & 1; - *dest |= bit << i; - } - ++dest; - } + // get selected bit from each 32 bit + uint32_t bit = (*ptr++ >> bi) & 1; + *dest |= bit << bitoffset; + ++bitoffset; + // extract destination in 32 bit batches + if (bitoffset == 32) { + bitoffset = 0; + ++dest; + } + } } + // copy back to buf and update size - memcpy(buf + digOffset - (*ctbDbitOffset), result.data(), result.size() * sizeof(uint64_t)); - (*((uint32_t*)buf)) = result.size() * sizeof(uint64_t); + memcpy(buf + digOffset, result, numResult32Bits * sizeof(uint32_t)); + (*((uint32_t*)buf)) = numResult32Bits * sizeof(uint32_t); } /** eiger specific */ From ab5aa78b8abc888b63c2f2f4969a1f8a6162ac87 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Tue, 14 May 2019 16:53:50 +0200 Subject: [PATCH 08/76] clang-tidy modernize --- slsReceiverSoftware/include/DataProcessor.h | 10 +++++----- slsReceiverSoftware/src/DataProcessor.cpp | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/slsReceiverSoftware/include/DataProcessor.h b/slsReceiverSoftware/include/DataProcessor.h index 21a1348fd..678a3ff25 100755 --- a/slsReceiverSoftware/include/DataProcessor.h +++ b/slsReceiverSoftware/include/DataProcessor.h @@ -53,7 +53,7 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { * Destructor * Calls Base Class DestroyThread() and decrements NumberofDataProcessors */ - ~DataProcessor(); + ~DataProcessor() override; //*** getters *** @@ -61,7 +61,7 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { * Returns if the thread is currently running * @returns true if thread is running, else false */ - bool IsRunning(); + bool IsRunning() override; /** * Get acquisition started flag @@ -170,7 +170,7 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { void SetupFileWriter(bool fwe, int* nd, uint32_t* maxf, char* fname, char* fpath, uint64_t* findex, bool* owenable, int* dindex, int* nunits, uint64_t* nf, uint32_t* dr, - uint32_t* portno, GeneralData* g = 0); + uint32_t* portno, GeneralData* g = nullptr); /** * Create New File @@ -231,7 +231,7 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { * Get Type * @return type */ - std::string GetType(); + std::string GetType() override; /** * Record First Indices (firstAcquisitionIndex, firstMeasurementIndex) @@ -250,7 +250,7 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { * Pop bound addresses, process them, * write to file if needed & free the address */ - void ThreadExecution(); + void ThreadExecution() override; /** * Frees dummy buffer, diff --git a/slsReceiverSoftware/src/DataProcessor.cpp b/slsReceiverSoftware/src/DataProcessor.cpp index e8cf7c276..64c82d718 100755 --- a/slsReceiverSoftware/src/DataProcessor.cpp +++ b/slsReceiverSoftware/src/DataProcessor.cpp @@ -16,9 +16,9 @@ #include "DataStreamer.h" #include "sls_detector_exceptions.h" -#include -#include +#include #include +#include const std::string DataProcessor::TypeName = "DataProcessor"; @@ -31,7 +31,7 @@ DataProcessor::DataProcessor(int ind, detectorType dtype, Fifo* f, std::vector * cdl, int* cdo, int* cad) : ThreadObject(ind), - runningFlag(0), + runningFlag(false), generalData(nullptr), fifo(f), myDetectorType(dtype), @@ -281,7 +281,7 @@ void DataProcessor::ThreadExecution() { "pop 0x" << std::hex << (void*)(buffer) << std::dec << ":" << buffer; //check dummy - uint32_t numBytes = (uint32_t)(*((uint32_t*)buffer)); + auto numBytes = (uint32_t)(*((uint32_t*)buffer)); FILE_LOG(logDEBUG1) << "DataProcessor " << index << ", Numbytes:" << numBytes; if (numBytes == DUMMY_PACKET_VALUE) { StopProcessing(buffer); @@ -316,7 +316,7 @@ void DataProcessor::StopProcessing(char* buf) { void DataProcessor::ProcessAnImage(char* buf) { - sls_receiver_header* rheader = (sls_receiver_header*) (buf + FIFO_HEADER_NUMBYTES); + auto* rheader = (sls_receiver_header*) (buf + FIFO_HEADER_NUMBYTES); sls_detector_header header = rheader->detHeader; uint64_t fnum = header.frameNumber; currentFrameIndex = fnum; @@ -371,7 +371,7 @@ void DataProcessor::ProcessAnImage(char* buf) { // call back with modified size else if (rawDataModifyReadyCallBack) { - uint32_t revsize = (uint32_t)(*((uint32_t*)buf)); + auto revsize = (uint32_t)(*((uint32_t*)buf)); rawDataModifyReadyCallBack( (char*)rheader, buf + FIFO_HEADER_NUMBYTES + sizeof(sls_receiver_header), @@ -456,7 +456,7 @@ void DataProcessor::PadMissingPackets(char* buf) { FILE_LOG(logDEBUG) << index << ": Padding Missing Packets"; uint32_t pperFrame = generalData->packetsPerFrame; - sls_receiver_header* header = (sls_receiver_header*) (buf + FIFO_HEADER_NUMBYTES); + auto* header = (sls_receiver_header*) (buf + FIFO_HEADER_NUMBYTES); uint32_t nmissing = pperFrame - header->detHeader.packetNumber; sls_bitset pmask = header->packetsMask; @@ -521,7 +521,7 @@ void DataProcessor::RearrangeDbitData(char* buf) { memset(result, 0, numResult32Bits * sizeof(uint32_t)); uint32_t* dest = result; - uint64_t* source = (uint64_t*)(buf + digOffset + (*ctbDbitOffset)); + auto* source = (uint64_t*)(buf + digOffset + (*ctbDbitOffset)); // loop through digital bit enable vector int bitoffset = 0; From 81e858ea4d684aa1584f02a9e5f56c7999920ddf Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Tue, 14 May 2019 17:05:27 +0200 Subject: [PATCH 09/76] clang-tidy implicit bool --- slsReceiverSoftware/src/DataProcessor.cpp | 40 +++++++++++------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/slsReceiverSoftware/src/DataProcessor.cpp b/slsReceiverSoftware/src/DataProcessor.cpp index 64c82d718..73610036d 100755 --- a/slsReceiverSoftware/src/DataProcessor.cpp +++ b/slsReceiverSoftware/src/DataProcessor.cpp @@ -74,8 +74,8 @@ DataProcessor::DataProcessor(int ind, detectorType dtype, Fifo* f, DataProcessor::~DataProcessor() { - if (file) delete file; - if (tempBuffer) delete [] tempBuffer; + if (file != nullptr) delete file; + if (tempBuffer != nullptr) delete [] tempBuffer; ThreadObject::DestroyThread(); } @@ -145,7 +145,7 @@ void DataProcessor::ResetParametersforNewMeasurement(){ firstMeasurementIndex = 0; measurementStartedFlag = false; - if (tempBuffer) { + if (tempBuffer != nullptr) { delete [] tempBuffer; tempBuffer = nullptr; } @@ -177,7 +177,7 @@ void DataProcessor::RecordFirstIndices(uint64_t fnum) { void DataProcessor::SetGeneralData(GeneralData* g) { generalData = g; generalData->Print(); - if (file) { + if (file != nullptr) { if (file->GetFileType() == HDF5) { file->SetNumberofPixels(generalData->nPixelsX, generalData->nPixelsY); } @@ -196,7 +196,7 @@ int DataProcessor::SetThreadPriority(int priority) { void DataProcessor::SetFileFormat(const fileFormat f) { - if (file && file->GetFileType() != f) { + if ((file != nullptr) && file->GetFileType() != f) { //remember the pointer values before they are destroyed int nd[MAX_DIMENSIONS];nd[0] = 0; nd[1] = 0; uint32_t* maxf = nullptr; @@ -219,11 +219,11 @@ void DataProcessor::SetupFileWriter(bool fwe, int* nd, uint32_t* maxf, GeneralData* g) { fileWriteEnable = fwe; - if (g) + if (g != nullptr) generalData = g; - if (file) { + if (file != nullptr) { delete file; file = nullptr; } @@ -263,12 +263,12 @@ int DataProcessor::CreateNewFile(bool en, uint64_t nf, uint64_t at, uint64_t st, void DataProcessor::CloseFiles() { - if (file) + if (file != nullptr) file->CloseAllFiles(); } void DataProcessor::EndofAcquisition(bool anyPacketsCaught, uint64_t numf) { - if (file && file->GetFileType() == HDF5) { + if ((file != nullptr) && file->GetFileType() == HDF5) { file->EndofAcquisition(anyPacketsCaught, numf); } } @@ -307,7 +307,7 @@ void DataProcessor::StopProcessing(char* buf) { else fifo->FreeAddress(buf); - if (file) + if (file != nullptr) file->CloseCurrentFile(); StopRunning(); FILE_LOG(logDEBUG1) << index << ": Processing Completed"; @@ -361,7 +361,7 @@ void DataProcessor::ProcessAnImage(char* buf) { } // normal call back - if (rawDataReadyCallBack) { + if (rawDataReadyCallBack != nullptr) { rawDataReadyCallBack( (char*)rheader, buf + FIFO_HEADER_NUMBYTES + sizeof(sls_receiver_header), @@ -370,7 +370,7 @@ void DataProcessor::ProcessAnImage(char* buf) { } // call back with modified size - else if (rawDataModifyReadyCallBack) { + else if (rawDataModifyReadyCallBack != nullptr) { auto revsize = (uint32_t)(*((uint32_t*)buf)); rawDataModifyReadyCallBack( (char*)rheader, @@ -382,7 +382,7 @@ void DataProcessor::ProcessAnImage(char* buf) { // write to file - if (file) + if (file != nullptr) file->WriteToFile(buf + FIFO_HEADER_NUMBYTES, sizeof(sls_receiver_header) + (uint32_t)(*((uint32_t*)buf)), //+ size of data (resizable from previous call back fnum-firstMeasurementIndex, nump); @@ -393,7 +393,7 @@ void DataProcessor::ProcessAnImage(char* buf) { bool DataProcessor::SendToStreamer() { //skip - if (!(*streamingFrequency)) { + if ((*streamingFrequency) == 0u) { if (!CheckTimer()) return false; } else { @@ -433,7 +433,7 @@ bool DataProcessor::CheckCount() { void DataProcessor::SetPixelDimension() { - if (file) { + if (file != nullptr) { if (file->GetFileType() == HDF5) { file->SetNumberofPixels(generalData->nPixelsX, generalData->nPixelsY); } @@ -472,7 +472,7 @@ void DataProcessor::PadMissingPackets(char* buf) { continue; // done with padding, exit loop earlier - if (!nmissing) + if (nmissing == 0u) break; FILE_LOG(logDEBUG) << "padding for " << index << " for pnum: " << pnum << std::endl; @@ -482,7 +482,7 @@ void DataProcessor::PadMissingPackets(char* buf) { //for gotthard, 1st packet: 4 bytes fnum, CACA + CACA, 639*2 bytes data // 2nd packet: 4 bytes fnum, previous 1*2 bytes data + 640*2 bytes data !! case GOTTHARD: - if(!pnum) + if(pnum == 0u) memset(buf + fifohsize + (pnum * dsize), 0xFF, dsize-2); else memset(buf + fifohsize + (pnum * dsize), 0xFF, dsize+2); @@ -507,7 +507,7 @@ void DataProcessor::RearrangeDbitData(char* buf) { int ctbDigitalDataBytes = totalSize - (*ctbAnalogDataBytes) - (*ctbDbitOffset); // no digital data - if (!ctbDigitalDataBytes) { + if (ctbDigitalDataBytes == 0) { FILE_LOG(logWARNING) << "No digital data for call back, yet dbitlist is not empty."; return; } @@ -566,7 +566,7 @@ void DataProcessor::InsertGapPixels(char* buf, uint32_t dr) { const uint32_t b1px = generalData->imageSize / (npx); // not double as not dealing with 4 bit mode const uint32_t b2px = 2 * b1px; - const uint32_t b1pxofst = (index ? b1px : 0); // left fpga (index 0) has no extra 1px offset, but right fpga has + const uint32_t b1pxofst = (index != 0 ? b1px : 0); // left fpga (index 0) has no extra 1px offset, but right fpga has const uint32_t b1chip = 256 * b1px; const uint32_t b1line = (nx * b1px); @@ -596,7 +596,7 @@ void DataProcessor::InsertGapPixels(char* buf, uint32_t dr) { dstgp1 = srcgp1 + b1px; srcgp2 = srcgp1 + b3px; dstgp2 = dstgp1 + b1px; - if (!index) { + if (index == 0u) { srcgp3 = srcptr + b1line - b2px; dstgp3 = srcgp3 + b1px; } else { From 29be6f3b345aac51a71bfe0b6b52ae124ae21ed3 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Tue, 14 May 2019 17:07:56 +0200 Subject: [PATCH 10/76] no check for null when deleting --- slsReceiverSoftware/src/DataProcessor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/slsReceiverSoftware/src/DataProcessor.cpp b/slsReceiverSoftware/src/DataProcessor.cpp index 73610036d..a33ffd06a 100755 --- a/slsReceiverSoftware/src/DataProcessor.cpp +++ b/slsReceiverSoftware/src/DataProcessor.cpp @@ -74,8 +74,8 @@ DataProcessor::DataProcessor(int ind, detectorType dtype, Fifo* f, DataProcessor::~DataProcessor() { - if (file != nullptr) delete file; - if (tempBuffer != nullptr) delete [] tempBuffer; + delete file; + delete [] tempBuffer; ThreadObject::DestroyThread(); } From 741ee3b44c483be4b085ad56bec1715029497a98 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Tue, 14 May 2019 17:08:07 +0200 Subject: [PATCH 11/76] ctb server bug fix: udp ip not reset before overwriting (smaller size creates problems) --- .../bin/ctbDetectorServer_developer | Bin 167808 -> 167848 bytes .../communication_funcs_UDP.h | 1 + slsSupportLib/include/versionAPI.h | 2 +- 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer b/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer index b550b0c93f5244021bf678c0ad25e4aae993769c..066549fcc91a34cfaeab3d85b2ebea2c788228c5 100755 GIT binary patch delta 51458 zcma%k4O~=3_y4`%g+&*=2+AUui)e^SuHXwM2-L;h8-_K|8oHH}$oH;Xd z=Jn3zf7G_@qqco#j!MsD7^V$E3d5GyGd_tKjL!re!|;p*Ga)As$4>wG^xLIDU41mg zDcv8>E%z02%dc0A5LNK{cJ09`VfT|f%-1JDOW=OK2Nu(Hy|7S8|g!$zG!h90T4mS3U zYb*4PQyF;Tn3Zp347t`Jo6-b5sQNg*m{rB|X+kexy?`-ll_puJDrafX)$j7xCJWWT z5P&6YN)~L%EW&WXR_=pfuV8g;br;NxcyzrUbcP1;3AV^uY+($H_zGKOv@qgZm8p@u zA;91RQf@`QHQ$o2ey~{kJ!0+mh~>BV2>cdV?C%g;>LoUuHCZ=EV)d*EQpZ;YMyd>C zrcY;MrwZPX*VyQ!I&IpbwkesP96zEqzkqkPGTlqt9z7$Kw7l#@3;G<8>x9}vvQ^6z+ zl}{T0g9h;Tik`lO6%cg1RJd$l2*4DbIu_Gn&If%yikENERkFGultItbTLnu3$}pR$ z2fnl-PMc#^uE!Q24-ulqfirO=F>ov)6@r)gD!=V7%Bz3VSf97Vzqm||g zt$?nAnya^t){*zxghb?iXt&zYy8JYDOQdkoR~0}T^g5Ja-4^n%E)N@PzhH#gFR0Nb z7EfgK!l^9`!c7w+YCg=;>IFM+yM*%}W&l?sz4{9pulg_*xE8op!kG{Czy|;yAmNS= z5`d=yPnB@{2Rh)>flrt4rVn~)_31(`2)PoW{sS!%tOCAD!cTpm0lp6SItjOZzymJ_ zUM}I)AE_vs(8)c z+Yg*XyyPi#_jFku6^KTsj|(kk#FY{QMoitDEVS9mB9J1#F5$hlS|TAS@T)M!P_^r` z$SQNM$I+$qa4+P0zn+{7UG)odL4p3=o|&=5w#x>+;)Cv^iKK}B9!2zSMLI(fH58!= zsay&j{xn(W0fl;O9WG>U^${}3+y33SvM(6%H?q|~+!#^;r(5A^DoeLA!qTlyG2l;|HuX(P5t5!Vk;0^ zfmrUY!8${V?S0pP*dbqhjaV~c&4|5mC)c`2iVeS;i`d>@e1X_1#8#0?Rj@Jqi;sX; z1FuHvQ+H$!?iBCbDMD)X7e$DzMQkl%58RO*ty8>mhdSCjTUH>p9x`()JciXy0kNNVIxg zoDV`iT0M`JZv3AOEl#78d(L=|qpdNw=4h3!6jW?8`|ndR3eJ-%vnsnv>1rgXZJ!RC z-!q#$A~J~3HjI-TH+i;g)MVp(4{F5q_jt^DE1W7Nv16_q#$b>!s4W5p9x-%#Y`Y(QhHPD1VXc7ojK-*R|0#j~9@X?vtqQ7D zk^b#F8K-@Y5yD!eMWw5s_!|eLD@VF=m2Lt!prHY)mN32G00&3qyOs$k-tAjT{YU;q z>tFYIkwukVWG%9cF{lEf@8^M}es8e)8@=W#1}LW6#vsf9)1$YPX7lGQ+HCwJMH96u zG=mdc9?>#}BD7eOg;n+Xn*fj6i|$c-ku_P!-Nqt(Y^ku&>Bu4rN$Jp$JxZo@7|%{8 zn>)l0)5Kvy7MF}R$09JIc7t9}fu;gY0~+GRY7?Dur3nMzp9dt;Nt(abg>4VR?2I#` z6lStDs1y4k`93HrtPXhHHm5k|rryd}l2N+nZ|YH|R|(s3M7SNX_HB`%cDb2>cxuvN zH!~3bIC-Yykno7@j1aM%#@ihR#8c~Zx@kas53;@E5H1DrDdbwmPV6n>A3P*{KJfWc z`t=UX9W5)6evcy`>22gm#1|pHNQz(VC_;QO;!7Pxi2syqMf?uL?~vkC9VWzYK>PxS z3GvH`Z^#g?9`W@gIiwRikxU60GPcbQbmbjXzm`9%kbV!KFh>>A_bR(pUSrasjzTq< zS~IuGkDByC52Ww0qd!vB{i!q@)3;+}@v2^du`rZ0wWmAbvVfl=oEu1Lg5Q$nd6B&l<#Yo$PQ zVBp8UG|cAPB4oVJj9}D(m`K^A*}n!Z)NJaGxtCL1_E!%y*!w#R+da<0hCaCiHr}zL z29_0WD9+kXGDfG(%X)3twZUPctexWHfBmz(zKj`h7*NPxog=ntni8@AHTr7LqVo6AYBxK68WT6ac%Uo&Ylus37S^)`W^0g-181$*kXE=C_ z-W;se3L9Wmy-A)>szI1d(BXU?Q-$LFxT!k^mk2~7h}jJF3Dl-< zGB(8S-V}_sDv2ZSgvA?Of{UHvGzX96LhfCaDgt#f0QnKbSZSFlP|?u(WP@ZWCjmMM-El;q-J}bX+p5O8_g9%J8u8lA`-9 zTQa|5F)4kuOSG|QC;aSA&s4MovP!<9tCGYbx@sv0UM}GSiZbZ%3cOmv`xenvOC9h! z3GY!vS1oqnb_tItqN|oR;NNB^}lLYpGGYS9DNOZe?I zbk&jxJX6A3*6_e{fagef^BTHpSq^-;gg315c)d0Zwm=YrApU*1w{4@!pqQ(}z3aVx z)MgR&Ywl+=$4*vo?39*z11zXUi^pgQW=2Rb(?S-kp+?I9o+07+YpBuY1D`M9d26WA z@`2||ckGP^0YzzFWex)<{OPfnbve8EdG~8h|%Qc&cPH z2XKdk>m{S9p|ILQ6-?udM-C}kHdKg6W05QtCqy=gSdTU(LF7pvGTpU9r*6r4P$wDGx5RmR) zNS6)_0oY5x48Rb8kUi`3;`H5iw+n9Flv@`U3Mj2P_Ml;;)u}c$T5Ri^4<^YBOj4IYGLjdNCOcs^{LjdLgRtO9M z*fn75fFS_;EfS4pBTxjOA|lPe5P;PIs|JPu>^QJfzz~2P2G#@&0oZWo0^By={=W?%@2d>YtoUjsi0QLjd+8upPhR)yPLjdLv%mxer82pR8a>cO6Vc0W|Y>R-oVSmgG`_uWqL@|Pt5QnK+ zTm~i_N+J^|rnn+6Nb-TG0cmWGYRX0Nql1$FWNrP_JI~I(~MH1XfqirlF58ygjd2;&{9F`>P6$HK*$un z@gXl-#Z>HwPvslCdC?MPpta248?|1vx|y)dOujMFi`FCCh%KdTzOlO(u`C-iebA!3 zXv=4##IyOv9$vIIbD;DbzOknlEo3gLZZ6;WuotaI4rJu;jnQ7T+-Fgp&+?7Ej9$c& zd02AH;~QhVXqp9RuM7Cb-d?oA=NX~!dA_la7j5Z6G{=Q}V_z>ClZ%COF5ejIMQZ}B z3A9ICG$ZYkOBW&YBEGSoS3-U0baD)rHoOi1#zGkG4TaPNPK~B9OOl-1+5me!CtibJnSas@r?;yw47yV zaLf3{Azm~)Xm-#Z^`hmy%m{fe^Nm9pqo=plf>;Y;qF2J{ui!xM6}~aai`D>I189$V z(dIA5YH~T>ILwRI0$K}bdN11YSJ94M5&2h#p0T@-yQZTUS$ zjD5R#T~AOJU_3TtHr%2MDqJQ&z+`40CNul64fBRVbBc2$ZuBhZZHZgk_1>ck-5FJu zT=HtwmW*)-7Zv=3YqrKP;b+a`{Y|nq_V%y}0?MJ%Zs<5S7ZYjLk zl%P)5+%%a@tSZU9vr0wgZBVI0cnp9p!6gt}LMmf}gPUFtrURpkz8m!2l-~9D>z?BM z>fRr1FX{0P5n?-W@?PyDY>-A9WKU1r}_Y>6L|1r_rYdW2*9kWG(RjTeg?Ce}cA zgBejMO4yLlp6B(#fbTJId~Y#1#h@Ei)`SgoCx6fly43&j1GF*!;n);kM<|paLdF-&i4y6E-CJ)#RUn| zyWqc|IN$QFg$2L&it=$H@iA!PJB<2VFg6Xu#?=+pTjlbOb}vl@j;ew+Dno@8C-u;H z`u8`X@s2<0UB`^4|ENcvtPg^nZT($#>+#l`o3Ft@ZdX+qV`wg`MNtq8r4{sTq| zQW+P_hLi8(q9PugxAPiedZ7z>C|=Vw2bpqysIgo?4e45x{g}xuw5n>!r1;qI2eUay zK8%kED*}h2ADrT)>r@TuxcC;@9@dbv@!{i>pHyjUpxkbx+Kp5%+-AhLpRB@O)OVH< zLiG>62=s~tbu+=(s9JM-4^p2(>QhMl)pbRqGuNp`)5z!nF|BAck-R-1Hmn)Bn~{5w zTch``Q;j;2ngQK{UK(9t-Gi<6?;z(kQr;%)z+nD*X@J&dQNf+6_hWx?Kj|^BZz~qO z@Q!4`*9V69X^>vCpO^-QjQFI~Df-$OwU!5~_MPz;oqd$a`Y}WeK(Yb*>7h=;?@FNp zq(T*x$|g!jigfblz<#Y1@FkKwXsRFoBjy-C64Ri^k_^aX*zXkmypDnxwNFI1s484g z@y9X1e59DaU%Sf>T`G4!y3PK`U3y_TsLM(C;BfW=89aEd@zMS&oz1*L6~!x_n|4m@ zmG<}U2J4W2-F|F;u234cQ~c!`W5po~>b>pn3<~__dz-prPge}M3aZ<28CYgtis?H6D2us^42;t}zc6n)mw%%_JtFtC#CmL}B4sjnk~^ZD79I zOM&;VDR)V}xuylPr1zfHQUyXYRni%~+<@icOvv;MDe2WdLVERfv(os`ygXcciO*lt zxh|oQYdWy)_}*jMdMJrQvB`{jfMO?d8Okc7R1sJffu#;iwZg^#dKHYeYetOpuoeei zQ!cPfyQT-{(`z{w=bR^S*+=|#a_+9h)LPZBR&}M>DMnnQ=UUWW$=5QFqiU^et`^8^ zsb-8)2Wp4z^YcwxB)$6+dCws0v7qVz_81Oy7nU%L`0m>Z-6=NPm1{9U*9;I)w3ZR; zC&`tz`~aHD0r0ld!#Apg)1Heo|5~dw6{31n>s4X7W{;5z4)_QK2ab6ec}>1Y>?iho z9K6xCQ*F-&%h79RN$U5~(AL{svGF|v1y=kh#10ffk3w`;3NbF(DK57w7jib(i@;91 zwvE&hQYSHDqN_A5C`}7WGsjM^=g`u;Z8srpTbD_hgFXUtkhI)WB2RhLh*lrmZnjA^ zyw9tKJA0L@w_Um2Gu~bS=7&pGYiWseJj^~(?rFX6DIFue4mvKKCF9ar@(3aQpf9#~ z4(^l$^{@2NwbO;788u+tEzkFyqT{M^I?&Z#1tIH8CZV(m>Hx`jej3^bawn?PYCs9< zp%OKLr_>do(wn88oF^$a7fo#-if2})jql8-k3S>b8d>%A1J zxT@SPIDXXzg)&S0q;~xsL@u6CZ{CCdcTJ!d?IgiuQDU^K)zINGTI;RQA~*xZ7PSX` zh1!D`|7MEEy(G`Ps?0^+xLOa%ekDuHlXlTU`D;eQ`}rfxg$LBb`(XjO-vAGI`yhOO z#6iJ4)BJnIM07I!RmCsQzG?@P1`?mt+VJ-?c_k^CGaP~gCVP@*KQ#c*fJ07k=ATMI z=;XHtrg?hA=nqlfUw%ayBx|lvMKcIB)ac0-)@>LgGLSAqO1JKcqRZD;s4j`*wa5Cj zGA_iE1CPaXg~(q>*kPf@YwtS636~i4FunrUL*TM{(~ee!iy`!Okf+{PSUhIlamZKL zacCz}(aEsV;{5*QX>na7?P+%%CTai8yDOlz9a8NmcRRPvIzLJ2t>iz$T2uN{A`Xj5 z=6}Lq_LEcGe_1h2^JQw9dGAuwr1X~O3VNY0()C5U?U$)(=-sYUm#Jx{ka7CxR!oyY z*63rs+L=-uWm?v^fWgcb*DDc<5KLCw1Dea@v~W!^=wj+zCa{Mz2add_%P4%XBlr_` z1b;e+30=L{8tKu?N^f}PvTYC)Jy-0DTVF+1r})_)N*&M^5)G%&ey$Fp?#$8RFF#k0 ziFP)Mn@tua2OF)$6JX_~z?Y)IY=* zdl(J!uv5HsiB>eNk#5a4DD__`b+?I84~0@!9-vegFQrlrvqH+@3urzsc&T*cQa$lc z35;G+q!f#u3>zTR0GYclDMl17Q6n12(3Hr*53Ypi;GB=V`N&)3&ikd5cK{(NJ)e1S z-bY?n8Emuyk-r4_4VRQkSbd3BLYpEiB4?K*qW0Xk#?t^gx@8ZRWPi2BDRzdfX#*%XD3*Fa0~ml!67LpJ2%*Yg z+V~qaC~W}kB!%C?@=7uZxjJ&-qz4-(4?OCicpVfkmw3>IQ1ctDlnf|WagkBCLuKRB z0t96=WyA>b(x{%Tc&)_kJ4cOS+jUw^;Gyk@eFQscmm1AxllatuU6+m0S(B|QZLvkZ znLZpdzoEao6yCl%m1ToNj^I${h#W0nNV-JcAM?hOa!Kf9xX5yI)~#8LSTd3_Gg&IV zhJuJAzCr|YXG>R~rXtKbq$-5V6IfKaQ^q!-q zCDYlQUZ_T@YNSeYOI#>Pyz;iZWUhm5bw|9H%>H(H{b)x{I~h5ywITN?d3#(;7-Pc* zx6LVDZ&W;&<|3`aQu5QdVaCEu-}Xpu^bRC^m0%QZDpedoTt7j~+$Bxep65^VUW z$ELyv3Eh#YS{$!+bS(JL>|QF zkg-BTlMH_yhCZzo@ps@<93dp7LPjM!QHIZ={UD;GJFC*Huxl)?3 z!38Bv2ydkkog+&oyb++u$EpK-b`al*(c^O7G+B}js#&uM}niByfiVA?N8pHIMyil*(tj2bLcg} z$CjEbyqeRP@EMd!mB3e7RO*5JOx(b(1h4HA+!Bc!LO0RzGran7n;KuCO-*m10{xiY z!1nay4oj7a!3Px$QWem-Luv!9gZ*T|q!ELA)!+oH#wq?G(r7JWyGXI`7bpVn=gBvc zi<4S&Y^z9gW=}2wyc5WT%wXf#f-2mlpMqJb=PqxU#&Z)(xdXo9U-WXVhc4gH!k7vA zAQ;D;Uz*#5AY}$*WYpkX9k<9;aZd3$k+x$xaa<$PcHF+8gI1p?WFuKNiut5eOd6dp zQX@Dq@A&&g^mqQ{t96Qf>s`V~x5=?R9y~TQysB^@xs$c6G_vo==aUz>W*gKsdtY5s zp(J@wF|US?dk$yCX+nNYTZA;-3@iE|1~3+3xKL1og?5d+moXFSuUhP>;B^-i&-(QR zTJpp<@Fkkp^*H+VSKg=^99`G2x?BjsWC0@cA@XG_-6typR#vkJ3z#JrXk(yOT6ck3 zDfEreI%ck7WJcUf&OQ-2LbeILq8g^5Q_rH)?hCBgTCH?rHhhMs*l4_toy&;JUUfAt zk~}5UWiomLTPch(Ye&DF665N@8>WQ%$(2mLnWANXBj=~|WH%5ls}H-D^v{ZA|AoK7 zWN}s(cCG}O0A)zfVL(G9=yq0TAD<)=GPO6`ULs7K+J*g-ESMV2CXuyMdq#VjCmqlK z-ZEmAD|!o4BU`EJH%ZrNM)nsH^kgX6F>N~gIiRa-JYlELWu4^N=?jDVyeyipnR!c) z?mNA&v`yTdT$sKj^ZfyC{}0Zls&6E=Q1D< z-!eR%99s)*5X2XrH&~d!HX0j-gQ%Ab7ROwJ)c{9uJh<5WF|_UlF1^U2r-P%1LeG5Y z$?L9}S)FRUD#OQ1Tl(P=)%IcX`P1RtfTO;+)A!@k-A1U8i!~T_EpnBR-fhG!50}35 zb3U5u`U`p?3zD*+?}&4B^N89f=Ufr=y+~r8Ngk)@Tfe~M*7x5pnxL-2Eth0&(DmYtjVP=Z{E8%;Eh-0{de#|Lmo>iR6va@y+z_G%^ zUZoD#)SDA@)XXDLfxZax%*-EqVo+v5y{ieYbaw$dry4h7Xe-_D2lB~`IkLjEFBnJpdcWVbfG z>qy$oj+wd}>374d@n@8YThlFiR&@XPXR3Q7vCN6;G-RyFT8VyF3GYbHY7&t;kzAV-9QN10sw_1YjV@B> zi8UbBK)TLNZbj!aWZB%oVM~#6DWv{!T9MjClKMV5FgL2x^|X7XnvmK=*qq?7CHIk9 zjo4}uo0Hti@zJEEB!58!`8205S6}OkkGoFhbTj(=3wwtr7#jwGmNljJ>4!=Dh^#yO*~DFSo3NZtuh(CoTj%#Q=8@hoxcJ316X%ESlG;TQ#8S6LjgLoL!!*-(cy8G!2MpAe-j3)>qb( zKj+2!wK<8aP$!9QerFa(oAd8~>XmpBcPLNN1Ns-|dd&9LNyThiPg1izvOFETi>a3$jWpuxV&Bc)cti2oZyPki)3E!3<%i8bj-rD-fYNt?!%SC*hF z4i_BY>mYp=3~8mKog&5sWBmA2z5;)W9A5Ac`v$qZAj+$rm7-yxcnS-}Q?$UQISLi` z4NfTadin&d*Q{3_aX04o#@ySOi%!8~p2B6C6NzH+O7Pi5`TYVab)2Hzv=W)eRv63F#qMzy8OBJ3ca*n93<@*pF4`nJ7j2XhgQlz zo6OGbV@w3sL~vbwTv=%U?|2os#=shH9`#tmnZ}46T-L}!o~+ZdHJ){A^KVI;z`t2z zDbg-It*cZSa&i73@4l$9udwKxw8u?4ENX2}_Vnpbx&^93V!vZiV0F%CMCKDtk_$d2@)-I7$laF4A@46AWH~uWQ+Y3jPLikG@UME*y z=--MKFE7AH(MK5d%pkpR2z(Afi~k*^CvZH*;v+}%VF-L`{^DR`17aI~o`80;;;6Fx z`1EKI;(NX{T4$KUh<|BupTs>ar!xS>CE`BB8Qh0B^Bk5?K3>a#=|}0wHXZd>95sOx z^OABxl(&JtE`&w=5!d`WRr>PzV-4=R;XD5_oOvyMF&7v2DQv)pzy^z|t*=Ip(Qi1M zitY@qte%+xW&0deRyi3*DD5$WDq#Ng}=bmIZEEXYf`-4Rt0| zUG8WVc&&PIpf=f(VNp%Qg^cMs-4I;{sFSA$>3*-^b$-~6#RlR;>O!@`RDC`U*nJGX zI<*epk$*H9UobyOCx)xQd=;2)tD&PL-L5!UV*{HfUi7{^XMEPJFt#e%prDNU>EH}3 zUP7Mp#4zd(Ps_NX((yHR zNIv|6Q+(tw{eIeetA~CG`BWrUw-3`VA)6moL)UhdeHufvIN9k$`zEOtmN;-N81f?f_LmO9zHJ+$IGp`)7#HUMS1*{j$x_bkqRDN-8_a%Job=fue9c)%;eiwV#0Ef zI~Tc6A5jc(_Xsrv-k4b4njx0T3Ov2MV^|4Tlz_!rH;Y{oiy`FA<*g~8BS)6Ugqe}s zjNB94xnGoW|3QLYZB2pZXC(_f|7ypuIbc=KPz9@M^Tt^L_0c zjb32R;!xqNQ~d5Qz1>9DxEBwjLy2>iFk-_)*yrH$h47s^_?Y+?8SxA#4?0iRpT&1r zXS)l}VXtAR*K%gSAxpeFR}Z{zz~hN4ExhJe52@4<_nbonSrosC z%e7ui=N(pVJ{27{K-~`a@GRmZG40n2=k%-Lte?5Hijy?4xrx1Lgz z#FXT)GT)6qOdZWOQflmZUyhmQ{DjPN+bnx6xt0}wLPh3LUrC(P@N~eSG2bIg1b2@21kaR$06u> z&-}-JNSU{G`l$+Pl#pX9B4>LlNilx1kb;~k=erC3xURirxO9TIR?Ud~b#l?LPmmB_GE? z^mxgC`n#(_p8D@`x{aw)cf6;sDCL!PN<->Vb3em=oeh#~DBWK_QajQyP$2EpRbqS8<73nMqf*Wf zXik!`s%@Zmp2v`<6Is5hV?TX8?o-t}#n*pS#^TR^q_xr8tw%n%<=4x4Or_kk_FD8} zHx=@Q(F+3ku zwEI79%+$`NH;(Y8;#|6WfHz{m>F(ZqHAg;LjXicqX(E-YgN+|9gsJy4>d81ygs17@ zc6P)KVcHVT)2n03KCMc?lwZKE%`}CE9(z#PDzG24fz!f;eKGdm=uwZI>UvxW>v_-g zayxcIq(h~LaH^Cl_#o6vk2lE|S>IL|lNqlEvm?k0uSXjm+^!R6J1`r^agu=JBmvJb z9aJ0vIY?`)<3dLKpa)eCGc2T8k2KQ{Dt%|gL0UJ=LUQ}{9<408ZjqsH^fa20-HhyA zrP5MQHC!s~p68unB&^sEhlJQQ=)s7&DEXfIlzgvJaumE41+TrQ;3ubgEPCmH;z@Z) z#Wl|}@WuY04xiv?Mt&fr~1ndUq-O%e{w_al z(-+8NgkJO&^kn>7c)cbL&*oswA@@%DL`NSy(ZT8xzQRHP4{~HACj5^trC-d{V2cGC z{Bf8Q#wn+agJ*q*Ewv`!DoYgpYT5?*DJkgtBN^FgLOOV)OAk=d_oLhxb~q)hBS>_e zirs`cticDKuRUSkjx^qxsfg#-emA_gFdqj}_##@w7ttd1oq<`nRv3qCg>iD+6x~W} zg@G3WH81ta!*V2};ONN1YyWV`Ota}#VuR>|FakV$5p3?`f7~NBh{=pRkYRo%z1s8P zd==i``PmtZlO1;{)bwir*-BJRI8fNVTvSwJ#D}C;eCT_zBcxY+^5(m86Sh!Gx)mn- zF%4LvHb^hcB>sZkqhFL46ZC?<0baa;8uGCz^re|B;8_wrXbOF4W-0Kc68^{(`qE4R z@B#^ccnW=KW`qE4V@CpgRq zZ}hBDs`(N|#_JEi;PnSG;@>^Pl$zXwnp8JpBe4+< z9&fOvk`@0BouY8{Xfa`f2ky9m5qCeEAYJZJ`1}Bg8IVMu3r%-P+%XH2r$$Vk+`O;; zJMtdMg^*n6j*VH7wF;`ZU1+nt?y2+Vp3ZKzIcU-J~b!vpmaUxdWp_!@C5Mv1>u<6`cS09 zRAEhXrJ%>RF{omh5yj{y5wbcRizk_UbgFE%ufI<_-LedYPE~Zn#S=`saK(aBWRp-+ z;nQ8kJ}P)H7mRkLP>FilF*Jqa_8T72Q(=0Brk#xtULp~{7kz;{DO+|RTr zP)VW7Dk)}{Rgy6(NlHcLzT35bDx{}M(iIygXIzk^Yam_WhDj2n%elUMH>R6h13aut z&(1uC8zDFveKC;Td3PL_g9emC#*=s#^akngg1%Ou?bk^p8zv=83@V;z!lTkpFzQd> zPqY^?zLD6qp~*Txx{Hy54^JN+&YVD>1y8_q9cQ12NxX<1kiV4ezSsUTVGJ~5R+(#k z1O6%#DKg3GwSyyN8FE8#!BAf2lY>+_&3fD2vLE&^QSvUUmJ63NKGYoZe)b=u0YI_-?wm*G~+Fs_%7gvo)#?V$|lvpdM%v{F&ag?+17OhhH zs#h);2QUeh*keE;s(&4_0h@|9lx3OY2A$8v&Qiot!LlG)akBcfl4SnDfMnH!ib>Uf zd-=8b4F{{gkt_f094o6!Q^@%#CpkZ@ZaF{YB$X~GU9+W}|b%0Pq-u^nU@RZ(I>x_&%5c0JOqPo$4=`McUkE=kA3KIUwP*)CWI9UcY+~4w& zWuLtB|CKIgV?RI5CA{W)i9EfrhfByC8~bsomoVQZ){Ub%10VzO-?Wg+1C&Qz*%ZdD z0C;>ffIUe6&7sEKu)uCt|EU68 zuKsff@F7?Ku>rP8{U=SR1zek$@bTZhn9QGAQ-)|y3c5jik|a&za$T}G*^No!$ob9P zI6c(V6W_8JP7+1>mv!nd3koX6TM7YfHS}W*ML1uaS4m&ulhvZlN=i#!DvKUJ9h{~& zFGH{U`kK<~E?lF%F7#!4BA-XqMm> zz%As=XT_ZEGR8-;=zrlxIUhBv3{kUw)S}Yq@Pume6V&%C$1|#)xMIZVh3UvY{W8AY zuq(%JHTELdzz_STxrocXOgDh>~xg9F-4(_M15apq{3NLc;9{_OsAJQ8VBJl~AXE8b`aZ;e+<3?04Hm7y z`XoO=(-phvn4d$XHx-=xr#zICS_rX}cjcruLC%ziaZ*bmH_OL`D^ly-Qls6uXKV=z zRpeV5?mC@f2X|cYmZ)U?74)1dxD_XTD@wg}mh`RYJ5OS!gt*Kr7Sk>09d%XNQ%Jo^ zd&8?wrU?$THwXD+OH$N)q?~_+mhbu%rNT5IO8MJMOP0yGvZBV0*3%v1KH=qFQ~v_&!yrcm2pvtNRVh3@VV^t%gX2A zD=z1P=U3QC%0g@wd95;%%LSB6KC6u4RsmW?YAPe6B%1vi@&;d4&W{r=)6TE}c}+-X zBAvFyat=TaGJ4x2KlL@NQm+xyHVvl*s3l)-i#N7`!P+Frvq=?TRgyfLR0CEg$+Jlw zFrOsPCPM&+B+=Pq8lEs~i$Lc$X+i|xh@^Y{Gkt3}6_Qe~;m|_*CXiOxThcdy-)5yj zZrcg?L%WTv2JJTe?9_S7VyM5Sz9zt~75HfUwhvl`obuj0oxJjps_hZnbV!{}gzcfO z^4**K*Q->7TtazBxL4fQS7mYi9w6?(J^AICn!`LcdmQO_MD`fTw{v) zQe1hyih4k%46jTi?aSU=1vIW8%f1}R9RhTS?ESJI*8r%2{P|@(cl#R79!S5h7H|o_ z<0VD1;j8gn*6*~j{_)ko6fIhU7Rz%+{RkFT^Fc=tJ7npFLcj=O0N`@K2%<0GQ-Be~ zJ5%&Ro9mcsUMJ7*>>MI9qL(!23P^(p&2_SFXZL}L01?E)Q{)v5-i^ns8drlsM-adB zqSH252znv8x-*_z4`@A!HusAzzmCn3>%)Z}Nj?a4mvC8fZ^3bwp7-EFJv6C8+A8v@ zIf}CZvXM>Zm`FPy`*l3#*@E+x7JL+toNGmQRR{Cf&}yL@T35{jx#@tWlNd|S(LItd z4@zPU6S3T^AFBsUaXci6{6#JF0ivyAdkb}tnk=jXZCwkMeqWzo{v=d zB*@y8D*;qO;;k`U)gO2mmdvmY_EX(p1l0}lU+Y6$BEUql#~Kqo04-zyT8OLmu!J#J z>?+3=;wWq(j-uW~hZH&zv^%(~1SQd3U;J8ul#jx$v?O_V*C;s`9&WmUhnsG^g`= z{?6^r?$Drra3ejxeuF!8!yhZn%C9FyN<5{lZ0WZ)B+aS3b7;yL4muq5{HD(cMc#4; z)|-x9(0vf3$yB@%(ntqIdW7JVKEWF>$z_=&uTl{5P5;2=QU1s^O4#A>!wt-uZz5wA z9wpLOiIj(>(T28jW#avKbo;iSn@9RhKYSDVYNE z2B?gDUG*$ieGAu{NuNEFIR_vIS-oc**Xu79J?tc)EI?T#=DQJG!C%H!ZS?-)8W--a?h+0-6xtB*p6=rB^RxIz66PIWieJk(*rq zA)2!TvXgH6leiYhXdyH9t`yroB72uQe{S2x9OR&j6pJSEjCIfwlRfe@fHDkjo4GQ0E@XdDd zb<83gt2>V02Nm`uX@&Jp%B~t%wX5WZ03S-CTesLrh8X=Ixii^7w<*>EJ;g;&1)NH_ z13S6tu<&%U=fD|mDWIif!@+lgWc%V7dMmhrgPsigG2AFqgNpNU9^8X>#b9H!2sph+ zqr@vQ^f9&~@GQFH6i3x7PwC97H=%u)(&_If{(yC-B8yRnxp~r>q5GG0$X$or(e;=M zlG8tSGP>(jsyR0%=BEGu)$nwr^R8i!^aQj7Hzpn(tMH>1b<1fdsm0vIWcV)0I~3uz z3DyT7X5Mv*-<+q5Eb21E^VBtIAW?3kv{dvQ-HnMQkm726km7<|WzPe@Jn(z(ynG7h z6s_m$!OuRH?%j5V<-kXcKlIIqLr8pxbo;4aAGrws>>6^Tpem$61*y4^Wk2=gWayKh zdiG3_ng?H8t#=y&O3D0aRoWrLPA>lx_Nd&bD6c4u7Edgh&`hKTg`dFEjCU81HbvTa zl4$M_C&pqY(I3|KlUdT82E`I|>s;>N)Y>vcGbJKZB3W}dipv3%Lv|h>%dG;miufNH z%as5sAybY#6;%$X+)3X^j60|7Q%pHW{ZL_=QrMG626vNti5_2v2k>`N9Li{;V*rIU}2 z_2+T{<&xvaqPcZ|))BV0=SWvA5`!i6ag`3g>ye3#8>x$XIzFwJaMZDCvj~-+7@!THr!9+ zgXydfX@C4_F0&2#16g!DoXY_*hZG+l$mIjdCqEvK<<V6eT}z_tVmLb>JDFTJ+D`)!8jgHim&T<6OeNRqVxtQH z6>u{wi?NBY{G_r!wBaOmLnlViU9k(! zjZxB_D-E|}yVicG#_9(?@`kGo<>}#vwFFskKADroKeGLNR44C|kh%pu(&)*h^WkH? zV^yG`j>o&}Fioe$XJ*FczFL9^B4|giag!(DL@&Jn_7^p_C zkT7Dc@5#x~FZEF_C{T!uRML9S_syn!>1V;@^y7tLBeT&vF^V??GYRSr(hshs0as{| z7|KO_*IEUjtN7#e3Uw$1Ya1-t%JVn$gB%7+#x`RNb!Xs zTnl1b$dL>0`0@VOA@V0P#mBfjfO%w-7{jFkN+rj{Vcc#&yGdw63|9!Kkc@2D8+Na; z5~PJ+En;g)bOnnTwJUSPn=mHB5W>42V&EO>wPmnc{5 zp8jPvR{>fD8PPbDt5(t3@oS9({nP>2)CnNpG(N;>0cwfR*oR95lt_Xu;-m#o7MXmp zKUV;#fV_QiG*=Pe12!iw_Td}>bZYJ2G?3G_rFoN^hH{C363GhCvH@iiYtxh5azJ?B z^4Az{BcP3B%&$@0AwY-7qFOkC>)-D8 ziulUh%Hh%jev_lIOhZ1viCUU)bgr7$3BWTnl@p3+=2dF1|F2{1q z)wD3zFZbuxgSMW;Tv@^G1GJB9y%Ouk1Y*V#NG@E-A_fC`CtbqH4hsDeb=V>ufj8<}Lsq6Ls+`xg6?ESJ}THmzZfo+R$~0e*niz_*X&*X!||l$=DiM7p5SE!|wuyp|#GJb3$h z`)4hKy_Ii!BcziQF-V@kV{=JZ1%|6g{EfNXZb;cpKDrUgwE$|_ZoOgjWKQyn;PDGC zJXz^@giGgX!~W7Sn9Bu}ORhPvD5L^O^v!PnkWhe(1?0(_{ai||xf$x=+mqOCeZZCT zJ{YMN{xzPngQ1=5{i~;+ItW${B3J%O>DDUUSA_E_{GbLf1Ymk$01^!#6K*ew zR??X6Nn^q-Ij3m+k-iv^fwURq((SoiHlS=Wxs$c75ll?+MFdYgh9mTRQb18sRO222>K3q|VuTWI_2g{D+ zssL7%4)bAWb4?*wQ4#qp*m*J}1{Y_VJojGc?`10~`C|M|vRmtGsKsK7|5r*B$(piCQ)R+vg$&kcog*+xwc$smEiFN7Iy+T|0+%U=OfdSy+Hjwlg4z zeND|Z0dCq^+?BoP$MxzGAoSY#Y7h2EM=qxeZZGYeFqn<>;g;($`joyjgzff_Y92QC z=jG4EA<8`5GoKf#qrViVn&+>>G0eQu9YfgOBUST;3(E)5bTowzU>d8LH zmfjCrg#G-q_+$gV5onErDyvq@}MV^+Up!O#!C)6nnt z-I$B?V}aop8=(8h&RYC96MpqObYa}ch18@YWs}a!X7bTH&fNA7d{{FTGh-EEsK7N9 z&*5=CS(Q*-+HR_dTo_N)&Sa+Ig)K<|YT=#SW9%!ev1HIX)4Ix2m72<|O57pB4nfv7 z&DxyQ$0AbgOJ=sEFvcIXp1;rKDB@b9Fb#$+zU zs2HZ1qm1w~Q{nXBMUJIx8L^9sDkH_WM)%aVwPtR(*=7c}LjVed^ zV{_U+_KT6~UqfA~OW9<0_W#vQRwc82(Gv3Imax;3%x+=1!f@Qq+Bt6o8_04w{nSEE z>8mMhKW=?87NVt+qx_QHlVkXDe;Ai+{ z7B5tk{yCZ@Tr+q!m##@=-{49BmXwB%VZ#8@@n*;vHriMl9w5|)t8@&L`aY`~5Q6(5 zNLL#klrlzFU|<8d2)rGcYM-m}8zWRBZFP9$wwntB<|B2$olqRXX)mU3Bm>RQ~_2@iW)jfkDy(^wrl$$-i?4DwU;is&3S`D0GqDdaKT=-Hkg^B`X|lkvkI zbTWQ-l2f-28I9iVHhAf#v26dO)?L|5hQlYtlfl9a7Fe?UjYV)e8#DF)V)4gr$|Ms^ ze0=W11RfFX2##hW9L*mbJo+G}$)BN4W^Fp#-_?p}FUX%8>T;o;9$DIu&UW{-qS6lI z*ifUV!{xjD(%(BA?QFEu(eC8-z3Ne@dBuG)fx|Siec@gPF)lvYgYMTAClqrzuM4{T znQ@)8D`u!lH;rRsjhcCkt-4y=R$ie?X$GJ+1_Qv zI76KWyoNMD%w{^p$&M;pVj#O7I#$VUhvt=)nN&;%l-Z1*AvR90Wf;v`UFxF|xIqY~ zL|q@R4vcsOZBs29Pp*K{y2sgsFi(%%mtbg7?hsDXD4dRYk$nd?8Y(7 z9}~TR$(Sef)#K7lX`jiMOP-1f6i$_npN!eACIYwVB1#J`p|xizYGArw==uDv4KBD^&%!{nz8$kq#a{jkz2UHt_6zQ0c2HVy|} zr9G#xBmB(~KI#DIvTzD?DT}~_p>)d>b}bTNb5+po9FxVK_4U{5M_^^DFO8kf8UwNh zzh!NM0%Yy{ayt7b%Q+y*v9t1NHo(W<(4P(fhSEI-Hf%g?q^AY0-PS6m74BNh!RQDP}I2Kg*5_-|u~B?bwxXsD%@7&M4n%e9sgV_ftiA|UJ{vPjS% zDk2htN?p_~A%-fS5zik0&ir}jopac`l&+WlqBU^4d4T6ku-e&%@Q<6gO00E*fVt3lhz4 z?TPleaq{t5|EiK7=zpd=P|0^IefwWjYInxTposhRJkfEN3us-TE5FuD&+V&A|6TuD zp^r{q<7WMyeXwoa;Gv%Pl+@?OJw@&2CDPv#kJ9l|^n2lf5ck3ldd{VWp@_e2R)E`c z`VS?fiU$J|Y|qCmW486z{$I9jPyPMnA4fLK9}<^6{|PsD?HQl@*~MbA+kbga?t41uo@vl7{b%MeWU21UsQ=Y+1or)|H64bf@~nLL{x0QPdldVh zUzS^kR+;#DghPP=eu0B|TfJkKBOGP%a-?KY<+m*H0)4sGeS=@MG`SJe2T@PIx3$W^ zJD8dbSFCxSZI{q3s%%(uSKMUgAYJ|aQ>(j}f?y#3V#`73v?U~{`y zFtaF_gH*7+GeP=1oW$d#zWOw8z5Z3iSJ_7`m%)#unDw0lUoFQ3!Z?!swr>7@fBE0b zCD#ZuS?BDVm&;M(;wTnp?%Ad1=&Qn9L-^6aVS)aEVeRo|13J97T#lJnLf=YE1{;f# z?P;T@*PQlpQp!#9w-{`%@Y(ufM!s`P%5IbXgA)2CS@W4srAg+LUAm?oTb@PtA&B0W zzJ4Sn%8_0!*kfqmi{f8B^?t$}%qKU&vy3kE(Ic?`^Q71nSaQX;(~NjzpSc{z6XgZz zlFB(C)nQ*Dvy{O&&ZCB(ejI1_|BVcH@fl}m_p!hF8_BKQxWVl{j^F=A{z`LwaGYp= zaGZT)vW)iiChR?~ylP3}^8s#g>y1WFpY|%@x5fHYe3hA8eK`w~<*a+9E+xxD_re9g zlcoP@Q?(#Png&;y#IdB~20Y51BLC=8WzvH$z9PTr4?132E&rGN)=TrFSJ_v^(|Ek& z;Wd&=yhPMbwEy>OGS?-EV3PgRYplRY>9lbh4-aln8z+SJmSNjN?3yMq zHPXhpArFQAJm8u3*D3efYkp z-s46Du3u>S{KLCjuiU*G#^3wQZLepUueYCBD<5&Gr)<6B&jjT_ABLpod*S zH`DZamijXPz}i1%nx3w|JoOYdzC|14*vB&{nql_C`Q2HW)=c6ujkm{|NnEHs!H@j~LmL_+h)d9)Yurm&g3zb-qe8>6csdbgO+zx_op{ z{-jVM`SxEC8DgFEiE~j^|I@5=Icbn}(vy8z-%Xc~eQV^tOqXMZrZLUZ%;xrNJTu!q zY9j}u`<+T1SU&z;r{<#QVsWoa`mZ9oek5Z3m|VqXealkJO-k7XvLVU*#6rLIek=Lux~MY!1L~B!FRvYS^N7L z^07zz4eVjle{XNI3^@4HfVP*p$;RON?^S3R{oze=%uoKEBFF!~N-WzXU-+I9hwgk= ziBC4kAO2@09FJv67x_!Wa@)dL?ImV?d#6D=^GP?1YkOW2@=v@w@t4$aUZrVPlru(C1zH7KLN{(tew_{A0>|f9qm; zEBMN>yXA}K+1@dRe17z<{v%Euk$lfRa-Qu2!w65lc*E2woHVvwDpSYr`M$FMXVWQx z669)*)YB>!J!I3L^DjVs_Pc_ zDO1PMyW%s?A*sjp&6nOWHeQa$H_NYO-=<7AkG?DJ?^y|^>3{A1JF`8^Txm9?TuHpE z8_k1DxBHhazs;3D`Id6`jHN3$=wB*#&p7kBxVm4>pL69a-_q@#X7_KD{*!LW-_mVx zY+pJ1VXOS%OZ|q^+q$<<{QIHgrjQ|NisZ#V^cu6acwp@-9$5S8n*#!b@m-!&4LqsR zpV+6{*cSA^gnn*gBVA=0s=u0S?Bx4{#|c^*Cg~<`V39oYDZlmQ`E+}Iq%q!w|32ii zcacZO|7Fl-7+iRH^zVg@iRFttSU?SNhApiIgU3DX=G*2E?Ht1oIrr7qOntkkZ;Utp zn0H@FD=9^!4ELVm;}JN4jYxB(p}l!{TJ22?Z3|BHPV;E zzBLbxJ0cZVuSfIbr2EUTVLcRk8vK@(d)Z;dp^7Q zVO{<2pU&Crd%ODIK_?2N=}9L}>Fisxygc;{n3<>d=X4iK9M1LG^IYi+)G$z5pX+^P z?NjaY1(*Jy-7ZHBY(&TQZ$uqzL=Q{Sjvl&wsOz{--{y4PHu=W~CqMDi_8ODcKA8{H z25~T&U&MG$eu8g>I<^$aH{=ryXx4ycivy+6-P_>9S5ru7>`QSaR!6MP>_VuXP`%^D zVmVkcL;5|?4O{5W{oM;yPQ|f)TfM^l>`w>izuWfV-G9D`*uPyq_Mi4fH@3_5_Xo}X z$__bmph*8!<3G1-KfgmpQ^Y)QM>XXQx$XhBSA$}Q#13h%a=cS2ztn!*(eLeSi}|kP zz+6~$THgm4nG0P5bD^tmE_|{_zB4cvc9n5k*EcO3@0W2+`#^{V$Q|SyvKBFrUV#)K2}m_k zf+Qog$a*B(F-dAqJ@Au=KM8RRsX32a5Tf`ZZ0V;S{=WErB*az6KBX;}kBg6m81{(} z6JhBEn3o^*_oGeo+t6xYZ1OC!8IAW86ETo3E%dc5>olH=GgQadFr8Bb{9o4a@K zRzq;N752hzcpLfzXyO($!N0>O$X^8AO@TcyAASv;@NcjM7Q;^XIy6kuL=p6c+u&qa z2*V)%bDZ(kc8++sFh~w>hIqk5*(&gv6Mrp&OeY;5;_ectA-4o+zP4vm5@KMcf zHEAR4*Ml@;L9iAnlkCq2Yd@CN_Sb^7aWc`qGguoVTkY@YsI#~0$hXT7?T0eV{-Y4> z$1b5`843HBQ?(!1lR`9u^s~Q0vS#qJmxXBKDf(UrWuo~M1vJ@*PNmu;J|rR5Yk!`Y z<`HO5o~rpvvwi1O?T0R=eNq(Y6+Yrpg)y7#f6nI8 zbqcxcx{{%(LWZU(8Jr+wa0(=*tKboMTgbTvCFhQWW0ghDolPK8$p}v& zBYfZl7yzRo7Ktc_2b7FGz`KE-^ACc_*mFw0bXCZgt|`ekU}W4dI1i#=Tsq8wr{P&8 zm$(YKgy&1J*piD_n2s((p=H&u#-e13QOJ~$a4hswazm()8&GIN986Slqq~qBz2QU{ z1R08rG_bJ*mMfV-k283l5d;~EO$H%1c|w0UQOV3ZLS_-q@`co&)dp`U$!aaLEs8)L zfo8~q><%S!Fi|ch%Ed&vm@;=Q%!G_xE}C0SLRv#17P2w~RxD$6LM&s&GWkA2=3~Kp zGbCR@hL8pMumg6&ULozYyM2a`mhCvr_9!8@FNC|{A$SbdDangQ?kIw#ke&vw!0A>& zo(DI;8}Js+7l8B4fLJU9i%rF}Q%~T0e5^Q)A)VHZvk9Co4Q9g{h{7}12#cIa&t^8^ zbQf_lG5x8wS&19;73=%oZ!@ zRxD#(3t2y`q+3xmuU5!Brt9o{Kb#~8XNiWfjQuReo{F|7!?my+9>50}iXB*LhZWMJ zH)!|`OqjTe1uVr8_mp=00hjT-xcwczKh*+_mMk|RvfPz8*2oT_Nr|jz;xVuS9#A5C zGP?*9OoFRmDole`m=8yPZ1y4GONLl7 z#PJ}UcqCi{Q}Nb+ zI?RNnuneArr{OhtLy6bjg?N1!q~X_T_;oD%I+lGs4Q9Y{XsIO7MxaB9ViOy&X-aIL zD8%+a7zg8(*ui0A#~kQ{bxORkNQgHULmGaAhTpgfuPMQwH;57}SF#$eg$1xkiQN;?wa$eCki!N<5!9 zJ^GX$m0|KSOuknLu~)%!@VpY`D}^Xeh77?zhG3sJ^iiS$3szvk3KXkAv5G^&A}Wq3 zvELxXek1gSevlsQrw9AVxSx#s>EV8Q_-2L>Z)U^Yuw01)u57X0;2M|;J7A|0Z=v8@ zDEL+^jDzVg6P|`=;Z1l;i7F4ikx=DHAQXl{3RF>`iUL&>sA`5S@Blod#KFlz9Aq{e zoCg=c6u1VSgr{K%+znCWAc`CsF2tdca0Ofmv!PXq!@fcs_Jfux0@X@X#|Tj!tHkfa z_+x%UEKPQ8UFdRn0RWJqOY&AGrO$9u_dO=T*(bIZP5A~On zIEij!ST?a`F}Ky2k~TJtdBC*M^8d} zeDo5$Ohaxob z6AL@BptFJb@2nz673g2@I@m`%0 zXWcpB4ue#DmWt1&Lo9UmJiMsH`{RXp-ybr4-)H*1-^>15DA5$j{BMdfa^@vMWldDp z)CIeh_#j${4`N^{WLQ2Zhn27ywkUDVlcTT~amMol#`9bZ@mM83#9uzdUp|}$&2R-= z39-h9SmVPc*sMe|{?I&w@o!#DU@b&}W)x^{g>6dwDOQL-#la%D12)1YCC=k`=W)FA zr{P&8E)c&!`~vX{#9N5B5N{#gLi{5o#771g1Vi9ScpCOVef%%3;Q}BP?trBG5THd>KV9qsV6gd`>wTmclZKBYuV>cF;fv z4SaT$_%-4TSqDRQWug#Q0%0mlQ{w6{ZV`sVd2j(_MqFh^T&;rDu#NG*+M&ef^yqVX z^!Y-#2$sPLhy#6&19f_E<>Cn=VHC`SIq(|1p~M$nLVV#3%`g-u!X(JheZkOuaTcCa z;##y2*J2>$uTlP*llA`^WB%uhLj3uX5`5QNT*u_sSHfh7$6m){ujBdGPb%>jHzEGw z4y`aBlKvMxow582LwRE@_crSxJ-k5=|4RP9lK-!vFbt-^HSiET0xewxx|Qe}D@50L zh%a>E3pYcAxH$u&=}k1fNkcbj=qpVB6{i0x2F5~6{S~JEss=ih__9@qFWZ#(TeT2> zt5Kqd4)xHX+pD>4S*ye?O^92ra0Oh+`hSZCZqYywrtQJBJ!vol*1>uuzV;X5>xoMI zeTEQ!p9S+^0dztv*Xt@ouNy3c#SjI1QLvXG>}3dheV{Kq25Xi0X1oyJ_(O*1n2JAOTB!gC*`v;F>D{(!)FS@XkqiT8X;>LfoAU<6t~I0*@&ve7UXggY5N1IplaH zI9^E(9nuTt!$MdO8Rupe}BhhESdqJRqu@F#fE#R@rOxYQ}>+9srH2m8nb_K_>#Rd|j4WFY%Vw(;9mknm0($bo8X;dug;?l?SxPQS6>?FUk}Gcsxw2Qu-(tz%V##ENIGG_%u7p)e{*L(X z^!RKJmdPman>j-MCIY6x3=WPR92`59d<|cC%@r2FB8UZEb3#o1n*O{8(hxICt~EeR zy%tli9Sc!(EefqohedD)JO*o(T!+Hz7}9l?*#uBvT_Q}Pr=#iVSS5?-X_3ywa4BbY z&UYb|@DMx#Tj5pC=nFZc$1C}Ag^(|kJ{=2APb7{rzs&5IPWkE7`!eNTrs2?VF02^p zP$y(4EeoPBWweqTN;x7|a0IU72;88g^@fnvTT0p(Q=5m9doqRGQvgw9PZdY+9FE@k zl-ohMGRjfm#(Lrm*@l}OwKa~~Zjk!Z8M<^1r0JATp8#>%Y@9bcP)(6moX1K58z!{j zJT^49Rl_?ReHBMw4>+8LIWq6TsrKxKm5#0#wW)(FtYVv4#Wu6}Y-aJ<%%ZcIMQ8Ix zcnNmEPR@!fHaWZxa#>q)SzB^*U>;=E%ymN6m|WJFOqTsjmi^3pSjZvRi$kzCjD>NK zWjl*yd-F8vHM4r=uxjQ+(LgOc0efJt5)CX?4J=j-WNaW~1DlivHYp8JFq&69`Tj({ z^9$HREQGfpul5VXFA%>#`~vY7;w{8KHuLHag)HkIv#fu@s{Kh0tLG;z1X`82L_?Qo z=n@Yuv7C3OaI?OK_rOiw1GiYtsj!C%zaGhQJ{m59i&3Zwg{s-gg|L;I!S3ibyQ4d7 zg1p!SdBcTp5iEi@@DTiT2>vvbVINw`?x~@H3L2@PmPkcSk$WZOs+3@{6D)RO z1oe-wk6EsHT5y!9I7)adw@FNe5Iivi*PdC=Z55tu&S2HbhE1@UTdDEfO8Ilk6vr(S z`RC$*b6LG2lDTABtt6kD$o1zb&y<>Z05WH1GIh++lusc49P&p&rrumU+Y%8&!8j_w zHWAn+m@WpNfM?-F6vE|0Cc{t|Nrfp?$f7WlDKWE{idRxG4TsZ_xy*pMEFyD9Q=b?0 zc|$))`I$_mnTv_%6EB3F@H%(1X6BmNRmm7uo0tslT)Vk*WmSs9B60LEE(xZO&3Cjw( ze`7IN#^5b;a$U}1vYZN+cfd}FX_u4lr&#ExrYj%Hc)W3?jxh6NByZNO3+hp~$JK!3<8wJ{B{=xi*8ySWhbnET~qT)`FwiD?@q6Z{vB04AH9*MIYB`dUFNJ~10 z<4g|4EgXtjXEIA!8OtE+MkebR~;~WIf94fxVPx!<@y2*^;$`Kq&=T$TqW(<*?A@u+Zfcz#_;J zpTiPwox!E%EJ(#xDz@?}uvS3UCoAidElLO*E3b`LfsI#zEe{sJW3U#YunmQ6t+0)9 zb0`=LL^*p>tMl`jdDeotd=Lv&g2wV)8LKMkEk-RjR!8_&>@0iP! zW1+LL(AmaAe;5dZARV*OvAh%HKgq6cIJ>%$tgyNCJogq2FQDOtkRDt09`{l}P|yI4 z6hy(iBNTL_pt}-VMhmfJETr5P%5BMpR!9R|PI5uo$!D|Ix&LIywlZW}i(v`G5?isv z){BtYC$^#4HZxX@ zNarP1#7k@&Z_{nOO}8C^$4JN2MG?dqnr#eC5#@>~x4nS#>GmQ5*SQGog16vpE<)qD z2#tq0v@n4QD6rOY(Gba^Te}>Te)dvNJo|l%95%1rH_wTv^Z;}t6*ojZKPFapqTK4*pFo6dJu!sjZSvgL& z7ZdHpM0>HoUMx^vPI@JAGx1P}5A4MU%9$1AM~Gvwy;!W=NxY7DH1QbX_)IxIQ$7uv zNyoSL;#=h-iH~Ofmro=RNWyG5hs$g%un!CDr{euoyq^m9Q{n#e@FLF_^L(iil^H@* zW)sKx_ThY$4a6IXuO_~hcm?qT#Od)qdR&3&E8-x&P=PO0kY16={NI;Hh5{0Bx(b}G zq7}A5#;$^~+lNK=VUhizC=doC;5ALj4eg_$%F#497Gk+dELTbXO7d66z*v|F zlek=`=WmXN0njp;02RJTg>Rzan`roEJ#65%-Iv>TKW@_%x9J8Ys(OVuD7fV2`5~Sk zW+)Da!Z|Pku7W9WEnE*9VH3o1hp}9>kvnh?I2?|I`ON?7LIS5rI18I$3%tXnxW=Wp z0UBwri3XcVU&HfM;#lYq7CL;Dim#DAo^*fGJ4wGzyn}cr<-I8HO?o%!J>*|V{zWhc z=E0lH|HHQ^Fqr}-5^$Eoia1_eT}>Q~59=B;1l0_|5fpQvm;>i>;9NC||`5jE$2XIO#zxPFRZ* z)-t_nnO<-6{B52er=sIjNe}-(1Am}_TAZ{NC#}5!Z&IFoZ9Z6=rg^tZ}vM3Maxq7y|tMj)fCo01D)xKmiT8)6g(D1I~gB)tMN` z^D{he%%QzJSPV;;|BX0HBhK<38o!6e@7;!XXc!Zp#l&Z+=qwf4@CnYX;?xcrDutD> z3Lb;CG;o3jPC}gZ49 zL*NYZCy;*y_t5LPhfaqm`YDQjdJ$fN-4G{jbLW1VA!=W&-%l?kkj(e^FiCq3WNg|? zVHx+%%<~TB`4t+vLPJ+D*%ij}3bWw~v*8N9as^*$$fRK`(6)w(Ss&Vnx9M>#)K&wj zr;U2rHR^SRqv2S}6*B)DaH?x0TqEI{Kb**e-BehPFNEO>;cz8P=7WtgKH#W;m*G`R z%PGJZM1Cjv>&Qn>-=n9^^st#8Hjjt?5GQZO$(vEQxsr0Flw;RFw2u3!p&X#5a-f=8 z3mafFU)8wES2nJ3y;I5cP8I1FNxwwgL>woY-UP`P%xNIFgCnIMM@o(hbL$}WMTBs4 zoWYTF0Y}n>qz94C)_-m_JjOYxg>zCXv@qYJ?r`IFlWU?LC8LK68SSm)FG!E!c(LpR zCp~tn%WEG>#7M(SXn4s=m<&0WEMfDy z+)TMp>fs!e(8dXHIp>(=D3EZSgf22r;c_Zm?hiR|1<$63bCg`ck#Ge^!Zh-wkuSZ2 zdnOK28CWc%QOQm8XcIl!VCAI8$#6prbSk+KOKdblEV=OzCsB+0~r9;*P6DK(i*9GS|z)6?SdLKgeO05}=C zLO19Iy&Z+GX&)La=XoDoRKn>YgwqoSLLAZ=38Ns3l#@lu*$A6>ANcY<@Pka*TBdAm zA!Gv7vIfBIIR|o^6l^nvoWRMILA+(1vs%oyc{h3+YCBkY0m)OBiHT0ODtm z2TR~I#1n}@;*eO<;lWg-ocLr&nS(xry%29i5Bnk$5EEiXLiI|*kZ>dti9(|7-Wl4f zvdx~Kp-r`an4$T|PIr8mU2?26=Qcf;va1A*ggT6hWh-Xmk{fjz%HTNDLBdkjD!R_BS_aBQ4Z% zoH~wE$MHI(9%(=tktU=CX+}DbR;0}!ooNWVJJH>Vp3Z!v5Gh7VkljcZ(v9>Wy$1OQ zfhfdakSD0?L??0`-DhX=rOu#t$@VVU>d975wtBMF8xar0(;yp3Yb33av_{ez^)xSg zT9)>{{kbgd2bMDwZlrLdH{yf%B7VpOgFHilGkSplBo>K7;*mro2}wcLAgM?il7Xx; z$SczjGZKn~A>l|Q5`{z~F$nctiNpV{P+>0_ddbjBVlSC`X{eWsy)gz&v?85I3(|qK zA=i;+q{pC1g%}YJ;@wcdE~J;R!Jw%qBpRVE6^q0pX-EbVXW>7IND{INNkP^isRqr3 z%3P?#l?q*{$dyK1X~fkV@!=VbyVAI;C*oz$22pkpWd~7q5Dg5Xfk913BhrA>BTl5w zppB?RNE>0{;fN}v2GJjMAmvC4(u%Yp6dFNABdQT98PSYfH)tabh>>s?(nDAvzK9p% zjrfq>3q2s68L1GI9nlH>5VJv>Gcue&91@MhAhF0~Bov84Ovp4O42eW0AOQw#3VBVH zNEK3z)YwaMv_Ok@wn6jGM~ac%q?aH%%MDr(Z3WRz5N!leR}ggs)gZJJ)I*)|ko-Y< zUg{2_?jY(8qI^&r(urJ0x{z+9!=MERAk-6_ij){;YQc2`$Q)uoCL=T$l7>)WNFzc8 WQ#}w0PNm_g6r4(fQ+YPE>;C~gdZOI` delta 51233 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 ^Xy;(B$z{dTANUcCRjQ?oF1q1@_{`E7y&K9SgQ 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 GH~$Y5m<84V diff --git a/slsDetectorServers/slsDetectorServer/communication_funcs_UDP.h b/slsDetectorServers/slsDetectorServer/communication_funcs_UDP.h index c983eb18e..e42343351 100755 --- a/slsDetectorServers/slsDetectorServer/communication_funcs_UDP.h +++ b/slsDetectorServers/slsDetectorServer/communication_funcs_UDP.h @@ -28,6 +28,7 @@ int getUdPSocketDescriptor() { int setUDPDestinationDetails(const char* ip, unsigned short int port) { udpDestinationPort = port; size_t len = strlen(ip); + memset(udpDestinationIp, 0, MAX_STR_LENGTH); strncpy(udpDestinationIp, ip, len > MAX_STR_LENGTH ? MAX_STR_LENGTH : len ); if (udpServerAddrInfo) { diff --git a/slsSupportLib/include/versionAPI.h b/slsSupportLib/include/versionAPI.h index dcbd57bee..1a6f701dc 100644 --- a/slsSupportLib/include/versionAPI.h +++ b/slsSupportLib/include/versionAPI.h @@ -7,4 +7,4 @@ #define APIRECEIVER 0x190405 #define APIGUI 0x190405 #define APIEIGER 0x190418 -#define APICTB 0x190503 +#define APICTB 0x190514 From 74d67261a94361c919061a8f9d54cefe4dc5c0e2 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Tue, 14 May 2019 17:09:24 +0200 Subject: [PATCH 12/76] no check for null when deleting --- slsDetectorSoftware/src/slsDetectorCommand.cpp | 2 +- slsReceiverSoftware/src/DataStreamer.cpp | 2 +- slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/slsDetectorSoftware/src/slsDetectorCommand.cpp b/slsDetectorSoftware/src/slsDetectorCommand.cpp index d43806288..4306b6d61 100755 --- a/slsDetectorSoftware/src/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp @@ -3439,7 +3439,7 @@ std::string slsDetectorCommand::cmdDetectorSize(int narg, char *args[], int acti ret = myDet->setDynamicRange(val, detPos); } else if (cmd == "roi") { const ROI* r = myDet->getROI(ret, detPos); - if (r != NULL) + delete [] r; } else if (cmd == "detsizechan") { sprintf(ans, "%d %d", myDet->getMaxNumberOfChannelsPerDetector(X), myDet->getMaxNumberOfChannelsPerDetector(Y)); diff --git a/slsReceiverSoftware/src/DataStreamer.cpp b/slsReceiverSoftware/src/DataStreamer.cpp index d76285da9..de30be551 100755 --- a/slsReceiverSoftware/src/DataStreamer.cpp +++ b/slsReceiverSoftware/src/DataStreamer.cpp @@ -46,7 +46,7 @@ DataStreamer::DataStreamer(int ind, Fifo* f, uint32_t* dr, std::vector* r, DataStreamer::~DataStreamer() { CloseZmqSocket(); - if (completeBuffer) delete [] completeBuffer; + delete [] completeBuffer; ThreadObject::DestroyThread(); } diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp index 41a728425..216f151f3 100755 --- a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp +++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp @@ -28,9 +28,9 @@ slsReceiverTCPIPInterface::~slsReceiverTCPIPInterface() { delete mySock; mySock=nullptr; } - if (interface) + delete interface; - if(receiver) + delete receiver; } From 55f482f915021b0f51abcc3705937bc8bfe064cd Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Tue, 14 May 2019 17:11:27 +0200 Subject: [PATCH 13/76] clang-tidy nullptr --- slsSupportLib/src/ClientSocket.cpp | 2 +- slsSupportLib/src/DataSocket.cpp | 8 ++++---- slsSupportLib/src/network_utils.cpp | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/slsSupportLib/src/ClientSocket.cpp b/slsSupportLib/src/ClientSocket.cpp index ab8978390..793ca1019 100755 --- a/slsSupportLib/src/ClientSocket.cpp +++ b/slsSupportLib/src/ClientSocket.cpp @@ -20,7 +20,7 @@ ClientSocket::ClientSocket(std::string stype, const std::string &host, hints.ai_socktype = SOCK_STREAM; hints.ai_flags |= AI_CANONNAME; - if (getaddrinfo(host.c_str(), NULL, &hints, &result) != 0) { + if (getaddrinfo(host.c_str(), nullptr, &hints, &result) != 0) { std::string msg = "ClientSocket cannot decode host:" + host + " on port " + std::to_string(port) + "\n"; throw SocketError(msg); diff --git a/slsSupportLib/src/DataSocket.cpp b/slsSupportLib/src/DataSocket.cpp index 83f223f82..1af3db89f 100755 --- a/slsSupportLib/src/DataSocket.cpp +++ b/slsSupportLib/src/DataSocket.cpp @@ -108,7 +108,7 @@ ConvertHostnameToInternetAddress(const std::string &hostname) { hints.ai_flags |= AI_CANONNAME; struct sockaddr_in serverAddr {}; - if (getaddrinfo(hostname.c_str(), NULL, &hints, &result) != 0) { + if (getaddrinfo(hostname.c_str(), nullptr, &hints, &result) != 0) { freeaddrinfo(result); std::string msg = "ClientSocket cannot decode host:" + hostname + "\n"; throw SocketError(msg); @@ -129,13 +129,13 @@ int ConvertHostnameToInternetAddress(const char *const hostname, hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; // get host info into res - int errcode = getaddrinfo(hostname, NULL, &hints, res); + int errcode = getaddrinfo(hostname, nullptr, &hints, res); if (errcode != 0) { FILE_LOG(logERROR) << "Could not convert hostname (" << hostname << ") to internet address (zmq):" << gai_strerror(errcode); } else { - if (*res == NULL) { + if (*res == nullptr) { FILE_LOG(logERROR) << "Could not converthostname (" << hostname << ") to internet address (zmq):" "gettaddrinfo returned null"; @@ -160,7 +160,7 @@ int ConvertInternetAddresstoIpString(struct ::addrinfo *res, char *ip, const int ipsize) { if (inet_ntop(res->ai_family, &((struct sockaddr_in *)res->ai_addr)->sin_addr, ip, - ipsize) != NULL) { + ipsize) != nullptr) { ::freeaddrinfo(res); return 0; } diff --git a/slsSupportLib/src/network_utils.cpp b/slsSupportLib/src/network_utils.cpp index d1b2afec7..a3dba74a8 100755 --- a/slsSupportLib/src/network_utils.cpp +++ b/slsSupportLib/src/network_utils.cpp @@ -83,7 +83,7 @@ uint32_t HostnameToIp(const char *hostname) { memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; - if (getaddrinfo(hostname, NULL, &hints, &result)) { + if (getaddrinfo(hostname, nullptr, &hints, &result)) { freeaddrinfo(result); throw RuntimeError("Could not convert hostname to ip"); } From 97692ae3ab24c31dc337665ffecfe560ff8fac31 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Tue, 14 May 2019 17:17:21 +0200 Subject: [PATCH 14/76] moved from c headers --- manual/manual-api/mainReceiver.cpp | 12 ++++++------ slsReceiverSoftware/src/DataStreamer.cpp | 2 +- slsReceiverSoftware/src/Listener.cpp | 4 ++-- slsReceiverSoftware/src/main.cpp | 8 ++++---- slsReceiverSoftware/src/slsReceiver.cpp | 10 +++++----- .../src/slsReceiverImplementation.cpp | 8 ++++---- .../src/slsReceiverTCPIPInterface.cpp | 14 +++++++------- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/manual/manual-api/mainReceiver.cpp b/manual/manual-api/mainReceiver.cpp index ca6e0f591..7762079e5 100755 --- a/manual/manual-api/mainReceiver.cpp +++ b/manual/manual-api/mainReceiver.cpp @@ -19,18 +19,18 @@ It is linked in manual/manual-api from slsReceiverSoftware/include ] #include "sls_detector_defs.h" #include "slsReceiverUsers.h" -#include -#include -#include //SIGINT +#include //SIGINT #include //system +#include +#include //#include "utilities.h" //#include "logger.h" +#include +#include #include //wait #include //wait -#include -#include //usleep -#include #include //tid +#include //usleep using namespace std; diff --git a/slsReceiverSoftware/src/DataStreamer.cpp b/slsReceiverSoftware/src/DataStreamer.cpp index de30be551..8a1fe7120 100755 --- a/slsReceiverSoftware/src/DataStreamer.cpp +++ b/slsReceiverSoftware/src/DataStreamer.cpp @@ -10,8 +10,8 @@ #include "ZmqSocket.h" #include "sls_detector_exceptions.h" +#include #include -#include const std::string DataStreamer::TypeName = "DataStreamer"; diff --git a/slsReceiverSoftware/src/Listener.cpp b/slsReceiverSoftware/src/Listener.cpp index f51ab178e..59b308de9 100755 --- a/slsReceiverSoftware/src/Listener.cpp +++ b/slsReceiverSoftware/src/Listener.cpp @@ -13,9 +13,9 @@ #include "container_utils.h" // For sls::make_unique<> #include "sls_detector_exceptions.h" -#include -#include +#include #include +#include const std::string Listener::TypeName = "Listener"; diff --git a/slsReceiverSoftware/src/main.cpp b/slsReceiverSoftware/src/main.cpp index 635298562..9c5331a94 100755 --- a/slsReceiverSoftware/src/main.cpp +++ b/slsReceiverSoftware/src/main.cpp @@ -5,14 +5,14 @@ #include "slsReceiverUsers.h" #include "logger.h" -#include -#include -#include //SIGINT +#include //SIGINT #include //system +#include +#include #include //wait #include //wait -#include //usleep #include +#include //usleep bool keeprunning; diff --git a/slsReceiverSoftware/src/slsReceiver.cpp b/slsReceiverSoftware/src/slsReceiver.cpp index d9b5855c1..eb84ab4df 100755 --- a/slsReceiverSoftware/src/slsReceiver.cpp +++ b/slsReceiverSoftware/src/slsReceiver.cpp @@ -3,13 +3,13 @@ * @short creates the UDP and TCP class objects ***********************************************/ -#include -#include -#include +#include #include -#include -#include #include +#include +#include +#include +#include #include "container_utils.h" // For sls::make_unique<> diff --git a/slsReceiverSoftware/src/slsReceiverImplementation.cpp b/slsReceiverSoftware/src/slsReceiverImplementation.cpp index 7bb1bd238..19be8d463 100755 --- a/slsReceiverSoftware/src/slsReceiverImplementation.cpp +++ b/slsReceiverSoftware/src/slsReceiverImplementation.cpp @@ -12,13 +12,13 @@ #include "Fifo.h" #include "ZmqSocket.h" //just for the zmq port define -#include // stat -#include -#include +#include //eperm #include //system +#include #include //strcpy -#include //eperm #include +#include +#include // stat /** cosntructor & destructor */ diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp index 216f151f3..29b3fe485 100755 --- a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp +++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp @@ -11,16 +11,16 @@ #include "slsReceiver.h" #include "versionAPI.h" -#include //EXIT -#include -#include -#include +#include +#include //EXIT +#include #include -#include +#include +#include //unique_ptr +#include +#include #include #include -#include -#include //unique_ptr slsReceiverTCPIPInterface::~slsReceiverTCPIPInterface() { stop(); From bc4d0452af0c695b52ff36c3d7f9f7c2cd5036ba Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Tue, 14 May 2019 17:25:43 +0200 Subject: [PATCH 15/76] removed unused error_defs.h --- python/src/Detector.h | 3 - slsDetectorSoftware/doxy.config | 1 - .../include/multiSlsDetector.h | 1 - slsDetectorSoftware/include/slsDetector.h | 2 +- slsSupportLib/CMakeLists.txt | 1 - slsSupportLib/include/error_defs.h | 342 ------------------ 6 files changed, 1 insertion(+), 349 deletions(-) delete mode 100755 slsSupportLib/include/error_defs.h diff --git a/python/src/Detector.h b/python/src/Detector.h index bb11b1a27..fd626ae37 100755 --- a/python/src/Detector.h +++ b/python/src/Detector.h @@ -7,12 +7,9 @@ #include #include -#include "error_defs.h" #include "multiSlsDetector.h" #include "slsDetector.h" -// #include "slsDetectorUtils.h" #include "sls_detector_defs.h" -// #include "sls_receiver_defs.h" class Detector { public: diff --git a/slsDetectorSoftware/doxy.config b/slsDetectorSoftware/doxy.config index c770b9cf0..daf9985d0 100755 --- a/slsDetectorSoftware/doxy.config +++ b/slsDetectorSoftware/doxy.config @@ -81,7 +81,6 @@ LATEX_HIDE_INDICES = YES PREDEFINED = __cplusplus INPUT = ../slsSupportLib/include/communication_funcs.h \ - ../slsSupportLib/include/error_defs.h \ ../slsSupportLib/include/sls_detector_defs.h \ ../slsSupportLib/include/sls_detector_funcs.h \ ../slsSupportLib/include/ansi.h \ diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 613034514..2a945e38a 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -1,7 +1,6 @@ #pragma once #include "SharedMemory.h" -#include "error_defs.h" #include "logger.h" #include "sls_detector_defs.h" diff --git a/slsDetectorSoftware/include/slsDetector.h b/slsDetectorSoftware/include/slsDetector.h index d4264abfb..3fc4c5d73 100755 --- a/slsDetectorSoftware/include/slsDetector.h +++ b/slsDetectorSoftware/include/slsDetector.h @@ -2,7 +2,7 @@ #include "ClientSocket.h" #include "SharedMemory.h" -#include "error_defs.h" +// #include "error_defs.h" #include "logger.h" #include "sls_detector_defs.h" #include "network_utils.h" diff --git a/slsSupportLib/CMakeLists.txt b/slsSupportLib/CMakeLists.txt index 6e2c640a6..7616de574 100755 --- a/slsSupportLib/CMakeLists.txt +++ b/slsSupportLib/CMakeLists.txt @@ -17,7 +17,6 @@ set(PUBLICHEADERS include/ansi.h include/sls_detector_defs.h include/sls_detector_funcs.h - include/error_defs.h include/versionAPI.h include/sls_detector_exceptions.h include/file_utils.h diff --git a/slsSupportLib/include/error_defs.h b/slsSupportLib/include/error_defs.h deleted file mode 100755 index 6b521689c..000000000 --- a/slsSupportLib/include/error_defs.h +++ /dev/null @@ -1,342 +0,0 @@ -/* - * error_defs.h - * - * Created on: Jan 18, 2013 - * Author: l_maliakal_d - */ - -#ifndef ERROR_DEFS_H_ -#define ERROR_DEFS_H_ - -#include "ansi.h" -#include "sls_detector_defs.h" - -#include -#include -#include -#include -// - -/** Error flags */ -/*Assumption: Only upto 63 detectors */ - -// multi errors -// 0xFFF0000000000000ULL -#define MULTI_DETECTORS_NOT_ADDED 0x8000000000000000ULL -#define MULTI_HAVE_DIFFERENT_VALUES 0x4000000000000000ULL -#define MULTI_CONFIG_FILE_ERROR 0x2000000000000000ULL -#define MULTI_POS_EXCEEDS_LIST 0x1000000000000000ULL -#define MUST_BE_MULTI_CMD 0x0800000000000000ULL -#define MULTI_OTHER_ERROR 0x0400000000000000ULL - -// sls errors -#define CRITICAL_ERROR_MASK 0xFFFFFFF - -// 0xFFFFFFF000000000ULL -#define CANNOT_CONNECT_TO_DETECTOR 0x4000000000000000ULL -#define CANNOT_CONNECT_TO_RECEIVER 0x2000000000000000ULL -#define COULDNOT_SET_CONTROL_PORT 0x1000000000000000ULL -#define COULDNOT_SET_STOP_PORT 0x0800000000000000ULL -#define COULDNOT_SET_DATA_PORT 0x0400000000000000ULL -#define FILE_PATH_DOES_NOT_EXIST 0x0200000000000000ULL -#define COULDNOT_CREATE_UDP_SOCKET 0x0100000000000000ULL -#define COULDNOT_CREATE_FILE 0x0080000000000000ULL -#define RECEIVER_DET_HOSTNAME_NOT_SET 0x0040000000000000ULL -#define RECEIVER_DET_HOSTTYPE_NOT_SET 0x0020000000000000ULL -#define DETECTOR_TEN_GIGA 0x0010000000000000ULL -#define DETECTOR_ACTIVATE 0x0008000000000000ULL -#define COULD_NOT_CONFIGURE_MAC 0x0004000000000000ULL -#define COULDNOT_START_RECEIVER 0x0002000000000000ULL // default error like starting threads -#define COULDNOT_STOP_RECEIVER 0x0001000000000000ULL -#define RECEIVER_DET_POSID_NOT_SET 0x0000800000000000ULL -#define RECEIVER_MULTI_DET_SIZE_NOT_SET 0x0000400000000000ULL -#define PREPARE_ACQUISITION 0x0000200000000000ULL -#define REGISER_WRITE_READ 0x0000100000000000ULL -#define VERSION_COMPATIBILITY 0x0000080000000000ULL -// 0xFFFFFF0000000000ULL - -// 0x000000FFFFFFFFFFULL -#define COULDNOT_SET_NETWORK_PARAMETER 0x0000000000000001ULL -#define COULDNOT_SET_ROI 0x0000000000000002ULL -#define RECEIVER_STREAMING_FREQUENCY 0x0000000000000004ULL -#define SETTINGS_NOT_SET 0x0000000000000008ULL -#define SETTINGS_FILE_NOT_OPEN 0x0000000000000010ULL -#define DETECTOR_TIMER_VALUE_NOT_SET 0x0000000000000020ULL -#define RECEIVER_ACQ_PERIOD_NOT_SET 0x0000000000000040ULL -#define RECEIVER_FRAME_NUM_NOT_SET 0x0000000000000080ULL -#define RECEIVER_DYNAMIC_RANGE 0x0000000000000100ULL -#define RECEIVER_TEN_GIGA 0x0000000000000200ULL -#define ALLTIMBITS_NOT_SET 0x0000000000000400ULL -#define COULD_NOT_SET_SPEED_PARAMETERS 0x0000000000000800ULL -#define COULD_NOT_SET_READOUT_FLAGS 0x0000000000001000ULL -#define COULD_NOT_SET_FIFO_DEPTH 0x0000000000002000ULL -#define COULD_NOT_SET_COUNTER_BIT 0x0000000000004000ULL -#define COULD_NOT_PULSE 0x0000000000008000ULL -#define COULD_NOT_SET_RATE_CORRECTION 0x0000000000010000ULL -#define DETECTOR_NETWORK_PARAMETER 0x0000000000020000ULL -#define RATE_CORRECTION_NOT_32or16BIT 0x0000000000040000ULL -#define RATE_CORRECTION_NO_TAU_PROVIDED 0x0000000000080000ULL -#define PROGRAMMING_ERROR 0x0000000000100000ULL -#define RECEIVER_ACTIVATE 0x0000000000200000ULL -#define DATA_STREAMING 0x0000000000400000ULL -#define RESET_ERROR 0x0000000000800000ULL -#define POWER_CHIP 0x0000000001000000ULL -#define RECEIVER_STREAMING_TIMER 0x0000000002000000ULL -#define RECEIVER_ACQ_TIME_NOT_SET 0x0000000004000000ULL -#define RECEIVER_FLIPPED_DATA_NOT_SET 0x0000000008000000ULL -#define THRESHOLD_NOT_SET 0x0000000010000000ULL -#define RECEIVER_FILE_FORMAT 0x0000000020000000ULL -#define RECEIVER_PARAMETER_NOT_SET 0x0000000040000000ULL -#define RECEIVER_TIMER_NOT_SET 0x0000000080000000ULL -#define RECEIVER_ENABLE_GAPPIXELS_NOT_SET 0x0000000100000000ULL -#define RESTREAM_STOP_FROM_RECEIVER 0x0000000200000000ULL -#define TEMPERATURE_CONTROL 0x0000000400000000ULL -#define AUTO_COMP_DISABLE 0x0000000800000000ULL -#define CONFIG_FILE 0x0000001000000000ULL -#define STORAGE_CELL_START 0x0000002000000000ULL -#define OTHER_ERROR_CODE 0x0000004000000000ULL -// 0x000000FFFFFFFFFFULL - - -/** @short class returning all error messages for error mask */ -class errorDefs { - - -public: - - /** Constructor */ - errorDefs():errorMask(0){ - strcpy(notAddedList,""); - }; - - /** Gets the error message - * param errorMask error mask - /returns error message from error mask - */ - static std::string getErrorMessage(int64_t slsErrorMask){ - - std::string retval = ""; - - if(slsErrorMask&CANNOT_CONNECT_TO_DETECTOR) - retval.append("Cannot connect to Detector\n"); - - if(slsErrorMask&CANNOT_CONNECT_TO_RECEIVER) - retval.append("Cannot connect to Receiver\n"); - - if(slsErrorMask&COULDNOT_SET_CONTROL_PORT) - retval.append("Could not set control port\n"); - - if(slsErrorMask&COULDNOT_SET_STOP_PORT) - retval.append("Could not set stop port\n"); - - if(slsErrorMask&COULDNOT_SET_DATA_PORT) - retval.append("Could not set receiver port\n"); - - if(slsErrorMask&FILE_PATH_DOES_NOT_EXIST) - retval.append("Path to Output Directory does not exist\n"); - - if(slsErrorMask&COULDNOT_CREATE_UDP_SOCKET) - retval.append("Could not create UDP socket to start receiver\n"); - - if(slsErrorMask&COULDNOT_CREATE_FILE) - retval.append("Could not create file to start receiver.\nCheck permissions of output directory or the overwrite flag\n"); - - if(slsErrorMask&RECEIVER_DET_HOSTNAME_NOT_SET) - retval.append("Could not send the detector hostname to the receiver.\n"); - - if(slsErrorMask&RECEIVER_DET_HOSTTYPE_NOT_SET) - retval.append("Could not send the detector type to the receiver.\n"); - - if(slsErrorMask&DETECTOR_TEN_GIGA) - retval.append("Could not enable/disable 10GbE in the detector.\n"); - - if(slsErrorMask&DETECTOR_ACTIVATE) - retval.append("Could not activate/deactivate detector\n"); - - if(slsErrorMask&RECEIVER_DET_POSID_NOT_SET) - retval.append("Could not set detector position id\n"); - - if(slsErrorMask&RECEIVER_MULTI_DET_SIZE_NOT_SET) - retval.append("Could not set multi detector size\n"); - - if(slsErrorMask&PREPARE_ACQUISITION) - retval.append("Could not prepare acquisition in detector\n"); - - if(slsErrorMask®ISER_WRITE_READ) - retval.append("Could not read/write register in detector\n"); - - if(slsErrorMask&VERSION_COMPATIBILITY) - retval.append("Incompatible versions with detector or receiver. Please check log for more details.\n"); - - - - if(slsErrorMask&COULD_NOT_CONFIGURE_MAC) - retval.append("Could not configure mac\n"); - - if(slsErrorMask&COULDNOT_SET_NETWORK_PARAMETER) - retval.append("Could not set network parameter.\n"); - - if(slsErrorMask&COULDNOT_SET_ROI) - retval.append("Could not set the exact region of interest. Verify ROI set by detector.\n"); - - if(slsErrorMask&RECEIVER_STREAMING_FREQUENCY) - retval.append("Could not set receiver read frequency.\n"); - - if(slsErrorMask&SETTINGS_NOT_SET) - retval.append("Could not set settings.\n"); - - if(slsErrorMask&SETTINGS_FILE_NOT_OPEN) - retval.append("Could not open settings file. Verify if it exists.\n"); - - if(slsErrorMask&COULDNOT_START_RECEIVER) - retval.append("Could not start receiver.\n"); - - if(slsErrorMask&COULDNOT_STOP_RECEIVER) - retval.append("Could not stop receiver.\n"); - - if(slsErrorMask&DETECTOR_TIMER_VALUE_NOT_SET) - retval.append("Could not set one of timer values in detector.\n"); - - if(slsErrorMask&RECEIVER_ACQ_PERIOD_NOT_SET) - retval.append("Could not set acquisition period in receiver.\n"); - - if(slsErrorMask&RECEIVER_FRAME_NUM_NOT_SET) - retval.append("Could not set frame number in receiver.\n"); - - if(slsErrorMask&RECEIVER_DYNAMIC_RANGE) - retval.append("Could not set dynamic range in receiver.\n"); - - if(slsErrorMask&RECEIVER_TEN_GIGA) - retval.append("Could not enable/disable 10GbE in the receiver.\n"); - - if(slsErrorMask&ALLTIMBITS_NOT_SET) - retval.append("Could not set all trimbits to value.\n"); - - if(slsErrorMask&COULD_NOT_SET_SPEED_PARAMETERS) - retval.append("Could not set the speed parameter value\n"); - - if(slsErrorMask&COULD_NOT_SET_READOUT_FLAGS) - retval.append("Could not set the readout flag\n"); - - if(slsErrorMask&COULD_NOT_SET_FIFO_DEPTH) - retval.append("Could not set receiver fifo depth\n"); - - if(slsErrorMask&COULD_NOT_SET_COUNTER_BIT) - retval.append("Could not set/reset counter bit\n"); - - if(slsErrorMask&COULD_NOT_PULSE) - retval.append("Could not pulse pixel or chip\n"); - - if(slsErrorMask&COULD_NOT_SET_RATE_CORRECTION) - retval.append("Could not set rate correction\n"); - - if(slsErrorMask&DETECTOR_NETWORK_PARAMETER) - retval.append("Could not set/get detector network parameter\n"); - - if(slsErrorMask&RATE_CORRECTION_NOT_32or16BIT) - retval.append("Rate correction Deactivated, must be in 32 or 16 bit mode\n"); - - if(slsErrorMask&RATE_CORRECTION_NO_TAU_PROVIDED) - retval.append("Rate correction Deactivated. No default tau provided in file\n"); - - if(slsErrorMask&PROGRAMMING_ERROR) - retval.append("Could not program FPGA\n"); - - if(slsErrorMask&RECEIVER_ACTIVATE) - retval.append("Could not activate/deactivate receiver\n"); - - if(slsErrorMask&DATA_STREAMING) - retval.append("Could not enable/disable Data Streaming\n"); - - if(slsErrorMask&RESET_ERROR) - retval.append("Could not reset the FPGA\n"); - - if(slsErrorMask&POWER_CHIP) - retval.append("Could not power on/off/get the chip\n"); - - if(slsErrorMask&RECEIVER_STREAMING_TIMER) - retval.append("Could not set receiver read timer\n"); - - if(slsErrorMask&RECEIVER_FLIPPED_DATA_NOT_SET) - retval.append("Could not set receiver flipped data/bottom\n"); - - if(slsErrorMask&THRESHOLD_NOT_SET) - retval.append("Could not set threshold\n"); - - if(slsErrorMask&RECEIVER_FILE_FORMAT) - retval.append("Could not set receiver file format\n"); - - if(slsErrorMask&RECEIVER_TIMER_NOT_SET) - retval.append("Could not set timer in receiver.\n"); - - if(slsErrorMask&RECEIVER_PARAMETER_NOT_SET) - retval.append("Could not set a paramater in receiver.\n"); - - if(slsErrorMask&RECEIVER_ENABLE_GAPPIXELS_NOT_SET) - retval.append("Could not enable/disable gap pixels in receiver.\n"); - - if(slsErrorMask&RESTREAM_STOP_FROM_RECEIVER) - retval.append("Could not restream stop from receiver.\n"); - - if(slsErrorMask&TEMPERATURE_CONTROL) - retval.append("Could not set/get threshold temperature, temp control or temp event.\n"); - - if(slsErrorMask&AUTO_COMP_DISABLE) - retval.append("Could not set/get auto comparator disable\n"); - - if(slsErrorMask&CONFIG_FILE) - retval.append("Could not load/write config file\n"); - - if(slsErrorMask&OTHER_ERROR_CODE) - retval.append("Some error occured.\n"); - - //------------------------------------------------------ length of message - - - return retval; - - } - - - /** Sets multi error mask - @param multi error mask to be set to - /returns multi error mask - */ - int64_t setErrorMask(int64_t i){errorMask=i;return getErrorMask();}; - - /**returns multi error mask */ - int64_t getErrorMask(){return errorMask;}; - - /** Clears error mask - /returns error mask - */ - int64_t clearErrorMask(){errorMask=0;return errorMask;}; - - /** Gets the not added detector list - /returns list - */ - char* getNotAddedList(){return notAddedList;}; - - /** Append the detector to not added detector list - * @param name append to the list - /returns list - */ - void appendNotAddedList(const char* name){strcat(notAddedList,name);strcat(notAddedList,"+");}; - - /** Clears not added detector list - /returns error mask - */ - void clearNotAddedList(){strcpy(notAddedList,"");}; - - -protected: - - /** Error Mask */ - int64_t errorMask; - - /** Detectors Not added List */ - char notAddedList[MAX_STR_LENGTH]; - -}; - -#endif /* ERROR_DEFS_H_ */ From 7314c52c63b1aa24ca843a7687f8fceb29881c7d Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Tue, 14 May 2019 17:32:21 +0200 Subject: [PATCH 16/76] removed unneccecary includes --- slsDetectorSoftware/include/slsDetector.h | 2 -- slsDetectorSoftware/src/slsDetector.cpp | 1 - slsSupportLib/include/ClientInterface.h | 1 - slsSupportLib/src/ClientInterface.cpp | 1 + slsSupportLib/tests/test-ClientInterface.cpp | 1 - slsSupportLib/tests/test-string_utils.cpp | 1 - 6 files changed, 1 insertion(+), 6 deletions(-) diff --git a/slsDetectorSoftware/include/slsDetector.h b/slsDetectorSoftware/include/slsDetector.h index 3fc4c5d73..7dcc0cd87 100755 --- a/slsDetectorSoftware/include/slsDetector.h +++ b/slsDetectorSoftware/include/slsDetector.h @@ -2,7 +2,6 @@ #include "ClientSocket.h" #include "SharedMemory.h" -// #include "error_defs.h" #include "logger.h" #include "sls_detector_defs.h" #include "network_utils.h" @@ -16,7 +15,6 @@ class ClientInterface; class multiSlsDetector; class ServerInterface; -class MySocketTCP; #define SLS_SHMVERSION 0x190503 #define MAX_RX_DBIT 64 diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index 606d0e772..4b667ef6d 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -1,7 +1,6 @@ #include "slsDetector.h" #include "ClientInterface.h" #include "ClientSocket.h" -#include "MySocketTCP.h" #include "ServerInterface.h" #include "SharedMemory.h" #include "file_utils.h" diff --git a/slsSupportLib/include/ClientInterface.h b/slsSupportLib/include/ClientInterface.h index 379d10bd6..19f3cd5e3 100755 --- a/slsSupportLib/include/ClientInterface.h +++ b/slsSupportLib/include/ClientInterface.h @@ -2,7 +2,6 @@ #include "sls_detector_defs.h" -#include "MySocketTCP.h" #include "ClientSocket.h" diff --git a/slsSupportLib/src/ClientInterface.cpp b/slsSupportLib/src/ClientInterface.cpp index a09ff6002..2d5a3c2fb 100755 --- a/slsSupportLib/src/ClientInterface.cpp +++ b/slsSupportLib/src/ClientInterface.cpp @@ -1,5 +1,6 @@ #include "ClientInterface.h" #include "ClientSocket.h" +#include ClientInterface::ClientInterface(sls::ClientSocket *socket, int n) : socket_(socket){} diff --git a/slsSupportLib/tests/test-ClientInterface.cpp b/slsSupportLib/tests/test-ClientInterface.cpp index 633e8a0f9..831ca51e8 100755 --- a/slsSupportLib/tests/test-ClientInterface.cpp +++ b/slsSupportLib/tests/test-ClientInterface.cpp @@ -1,5 +1,4 @@ #include "ClientInterface.h" -#include "MySocketTCP.h" #include "catch.hpp" //tests to add diff --git a/slsSupportLib/tests/test-string_utils.cpp b/slsSupportLib/tests/test-string_utils.cpp index efbf99b76..d31a7fbc2 100755 --- a/slsSupportLib/tests/test-string_utils.cpp +++ b/slsSupportLib/tests/test-string_utils.cpp @@ -1,4 +1,3 @@ -#include "MySocketTCP.h" #include "catch.hpp" #include "logger.h" #include From 24fc5de58d0bd206f773d8ecb6fca7e5b122f6da Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Tue, 14 May 2019 17:34:51 +0200 Subject: [PATCH 17/76] clang-tidy header include order --- slsDetectorSoftware/src/multiSlsDetector.cpp | 2 +- slsReceiverSoftware/src/BinaryFile.cpp | 2 +- slsReceiverSoftware/src/DataProcessor.cpp | 4 ++-- slsReceiverSoftware/src/DataStreamer.cpp | 2 +- slsReceiverSoftware/src/Fifo.cpp | 2 +- slsReceiverSoftware/src/Listener.cpp | 4 ++-- slsReceiverSoftware/src/main.cpp | 4 ++-- slsReceiverSoftware/src/slsReceiver.cpp | 2 +- slsReceiverSoftware/src/slsReceiverImplementation.cpp | 4 ++-- slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp | 4 ++-- slsSupportLib/src/ServerSocket.cpp | 2 +- slsSupportLib/tests/test-Sockets.cpp | 2 +- slsSupportLib/tests/test-network_utils.cpp | 2 +- 13 files changed, 18 insertions(+), 18 deletions(-) diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index a227fb1eb..6da911c14 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -12,8 +12,8 @@ #include "container_utils.h" -#include "string_utils.h" #include "network_utils.h" +#include "string_utils.h" #include #include diff --git a/slsReceiverSoftware/src/BinaryFile.cpp b/slsReceiverSoftware/src/BinaryFile.cpp index 2ad806e86..6b9ec97e9 100755 --- a/slsReceiverSoftware/src/BinaryFile.cpp +++ b/slsReceiverSoftware/src/BinaryFile.cpp @@ -5,8 +5,8 @@ ***********************************************/ #include "BinaryFile.h" -#include "receiver_defs.h" #include "Fifo.h" +#include "receiver_defs.h" #include diff --git a/slsReceiverSoftware/src/DataProcessor.cpp b/slsReceiverSoftware/src/DataProcessor.cpp index a33ffd06a..1b5721083 100755 --- a/slsReceiverSoftware/src/DataProcessor.cpp +++ b/slsReceiverSoftware/src/DataProcessor.cpp @@ -7,9 +7,9 @@ #include "DataProcessor.h" -#include "GeneralData.h" -#include "Fifo.h" #include "BinaryFile.h" +#include "Fifo.h" +#include "GeneralData.h" #ifdef HDF5C #include "HDF5File.h" #endif diff --git a/slsReceiverSoftware/src/DataStreamer.cpp b/slsReceiverSoftware/src/DataStreamer.cpp index 8a1fe7120..ca8c9c59c 100755 --- a/slsReceiverSoftware/src/DataStreamer.cpp +++ b/slsReceiverSoftware/src/DataStreamer.cpp @@ -5,8 +5,8 @@ #include "DataStreamer.h" -#include "GeneralData.h" #include "Fifo.h" +#include "GeneralData.h" #include "ZmqSocket.h" #include "sls_detector_exceptions.h" diff --git a/slsReceiverSoftware/src/Fifo.cpp b/slsReceiverSoftware/src/Fifo.cpp index 74c90c7a3..9e744a0d7 100755 --- a/slsReceiverSoftware/src/Fifo.cpp +++ b/slsReceiverSoftware/src/Fifo.cpp @@ -8,9 +8,9 @@ #include "Fifo.h" #include "sls_detector_exceptions.h" -#include #include #include +#include Fifo::Fifo(int ind, uint32_t fifoItemSize, uint32_t depth): diff --git a/slsReceiverSoftware/src/Listener.cpp b/slsReceiverSoftware/src/Listener.cpp index 59b308de9..8760d6dba 100755 --- a/slsReceiverSoftware/src/Listener.cpp +++ b/slsReceiverSoftware/src/Listener.cpp @@ -7,10 +7,10 @@ #include "Listener.h" -#include "GeneralData.h" #include "Fifo.h" -#include "genericSocket.h" +#include "GeneralData.h" #include "container_utils.h" // For sls::make_unique<> +#include "genericSocket.h" #include "sls_detector_exceptions.h" #include diff --git a/slsReceiverSoftware/src/main.cpp b/slsReceiverSoftware/src/main.cpp index 9c5331a94..c2fbd0194 100755 --- a/slsReceiverSoftware/src/main.cpp +++ b/slsReceiverSoftware/src/main.cpp @@ -1,9 +1,9 @@ /* A simple server in the internet domain using TCP The port number is passed as an argument */ -#include "sls_detector_defs.h" -#include "slsReceiverUsers.h" #include "logger.h" +#include "slsReceiverUsers.h" +#include "sls_detector_defs.h" #include //SIGINT #include //system diff --git a/slsReceiverSoftware/src/slsReceiver.cpp b/slsReceiverSoftware/src/slsReceiver.cpp index eb84ab4df..9be63de83 100755 --- a/slsReceiverSoftware/src/slsReceiver.cpp +++ b/slsReceiverSoftware/src/slsReceiver.cpp @@ -13,11 +13,11 @@ #include "container_utils.h" // For sls::make_unique<> +#include "logger.h" #include "slsReceiver.h" #include "slsReceiverTCPIPInterface.h" #include "sls_detector_exceptions.h" #include "versionAPI.h" -#include "logger.h" slsReceiver::slsReceiver(int argc, char *argv[]): tcpipInterface (nullptr) { diff --git a/slsReceiverSoftware/src/slsReceiverImplementation.cpp b/slsReceiverSoftware/src/slsReceiverImplementation.cpp index 19be8d463..ca1a91da0 100755 --- a/slsReceiverSoftware/src/slsReceiverImplementation.cpp +++ b/slsReceiverSoftware/src/slsReceiverImplementation.cpp @@ -5,11 +5,11 @@ #include "slsReceiverImplementation.h" -#include "GeneralData.h" -#include "Listener.h" #include "DataProcessor.h" #include "DataStreamer.h" #include "Fifo.h" +#include "GeneralData.h" +#include "Listener.h" #include "ZmqSocket.h" //just for the zmq port define #include //eperm diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp index 29b3fe485..28a2f820f 100755 --- a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp +++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp @@ -4,11 +4,11 @@ ***********************************************/ #include "slsReceiverTCPIPInterface.h" -#include "slsReceiverImplementation.h" #include "MySocketTCP.h" #include "ServerInterface.h" -#include "slsReceiverUsers.h" #include "slsReceiver.h" +#include "slsReceiverImplementation.h" +#include "slsReceiverUsers.h" #include "versionAPI.h" #include diff --git a/slsSupportLib/src/ServerSocket.cpp b/slsSupportLib/src/ServerSocket.cpp index 54943cc79..0876c212c 100755 --- a/slsSupportLib/src/ServerSocket.cpp +++ b/slsSupportLib/src/ServerSocket.cpp @@ -6,10 +6,10 @@ #include "string_utils.h" #include +#include #include #include #include -#include #define DEFAULT_PACKET_SIZE 1286 #define SOCKET_BUFFER_SIZE (100 * 1024 * 1024) // 100 MB #define DEFAULT_BACKLOG 5 diff --git a/slsSupportLib/tests/test-Sockets.cpp b/slsSupportLib/tests/test-Sockets.cpp index 8726c2515..dae1fd6af 100644 --- a/slsSupportLib/tests/test-Sockets.cpp +++ b/slsSupportLib/tests/test-Sockets.cpp @@ -1,9 +1,9 @@ #include "ClientSocket.h" #include "ServerSocket.h" #include "catch.hpp" +#include #include #include -#include std::vector server() { std::cout << "starting server\n"; diff --git a/slsSupportLib/tests/test-network_utils.cpp b/slsSupportLib/tests/test-network_utils.cpp index 41e422812..c9457da4f 100755 --- a/slsSupportLib/tests/test-network_utils.cpp +++ b/slsSupportLib/tests/test-network_utils.cpp @@ -4,8 +4,8 @@ #include #include -#include "string_utils.h" #include "sls_detector_exceptions.h" +#include "string_utils.h" using namespace sls; From 45ae8a41abc322b45eff9a6fa13e27e1ca94caec Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Tue, 14 May 2019 17:43:34 +0200 Subject: [PATCH 18/76] updating eiger server --- .../bin/eigerDetectorServer_developer | Bin 288955 -> 289172 bytes slsSupportLib/include/versionAPI.h | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer b/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer index 3d6fbf81ed41410b00140e81bcd29503586f7f12..e8fc3dea528c8820f84b37f8838ef8fd606983d4 100755 GIT binary patch delta 44696 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ν>{~ZYKLm6 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 delta 43791 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 Date: Tue, 14 May 2019 18:38:30 +0200 Subject: [PATCH 19/76] ctb server: added adcvpp option to get and in mv --- slsDetectorServers/ctbDetectorServer/Makefile | 2 +- .../bin/ctbDetectorServer_developer | Bin 167848 -> 151744 bytes slsDetectorServers/slsDetectorServer/AD9257.h | 82 ++++++++++++++++-- .../slsDetectorFunctionList.h | 4 +- .../slsDetectorServer_funcs.c | 21 +++-- slsSupportLib/include/versionAPI.h | 2 +- 6 files changed, 92 insertions(+), 19 deletions(-) diff --git a/slsDetectorServers/ctbDetectorServer/Makefile b/slsDetectorServers/ctbDetectorServer/Makefile index 57505e19b..e996e0f00 100755 --- a/slsDetectorServers/ctbDetectorServer/Makefile +++ b/slsDetectorServers/ctbDetectorServer/Makefile @@ -1,6 +1,6 @@ CROSS = bfin-uclinux- CC = $(CROSS)gcc -CFLAGS += -Wall -DCHIPTESTBOARDD -DSTOP_SERVER -DDEBUG1 #-DJCTB -DVERBOSEI #-DVERBOSE +CFLAGS += -Wall -DCHIPTESTBOARDD -DSTOP_SERVER #-DDEBUG1 #-DJCTB -DVERBOSEI #-DVERBOSE LDLIBS += -lm -lstdc++ PROGS = ctbDetectorServer diff --git a/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer b/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer index 066549fcc91a34cfaeab3d85b2ebea2c788228c5..f0f2fbc3f31dfb94b993919227c37321c7ecdb13 100755 GIT binary patch delta 82875 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 Yz~*IQD{7$Lyg{fJc|E~Do{SXzKQ68i$^ZZW literal 167848 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 y5i=Df72gjbAEaLF2i{%F;MogmEh3R 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

cFMhiO%8+qV|wKPd`Dsy>`z9(Z~{=d-jUj zNoHPrwHbGt-rJ}l#YQ{jYcp6gV%oS~jS=?O{LL>L0~AS+y7sQ1O__~To7XJC&qc#z z(9|@XjF!>V#K~yy!PxKb)(~ro}z_@Uf!USV0x`98zXXGA7XLjxsPt+Svfj{ zv)`U3>R&hWmkj&fUW?G`;T}8O8D)Jl4$alVcP-3( zMPsf`+0J<|?sVkYtavhTjqTam6D@)3c9sGiCloLF&4HF>nwxLH>D9ubH%m0WuDRZN zxYjqj`s^@_cD&`eR%kXD(7aKi4R!VP7Akn)4w3&>sAcJ8cV4fLlf7da?Kq(+?drbG zisj$^VoZ?J8I$02!t3xZnM!-l9fQT)UAV8u~5LU|f@549|6S%b>SuDz_;IrMxx(OKvtqW9o6+#SNcC%oNrwP@&C zMh1zdpL_MDJT}XT&UF{uXJt{GJ}dq85wBP&38>xO)rXb_SO1UnnASWXt^0L{C=avh zndn?TPF#B@l&9k5%sst3>KFMun#RTd>DzwnG#8i;BJA#BDbku%HqRYj(NwV6`62@#uV5 zqalARO_%;^+7{MXl&_Jo8{V0Tx_3h@S;O6_S+h~{VSS?0F32M6f0Q=@;YlUstVr4)8oaEKc4~>vaynsXwk<7-+Vfp7tGkF@`ybVp zC4UpPCGK<7rc8(t0SCf)-b|Mvahhh*{*ObvWg87vsKZ#gr_jrA z;526g$+mee;=n1%BjOLQ(VYWzu?GVU;)KXlwqa)=6Ac2ZL-MLQO;io1XP6DfSbI(LP4Tqg$D zJlg4J6H8j`Blo#Z^jl{2cc;H#Wy`2VM-fzG=8NaGjM}G<*6Qh2yvjH5s&o`ub!P@v zd26h)%xuLfhl^EUa7lsIRrZCJuG((Ux=KImPM||0SYJx<>K%DB*l&@npy}@ znSctRaZhp_q~&@p6R0Aj<%&pj=9~bk2%CpTfyh6CyGtEQ)4Pb>M}|t%!cQbR=f^cO za*L8{Q~t6Gi$)i5A*!vge$=5|UM%(AyglJ(TRK}xr#%LTatWRGK#TcO&1}#2X%RPr zC5IMIWzBt+(~`L~jqzG}{cpAak-AM39piE1A+tZl=6SDLu@UN}X|cV~0%xDHC`}ou7@ZSV;mWB9X?X>@zce?vPr)h52_HX14Db@?C80&w=*i zf9h{z3)iU?hw!l?$7h`_(>MNal*_M*s?Qv(Nm%P=;D1u~TRlW&{c`R|71q;3_|1(X z|OWzDOs^ z&P>FqjCv+P9p(e*pU?i8H(|?i)_>%36T0=V<}V*)kfJGZ3qije&3u<@Uxz*9W0O#|D4wED^l#l=3N$Xaov%Eo^>Ee`%8l&|m(g>%(15uN)Hj7e41J z(nZQQq5Q{{BKI2$Ur{W|zcKS4M~Q>qyfyN{&7>hV#d40GU=h-NcgZg3IFl|71%idz zys|0%yXp1c?V~??AhNbJPqqGsb*Ha-^ya^A(~jRA-Tm8YdVC`a`DkHp^yho8ik!v) zURq>At-piw)p|gKnYhvjCSMb#i{>_$aH_s9PFOF_=KIF&E5F!@@j^dQ^_|84`zTt& zaqt|7otC6#-&t|#yTw#v^7ocb-{D+>YB0KQA7Ep=L==5Lol2X&xA2QM_L(j{#rz8^ z?zcIG6{7I+Kz`t=ICy!Ok-(rI7IW)4x}sxF@p4&hQWSl^d*F~wd2b9A$4`m7ub2&p z%iV%oJ$dB+c?5uLtES=QO1VurxU{9LdWwknaiG67?>-dDds9UAkKrS&_hVP8@hPGA zPPbs;xJ3NkVbb{Gt=P%7^tMXV6nkN;xb$NmCt_(E~DEWiV3T#UCV3B@hAdl1s z{lp&(y1EZ)9il<|Pr9Eh);~^oULDBa%@omBbzb_Cu)C@QJlJq?<|-E7x#IR!3;+76 z2>9ul(C@mr2*KPQVNst%0DVt?kq#f|7Bn3`ApZ3& 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 diff --git a/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c index ca5614029..2395d6687 100755 --- a/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c @@ -21,6 +21,8 @@ extern int debugflag; // Global variable from communication_funcs.c extern int isControlServer; +extern void getMacAddressinString(char* cmac, int size, uint64_t mac); +extern void getIpAddressinString(char* cip, uint32_t ip); int firmware_compatibility = OK; int firmware_check_done = 0; @@ -1213,24 +1215,14 @@ enum externalCommunicationMode getTiming() { int configureMAC(uint32_t destip, uint64_t destmac, uint64_t sourcemac, uint32_t sourceip, uint32_t udpport, uint32_t udpport2) { #ifndef VIRTUAL FILE_LOG(logINFO, ("Configuring MAC\n")); - char src_mac[50], src_ip[50],dst_mac[50], dst_ip[50]; - int src_port = 0xE185; - sprintf(src_ip,"%d.%d.%d.%d",(sourceip>>24)&0xff,(sourceip>>16)&0xff,(sourceip>>8)&0xff,(sourceip)&0xff); - sprintf(dst_ip,"%d.%d.%d.%d",(destip>>24)&0xff,(destip>>16)&0xff,(destip>>8)&0xff,(destip)&0xff); - sprintf(src_mac,"%02x:%02x:%02x:%02x:%02x:%02x",(unsigned int)((sourcemac>>40)&0xFF), - (unsigned int)((sourcemac>>32)&0xFF), - (unsigned int)((sourcemac>>24)&0xFF), - (unsigned int)((sourcemac>>16)&0xFF), - (unsigned int)((sourcemac>>8)&0xFF), - (unsigned int)((sourcemac>>0)&0xFF)); - sprintf(dst_mac,"%02x:%02x:%02x:%02x:%02x:%02x",(unsigned int)((destmac>>40)&0xFF), - (unsigned int)((destmac>>32)&0xFF), - (unsigned int)((destmac>>24)&0xFF), - (unsigned int)((destmac>>16)&0xFF), - (unsigned int)((destmac>>8)&0xFF), - (unsigned int)((destmac>>0)&0xFF)); - + + int src_port = DEFAULT_UDP_SOURCE_PORT; + char src_mac[50], src_ip[INET_ADDRSTRLEN],dst_mac[50], dst_ip[INET_ADDRSTRLEN]; + getMacAddressinString(src_mac, 50, sourcemac); + getMacAddressinString(dst_mac, 50, destmac); + getIpAddressinString(src_ip, sourceip); + getIpAddressinString(dst_ip, destip); FILE_LOG(logINFO, ( "\tSource IP : %s\n" diff --git a/slsDetectorServers/eigerDetectorServer/slsDetectorServer_defs.h b/slsDetectorServers/eigerDetectorServer/slsDetectorServer_defs.h index 3ab0c42f6..71bf95ca0 100755 --- a/slsDetectorServers/eigerDetectorServer/slsDetectorServer_defs.h +++ b/slsDetectorServers/eigerDetectorServer/slsDetectorServer_defs.h @@ -47,6 +47,7 @@ enum {E_PARALLEL, E_NON_PARALLEL, E_SAFE}; #define NORMAL_HIGHVOLTAGE_OUTPUTPORT "/sys/class/hwmon/hwmon5/device/out0_output" #define SPECIAL9M_HIGHVOLTAGE_PORT "/dev/ttyS1" #define SPECIAL9M_HIGHVOLTAGE_BUFFERSIZE (16) +#define DEFAULT_UDP_SOURCE_PORT (0xE185) /** Default Parameters */ #define DEFAULT_NUM_FRAMES (1) diff --git a/slsDetectorServers/slsDetectorServer/communication_funcs.c b/slsDetectorServers/slsDetectorServer/communication_funcs.c index 9dbfbacee..11de0f631 100755 --- a/slsDetectorServers/slsDetectorServer/communication_funcs.c +++ b/slsDetectorServers/slsDetectorServer/communication_funcs.c @@ -520,3 +520,19 @@ int Server_SendResult(int fileDes, intType itype, int update, void* retval, int return ret; } + + +void getMacAddressinString(char* cmac, int size, uint64_t mac) { + memset(cmac, 0, size); + sprintf(cmac,"%02x:%02x:%02x:%02x:%02x:%02x",(unsigned int)((mac>>40)&0xFF), + (unsigned int)((mac>>32)&0xFF), + (unsigned int)((mac>>24)&0xFF), + (unsigned int)((mac>>16)&0xFF), + (unsigned int)((mac>>8)&0xFF), + (unsigned int)((mac>>0)&0xFF)); +} + +void getIpAddressinString(char* cip, uint32_t ip) { + memset(cip, 0, INET_ADDRSTRLEN); + inet_ntop(AF_INET, &ip, cip, INET_ADDRSTRLEN); +} \ No newline at end of file diff --git a/slsDetectorServers/slsDetectorServer/communication_funcs.h b/slsDetectorServers/slsDetectorServer/communication_funcs.h index 633139740..cfe4b5637 100755 --- a/slsDetectorServers/slsDetectorServer/communication_funcs.h +++ b/slsDetectorServers/slsDetectorServer/communication_funcs.h @@ -52,4 +52,19 @@ int Server_VerifyLock(); */ int Server_SendResult(int fileDes, intType itype, int update, void* retval, int retvalSize); +/** + * Convert mac address from integer to char array + * @param cmac char arrary result + * @param size size of char array result + * @param mac mac address as an integer + */ +void getMacAddressinString(char* cmac, int size, uint64_t mac); + +/** + * Convert ip address from integer to char array + * @param cip char arrary result + * @param ip ip address as an integer + */ +void getIpAddressinString(char* cip, uint32_t ip); + #endif diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c index 7c318bc9c..b5aeaca75 100755 --- a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c +++ b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c @@ -2298,8 +2298,6 @@ int send_update(int file_des) { - - int configure_mac(int file_des) { ret = OK; memset(mess, 0, sizeof(mess)); @@ -2323,9 +2321,12 @@ int configure_mac(int file_des) { // dest ip uint32_t dstIp = 0; sscanf(args[1], "%x", &dstIp); - FILE_LOG(logDEBUG1, ("Dst Ip Addr: %d.%d.%d.%d = 0x%x \n", - (dstIp >> 24) & 0xff, (dstIp >> 16) & 0xff, (dstIp >> 8) & 0xff, (dstIp) & 0xff, - dstIp)); + { + char ipstring[INET_ADDRSTRLEN]; + getIpAddressinString(ipstring, dstIp); + FILE_LOG(logINFO, ("Dst Ip Addr: %s\n", ipstring)); + } + // dest mac uint64_t dstMac = 0; #ifdef VIRTUAL @@ -2333,23 +2334,19 @@ int configure_mac(int file_des) { #else sscanf(args[2], "%llx", &dstMac); #endif - FILE_LOG(logDEBUG1, ("Dst Mac Addr: (0x) ")); { - int iloop = 5; - for (iloop = 5; iloop >= 0; --iloop) { - printf ("%x", (unsigned int)(((dstMac >> (8 * iloop)) & 0xFF))); - if (iloop > 0) { - printf(":"); - } - } + char macstring[50]; + getMacAddressinString(macstring, 50, dstMac); + FILE_LOG(logDEBUG1, ("Dst Mac Addr: %s\n", macstring)); } - FILE_LOG(logDEBUG1, (" = %llx\n", dstMac)); // source ip uint32_t srcIp = 0; sscanf(args[3], "%x", &srcIp); - FILE_LOG(logDEBUG1, ("Src Ip Addr: %d.%d.%d.%d = 0x%x \n", - (srcIp >> 24) & 0xff, (srcIp >> 16) & 0xff, (srcIp >> 8) & 0xff, (srcIp) & 0xff, - srcIp)); + { + char ipstring[INET_ADDRSTRLEN]; + getIpAddressinString(ipstring, srcIp); + FILE_LOG(logINFO, ("Src Ip Addr: %s\n", ipstring)); + } // source mac uint64_t srcMac = 0; #ifdef VIRTUAL @@ -2357,17 +2354,11 @@ int configure_mac(int file_des) { #else sscanf(args[4], "%llx", &srcMac); #endif - FILE_LOG(logDEBUG1, ("Src Mac Addr: (0x) ")); { - int iloop = 5; - for (iloop = 5; iloop >= 0; --iloop) { - printf("%x", (unsigned int)(((srcMac >> (8 * iloop)) & 0xFF))); - if (iloop > 0) { - printf(":"); - } - } + char macstring[50]; + getMacAddressinString(macstring, 50, srcMac); + FILE_LOG(logDEBUG1, ("Src Mac Addr: %s\n", macstring)); } - FILE_LOG(logDEBUG1, (" = %llx\n", srcMac)); #if defined(JUNGFRAUD) || defined(EIGERD) // source port 2 @@ -2379,9 +2370,11 @@ int configure_mac(int file_des) { // dest ip2 uint32_t dstIp2 = 0; sscanf(args[6], "%x", &dstIp2); - FILE_LOG(logDEBUG1, ("Dst Ip Addr: %d.%d.%d.%d = 0x%x \n", - (dstIp2 >> 24) & 0xff, (dstIp2 >> 16) & 0xff, (dstIp2 >> 8) & 0xff, (dstIp2) & 0xff, - dstIp2)); + { + char ipstring[INET_ADDRSTRLEN]; + getIpAddressinString(ipstring, dstIp2); + FILE_LOG(logDEBUG1, ("Dst Ip Addr2: %s\n", ipstring)); + } // dest mac2 uint64_t dstMac2 = 0; #ifdef VIRTUAL @@ -2389,23 +2382,19 @@ int configure_mac(int file_des) { #else sscanf(args[7], "%llx", &dstMac2); #endif - FILE_LOG(logDEBUG1, ("Dst Mac Addr: (0x) ")); { - int iloop = 5; - for (iloop = 5; iloop >= 0; --iloop) { - printf ("%x", (unsigned int)(((dstMac2 >> (8 * iloop)) & 0xFF))); - if (iloop > 0) { - printf(":"); - } - } + char macstring[50]; + getMacAddressinString(macstring, 50, dstMac2); + FILE_LOG(logDEBUG1, ("Dst Mac Addr2: %s\n", macstring)); } - FILE_LOG(logDEBUG1, (" = %llx\n", dstMac2)); // source ip2 uint32_t srcIp2 = 0; sscanf(args[8], "%x", &srcIp2); - FILE_LOG(logDEBUG1, ("Src Ip Addr: %d.%d.%d.%d = 0x%x \n", - (srcIp2 >> 24) & 0xff, (srcIp2 >> 16) & 0xff, (srcIp2 >> 8) & 0xff, (srcIp2) & 0xff, - srcIp2)); + { + char ipstring[INET_ADDRSTRLEN]; + getIpAddressinString(ipstring, srcIp2); + FILE_LOG(logDEBUG1, ("Src Ip Addr2: %s\n", ipstring)); + } // source mac2 uint64_t srcMac2 = 0; #ifdef VIRTUAL @@ -2413,17 +2402,11 @@ int configure_mac(int file_des) { #else sscanf(args[9], "%llx", &srcMac2); #endif - FILE_LOG(logDEBUG1, ("Src Mac Addr: (0x) ")); { - int iloop = 5; - for (iloop = 5; iloop >= 0; --iloop) { - printf("%x", (unsigned int)(((srcMac2 >> (8 * iloop)) & 0xFF))); - if (iloop > 0) { - printf(":"); - } - } + char macstring[50]; + getMacAddressinString(macstring, 50, srcMac2); + FILE_LOG(logDEBUG1, ("Src Mac Addr2: %s\n", macstring)); } - FILE_LOG(logDEBUG1, (" = %llx\n", srcMac2)); // number of interfaces int numInterfaces = 0; diff --git a/slsSupportLib/include/versionAPI.h b/slsSupportLib/include/versionAPI.h index b31d1f42a..4a39bc3a9 100644 --- a/slsSupportLib/include/versionAPI.h +++ b/slsSupportLib/include/versionAPI.h @@ -6,5 +6,5 @@ #define APILIB 0x190405 #define APIRECEIVER 0x190405 #define APIGUI 0x190405 -#define APIEIGER 0x190514 #define APICTB 0x190514 +#define APIEIGER 0x190516 From 415567006f17770e2838b990ffbec8a96d8df6c0 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Thu, 16 May 2019 15:16:11 +0200 Subject: [PATCH 38/76] non used header --- slsDetectorSoftware/src/slsDetector.cpp | 1 - slsSupportLib/CMakeLists.txt | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index b904dc26a..3209b85e1 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -1,6 +1,5 @@ #include "slsDetector.h" #include "ClientSocket.h" -#include "ServerInterface.h" #include "SharedMemory.h" #include "file_utils.h" #include "multiSlsDetector.h" diff --git a/slsSupportLib/CMakeLists.txt b/slsSupportLib/CMakeLists.txt index 1a675972f..ec5cbfb6a 100755 --- a/slsSupportLib/CMakeLists.txt +++ b/slsSupportLib/CMakeLists.txt @@ -28,7 +28,7 @@ set(PUBLICHEADERS include/ClientSocket.h include/DataSocket.h include/ServerSocket.h - include/ServerInterface.h + include/ServerInterface2.h include/network_utils.h include/FixedCapacityContainer.h ) From fff79fbbb655816ed8dcd81ad6baaf65aedd8469 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Thu, 16 May 2019 16:58:03 +0200 Subject: [PATCH 39/76] const char* for command --- .../include/slsDetectorCommand.h | 96 +++---- .../src/slsDetectorCommand.cpp | 96 +++---- slsSupportLib/include/CmdLineParser.h | 3 +- slsSupportLib/src/CmdLineParser.cpp | 37 ++- slsSupportLib/tests/test-CmdLineParser.cpp | 243 +++++++++--------- 5 files changed, 243 insertions(+), 232 deletions(-) diff --git a/slsDetectorSoftware/include/slsDetectorCommand.h b/slsDetectorSoftware/include/slsDetectorCommand.h index 39fb02d5c..f9cb934a7 100755 --- a/slsDetectorSoftware/include/slsDetectorCommand.h +++ b/slsDetectorSoftware/include/slsDetectorCommand.h @@ -29,14 +29,14 @@ class slsDetectorCommand : public virtual slsDetectorDefs { * @param action can be PUT_ACTION or GET_ACTION(from text client even READOUT_ACTION for acquisition) * @param detPos -1 for all detectors in multi detector list or position of a specific detector in list */ - std::string executeLine(int narg, char *args[], int action, int detPos = -1); + std::string executeLine(int narg, const char * const args[], int action, int detPos = -1); /* /\** */ /* returns the help for the executeLine command */ /* \param os output stream to return the help to */ /* \param action can be PUT_ACTION or GET_ACTION (from text client even READOUT_ACTION for acquisition) */ /* *\/ */ - std::string helpLine(int narg, char *args[], int action=HELP_ACTION, int detPos = -1); + std::string helpLine(int narg, const char * const args[], int action=HELP_ACTION, int detPos = -1); static std::string helpAcquire(int action); static std::string helpData(int action); static std::string helpStatus(int action); @@ -96,56 +96,56 @@ class slsDetectorCommand : public virtual slsDetectorDefs { multiSlsDetector *myDet; - std::string cmdUnderDevelopment(int narg, char *args[], int action, int detPos = -1); - std::string cmdUnknown(int narg, char *args[], int action, int detPos = -1); - std::string cmdAcquire(int narg, char *args[], int action, int detPos = -1); - std::string cmdData(int narg, char *args[], int action, int detPos = -1); - std::string cmdStatus(int narg, char *args[], int action, int detPos = -1); - std::string cmdDataStream(int narg, char *args[], int action, int detPos = -1); - std::string cmdFree(int narg, char *args[], int action, int detPos = -1); - std::string cmdHostname(int narg, char *args[], int action, int detPos = -1); - std::string cmdUser(int narg, char *args[], int action, int detPos = -1); - std::string cmdHelp(int narg, char *args[], int action, int detPos = -1); - std::string cmdExitServer(int narg, char *args[], int action, int detPos = -1); - std::string cmdSettingsDir(int narg, char *args[], int action, int detPos = -1); - std::string cmdTrimEn(int narg, char *args[], int action, int detPos = -1); - std::string cmdOutDir(int narg, char *args[], int action, int detPos = -1); - std::string cmdFileName(int narg, char *args[], int action, int detPos = -1); - std::string cmdFileIndex(int narg, char *args[], int action, int detPos = -1); - std::string cmdRateCorr(int narg, char *args[], int action, int detPos = -1); - std::string cmdNetworkParameter(int narg, char *args[], int action, int detPos = -1); - std::string cmdPort(int narg, char *args[], int action, int detPos = -1); - std::string cmdLock(int narg, char *args[], int action, int detPos = -1); - std::string cmdLastClient(int narg, char *args[], int action, int detPos = -1); - std::string cmdOnline(int narg, char *args[], int action, int detPos = -1); - std::string cmdConfigureMac(int narg, char *args[], int action, int detPos = -1); - std::string cmdDetectorSize(int narg, char *args[], int action, int detPos = -1); - std::string cmdSettings(int narg, char *args[], int action, int detPos = -1); - std::string cmdSN(int narg, char *args[], int action, int detPos = -1); - std::string cmdDigiTest(int narg, char *args[], int action, int detPos = -1); - std::string cmdRegister(int narg, char *args[], int action, int detPos = -1); - std::string cmdDAC(int narg, char *args[], int action, int detPos = -1); - std::string cmdTiming(int narg, char *args[], int action, int detPos = -1); - std::string cmdTimer(int narg, char *args[], int action, int detPos = -1); - std::string cmdTimeLeft(int narg, char *args[], int action, int detPos = -1); - std::string cmdSpeed(int narg, char *args[], int action, int detPos = -1); - std::string cmdAdvanced(int narg, char *args[], int action, int detPos = -1); - std::string cmdConfiguration(int narg, char *args[], int action, int detPos = -1); - std::string cmdImage(int narg, char *args[], int action, int detPos = -1); - std::string cmdCounter(int narg, char *args[], int action, int detPos = -1); - std::string cmdADC(int narg, char *args[], int action, int detPos = -1); - std::string cmdTempControl(int narg, char *args[], int action, int detPos = -1); - std::string cmdEnablefwrite(int narg, char *args[], int action, int detPos = -1); - std::string cmdOverwrite(int narg, char *args[], int action, int detPos = -1); - std::string cmdReceiver(int narg, char *args[], int action, int detPos = -1); - std::string cmdPattern(int narg, char *args[], int action, int detPos = -1); - std::string cmdPulse(int narg, char *args[], int action, int detPos = -1); - std::string cmdProcessor(int narg, char *args[], int action, int detPos = -1); + std::string cmdUnderDevelopment(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdUnknown(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdAcquire(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdData(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdStatus(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdDataStream(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdFree(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdHostname(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdUser(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdHelp(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdExitServer(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdSettingsDir(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdTrimEn(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdOutDir(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdFileName(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdFileIndex(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdRateCorr(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdNetworkParameter(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdPort(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdLock(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdLastClient(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdOnline(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdConfigureMac(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdDetectorSize(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdSettings(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdSN(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdDigiTest(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdRegister(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdDAC(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdTiming(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdTimer(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdTimeLeft(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdSpeed(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdAdvanced(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdConfiguration(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdImage(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdCounter(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdADC(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdTempControl(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdEnablefwrite(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdOverwrite(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdReceiver(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdPattern(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdPulse(int narg, const char * const args[], int action, int detPos = -1); + std::string cmdProcessor(int narg, const char * const args[], int action, int detPos = -1); int numberOfCommands; std::string cmd; - typedef std::string (slsDetectorCommand::*MemFuncGetter)(int narg, char *args[], int action, int detPos); + typedef std::string (slsDetectorCommand::*MemFuncGetter)(int narg, const char * const args[], int action, int detPos); struct FuncTable diff --git a/slsDetectorSoftware/src/slsDetectorCommand.cpp b/slsDetectorSoftware/src/slsDetectorCommand.cpp index 4208c0c25..a1d02ca49 100755 --- a/slsDetectorSoftware/src/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp @@ -2130,7 +2130,7 @@ slsDetectorCommand::slsDetectorCommand(multiSlsDetector *det) { //----------------------------------------------------------- -std::string slsDetectorCommand::executeLine(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::executeLine(int narg, const char * const args[], int action, int detPos) { if (action == READOUT_ACTION) return cmdAcquire(narg, args, action, detPos); @@ -2161,14 +2161,14 @@ std::string slsDetectorCommand::executeLine(int narg, char *args[], int action, return cmdUnknown(narg, args, action, detPos); } -std::string slsDetectorCommand::cmdUnknown(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdUnknown(int narg, const char * const args[], int action, int detPos) { return std::string("Unknown command ") + std::string(args[0]) + std::string("\n") + helpLine(0, args, action, detPos); } -std::string slsDetectorCommand::cmdUnderDevelopment(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdUnderDevelopment(int narg, const char * const args[], int action, int detPos) { return std::string("Must still develop ") + std::string(args[0]) + std::string(" ( ") + cmd + std::string(" )\n"); } -std::string slsDetectorCommand::helpLine(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::helpLine(int narg, const char * const args[], int action, int detPos) { std::ostringstream os; @@ -2187,7 +2187,7 @@ std::string slsDetectorCommand::helpLine(int narg, char *args[], int action, int return executeLine(narg, args, HELP_ACTION, detPos); } -std::string slsDetectorCommand::cmdAcquire(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdAcquire(int narg, const char * const args[], int action, int detPos) { #ifdef VERBOSE std::cout << std::string("Executing command ") + std::string(args[0]) + std::string(" ( ") + cmd + std::string(" )\n"); #endif @@ -2232,7 +2232,7 @@ std::string slsDetectorCommand::helpAcquire(int action) { return os.str(); } -std::string slsDetectorCommand::cmdData(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdData(int narg, const char * const args[], int action, int detPos) { #ifdef VERBOSE std::cout << std::string("Executing command ") + std::string(args[0]) + std::string(" ( ") + cmd + std::string(" )\n"); @@ -2264,7 +2264,7 @@ std::string slsDetectorCommand::helpData(int action) { return std::string("data \t gets all data from the detector (if any) processes them and writes them to file according to the preferences already setup\n"); } -std::string slsDetectorCommand::cmdStatus(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdStatus(int narg, const char * const args[], int action, int detPos) { #ifdef VERBOSE std::cout << std::string("Executing command ") + std::string(args[0]) + std::string(" ( ") + cmd + std::string(" )\n"); @@ -2317,7 +2317,7 @@ std::string slsDetectorCommand::helpStatus(int action) { return os.str(); } -std::string slsDetectorCommand::cmdDataStream(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdDataStream(int narg, const char * const args[], int action, int detPos) { #ifdef VERBOSE std::cout << std::string("Executing command ") + std::string(args[0]) + std::string(" ( ") + cmd + std::string(" )\n"); @@ -2351,7 +2351,7 @@ std::string slsDetectorCommand::helpDataStream(int action) { return os.str(); } -std::string slsDetectorCommand::cmdFree(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdFree(int narg, const char * const args[], int action, int detPos) { #ifdef VERBOSE std::cout << std::string("Executing command ") + std::string(args[0]) + std::string(" ( ") + cmd + std::string(" )\n"); @@ -2367,7 +2367,7 @@ std::string slsDetectorCommand::helpFree(int action) { return std::string("free \t frees the shared memory\n"); } -std::string slsDetectorCommand::cmdHostname(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdHostname(int narg, const char * const args[], int action, int detPos) { #ifdef VERBOSE std::cout << std::string("Executing command ") + std::string(args[0]) + std::string(" ( ") + cmd + std::string(" )\n"); #endif @@ -2429,7 +2429,7 @@ std::string slsDetectorCommand::helpHostname(int action) { return os.str(); } -std::string slsDetectorCommand::cmdUser(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdUser(int narg, const char * const args[], int action, int detPos) { #ifdef VERBOSE std::cout << std::string("Executing command ") + std::string(args[0]) + std::string(" ( ") + cmd + std::string(" )\n"); #endif @@ -2459,7 +2459,7 @@ std::string slsDetectorCommand::helpUser(int action) { return os.str(); } -std::string slsDetectorCommand::cmdHelp(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdHelp(int narg, const char * const args[], int action, int detPos) { #ifdef VERBOSE std::cout << std::string("Executing command ") + std::string(args[0]) + std::string(" ( ") + cmd + std::string(" )\n"); #endif @@ -2472,7 +2472,7 @@ std::string slsDetectorCommand::cmdHelp(int narg, char *args[], int action, int return helpLine(0, args, action, detPos); } -std::string slsDetectorCommand::cmdExitServer(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdExitServer(int narg, const char * const args[], int action, int detPos) { #ifdef VERBOSE std::cout << std::string("Executing command ") + std::string(args[0]) + std::string(" ( ") + cmd + std::string(" )\n"); #endif @@ -2520,7 +2520,7 @@ std::string slsDetectorCommand::helpExitServer(int action) { return os.str(); } -std::string slsDetectorCommand::cmdSettingsDir(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdSettingsDir(int narg, const char * const args[], int action, int detPos) { #ifdef VERBOSE std::cout << std::string("Executing command ") + std::string(args[0]) + std::string(" ( ") + cmd + std::string(" )\n"); #endif @@ -2548,7 +2548,7 @@ std::string slsDetectorCommand::helpSettingsDir(int action) { return os.str(); } -std::string slsDetectorCommand::cmdTrimEn(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdTrimEn(int narg, const char * const args[], int action, int detPos) { std::vector energies; if (action == HELP_ACTION) return helpTrimEn(action); @@ -2579,7 +2579,7 @@ std::string slsDetectorCommand::helpTrimEn(int action) { return os.str(); } -std::string slsDetectorCommand::cmdOutDir(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdOutDir(int narg, const char * const args[], int action, int detPos) { myDet->setReceiverOnline(ONLINE_FLAG, detPos); if (action == HELP_ACTION) return helpOutDir(action); @@ -2599,7 +2599,7 @@ std::string slsDetectorCommand::helpOutDir(int action) { return os.str(); } -std::string slsDetectorCommand::cmdFileName(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdFileName(int narg, const char * const args[], int action, int detPos) { myDet->setReceiverOnline(ONLINE_FLAG, detPos); if (action == HELP_ACTION) return helpFileName(action); @@ -2635,7 +2635,7 @@ std::string slsDetectorCommand::helpFileName(int action) { return os.str(); } -std::string slsDetectorCommand::cmdEnablefwrite(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdEnablefwrite(int narg, const char * const args[], int action, int detPos) { int i; char ans[100]; @@ -2681,7 +2681,7 @@ std::string slsDetectorCommand::helpEnablefwrite(int action) { return os.str(); } -std::string slsDetectorCommand::cmdOverwrite(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdOverwrite(int narg, const char * const args[], int action, int detPos) { int i; char ans[100]; myDet->setReceiverOnline(ONLINE_FLAG, detPos); @@ -2707,7 +2707,7 @@ std::string slsDetectorCommand::helpOverwrite(int action) { return os.str(); } -std::string slsDetectorCommand::cmdFileIndex(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdFileIndex(int narg, const char * const args[], int action, int detPos) { myDet->setReceiverOnline(ONLINE_FLAG, detPos); if (action == HELP_ACTION) { return helpFileName(action); @@ -2727,7 +2727,7 @@ std::string slsDetectorCommand::helpFileIndex(int action) { return os.str(); } -std::string slsDetectorCommand::cmdRateCorr(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdRateCorr(int narg, const char * const args[], int action, int detPos) { if (action == HELP_ACTION) { return helpRateCorr(action); @@ -2754,7 +2754,7 @@ std::string slsDetectorCommand::helpRateCorr(int action) { return os.str(); } -// std::string slsDetectorCommand::cmdThreaded(int narg, char *args[], int action, int detPos){ +// std::string slsDetectorCommand::cmdThreaded(int narg, const char * const args[], int action, int detPos){ // int ival; // char answer[1000]; @@ -2780,7 +2780,7 @@ std::string slsDetectorCommand::helpThreaded(int action) { return os.str(); } -std::string slsDetectorCommand::cmdImage(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdImage(int narg, const char * const args[], int action, int detPos) { std::string sval; int retval = FAIL; if (action == HELP_ACTION) @@ -2815,7 +2815,7 @@ std::string slsDetectorCommand::helpImage(int action) { return os.str(); } -std::string slsDetectorCommand::cmdCounter(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdCounter(int narg, const char * const args[], int action, int detPos) { int ival; char answer[100]; std::string sval; @@ -2876,7 +2876,7 @@ std::string slsDetectorCommand::helpCounter(int action) { return os.str(); } -std::string slsDetectorCommand::cmdNetworkParameter(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdNetworkParameter(int narg, const char * const args[], int action, int detPos) { char ans[100] = {0}; int i; @@ -3127,7 +3127,7 @@ std::string slsDetectorCommand::helpNetworkParameter(int action) { return os.str(); } -std::string slsDetectorCommand::cmdPort(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdPort(int narg, const char * const args[], int action, int detPos) { if (action == HELP_ACTION) return helpPort(action); @@ -3175,7 +3175,7 @@ std::string slsDetectorCommand::helpPort(int action) { return os.str(); } -std::string slsDetectorCommand::cmdLock(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdLock(int narg, const char * const args[], int action, int detPos) { if (action == HELP_ACTION) return helpLock(action); @@ -3226,7 +3226,7 @@ std::string slsDetectorCommand::helpLock(int action) { return os.str(); } -std::string slsDetectorCommand::cmdLastClient(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdLastClient(int narg, const char * const args[], int action, int detPos) { if (action == HELP_ACTION) return helpLastClient(action); @@ -3257,7 +3257,7 @@ std::string slsDetectorCommand::helpLastClient(int action) { return os.str(); } -std::string slsDetectorCommand::cmdOnline(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdOnline(int narg, const char * const args[], int action, int detPos) { if (action == HELP_ACTION) { return helpOnline(action); @@ -3341,7 +3341,7 @@ std::string slsDetectorCommand::helpOnline(int action) { return os.str(); } -std::string slsDetectorCommand::cmdConfigureMac(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdConfigureMac(int narg, const char * const args[], int action, int detPos) { if (action == HELP_ACTION) { return helpConfigureMac(action); @@ -3372,7 +3372,7 @@ std::string slsDetectorCommand::helpConfigureMac(int action) { return os.str(); } -std::string slsDetectorCommand::cmdDetectorSize(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdDetectorSize(int narg, const char * const args[], int action, int detPos) { if (action == HELP_ACTION) return helpDetectorSize(action); @@ -3489,7 +3489,7 @@ std::string slsDetectorCommand::helpDetectorSize(int action) { return os.str(); } -std::string slsDetectorCommand::cmdSettings(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdSettings(int narg, const char * const args[], int action, int detPos) { if (action == HELP_ACTION) return helpSettings(action); @@ -3607,7 +3607,7 @@ std::string slsDetectorCommand::helpSettings(int action) { return os.str(); } -std::string slsDetectorCommand::cmdSN(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdSN(int narg, const char * const args[], int action, int detPos) { char answer[1000]; @@ -3700,7 +3700,7 @@ std::string slsDetectorCommand::helpSN(int action) { return os.str(); } -std::string slsDetectorCommand::cmdDigiTest(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdDigiTest(int narg, const char * const args[], int action, int detPos) { char answer[1000]; @@ -3751,7 +3751,7 @@ std::string slsDetectorCommand::helpDigiTest(int action) { return os.str(); } -std::string slsDetectorCommand::cmdRegister(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdRegister(int narg, const char * const args[], int action, int detPos) { if (action == HELP_ACTION) return helpRegister(action); @@ -3869,7 +3869,7 @@ std::string slsDetectorCommand::helpRegister(int action) { return os.str(); } -std::string slsDetectorCommand::cmdDAC(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdDAC(int narg, const char * const args[], int action, int detPos) { if (action == HELP_ACTION) return helpDAC(action); @@ -4215,7 +4215,7 @@ std::string slsDetectorCommand::helpDAC(int action) { return os.str(); } -std::string slsDetectorCommand::cmdADC(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdADC(int narg, const char * const args[], int action, int detPos) { dacIndex adc; int idac; @@ -4342,7 +4342,7 @@ std::string slsDetectorCommand::helpADC(int action) { return os.str(); } -std::string slsDetectorCommand::cmdTempControl(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdTempControl(int narg, const char * const args[], int action, int detPos) { char answer[1000] = ""; int val = -1; @@ -4409,7 +4409,7 @@ std::string slsDetectorCommand::helpTempControl(int action) { return os.str(); } -std::string slsDetectorCommand::cmdTiming(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdTiming(int narg, const char * const args[], int action, int detPos) { #ifdef VERBOSE std::cout << std::string("Executing command ") + std::string(args[0]) + std::string(" ( ") + cmd + std::string(" )\n"); #endif @@ -4435,7 +4435,7 @@ std::string slsDetectorCommand::helpTiming(int action) { return os.str(); } -std::string slsDetectorCommand::cmdTimer(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdTimer(int narg, const char * const args[], int action, int detPos) { timerIndex index; int64_t t = -1, ret; double val, rval; @@ -4565,7 +4565,7 @@ std::string slsDetectorCommand::helpTimer(int action) { return os.str(); } -std::string slsDetectorCommand::cmdTimeLeft(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdTimeLeft(int narg, const char * const args[], int action, int detPos) { timerIndex index; int64_t ret; double rval; @@ -4635,7 +4635,7 @@ std::string slsDetectorCommand::helpTimeLeft(int action) { return os.str(); } -std::string slsDetectorCommand::cmdSpeed(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdSpeed(int narg, const char * const args[], int action, int detPos) { speedVariable index; int t = -1, ret = 0, mode = 0; @@ -4732,7 +4732,7 @@ std::string slsDetectorCommand::helpSpeed(int action) { return os.str(); } -std::string slsDetectorCommand::cmdAdvanced(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdAdvanced(int narg, const char * const args[], int action, int detPos) { char answer[1000] = ""; @@ -4970,7 +4970,7 @@ std::string slsDetectorCommand::helpAdvanced(int action) { return os.str(); } -std::string slsDetectorCommand::cmdConfiguration(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdConfiguration(int narg, const char * const args[], int action, int detPos) { if (action == HELP_ACTION) return helpConfiguration(action); @@ -5040,7 +5040,7 @@ std::string slsDetectorCommand::helpConfiguration(int action) { return os.str(); } -std::string slsDetectorCommand::cmdReceiver(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdReceiver(int narg, const char * const args[], int action, int detPos) { char answer[100]; int ival = -1; @@ -5288,7 +5288,7 @@ std::string slsDetectorCommand::helpPattern(int action) { return os.str(); } -std::string slsDetectorCommand::cmdPattern(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdPattern(int narg, const char * const args[], int action, int detPos) { if (action == HELP_ACTION) return helpPattern(action); @@ -5758,7 +5758,7 @@ std::string slsDetectorCommand::helpPulse(int action) { return os.str(); } -std::string slsDetectorCommand::cmdPulse(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdPulse(int narg, const char * const args[], int action, int detPos) { int retval = FAIL; if (action == HELP_ACTION) @@ -5820,7 +5820,7 @@ std::string slsDetectorCommand::helpProcessor(int action) { return os.str(); } -std::string slsDetectorCommand::cmdProcessor(int narg, char *args[], int action, int detPos) { +std::string slsDetectorCommand::cmdProcessor(int narg, const char * const args[], int action, int detPos) { if (action == HELP_ACTION) return helpProcessor(action); diff --git a/slsSupportLib/include/CmdLineParser.h b/slsSupportLib/include/CmdLineParser.h index 8066438d3..245f8ad26 100755 --- a/slsSupportLib/include/CmdLineParser.h +++ b/slsSupportLib/include/CmdLineParser.h @@ -10,14 +10,13 @@ class CmdLineParser { void Parse(const std::string &s); void Print(); - //getters int multi_id() const { return multi_id_; }; int detector_id() const { return detector_id_; }; int n_arguments() const { return arguments_.size(); } const std::string &command() const { return command_; } const std::string &executable() const { return executable_; } const std::vector &arguments() const { return arguments_; }; - std::vector argv(); + std::vector argv() const; private: void DecodeIdAndPosition(const char *c); diff --git a/slsSupportLib/src/CmdLineParser.cpp b/slsSupportLib/src/CmdLineParser.cpp index 9ede50612..23a6a8950 100755 --- a/slsSupportLib/src/CmdLineParser.cpp +++ b/slsSupportLib/src/CmdLineParser.cpp @@ -5,10 +5,11 @@ #include #include #include -//printing function for debugging + void CmdLineParser::Print() { std::cout << "\nCmdLineParser::Print()\n"; - std::cout << "\tmulti_id: " << multi_id_ << ", detector_id: " << detector_id_ << std::endl; + std::cout << "\tmulti_id: " << multi_id_ + << ", detector_id: " << detector_id_ << std::endl; std::cout << "\texecutable: " << executable_ << '\n'; std::cout << "\tcommand: " << command_ << '\n'; std::cout << "\tn_arguments: " << n_arguments() << '\n'; @@ -20,26 +21,21 @@ void CmdLineParser::Print() { }; void CmdLineParser::Parse(int argc, char *argv[]) { - //first element of argv is the command used to call the executable ->skipping - //and if this is the only command skip all - executable_ = argv[0]; + executable_ = argv[0]; //first arg is calling binary if (argc > 1) { - //second element is cmd string that needs to be decoded DecodeIdAndPosition(argv[1]); - //The rest of the arguments goes into a vector for later processing for (int i = 2; i < argc; ++i) { - arguments_.emplace_back(std::string(argv[i])); + arguments_.emplace_back(argv[i]); } } -}; +} void CmdLineParser::Parse(const std::string &s) { std::istringstream iss(s); auto it = std::istream_iterator(iss); - //read the first element and increment command_ = *it++; - arguments_ = std::vector(it, std::istream_iterator()); - ; + arguments_ = + std::vector(it, std::istream_iterator()); DecodeIdAndPosition(command_.c_str()); } @@ -51,19 +47,23 @@ void CmdLineParser::DecodeIdAndPosition(const char *c) { if (contains_id && contains_pos) { int r = sscanf(c, "%d-%d:%s", &multi_id_, &detector_id_, tmp); if (r != 3) { - throw(std::invalid_argument("Cannot decode client or detector id from: \"" + std::string(c) + "\"\n")); + throw(std::invalid_argument( + "Cannot decode client or detector id from: \"" + + std::string(c) + "\"\n")); } command_ = tmp; } else if (contains_id && !contains_pos) { int r = sscanf(c, "%d-%s", &multi_id_, tmp); if (r != 2) { - throw(std::invalid_argument("Cannot decode client id from: \"" + std::string(c) + "\"\n")); + throw(std::invalid_argument("Cannot decode client id from: \"" + + std::string(c) + "\"\n")); } command_ = tmp; } else if (!contains_id && contains_pos) { int r = sscanf(c, "%d:%s", &detector_id_, tmp); if (r != 2) { - throw(std::invalid_argument("Cannot decode detector id from: \"" + std::string(c) + "\"\n")); + throw(std::invalid_argument("Cannot decode detector id from: \"" + + std::string(c) + "\"\n")); } command_ = tmp; } else { @@ -71,12 +71,11 @@ void CmdLineParser::DecodeIdAndPosition(const char *c) { } } -std::vector CmdLineParser::argv() { - std::vector vec; - if (command_.empty()!=true){ +std::vector CmdLineParser::argv() const { + std::vector vec; + if (command_.empty() != true) { vec.push_back(&command_.front()); } - for (auto &arg : arguments_) { vec.push_back(&arg.front()); } diff --git a/slsSupportLib/tests/test-CmdLineParser.cpp b/slsSupportLib/tests/test-CmdLineParser.cpp index df4c3e27a..5cb4aaa9c 100755 --- a/slsSupportLib/tests/test-CmdLineParser.cpp +++ b/slsSupportLib/tests/test-CmdLineParser.cpp @@ -2,13 +2,124 @@ #include "catch.hpp" #include #include -//tests to add -//help for all docs -//command for all depreciated commands +// tests to add +// help for all docs +// command for all depreciated commands -TEST_CASE("Parse with no arguments results in no command and default id") { - //build up argc and argv - //first argument is the command used to call the binary +using vs = std::vector; + +SCENARIO("Construction", "[support]") { + GIVEN("A default constructed CmdLineParser") { + CmdLineParser p; + THEN("The state of the object is valid") { + REQUIRE(p.detector_id() == -1); + REQUIRE(p.multi_id() == 0); + REQUIRE(p.command().empty()); + REQUIRE(p.arguments().empty()); + REQUIRE(p.argv().empty()); + REQUIRE(p.argv().data() == nullptr); + } + } +} + +SCENARIO("Parsing a string with the command line parser", "[support]") { + GIVEN("A CmdLineParser") { + CmdLineParser p; + WHEN("Parsing an empty string") { + std::string s; + p.Parse(s); + THEN("command and arguments are empty") { + REQUIRE(p.detector_id() == -1); + REQUIRE(p.multi_id() == 0); + REQUIRE(p.command().empty()); + REQUIRE(p.arguments().empty()); + REQUIRE(p.argv().empty()); + } + } + WHEN("Parsing a string with a single command") { + std::string s = "vrf"; + p.Parse(s); + THEN("command is assigned and id's remain default") { + REQUIRE(p.command() == "vrf"); + REQUIRE(p.detector_id() == -1); + REQUIRE(p.multi_id() == 0); + REQUIRE(p.arguments().empty()); + REQUIRE(p.argv().size() == 1); + } + } + WHEN("Parsing a string with command and value") { + std::string s = "vthreshold 1500"; + p.Parse(s); + THEN("cmd and value are assigned and id's remain default") { + REQUIRE(p.command() == "vthreshold"); + REQUIRE(p.arguments()[0] == "1500"); + REQUIRE(p.arguments().size() == 1); + REQUIRE(p.detector_id() == -1); + REQUIRE(p.multi_id() == 0); + } + } + WHEN("Parsing a string with detector id and command") { + vs arg{"9:vcp", "53:vthreshold", "128:vtrim", "5:threshold"}; + std::vector det_id{9, 53, 128, 5}; + vs res{"vcp", "vthreshold", "vtrim", "threshold"}; + + THEN("Values are correctly decoded") { + for (size_t i = 0; i != arg.size(); ++i) { + p.Parse(arg[i]); + REQUIRE(p.detector_id() == det_id[i]); + REQUIRE(p.multi_id() == 0); + REQUIRE(p.command() == res[i]); + REQUIRE(p.arguments().empty()); + REQUIRE(p.argv().size() == 1); + } + } + } + WHEN("Parsing a string with multi_id detector id and command") { + vs arg{"8-12:vrf", "0-52:vcmp", "19-10:vtrim", "31-127:threshold"}; + std::vector det_id{12, 52, 10, 127}; + std::vector multi_id{8, 0, 19, 31}; + vs res{"vrf", "vcmp", "vtrim", "threshold"}; + + THEN("Values are correctly decoded") { + for (size_t i = 0; i != arg.size(); ++i) { + p.Parse(arg[i]); + REQUIRE(p.detector_id() == det_id[i]); + REQUIRE(p.multi_id() == multi_id[i]); + REQUIRE(p.command() == res[i]); + REQUIRE(p.arguments().empty()); + REQUIRE(p.argv().size() == 1); + } + } + } + + WHEN("Parsing string with cmd and multiple arguments"){ + std::string s = "trimen 5000 6000 7000"; + p.Parse(s); + THEN("cmd and args are correct"){ + REQUIRE(p.command() == "trimen"); + REQUIRE(p.arguments().size() == 3); + REQUIRE(p.arguments()[0] == "5000"); + REQUIRE(p.arguments()[1] == "6000"); + REQUIRE(p.arguments()[2] == "7000"); + } + } + + WHEN("Cliend id and or detector id cannot be decoded") { + vs arg{"o:cmd", "-5:cmd", "aedpva:cmd", + "5-svc:vrf", "asv-5:cmd", "savc-asa:cmd"}; + THEN("Parsing Throws") { + for (size_t i = 0; i != arg.size(); ++i) { + REQUIRE_THROWS(p.Parse(arg[i])); + } + } + } + } +} + +TEST_CASE("Parse with no arguments results in no command and default id", + "[support]") { + // build up argc and argv + // first argument is the command used to call the binary int argc = 1; char *argv[argc]; char a0[] = "call"; @@ -23,18 +134,9 @@ TEST_CASE("Parse with no arguments results in no command and default id") { REQUIRE(p.arguments().empty()); } -TEST_CASE("Parse empty string") { - std::string s; - CmdLineParser p; - p.Parse(s); - - REQUIRE(p.detector_id() == -1); - REQUIRE(p.multi_id() == 0); - REQUIRE(p.command().empty()); - REQUIRE(p.arguments().empty()); -} - -TEST_CASE("Parse a command without client id and detector id results in default") { +TEST_CASE( + "Parse a command without client id and detector id results in default", + "[support]") { int argc = 2; char *argv[argc]; char a0[] = "call"; @@ -51,18 +153,8 @@ TEST_CASE("Parse a command without client id and detector id results in default" REQUIRE(p.arguments().empty()); } -TEST_CASE("Parse a string without client id and detector id results in default") { - std::string s = "vrf"; - CmdLineParser p; - p.Parse(s); - - REQUIRE(p.detector_id() == -1); - REQUIRE(p.multi_id() == 0); - REQUIRE(p.command() == "vrf"); - REQUIRE(p.arguments().empty()); -} - -TEST_CASE("Parse a command with value but without client or detector id") { +TEST_CASE("Parse a command with value but without client or detector id", + "[support]") { int argc = 3; char *argv[argc]; char a0[] = "call"; @@ -81,18 +173,6 @@ TEST_CASE("Parse a command with value but without client or detector id") { REQUIRE(p.arguments().size() == 1); REQUIRE(p.arguments()[0] == "3000"); } -TEST_CASE("Parse a string with value but without client or detector id") { - std::string s = "vrf 3000\n"; - - CmdLineParser p; - p.Parse(s); - - REQUIRE(p.detector_id() == -1); - REQUIRE(p.multi_id() == 0); - REQUIRE(p.command() == "vrf"); - REQUIRE(p.arguments().size() == 1); - REQUIRE(p.arguments()[0] == "3000"); -} TEST_CASE("Decodes position") { int argc = 2; @@ -110,19 +190,8 @@ TEST_CASE("Decodes position") { REQUIRE(p.command() == "vrf"); REQUIRE(p.arguments().empty()); } -TEST_CASE("Decodes position from string") { - std::string s = "7:vrf\n"; - CmdLineParser p; - p.Parse(s); - - REQUIRE(p.detector_id() == 7); - REQUIRE(p.multi_id() == 0); - REQUIRE(p.command() == "vrf"); - REQUIRE(p.arguments().empty()); -} - -TEST_CASE("Decodes double digit position") { +TEST_CASE("Decodes double digit position", "[support]") { int argc = 2; char *argv[argc]; char a0[] = "call"; @@ -139,19 +208,7 @@ TEST_CASE("Decodes double digit position") { REQUIRE(p.arguments().empty()); } -TEST_CASE("Decodes double digit position from string") { - - std::string s = "73:vcmp"; - CmdLineParser p; - p.Parse(s); - - REQUIRE(p.detector_id() == 73); - REQUIRE(p.multi_id() == 0); - REQUIRE(p.command() == "vcmp"); - REQUIRE(p.arguments().empty()); -} - -TEST_CASE("Decodes position and id") { +TEST_CASE("Decodes position and id", "[support]") { int argc = 2; char *argv[argc]; char a0[] = "call"; @@ -167,18 +224,8 @@ TEST_CASE("Decodes position and id") { REQUIRE(p.command() == "vrf"); REQUIRE(p.arguments().empty()); } -TEST_CASE("Decodes position and id from string") { - std::string s = "5-8:vrf"; - CmdLineParser p; - p.Parse(s); - REQUIRE(p.detector_id() == 8); - REQUIRE(p.multi_id() == 5); - REQUIRE(p.command() == "vrf"); - REQUIRE(p.arguments().empty()); -} - -TEST_CASE("Double digit id") { +TEST_CASE("Double digit id", "[support]") { int argc = 2; char *argv[argc]; char a0[] = "call"; @@ -195,18 +242,7 @@ TEST_CASE("Double digit id") { REQUIRE(p.arguments().empty()); } -TEST_CASE("Double digit id from string") { - std::string s = "56-8:vrf"; - CmdLineParser p; - p.Parse(s); - - REQUIRE(p.detector_id() == 8); - REQUIRE(p.multi_id() == 56); - REQUIRE(p.command() == std::string("vrf")); - REQUIRE(p.arguments().empty()); -} - -TEST_CASE("Calling with wrong id throws invalid_argument") { +TEST_CASE("Calling with wrong id throws invalid_argument", "[support]") { int argc = 2; char *argv[argc]; @@ -218,13 +254,8 @@ TEST_CASE("Calling with wrong id throws invalid_argument") { CmdLineParser p; CHECK_THROWS(p.Parse(argc, argv)); } -TEST_CASE("Calling with string with wrong id throws invalid_argument") { - std::string s = "asvldkn:vrf"; - CmdLineParser p; - CHECK_THROWS(p.Parse(s)); -} -TEST_CASE("Calling with wrong client throws invalid_argument") { +TEST_CASE("Calling with wrong client throws invalid_argument", "[support]") { int argc = 2; char *argv[argc]; char a0[] = "call"; @@ -235,26 +266,9 @@ TEST_CASE("Calling with wrong client throws invalid_argument") { CmdLineParser p; CHECK_THROWS(p.Parse(argc, argv)); } -TEST_CASE("Calling with string with wrong client throws invalid_argument") { - std::string s = "lki-3:vrf"; - CmdLineParser p; - CHECK_THROWS(p.Parse(s)); -} -TEST_CASE("Parses string with two arguments") { - std::string s = "trimen 3000 4000\n"; +TEST_CASE("Build up argv", "[support]") { CmdLineParser p; - p.Parse(s); - - REQUIRE("trimen" == p.command()); - REQUIRE("3000" == p.arguments()[0]); - REQUIRE("4000" == p.arguments()[1]); - REQUIRE(p.arguments().size() == 2); -} - -TEST_CASE("Build up argv"){ - CmdLineParser p; - // p.argv(); REQUIRE(p.argv().empty()); REQUIRE(p.argv().data() == nullptr); @@ -262,5 +276,4 @@ TEST_CASE("Build up argv"){ p.Parse(s); REQUIRE(p.argv().data() != nullptr); REQUIRE(p.argv().size() == 3); - } \ No newline at end of file From 591ff53b84ca013a62337d451812281274d3d21e Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Fri, 17 May 2019 09:08:13 +0200 Subject: [PATCH 40/76] fixed MacAddr 0 output --- slsSupportLib/src/network_utils.cpp | 18 ++++++------------ slsSupportLib/tests/test-network_utils.cpp | 4 ++-- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/slsSupportLib/src/network_utils.cpp b/slsSupportLib/src/network_utils.cpp index 6147cfb19..6c3e25caa 100755 --- a/slsSupportLib/src/network_utils.cpp +++ b/slsSupportLib/src/network_utils.cpp @@ -20,9 +20,7 @@ IpAddr::IpAddr(const std::string &address) { inet_pton(AF_INET, address.c_str(), &addr_); } -IpAddr::IpAddr(const char *address) { - inet_pton(AF_INET, address, &addr_); -} +IpAddr::IpAddr(const char *address) { inet_pton(AF_INET, address, &addr_); } std::string IpAddr::str() const { char ipstring[INET_ADDRSTRLEN]{}; @@ -31,9 +29,9 @@ std::string IpAddr::str() const { } std::string IpAddr::hex() const { std::ostringstream ss; + ss << std::hex << std::setfill('0'); for (int i = 0; i != 4; ++i) { - ss << std::hex << std::setfill('0') << std::setw(2) - << ((addr_ >> i * 8) & 0xFF); + ss << std::setw(2) << ((addr_ >> i * 8) & 0xFF); } return ss.str(); } @@ -56,18 +54,14 @@ std::string MacAddr::to_hex(const char delimiter) const { for (int i = 32; i >= 0; i -= 8) { if (delimiter) ss << delimiter; - ss << ((addr_ >> i) & 0xFF); + ss << std::setw(2) << ((addr_ >> i) & 0xFF); } return ss.str(); } -std::string MacAddr::str() const { - return to_hex(':'); -} +std::string MacAddr::str() const { return to_hex(':'); } -std::string MacAddr::hex() const { - return to_hex(); -} +std::string MacAddr::hex() const { return to_hex(); } std::ostream &operator<<(std::ostream &out, const IpAddr &addr) { return out << addr.str(); diff --git a/slsSupportLib/tests/test-network_utils.cpp b/slsSupportLib/tests/test-network_utils.cpp index a9d68ae19..43a08795a 100755 --- a/slsSupportLib/tests/test-network_utils.cpp +++ b/slsSupportLib/tests/test-network_utils.cpp @@ -11,9 +11,9 @@ using namespace sls; TEST_CASE("Convert mac address using classes", "[support]") { - std::vector vec_addr{346856806822, 346856806852, 262027939863028}; + std::vector vec_addr{346856806822, 346856806852, 262027939863028,0, 281474976710655}; std::vector vec_ans{"00:50:c2:46:d9:a6", "00:50:c2:46:d9:c4", - "ee:50:22:46:d9:f4"}; + "ee:50:22:46:d9:f4", "00:00:00:00:00:00", "ff:ff:ff:ff:ff:ff"}; for (size_t i = 0; i != vec_addr.size(); ++i) { auto mac0 = MacAddr(vec_addr[i]); auto mac1 = MacAddr(vec_ans[i]); From 3e5d34647ef4de7a060c091365571bff1df94a56 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Fri, 17 May 2019 10:00:49 +0200 Subject: [PATCH 41/76] updated test for argument parser --- slsSupportLib/include/CmdLineParser.h | 2 +- slsSupportLib/src/CmdLineParser.cpp | 2 +- slsSupportLib/tests/test-CmdLineParser.cpp | 68 ++++------------------ 3 files changed, 13 insertions(+), 59 deletions(-) diff --git a/slsSupportLib/include/CmdLineParser.h b/slsSupportLib/include/CmdLineParser.h index 245f8ad26..af11254d3 100755 --- a/slsSupportLib/include/CmdLineParser.h +++ b/slsSupportLib/include/CmdLineParser.h @@ -6,7 +6,7 @@ class CmdLineParser { public: - void Parse(int argc, char *argv[]); + void Parse(int argc, const char * const argv[]); void Parse(const std::string &s); void Print(); diff --git a/slsSupportLib/src/CmdLineParser.cpp b/slsSupportLib/src/CmdLineParser.cpp index 23a6a8950..cc502978d 100755 --- a/slsSupportLib/src/CmdLineParser.cpp +++ b/slsSupportLib/src/CmdLineParser.cpp @@ -20,7 +20,7 @@ void CmdLineParser::Print() { std::cout << "\n\n"; }; -void CmdLineParser::Parse(int argc, char *argv[]) { +void CmdLineParser::Parse(int argc, const char * const argv[]) { executable_ = argv[0]; //first arg is calling binary if (argc > 1) { DecodeIdAndPosition(argv[1]); diff --git a/slsSupportLib/tests/test-CmdLineParser.cpp b/slsSupportLib/tests/test-CmdLineParser.cpp index 5cb4aaa9c..5a34e7bd5 100755 --- a/slsSupportLib/tests/test-CmdLineParser.cpp +++ b/slsSupportLib/tests/test-CmdLineParser.cpp @@ -92,10 +92,10 @@ SCENARIO("Parsing a string with the command line parser", "[support]") { } } - WHEN("Parsing string with cmd and multiple arguments"){ + WHEN("Parsing string with cmd and multiple arguments") { std::string s = "trimen 5000 6000 7000"; p.Parse(s); - THEN("cmd and args are correct"){ + THEN("cmd and args are correct") { REQUIRE(p.command() == "trimen"); REQUIRE(p.arguments().size() == 3); REQUIRE(p.arguments()[0] == "5000"); @@ -121,10 +121,7 @@ TEST_CASE("Parse with no arguments results in no command and default id", // build up argc and argv // first argument is the command used to call the binary int argc = 1; - char *argv[argc]; - char a0[] = "call"; - argv[0] = static_cast(a0); - + const char* const argv[]{"call"}; CmdLineParser p; p.Parse(argc, argv); @@ -138,12 +135,7 @@ TEST_CASE( "Parse a command without client id and detector id results in default", "[support]") { int argc = 2; - char *argv[argc]; - char a0[] = "call"; - char a1[] = "vrf"; - argv[0] = static_cast(a0); - argv[1] = static_cast(a1); - + const char*const argv[]{"caller", "vrf"}; CmdLineParser p; p.Parse(argc, argv); @@ -156,14 +148,7 @@ TEST_CASE( TEST_CASE("Parse a command with value but without client or detector id", "[support]") { int argc = 3; - char *argv[argc]; - char a0[] = "call"; - char a1[] = "vrf"; - char a2[] = "3000"; - argv[0] = static_cast(a0); - argv[1] = static_cast(a1); - argv[2] = static_cast(a2); - + const char* const argv[]{"caller", "vrf", "3000"}; CmdLineParser p; p.Parse(argc, argv); @@ -176,11 +161,7 @@ TEST_CASE("Parse a command with value but without client or detector id", TEST_CASE("Decodes position") { int argc = 2; - char *argv[argc]; - char a0[] = "call"; - char a1[] = "7:vrf"; - argv[0] = static_cast(a0); - argv[1] = static_cast(a1); + const char*const argv[]{"caller", "7:vrf"}; CmdLineParser p; p.Parse(argc, argv); @@ -193,12 +174,7 @@ TEST_CASE("Decodes position") { TEST_CASE("Decodes double digit position", "[support]") { int argc = 2; - char *argv[argc]; - char a0[] = "call"; - char a1[] = "73:vcmp"; - argv[0] = static_cast(a0); - argv[1] = static_cast(a1); - + const char* const argv[]{"caller", "73:vcmp"}; CmdLineParser p; p.Parse(argc, argv); @@ -210,12 +186,7 @@ TEST_CASE("Decodes double digit position", "[support]") { TEST_CASE("Decodes position and id", "[support]") { int argc = 2; - char *argv[argc]; - char a0[] = "call"; - char a1[] = "5-8:vrf"; - argv[0] = static_cast(a0); - argv[1] = static_cast(a1); - + const char* const argv[]{"caller", "5-8:vrf"}; CmdLineParser p; p.Parse(argc, argv); @@ -227,15 +198,9 @@ TEST_CASE("Decodes position and id", "[support]") { TEST_CASE("Double digit id", "[support]") { int argc = 2; - char *argv[argc]; - char a0[] = "call"; - char a1[] = "56-8:vrf"; - argv[0] = static_cast(a0); - argv[1] = static_cast(a1); - + const char *const argv[]{"caller", "56-8:vrf"}; CmdLineParser p; p.Parse(argc, argv); - REQUIRE(p.detector_id() == 8); REQUIRE(p.multi_id() == 56); REQUIRE(p.command() == "vrf"); @@ -243,26 +208,15 @@ TEST_CASE("Double digit id", "[support]") { } TEST_CASE("Calling with wrong id throws invalid_argument", "[support]") { - int argc = 2; - char *argv[argc]; - char a0[] = "call"; - char a1[] = "asvldkn:vrf"; - argv[0] = static_cast(a0); - argv[1] = static_cast(a1); - + const char *const argv[]{"caller", "asvldkn:vrf"}; CmdLineParser p; CHECK_THROWS(p.Parse(argc, argv)); } TEST_CASE("Calling with wrong client throws invalid_argument", "[support]") { int argc = 2; - char *argv[argc]; - char a0[] = "call"; - char a1[] = "lki-3:vrf"; - argv[0] = static_cast(a0); - argv[1] = static_cast(a1); - + const char *const argv[]{"caller", "lki-3:vrf"}; CmdLineParser p; CHECK_THROWS(p.Parse(argc, argv)); } From 1a1c6b9b4223d5913fbaeb650debcf0bcf0eaa8c Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Fri, 17 May 2019 19:19:03 +0200 Subject: [PATCH 42/76] jungfrau server: feature finish: switching between 2 interfaces --- .../jungfrauDetectorServer/RegisterDefs.h | 48 ++- .../bin/jungfrauDetectorServer_developer | Bin 0 -> 120136 bytes .../bin/jungfrauDetectorServer_refactor | Bin 115588 -> 0 bytes .../slsDetectorFunctionList.c | 308 ++++++++++++------ .../slsDetectorServer_defs.h | 57 ++-- .../slsDetectorServer/communication_funcs.c | 5 +- .../slsDetectorServer/communication_funcs.h | 1 + .../slsDetectorFunctionList.h | 7 + .../slsDetectorServer_funcs.c | 17 +- .../include/slsDetectorUsers.h | 2 +- slsDetectorSoftware/src/slsDetector.cpp | 2 +- .../src/slsDetectorCommand.cpp | 17 +- slsReceiverSoftware/include/GeneralData.h | 8 +- slsReceiverSoftware/src/Listener.cpp | 11 +- slsSupportLib/include/versionAPI.h | 5 +- 15 files changed, 312 insertions(+), 176 deletions(-) create mode 100755 slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer delete mode 100755 slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_refactor diff --git a/slsDetectorServers/jungfrauDetectorServer/RegisterDefs.h b/slsDetectorServers/jungfrauDetectorServer/RegisterDefs.h index 0129d8be9..e25b1942f 100755 --- a/slsDetectorServers/jungfrauDetectorServer/RegisterDefs.h +++ b/slsDetectorServers/jungfrauDetectorServer/RegisterDefs.h @@ -197,15 +197,16 @@ #define CONFIG_RDT_TMR_MSK (0x0000FFFF << CONFIG_RDT_TMR_OFST) #define CONFIG_OPRTN_MDE_2_X_10GbE_OFST (16) #define CONFIG_OPRTN_MDE_2_X_10GbE_MSK (0x00000001 << CONFIG_OPRTN_MDE_2_X_10GbE_OFST) -#define CONFIG_OPRTN_MDE_1_X_10GBE_VAL ((0x0 << CONFIG_OPRTN_MDE_2_X_10GbE_OFST) & CONFIG_OPRTN_MDE_2_X_10GbE_MSK) +// if 0, outer is the primary interface +#define CONFIG_INNR_PRIMRY_INTRFCE_OFST (17) +#define CONFIG_INNR_PRIMRY_INTRFCE_MSK (0x00000001 << CONFIG_INNR_PRIMRY_INTRFCE_OFST) #define CONFIG_READOUT_SPEED_OFST (20) #define CONFIG_READOUT_SPEED_MSK (0x00000003 << CONFIG_READOUT_SPEED_OFST) #define CONFIG_QUARTER_SPEED_10MHZ_VAL ((0x0 << CONFIG_READOUT_SPEED_OFST) & CONFIG_READOUT_SPEED_MSK) #define CONFIG_HALF_SPEED_20MHZ_VAL ((0x1 << CONFIG_READOUT_SPEED_OFST) & CONFIG_READOUT_SPEED_MSK) #define CONFIG_FULL_SPEED_40MHZ_VAL ((0x2 << CONFIG_READOUT_SPEED_OFST) & CONFIG_READOUT_SPEED_MSK) -#define CONFIG_TDMA_OFST (24) -#define CONFIG_TDMA_MSK (0x00000001 << CONFIG_TDMA_OFST) -#define CONFIG_TDMA_DISABLE_VAL ((0x0 << CONFIG_TDMA_OFST) & CONFIG_TDMA_MSK) +#define CONFIG_TDMA_ENABLE_OFST (24) +#define CONFIG_TDMA_ENABLE_MSK (0x00000001 << CONFIG_TDMA_ENABLE_OFST) #define CONFIG_TDMA_TIMESLOT_OFST (25) // 1ms #define CONFIG_TDMA_TIMESLOT_MSK (0x0000001F << CONFIG_TDMA_TIMESLOT_OFST) #define CONFIG_ETHRNT_FLW_CNTRL_OFST (31) @@ -234,6 +235,12 @@ #define CONTROL_ACQ_FIFO_CLR_MSK (0x00000001 << CONTROL_ACQ_FIFO_CLR_OFST) #define CONTROL_STORAGE_CELL_NUM_OFST (16) #define CONTROL_STORAGE_CELL_NUM_MSK (0x0000000F << CONTROL_STORAGE_CELL_NUM_OFST) +#define CONTROL_RX_ADDTNL_ENDPTS_NUM_OFST (20) +#define CONTROL_RX_ADDTNL_ENDPTS_NUM_MSK (0x0000003F << CONTROL_RX_ADDTNL_ENDPTS_NUM_OFST) +#define CONTROL_RX_ENDPTS_START_OFST (26) +#define CONTROL_RX_ENDPTS_START_MSK (0x0000003F << CONTROL_RX_ENDPTS_START_OFST) + + /* Reconfiguratble PLL Paramater Register */ #define PLL_PARAM_REG (0x50 << MEM_MAP_SHIFT) @@ -400,6 +407,32 @@ #define COORD_0_Z_OFST (0) #define COORD_0_Z_MSK (0x0000FFFF << COORD_0_Z_OFST) +/** Module row coordinates */ +/*#define COORD_ROW_REG (0x7C << MEM_MAP_SHIFT) + +#define COORD_ROW_OUTER_OFST (0) +#define COORD_ROW_OUTER_MSK (0x0000FFFF << COORD_ROW_OUTER_OFST) +#define COORD_ROW_INNER_OFST (16) +#define COORD_ROW_INNER_MSK (0x0000FFFF << COORD_ROW_INNER_OFST) +*/ +/** Module column coordinates */ +/*#define COORD_COL_REG (0x7D << MEM_MAP_SHIFT) + +#define COORD_COL_OUTER_OFST (0) +#define COORD_COL_OUTER_MSK (0x0000FFFF << COORD_COL_OUTER_OFST) +#define COORD_COL_INNER_OFST (16) +#define COORD_COL_INNER_MSK (0x0000FFFF << COORD_COL_INNER_OFST) +*/ + +/** Module column coordinates */ +/*#define COORD_RESERVED_REG (0x7E << MEM_MAP_SHIFT) + +#define COORD_RESERVED_OUTER_OFST (0) +#define COORD_RESERVED_OUTER_MSK (0x0000FFFF << COORD_RESERVED_OUTER_OFST) +#define COORD_RESERVED_INNER_OFST (16) +#define COORD_RESERVED_INNER_MSK (0x0000FFFF << COORD_RESERVED_INNER_OFST) +*/ + /* ASIC Control Register */ #define ASIC_CTRL_REG (0x7F << MEM_MAP_SHIFT) // tPC = (PCT + 1) * 25ns @@ -440,6 +473,13 @@ +/* Round Robin */ +#define RXR_ENDPOINTS_MAX (64) +#define RXR_ENDPOINT_OUTER_START_REG (0x1000 << MEM_MAP_SHIFT) +#define RXR_ENDPOINT_INNER_START_REG (0x2000 << MEM_MAP_SHIFT) + +#define RXR_ENDPOINT_OFST (0x10 << MEM_MAP_SHIFT) + diff --git a/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer b/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer new file mode 100755 index 0000000000000000000000000000000000000000..4ed0aa93cc99c6c020c29704c1b22141716868f5 GIT binary patch literal 120136 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

vuJ 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 literal 0 HcmV?d00001 diff --git a/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_refactor b/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_refactor deleted file mode 100755 index ab33ee12141a07fc122e4f0cda489f74cda48799..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 115588 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

vF1J>&4_=b(~LOa%4KVU6_^!`_IrYH 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 DETECTOR_TYPE_OFST); - if (type != BOARD_JUNGFRAU_TYPE){ - FILE_LOG(logERROR, ("This is not a Jungfrau Server (read %d, expected %d)\n", type, BOARD_JUNGFRAU_TYPE)); + if (type != JUNGFRAU){ + FILE_LOG(logERROR, ("This is not a Jungfrau Server (read %d, expected %d)\n", type, JUNGFRAU)); return FAIL; } @@ -423,11 +422,11 @@ void setupDetector() { resetCore(); alignDeserializer(); - - configureASICTimer(); bus_w(ADC_PORT_INVERT_REG, ADC_PORT_INVERT_VAL); + initReadoutConfiguration(); + //Initialization of acquistion parameters setSettings(DEFAULT_SETTINGS); @@ -654,12 +653,12 @@ int64_t getTimeLeft(enum timerIndex ind){ retval = get64BitReg(GET_PERIOD_LSB_REG, GET_PERIOD_MSB_REG) / (1E-3 * CLK_SYNC); FILE_LOG(logINFO, ("Getting period left: %lldns\n", (long long int)retval)); break; -/* + case DELAY_AFTER_TRIGGER: - retval = get64BitReg(xxx) / (1E-3 * CLK_SYNC); + retval = get64BitReg(GET_DELAY_LSB_REG, GET_DELAY_MSB_REG) / (1E-3 * CLK_SYNC); FILE_LOG(logINFO, ("Getting delay left: %lldns\n", (long long int)retval)); break; -*/ + case CYCLES_NUMBER: retval = get64BitReg(GET_CYCLES_LSB_REG, GET_CYCLES_MSB_REG); FILE_LOG(logINFO, ("Getting number of cycles left: %lld\n", (long long int)retval)); @@ -983,40 +982,106 @@ enum externalCommunicationMode getTiming() { /* configure mac */ +void setNumberofUDPInterfaces(int val) { + uint32_t addr = CONFIG_REG; + // enable 2 interfaces + if (val > 1) { + FILE_LOG(logINFOBLUE, ("Setting #Interfaces: 2\n")); + bus_w(addr, bus_r(addr) | CONFIG_OPRTN_MDE_2_X_10GbE_MSK); + } + // enable only 1 interface + else { + FILE_LOG(logINFOBLUE, ("Setting #Interfaces: 1\n")); + bus_w(addr, bus_r(addr) &~ CONFIG_OPRTN_MDE_2_X_10GbE_MSK); + } +} -long int calcChecksum(int sourceip, int destip) { - ip_header ip; - ip.ip_ver = 0x4; - ip.ip_ihl = 0x5; - ip.ip_tos = 0x0; - ip.ip_len = IP_PACKETSIZE; - ip.ip_ident = 0x0000; - ip.ip_flag = 0x2; //not nibble aligned (flag& offset - ip.ip_offset = 0x000; - ip.ip_ttl = 0x40; - ip.ip_protocol = 0x11; - ip.ip_chksum = 0x0000 ; // pseudo - ip.ip_sourceip = sourceip; - ip.ip_destip = destip; +void selectPrimaryInterface(int val) { + uint32_t addr = CONFIG_REG; - int count = sizeof(ip); + // inner (user input: 1) + if (val == 1) { + FILE_LOG(logINFOBLUE, ("Setting Primary Interface: 1 (Inner)\n")); + bus_w(addr, bus_r(addr) | CONFIG_INNR_PRIMRY_INTRFCE_MSK); + } + // outer (user input: 2) + else { + FILE_LOG(logINFOBLUE, ("Setting Primary Interface: 2 (Outer)\n")); + bus_w(addr, bus_r(addr) &~ CONFIG_INNR_PRIMRY_INTRFCE_MSK); + } +} - unsigned short *addr; - addr = (unsigned short*) &(ip); /* warning: assignment from incompatible pointer type */ +void setupHeader(int iRxEntry, enum interfaceType type, uint32_t destip, uint64_t destmac, uint32_t destport, uint64_t sourcemac, uint32_t sourceip, uint32_t sourceport) { + + // start addr + uint32_t addr = (type == INNER ? RXR_ENDPOINT_INNER_START_REG : RXR_ENDPOINT_OUTER_START_REG); + // calculate rxr endpoint offset + addr += (iRxEntry * RXR_ENDPOINT_OFST); + // get struct memory + udp_header *udp = (udp_header*) (CSP0BASE + addr * 2); + memset(udp, 0, sizeof(udp_header)); + // mac addresses + // msb (32) + lsb (16) + udp->udp_destmac_msb = ((destmac >> 16) & BIT32_MASK); + udp->udp_destmac_lsb = ((destmac >> 0) & BIT16_MASK); + // msb (16) + lsb (32) + udp->udp_srcmac_msb = ((sourcemac >> 32) & BIT16_MASK); + udp->udp_srcmac_lsb = ((sourcemac >> 0) & BIT32_MASK); + + // ip addresses + udp->ip_srcip_msb = ((sourceip >> 16) & BIT16_MASK); + udp->ip_srcip_lsb = ((sourceip >> 0) & BIT16_MASK); + udp->ip_destip_msb = ((destip >> 16) & BIT16_MASK); + udp->ip_destip_lsb = ((destip >> 0) & BIT16_MASK); + + // source port + udp->udp_srcport = sourceport; + udp->udp_destport = destport; + + // other defines + udp->udp_ethertype = 0x800; + udp->ip_ver = 0x4; + udp->ip_ihl = 0x5; + udp->ip_flags = 0x2; //FIXME + udp->ip_ttl = 0x40; + udp->ip_protocol = 0x11; + // total length is redefined in firmware + + calcChecksum(udp); +} + +void calcChecksum(udp_header* udp) { + int count = IP_HEADER_SIZE; long int sum = 0; - while( count > 1 ) { + + // start at ip_tos as the memory is not continous for ip header + uint16_t *addr = (uint16_t*) (&(udp->ip_tos)); + + sum += *addr++; + count -= 2; + + // ignore ethertype (from udp header) + addr++; + + // from identification to srcip_lsb + while( count > 2 ) { sum += *addr++; count -= 2; } + + // ignore src udp port (from udp header) + addr++; + if (count > 0) sum += *addr; // Add left-over byte, if any - while (sum>>16) + while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16);// Fold 32-bit sum to 16 bits - long int checksum = (~sum) & 0xffff; - FILE_LOG(logINFO, ("IP checksum is 0x%lx\n",checksum)); - return checksum; + long int checksum = sum & 0xffff; + checksum += UDP_IP_HEADER_LENGTH_BYTES; + FILE_LOG(logINFO, ("\tIP checksum is 0x%lx\n",checksum)); + udp->ip_checksum = checksum; } @@ -1034,6 +1099,7 @@ int configureMAC(int numInterfaces, int selInterface, FILE_LOG(logINFO, ("\t#Interfaces : %d\n", numInterfaces)); FILE_LOG(logINFO, ("\tInterface : %d\n\n", selInterface)); + FILE_LOG(logINFO, ("\tInner\n")); FILE_LOG(logINFO, ("\tSource IP : %d.%d.%d.%d \t\t(0x%08x)\n", (sourceip>>24)&0xff,(sourceip>>16)&0xff,(sourceip>>8)&0xff,(sourceip)&0xff, sourceip)); FILE_LOG(logINFO, ("\tSource MAC : %02x:%02x:%02x:%02x:%02x:%02x \t(0x%010llx)\n", @@ -1059,6 +1125,7 @@ int configureMAC(int numInterfaces, int selInterface, FILE_LOG(logINFO, ("\tDest. Port : %d \t\t\t(0x%08x)\n\n",udpport, udpport)); uint32_t sourceport2 = DEFAULT_TX_UDP_PORT + 1; + FILE_LOG(logINFO, ("\tOuter\n")); FILE_LOG(logINFO, ("\tSource IP2 : %d.%d.%d.%d \t\t(0x%08x)\n", (sourceip2>>24)&0xff,(sourceip2>>16)&0xff,(sourceip2>>8)&0xff,(sourceip2)&0xff, sourceip2)); FILE_LOG(logINFO, ("\tSource MAC2 : %02x:%02x:%02x:%02x:%02x:%02x \t(0x%010llx)\n", @@ -1083,35 +1150,16 @@ int configureMAC(int numInterfaces, int selInterface, (long long unsigned int)destmac2)); FILE_LOG(logINFO, ("\tDest. Port2 : %d \t\t\t(0x%08x)\n",udpport2, udpport2)); - long int checksum=calcChecksum(sourceip, destip); - bus_w(TX_IP_REG, sourceip); - bus_w(RX_IP_REG, destip); + // default one rxr entry (others not yet implemented in client yet) + int iRxEntry = 0; + // top + setupHeader(iRxEntry, INNER, destip, destmac, udpport, sourcemac, sourceip, sourceport); + // bottom + setupHeader(iRxEntry, OUTER, destip2, destmac2, udpport2, sourcemac2, sourceip2, sourceport2); - uint32_t val = 0; + setNumberofUDPInterfaces(numInterfaces); + selectPrimaryInterface(selInterface); - val = ((sourcemac >> LSB_OF_64_BIT_REG_OFST) & BIT_32_MSK); - bus_w(TX_MAC_LSB_REG, val); - FILE_LOG(logDEBUG1, ("Read from TX_MAC_LSB_REG: 0x%08x\n", bus_r(TX_MAC_LSB_REG))); - - val = ((sourcemac >> MSB_OF_64_BIT_REG_OFST) & BIT_32_MSK); - bus_w(TX_MAC_MSB_REG,val); - FILE_LOG(logDEBUG1, ("Read from TX_MAC_MSB_REG: 0x%08x\n", bus_r(TX_MAC_MSB_REG))); - - val = ((destmac >> LSB_OF_64_BIT_REG_OFST) & BIT_32_MSK); - bus_w(RX_MAC_LSB_REG, val); - FILE_LOG(logDEBUG1, ("Read from RX_MAC_LSB_REG: 0x%08x\n", bus_r(RX_MAC_LSB_REG))); - - val = ((destmac >> MSB_OF_64_BIT_REG_OFST) & BIT_32_MSK); - bus_w(RX_MAC_MSB_REG, val); - FILE_LOG(logDEBUG1, ("Read from RX_MAC_MSB_REG: 0x%08x\n", bus_r(RX_MAC_MSB_REG))); - - val = (((sourceport << UDP_PORT_TX_OFST) & UDP_PORT_TX_MSK) | - ((udpport << UDP_PORT_RX_OFST) & UDP_PORT_RX_MSK)); - bus_w(UDP_PORT_REG, val); - FILE_LOG(logDEBUG1, ("Read from UDP_PORT_REG: 0x%08x\n", bus_r(UDP_PORT_REG))); - - bus_w(TX_IP_CHECKSUM_REG,(checksum << TX_IP_CHECKSUM_OFST) & TX_IP_CHECKSUM_MSK); - FILE_LOG(logDEBUG1, ("Read from TX_IP_CHECKSUM_REG: 0x%08x\n", bus_r(TX_IP_CHECKSUM_REG))); cleanFifos(); resetCore(); alignDeserializer(); @@ -1121,20 +1169,20 @@ int configureMAC(int numInterfaces, int selInterface, int setDetectorPosition(int pos[]) { int ret = OK; - FILE_LOG(logDEBUG1, ("Setting detector position: (%d, %d)\n", pos[0], pos[1])); + FILE_LOG(logDEBUG1, ("Setting detector position: (%d, %d)\n", pos[X], pos[Y])); bus_w(COORD_0_REG, bus_r(COORD_0_REG) & (~(COORD_0_X_MSK))); - bus_w(COORD_0_REG, bus_r(COORD_0_REG) | ((pos[0] << COORD_0_X_OFST) & COORD_0_X_MSK)); - if ((bus_r(COORD_0_REG) & COORD_0_X_MSK) != ((pos[0] << COORD_0_X_OFST) & COORD_0_X_MSK)) + bus_w(COORD_0_REG, bus_r(COORD_0_REG) | ((pos[X] << COORD_0_X_OFST) & COORD_0_X_MSK)); + if ((bus_r(COORD_0_REG) & COORD_0_X_MSK) != ((pos[X] << COORD_0_X_OFST) & COORD_0_X_MSK)) ret = FAIL; bus_w(COORD_0_REG, bus_r(COORD_0_REG) & (~(COORD_0_Y_MSK))); - bus_w(COORD_0_REG, bus_r(COORD_0_REG) | ((pos[1] << COORD_0_Y_OFST) & COORD_0_Y_MSK)); - if ((bus_r(COORD_0_REG) & COORD_0_Y_MSK) != ((pos[1] << COORD_0_Y_OFST) & COORD_0_Y_MSK)) + bus_w(COORD_0_REG, bus_r(COORD_0_REG) | ((pos[Y] << COORD_0_Y_OFST) & COORD_0_Y_MSK)); + if ((bus_r(COORD_0_REG) & COORD_0_Y_MSK) != ((pos[Y] << COORD_0_Y_OFST) & COORD_0_Y_MSK)) ret = FAIL; if (ret == OK) { - FILE_LOG(logINFO, ("Position set to [%d, %d]\n", pos[0], pos[1])); + FILE_LOG(logINFO, ("Position set to [%d, %d]\n", pos[X], pos[Y])); } return ret; } @@ -1143,6 +1191,42 @@ int setDetectorPosition(int pos[]) { /* jungfrau specific - powerchip, autocompdisable, asictimer, clockdiv, pll, flashing fpga */ +void initReadoutConfiguration() { + + FILE_LOG(logINFO, ("Initializing Readout Configuration:\n" + "\t Reset readout Timer\n" + "\t 1 x 10G mode\n" + "\t outer interface is primary\n" + "\t half speed\n" + "\t TDMA disabled, 0 as TDMA slot\n" + "\t Ethernet overflow disabled\n" + "\t Reset Round robin entries\n")); + + uint32_t val = 0; + // reset readouttimer + val &= ~CONFIG_RDT_TMR_MSK; + // 1 x 10G mode + val &= ~CONFIG_OPRTN_MDE_2_X_10GbE_MSK; + // outer interface + val &= ~CONFIG_INNR_PRIMRY_INTRFCE_MSK; + // half speed + val &= ~CONFIG_READOUT_SPEED_MSK; + val |= CONFIG_HALF_SPEED_20MHZ_VAL; + // tdma disable + val &= ~CONFIG_TDMA_ENABLE_MSK; + // tdma slot 0 + val &= ~CONFIG_TDMA_TIMESLOT_MSK; + // no ethernet overflow + val &= ~CONFIG_ETHRNT_FLW_CNTRL_MSK; + bus_w(CONFIG_REG, val); + + val = bus_r(CONTROL_REG); + // reset (addtional round robin entry) rx endpoints num + val &= CONTROL_RX_ADDTNL_ENDPTS_NUM_MSK; + // reset start of round robin entry to 0 + val &= CONTROL_RX_ENDPTS_START_MSK; + bus_w(CONTROL_REG, val); +} int powerChip (int on){ @@ -1191,62 +1275,56 @@ void setClockDivider(int val) { if(runBusy()) stopStateMachine(); - uint32_t txndelay_msk = 0; + switch(val) { - switch(val){ + case FULL_SPEED: + FILE_LOG(logINFO, ("Setting Full Speed (40 MHz):\n")); - // todo in firmware, for now setting half speed - case FULL_SPEED://40 - FILE_LOG(logINFO, ("Setting Half Speed (20 MHz):\n")); + bus_w(SAMPLE_REG, SAMPLE_ADC_FULL_SPEED); + FILE_LOG(logINFO, ("\tSet Sample Reg to 0x%x\n", bus_r(SAMPLE_REG))); - FILE_LOG(logINFO, ("\tSetting Sample Reg to 0x%x\n", SAMPLE_ADC_HALF_SPEED)); - bus_w(SAMPLE_REG, SAMPLE_ADC_HALF_SPEED); + bus_w(CONFIG_REG, (bus_r(CONFIG_REG) & ~CONFIG_READOUT_SPEED_MSK) | CONFIG_FULL_SPEED_40MHZ_VAL); + FILE_LOG(logINFO, ("\tSet Config Reg to 0x%x\n", bus_r(CONFIG_REG))); - txndelay_msk = (bus_r(CONFIG_REG) & CONFIG_TDMA_TIMESLOT_MSK); // read config tdma timeslot value - FILE_LOG(logINFO, ("\tSetting Config Reg to 0x%x\n", CONFIG_HALF_SPEED | txndelay_msk)); - bus_w(CONFIG_REG, CONFIG_HALF_SPEED | txndelay_msk); - - FILE_LOG(logINFO, ("\tSetting ADC Ofst Reg to 0x%x\n", ADC_OFST_HALF_SPEED_VAL)); - bus_w(ADC_OFST_REG, ADC_OFST_HALF_SPEED_VAL); - - FILE_LOG(logINFO, ("\tSetting ADC Phase Reg to 0x%x\n", ADC_PHASE_HALF_SPEED)); - setAdcPhase(ADC_PHASE_HALF_SPEED, 0); + bus_w(ADC_OFST_REG, ADC_OFST_FULL_SPEED_VAL); + FILE_LOG(logINFO, ("\tSet ADC Ofst Reg to 0x%x\n", bus_r(ADC_OFST_REG))); + setAdcPhase(ADC_PHASE_FULL_SPEED, 0); + FILE_LOG(logINFO, ("\tSet ADC Phase Reg to 0x%x\n", ADC_PHASE_FULL_SPEED)); break; + case HALF_SPEED: FILE_LOG(logINFO, ("Setting Half Speed (20 MHz):\n")); - FILE_LOG(logINFO, ("\tSetting Sample Reg to 0x%x\n", SAMPLE_ADC_HALF_SPEED)); bus_w(SAMPLE_REG, SAMPLE_ADC_HALF_SPEED); + FILE_LOG(logINFO, ("\tSet Sample Reg to 0x%x\n", bus_r(SAMPLE_REG))); - txndelay_msk = (bus_r(CONFIG_REG) & CONFIG_TDMA_TIMESLOT_MSK); // read config tdma timeslot value - FILE_LOG(logINFO, ("\tSetting Config Reg to 0x%x\n", CONFIG_HALF_SPEED | txndelay_msk)); - bus_w(CONFIG_REG, CONFIG_HALF_SPEED | txndelay_msk); + bus_w(CONFIG_REG, (bus_r(CONFIG_REG) & ~CONFIG_READOUT_SPEED_MSK) | CONFIG_HALF_SPEED_20MHZ_VAL); + FILE_LOG(logINFO, ("\tSet Config Reg to 0x%x\n", bus_r(CONFIG_REG))); - FILE_LOG(logINFO, ("\tSetting ADC Ofst Reg to 0x%x\n", ADC_OFST_HALF_SPEED_VAL)); bus_w(ADC_OFST_REG, ADC_OFST_HALF_SPEED_VAL); + FILE_LOG(logINFO, ("\tSet ADC Ofst Reg to 0x%x\n", bus_r(ADC_OFST_REG))); - FILE_LOG(logINFO, ("\tSetting ADC Phase Reg to 0x%x\n", ADC_PHASE_HALF_SPEED)); setAdcPhase(ADC_PHASE_HALF_SPEED, 0); - + FILE_LOG(logINFO, ("\tSet ADC Phase Reg to 0x%x\n", ADC_PHASE_HALF_SPEED)); break; + case QUARTER_SPEED: FILE_LOG(logINFO, ("Setting Half Speed (10 MHz):\n")); - FILE_LOG(logINFO, ("\tSetting Sample Reg to 0x%x\n", SAMPLE_ADC_QUARTER_SPEED)); bus_w(SAMPLE_REG, SAMPLE_ADC_QUARTER_SPEED); + FILE_LOG(logINFO, ("\tSet Sample Reg to 0x%x\n", bus_r(SAMPLE_REG))); - txndelay_msk = (bus_r(CONFIG_REG) & CONFIG_TDMA_TIMESLOT_MSK); // read config tdma timeslot value - FILE_LOG(logINFO, ("\tSetting Config Reg to 0x%x\n", CONFIG_QUARTER_SPEED | txndelay_msk)); - bus_w(CONFIG_REG, CONFIG_QUARTER_SPEED | txndelay_msk); + bus_w(CONFIG_REG, (bus_r(CONFIG_REG) & ~CONFIG_READOUT_SPEED_MSK) | CONFIG_QUARTER_SPEED_10MHZ_VAL); + FILE_LOG(logINFO, ("\tSet Config Reg to 0x%x\n", bus_r(CONFIG_REG))); - FILE_LOG(logINFO, ("\tSetting ADC Ofst Reg to 0x%x\n", ADC_OFST_QUARTER_SPEED_VAL)); bus_w(ADC_OFST_REG, ADC_OFST_QUARTER_SPEED_VAL); + FILE_LOG(logINFO, ("\tSet ADC Ofst Reg to 0x%x\n", bus_r(ADC_OFST_REG))); - FILE_LOG(logINFO, ("\tSetting ADC Phase Reg to 0x%x\n", ADC_PHASE_QUARTER_SPEED)); setAdcPhase(ADC_PHASE_QUARTER_SPEED, 0); - + FILE_LOG(logINFO, ("\tSet ADC Phase Reg to 0x%x\n", ADC_PHASE_QUARTER_SPEED)); break; + } } } @@ -1410,22 +1488,38 @@ void alignDeserializer() { int setNetworkParameter(enum NETWORKINDEX mode, int value) { - if (mode != TXN_FRAME) - return -1; + switch(mode) { - if (value >= 0) { - FILE_LOG(logINFO, ("Setting transmission delay: %d\n", value)); - bus_w(CONFIG_REG, (bus_r(CONFIG_REG) &~CONFIG_TDMA_TIMESLOT_MSK) - | (((value << CONFIG_TDMA_TIMESLOT_OFST) & CONFIG_TDMA_TIMESLOT_MSK))); - if (value == 0) - bus_w(CONFIG_REG, bus_r(CONFIG_REG) &~ CONFIG_TDMA_MSK); - else - bus_w(CONFIG_REG, bus_r(CONFIG_REG) | CONFIG_TDMA_MSK); - FILE_LOG(logDEBUG1, ("Transmission delay read %d\n", - ((bus_r(CONFIG_REG) & CONFIG_TDMA_TIMESLOT_MSK) >> CONFIG_TDMA_TIMESLOT_OFST))); - } + case TXN_FRAME: + if (value >= 0) { + FILE_LOG(logINFO, ("Setting transmission delay: %d\n", value)); + bus_w(CONFIG_REG, (bus_r(CONFIG_REG) &~CONFIG_TDMA_TIMESLOT_MSK) + | (((value << CONFIG_TDMA_TIMESLOT_OFST) & CONFIG_TDMA_TIMESLOT_MSK))); + if (value == 0) { + FILE_LOG(logINFO, ("Switching off transmission delay\n")); + bus_w(CONFIG_REG, bus_r(CONFIG_REG) &~ CONFIG_TDMA_ENABLE_MSK); + } else { + FILE_LOG(logINFO, ("Switching on transmission delay\n")); + bus_w(CONFIG_REG, bus_r(CONFIG_REG) | CONFIG_TDMA_ENABLE_MSK); + } + FILE_LOG(logDEBUG1, ("Transmission delay read %d\n", + ((bus_r(CONFIG_REG) & CONFIG_TDMA_TIMESLOT_MSK) >> CONFIG_TDMA_TIMESLOT_OFST))); + } + return ((bus_r(CONFIG_REG) & CONFIG_TDMA_TIMESLOT_MSK) >> CONFIG_TDMA_TIMESLOT_OFST); + + case FLOW_CONTROL_10G: + if (value == 0) { + FILE_LOG(logINFO, ("Switching off 10G flow control\n")); + bus_w(CONFIG_REG, bus_r(CONFIG_REG) &~ CONFIG_ETHRNT_FLW_CNTRL_MSK); + } else { + FILE_LOG(logINFO, ("Switching on 10G flow control\n")); + bus_w(CONFIG_REG, bus_r(CONFIG_REG) | CONFIG_ETHRNT_FLW_CNTRL_MSK); + } + return ((bus_r(CONFIG_REG) & CONFIG_ETHRNT_FLW_CNTRL_MSK) >> CONFIG_ETHRNT_FLW_CNTRL_OFST); - return ((bus_r(CONFIG_REG) & CONFIG_TDMA_TIMESLOT_MSK) >> CONFIG_TDMA_TIMESLOT_OFST); + default: + return -1; + } } diff --git a/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_defs.h b/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_defs.h index f90873e5e..18ab6eb82 100755 --- a/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_defs.h +++ b/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_defs.h @@ -4,24 +4,36 @@ #define MIN_REQRD_VRSN_T_RD_API 0x171220 -#define REQRD_FRMWR_VRSN 0x181206 // temp bug fix from last version, timing mode is backwards compatible +#define REQRD_FRMWR_VRSN 0x190509 -#define BOARD_JUNGFRAU_TYPE (8) #define CTRL_SRVR_INIT_TIME_US (300 * 1000) /* Struct Definitions */ -typedef struct ip_header_struct { - uint16_t ip_len; - uint8_t ip_tos; - uint8_t ip_ihl:4 ,ip_ver:4; - uint16_t ip_offset:13,ip_flag:3; - uint16_t ip_ident; - uint16_t ip_chksum; - uint8_t ip_protocol; - uint8_t ip_ttl; - uint32_t ip_sourceip; - uint32_t ip_destip; -} ip_header; +typedef struct udp_header_struct { + uint32_t udp_destmac_msb; + uint16_t udp_srcmac_msb; + uint16_t udp_destmac_lsb; + uint32_t udp_srcmac_lsb; + uint8_t ip_tos; + uint8_t ip_ihl: 4, ip_ver: 4; + uint16_t udp_ethertype; + uint16_t ip_identification; + uint16_t ip_totallength; + uint8_t ip_protocol; + uint8_t ip_ttl; + uint16_t ip_fragmentoffset: 13, ip_flags: 3; + uint16_t ip_srcip_msb; + uint16_t ip_checksum; + uint16_t ip_destip_msb; + uint16_t ip_srcip_lsb; + uint16_t udp_srcport; + uint16_t ip_destip_lsb; + uint16_t udp_checksum; + uint16_t udp_destport; +} udp_header; + +#define IP_HEADER_SIZE 20 + /* Enums */ enum CLK_SPEED_INDEX {FULL_SPEED, HALF_SPEED, QUARTER_SPEED}; @@ -36,7 +48,7 @@ enum DACINDEX {VB_COMP, VDD_PROT, VIN_COM, VREF_PRECH, VB_PIXBUF, VB_DS, VREF 480, /* VREF_DS */ \ 420 /* VREF_COMP */ \ }; -enum NETWORKINDEX { TXN_FRAME }; +enum NETWORKINDEX { TXN_FRAME, FLOWCTRL_10G }; /* Hardware Definitions */ #define NCHAN (256 * 256) @@ -46,7 +58,6 @@ enum NETWORKINDEX { TXN_FRAME }; #define DYNAMIC_RANGE (16) #define NUM_BYTES_PER_PIXEL (DYNAMIC_RANGE / 8) #define DATA_BYTES (NCHIP * NCHAN * NUM_BYTES_PER_PIXEL) -#define IP_PACKETSIZE (0x2052) #define CLK_RUN (40) /* MHz */ #define CLK_SYNC (20) /* MHz */ @@ -77,19 +88,21 @@ enum NETWORKINDEX { TXN_FRAME }; #define MAX_STORAGE_CELL_DLY_NS_VAL ((ASIC_CTRL_EXPSRE_TMR_MSK >> ASIC_CTRL_EXPSRE_TMR_OFST) * ASIC_CTRL_EXPSRE_TMR_STEPS) #define ACQ_TIME_MIN_CLOCK (2) +#define SAMPLE_ADC_FULL_SPEED (SAMPLE_ADC_HALF_SPEED) #define SAMPLE_ADC_HALF_SPEED (SAMPLE_DECMT_FACTOR_2_VAL + SAMPLE_DGTL_SAMPLE_0_VAL + SAMPLE_ADC_DECMT_FACTOR_0_VAL + SAMPLE_ADC_SAMPLE_0_VAL) /* 0x1000 */ #define SAMPLE_ADC_QUARTER_SPEED (SAMPLE_DECMT_FACTOR_4_VAL + SAMPLE_DGTL_SAMPLE_8_VAL + SAMPLE_ADC_DECMT_FACTOR_1_VAL + SAMPLE_ADC_SAMPLE_0_VAL) /* 0x2810 */ -#define CONFIG_HALF_SPEED (CONFIG_TDMA_DISABLE_VAL + CONFIG_HALF_SPEED_20MHZ_VAL + CONFIG_OPRTN_MDE_1_X_10GBE_VAL) /**0x100000 */ -#define CONFIG_QUARTER_SPEED (CONFIG_TDMA_DISABLE_VAL + CONFIG_QUARTER_SPEED_10MHZ_VAL + CONFIG_OPRTN_MDE_1_X_10GBE_VAL) + +#define ADC_OFST_FULL_SPEED_VAL (0x20)//(0x1f) //(0x20) #define ADC_OFST_HALF_SPEED_VAL (0x20)//(0x1f) //(0x20) #define ADC_OFST_QUARTER_SPEED_VAL (0x0f) //(0x0f) + +#define ADC_PHASE_FULL_SPEED (0x2D) //45 #define ADC_PHASE_HALF_SPEED (0x2D) //45 #define ADC_PHASE_QUARTER_SPEED (0x2D) //45 + #define ADC_PORT_INVERT_VAL (0x5A5A5A5A)//(0x453b2a9c) #define MAX_PHASE_SHIFTS (160) -/* MSB & LSB DEFINES */ -#define MSB_OF_64_BIT_REG_OFST (32) -#define LSB_OF_64_BIT_REG_OFST (0) -#define BIT_32_MSK (0xFFFFFFFF) +#define BIT16_MASK (0xFFFF) +#define UDP_IP_HEADER_LENGTH_BYTES (28) \ No newline at end of file diff --git a/slsDetectorServers/slsDetectorServer/communication_funcs.c b/slsDetectorServers/slsDetectorServer/communication_funcs.c index 11de0f631..153b4c719 100755 --- a/slsDetectorServers/slsDetectorServer/communication_funcs.c +++ b/slsDetectorServers/slsDetectorServer/communication_funcs.c @@ -524,7 +524,8 @@ int Server_SendResult(int fileDes, intType itype, int update, void* retval, int void getMacAddressinString(char* cmac, int size, uint64_t mac) { memset(cmac, 0, size); - sprintf(cmac,"%02x:%02x:%02x:%02x:%02x:%02x",(unsigned int)((mac>>40)&0xFF), + sprintf(cmac,"%02x:%02x:%02x:%02x:%02x:%02x", + (unsigned int)((mac>>40)&0xFF), (unsigned int)((mac>>32)&0xFF), (unsigned int)((mac>>24)&0xFF), (unsigned int)((mac>>16)&0xFF), @@ -535,4 +536,4 @@ void getMacAddressinString(char* cmac, int size, uint64_t mac) { void getIpAddressinString(char* cip, uint32_t ip) { memset(cip, 0, INET_ADDRSTRLEN); inet_ntop(AF_INET, &ip, cip, INET_ADDRSTRLEN); -} \ No newline at end of file +} diff --git a/slsDetectorServers/slsDetectorServer/communication_funcs.h b/slsDetectorServers/slsDetectorServer/communication_funcs.h index cfe4b5637..ab6ebd8e2 100755 --- a/slsDetectorServers/slsDetectorServer/communication_funcs.h +++ b/slsDetectorServers/slsDetectorServer/communication_funcs.h @@ -67,4 +67,5 @@ void getMacAddressinString(char* cmac, int size, uint64_t mac); */ void getIpAddressinString(char* cip, uint32_t ip); + #endif diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h b/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h index c54a96777..c18fec0dc 100755 --- a/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h +++ b/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h @@ -13,6 +13,7 @@ Here are the definitions, but the actual implementation should be done for each ****************************************************/ +enum interfaceType {OUTER, INNER}; // basic tests int isFirmwareCheckDone(); @@ -213,6 +214,11 @@ int getExtSignal(); // configure mac #ifdef GOTTHARDD void calcChecksum(mac_conf* mac, int sourceip, int destip); +#elif JUNGFRAUD +void setNumberofUDPInterfaces(int val); +void selectPrimaryInterface(int val); +void setupHeader(int iRxEntry, enum interfaceType type, uint32_t destip, uint64_t destmac, uint32_t destport, uint64_t sourcemac, uint32_t sourceip, uint32_t sourceport); +void calcChecksum(udp_header* udp); #endif #if defined(CHIPTESTBOARDD) || defined(MOENCHD) long int calcChecksum(int sourceip, int destip); @@ -285,6 +291,7 @@ int resetCounterBlock(int startACQ); // jungfrau specific - powerchip, autocompdisable, clockdiv, asictimer, clock, pll, flashing firmware #elif JUNGFRAUD +void initReadoutConfiguration(); int powerChip (int on); int autoCompDisable(int on); void configureASICTimer(); diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c index b5aeaca75..3689a6061 100755 --- a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c +++ b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c @@ -1719,13 +1719,6 @@ int get_time_left(int file_des) { // only get // check index -#ifdef JUNGFRAUD - if (ind == DELAY_AFTER_TRIGGER) { - ret = FAIL; - sprintf(mess,"Timer Left Index (%d) is not implemented for this release.\n", (int)ind); - FILE_LOG(logERROR,(mess)); - } -#endif if (ret == OK) { switch(ind) { #ifdef EIGERD @@ -2417,9 +2410,9 @@ int configure_mac(int file_des) { #endif #if defined(JUNGFRAUD) || defined(EIGERD) int pos[2] = {0, 0}; - sscanf(args[12], "%x", &pos[0]); - sscanf(args[13], "%x", &pos[1]); - FILE_LOG(logDEBUG1, ("Position: [%d, %d]\n", pos[0], pos[1])); + sscanf(args[12], "%x", &pos[X]); + sscanf(args[13], "%x", &pos[Y]); + FILE_LOG(logDEBUG1, ("Position: [%d, %d]\n", pos[X], pos[Y])); #endif @@ -3227,10 +3220,12 @@ int set_network_parameter(int file_des) { if ((value == -1) || (Server_VerifyLock() == OK)) { // check index switch (mode) { -#ifdef EIGERD + case FLOW_CONTROL_10G: serverIndex = FLOWCTRL_10G; break; + +#ifdef EIGERD case DETECTOR_TXN_DELAY_LEFT: serverIndex = TXN_LEFT; break; diff --git a/slsDetectorSoftware/include/slsDetectorUsers.h b/slsDetectorSoftware/include/slsDetectorUsers.h index 3b74cec0b..c92323ac6 100755 --- a/slsDetectorSoftware/include/slsDetectorUsers.h +++ b/slsDetectorSoftware/include/slsDetectorUsers.h @@ -521,7 +521,7 @@ public: int setHighVoltage(int i = -1, int detPos = -1); /** - * Set 10GbE Flow Control (Eiger) + * Set 10GbE Flow Control (Eiger and Jungfrau) * @param enable 1 to set, 0 to unset, -1 gets * @param detPos -1 for all detectors in list or specific detector position * @returns 10GbE flow Control diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index d505b3eba..58ebf45e1 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -1438,7 +1438,7 @@ int slsDetector::configureMAC() { // 2d positions to detector to put into udp header { int pos[2] = {0, 0}; - int max = shm()->multiSize[1] * (shm()->numUDPInterfaces); + int max = shm()->multiSize[Y] * (shm()->numUDPInterfaces); // row pos[0] = (detId % max); // col for horiz. udp ports diff --git a/slsDetectorSoftware/src/slsDetectorCommand.cpp b/slsDetectorSoftware/src/slsDetectorCommand.cpp index 4208c0c25..560487e48 100755 --- a/slsDetectorSoftware/src/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp @@ -676,19 +676,12 @@ slsDetectorCommand::slsDetectorCommand(multiSlsDetector *det) { ++i; /*! \page timing - - delayl gets delay left. Used in GOTTHARD only. Only get! \c Returns \c (double with 9 decimal digits) + - delayl gets delay left. Used in GOTTHARD, JUNGFRAU, MOENCH and CTB only. Only get! \c Returns \c (double with 9 decimal digits) */ descrToFuncMap[i].m_pFuncName = "delayl"; descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdTimeLeft; ++i; - /*! \page timing - - gatesl gets number of gates left. Used in GOTTHARD only. Only get! \c Returns \c (double with 9 decimal digits) - */ - descrToFuncMap[i].m_pFuncName = "gatesl"; - descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdTimeLeft; - ++i; - /*! \page config - framesl gets number of frames left. Used in GOTTHARD and Jungfrau only. Only get! \c Returns \c (double with 9 decimal digits) */ @@ -1700,7 +1693,7 @@ slsDetectorCommand::slsDetectorCommand(multiSlsDetector *det) { ++i; /*! \page network - - flowcontrol_10g [delay] Enables/disables 10 GbE flow control. 1 enables, 0 disables. Used for EIGER only. \c Returns \c (int) + - flowcontrol_10g [delay] Enables/disables 10 GbE flow control. 1 enables, 0 disables. Used for EIGER and JUNGFRAU only. \c Returns \c (int) */ descrToFuncMap[i].m_pFuncName = "flowcontrol_10g"; descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdNetworkParameter; @@ -3076,7 +3069,7 @@ std::string slsDetectorCommand::helpNetworkParameter(int action) { os << "txndelay_left port \n sets detector transmission delay of the left port" << std::endl; os << "txndelay_right port \n sets detector transmission delay of the right port" << std::endl; os << "txndelay_frame port \n sets detector transmission delay of the entire frame" << std::endl; - os << "flowcontrol_10g port \n sets flow control for 10g for eiger" << std::endl; + os << "flowcontrol_10g port \n sets flow control for 10g for eiger and jungfrau" << std::endl; os << "zmqport port \n sets the 0MQ (TCP) port of the client to where final data is streamed to (eg. for GUI). The default already connects with rx_zmqport for the GUI. " "Use single-detector command to set individually or multi-detector command to calculate based on port for the rest." "Must restart streaming in client with new port from gui/external gui" @@ -3116,7 +3109,7 @@ std::string slsDetectorCommand::helpNetworkParameter(int action) { os << "txndelay_left \n gets detector transmission delay of the left port" << std::endl; os << "txndelay_right \n gets detector transmission delay of the right port" << std::endl; os << "txndelay_frame \n gets detector transmission delay of the entire frame" << std::endl; - os << "flowcontrol_10g \n gets flow control for 10g for eiger" << std::endl; + os << "flowcontrol_10g \n gets flow control for 10g for eiger and jungfrau" << std::endl; os << "zmqport \n gets the 0MQ (TCP) port of the client to where final data is streamed to" << std::endl; os << "rx_zmqport \n gets the 0MQ (TCP) port of the receiver from where data is streamed from" << std::endl; os << "zmqip \n gets the 0MQ (TCP) ip of the client to where final data is streamed to.If no custom ip, empty until first time connect to receiver" << std::endl; @@ -4581,8 +4574,6 @@ std::string slsDetectorCommand::cmdTimeLeft(int narg, char *args[], int action, index = FRAME_PERIOD; else if (cmd == "delayl") index = DELAY_AFTER_TRIGGER; - else if (cmd == "gatesl") - index = GATES_NUMBER; else if (cmd == "framesl") index = FRAME_NUMBER; else if (cmd == "cyclesl") diff --git a/slsReceiverSoftware/include/GeneralData.h b/slsReceiverSoftware/include/GeneralData.h index b7c955ed1..c3bda3ef9 100755 --- a/slsReceiverSoftware/include/GeneralData.h +++ b/slsReceiverSoftware/include/GeneralData.h @@ -27,9 +27,6 @@ public: /** Number of Pixels in y axis */ uint32_t nPixelsY; - /** emptybuffer (mainly for jungfrau) */ - uint32_t emptyHeader; - /** Size of header in Packet */ uint32_t headerSizeinPacket; @@ -95,7 +92,6 @@ public: myDetectorType(slsDetectorDefs::GENERIC), nPixelsX(0), nPixelsY(0), - emptyHeader(0), headerSizeinPacket(0), dataSize(0), packetSize(0), @@ -228,7 +224,6 @@ public: FILE_LOG(level) << "myDetectorType: " << slsDetectorDefs::detectorTypeToString(myDetectorType); FILE_LOG(level) << "Pixels X: " << nPixelsX; FILE_LOG(level) << "Pixels Y: " << nPixelsY; - FILE_LOG(level) << "Empty Header: " << emptyHeader; FILE_LOG(level) << "Header Size in Packet: " << headerSizeinPacket; FILE_LOG(level) << "Data Size: " << dataSize; FILE_LOG(level) << "Packet Size: " << packetSize; @@ -506,8 +501,7 @@ class JungfrauData : public GeneralData { myDetectorType = slsDetectorDefs::JUNGFRAU; nPixelsX = (256*4); nPixelsY = 512; - emptyHeader = 6; - headerSizeinPacket = emptyHeader + sizeof(slsDetectorDefs::sls_detector_header); + headerSizeinPacket = sizeof(slsDetectorDefs::sls_detector_header); dataSize = 8192; packetSize = headerSizeinPacket + dataSize; packetsPerFrame = 128; diff --git a/slsReceiverSoftware/src/Listener.cpp b/slsReceiverSoftware/src/Listener.cpp index 8760d6dba..4ffccbd32 100755 --- a/slsReceiverSoftware/src/Listener.cpp +++ b/slsReceiverSoftware/src/Listener.cpp @@ -353,7 +353,6 @@ uint32_t Listener::ListenToAnImage(char* buf) { uint32_t numpackets = 0; uint32_t dsize = generalData->dataSize; uint32_t hsize = generalData->headerSizeinPacket; //(includes empty header) - uint32_t esize = generalData->emptyHeader; uint32_t fifohsize = generalData->fifoBufferHeaderSize; uint32_t pperFrame = generalData->packetsPerFrame; bool isHeaderEmpty = true; @@ -397,13 +396,13 @@ uint32_t Listener::ListenToAnImage(char* buf) { //check if its the current image packet // -------------------------- new header ---------------------------------------------------------------------- if (standardheader) { - old_header = (sls_detector_header*) (&carryOverPacket[esize]); + old_header = (sls_detector_header*) (&carryOverPacket[0]); fnum = old_header->frameNumber; pnum = old_header->packetNumber; } // -------------------old header ----------------------------------------------------------------------------- else { - generalData->GetHeaderInfo(index, &carryOverPacket[esize], + generalData->GetHeaderInfo(index, &carryOverPacket[0], *dynamicRange, oddStartingPacket, fnum, pnum, snum, bid); } //------------------------------------------------------------------------------------------------------------ @@ -515,7 +514,7 @@ uint32_t Listener::ListenToAnImage(char* buf) { // -------------------------- new header ---------------------------------------------------------------------- if (standardheader) { - old_header = (sls_detector_header*) (&listeningPacket[esize]); + old_header = (sls_detector_header*) (&listeningPacket[0]); fnum = old_header->frameNumber; pnum = old_header->packetNumber; } @@ -523,10 +522,10 @@ uint32_t Listener::ListenToAnImage(char* buf) { else { // set first packet to be odd or even (check required when switching from roi to no roi) if (myDetectorType == GOTTHARD && !measurementStartedFlag) { - oddStartingPacket = generalData->SetOddStartingPacket(index, &listeningPacket[esize]); + oddStartingPacket = generalData->SetOddStartingPacket(index, &listeningPacket[0]); } - generalData->GetHeaderInfo(index, &listeningPacket[esize], + generalData->GetHeaderInfo(index, &listeningPacket[0], *dynamicRange, oddStartingPacket, fnum, pnum, snum, bid); } //------------------------------------------------------------------------------------------------------------ diff --git a/slsSupportLib/include/versionAPI.h b/slsSupportLib/include/versionAPI.h index 4a39bc3a9..689b78438 100644 --- a/slsSupportLib/include/versionAPI.h +++ b/slsSupportLib/include/versionAPI.h @@ -2,9 +2,10 @@ #define GITBRANCH "refgui" #define APIGOTTHARD 0x190108 #define APIMOENCH 0x181108 -#define APIJUNGFRAU 0x190405 #define APILIB 0x190405 #define APIRECEIVER 0x190405 #define APIGUI 0x190405 -#define APICTB 0x190514 #define APIEIGER 0x190516 +#define APICTB 0x190516 + +#define APIJUNGFRAU 0x190517 From 452fd1e457bf5e57b52fb4e82ae3e41aeb05778c Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Wed, 22 May 2019 09:45:08 +0200 Subject: [PATCH 43/76] new defaults for CMake --- CMakeLists.txt | 35 +++++++++-------------------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f6e49c817..70c2019ba 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,13 +1,9 @@ cmake_minimum_required(VERSION 3.9) project(slsDetectorPackage) + set(PROJECT_VERSION 5.0.0) - -include(CheckIPOSupported) - - - - include(cmake/project_version.cmake) +include(CheckIPOSupported) # Include additional modules that are used unconditionally include(GNUInstallDirs) @@ -35,11 +31,11 @@ if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) endif() option (SLS_USE_HDF5 "HDF5 File format" OFF) -option (SLS_USE_TEXTCLIENT "Text Client" OFF) -option (SLS_USE_RECEIVER "Receiver" OFF) +option (SLS_USE_TEXTCLIENT "Text Client" ON) +option (SLS_USE_RECEIVER "Receiver" ON) option (SLS_USE_GUI "GUI" OFF) -option (SLS_USE_TESTS "TESTS" ON) -option (SLS_USE_INTEGRATION_TESTS "Integration Tests" ON) +option (SLS_USE_TESTS "TESTS" OFF) +option (SLS_USE_INTEGRATION_TESTS "Integration Tests" OFF) option(SLS_USE_SANITIZER "Sanitizers for debugging" OFF) option(SLS_USE_PYTHON "Python bindings" OFF) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) @@ -91,12 +87,10 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") -Wno-misleading-indentation # mostly in rapidjson remove using clang format -Wduplicated-cond -Wnull-dereference ) - endif() if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 8.0) target_compile_options(slsProjectWarnings INTERFACE -Wno-class-memaccess ) - endif() endif() @@ -106,11 +100,10 @@ if(SLS_USE_SANITIZER) target_link_libraries(slsProjectOptions INTERFACE -fsanitize=address,undefined) # target_compile_options(slsProjectOptions INTERFACE -fsanitize=thread) # target_link_libraries(slsProjectOptions INTERFACE -fsanitize=thread) - - endif() +endif() -# Install fake the library +# Install fake the libraries install(TARGETS slsProjectOptions slsProjectWarnings EXPORT "${TARGETS_EXPORT_NAME}" LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} @@ -122,8 +115,6 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_INSTALL_RPATH "$ORIGIN") set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) - - find_package(Doxygen) find_package(ZeroMQ 4 REQUIRED) @@ -132,15 +123,13 @@ if (SLS_USE_TESTS) add_subdirectory(tests) endif(SLS_USE_TESTS) -# Support library containing functionallity common to -# detector and receiver +# Common functionallity to detector and receiver add_subdirectory(slsSupportLib) if (SLS_USE_TEXTCLIENT) add_subdirectory(slsDetectorSoftware) endif (SLS_USE_TEXTCLIENT) - if (SLS_USE_RECEIVER) if (SLS_USE_HDF5) find_package(HDF5 1.10 COMPONENTS CXX REQUIRED) @@ -157,8 +146,6 @@ if (SLS_USE_GUI) endif() endif (SLS_USE_GUI) - - if (SLS_USE_INTEGRATION_TESTS) add_subdirectory(integrationTests) endif (SLS_USE_INTEGRATION_TESTS) @@ -173,13 +160,9 @@ configure_file( .clang-tidy if (DOXYGEN_FOUND) - # set input and output files set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/doxygen/Doxyfile.in) set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) - - # request to configure the file configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY) - message("Doxygen build started") # note the option ALL which allows to build the docs together with the application add_custom_target( docs From 10f89599e02686d2349b5b093c712600793a9fe9 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Wed, 22 May 2019 19:11:35 +0200 Subject: [PATCH 44/76] bug fix: hdf5 printError still called once. replcaed with printErrorStack --- slsReceiverSoftware/include/HDF5FileStatic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slsReceiverSoftware/include/HDF5FileStatic.h b/slsReceiverSoftware/include/HDF5FileStatic.h index 7f89a3348..0a7955d4f 100755 --- a/slsReceiverSoftware/include/HDF5FileStatic.h +++ b/slsReceiverSoftware/include/HDF5FileStatic.h @@ -284,7 +284,7 @@ public: } catch(Exception error){ FILE_LOG(logERROR) << "Could not extend dataset in object " << ind; - error.printError(); + error.printErrorStack(); return 1; } return 0; From 43dc9df6dbf38e906c1ea12f1fd601e874f0d43c Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Fri, 24 May 2019 10:25:34 +0200 Subject: [PATCH 45/76] removed unused scripts --- examples/ang.off | 24 --- examples/bad.chans | 5 - .../config_gen_script/generic_example.config | 39 +++++ .../generic_example.config_gen | 47 ++++++ examples/mythen.config | 32 ---- examples/receiver.config | 1 - examples/remove_shm.sh | 10 -- examples/scripts/HeaderBeforeAfter.awk | 142 ------------------ examples/scripts/ScanScript.awk | 87 ----------- examples/scripts/ScriptBeforeAfter.awk | 100 ------------ examples/scripts/StartStopScript.awk | 79 ---------- examples/two_no_receiver.config | 64 -------- 12 files changed, 86 insertions(+), 544 deletions(-) delete mode 100755 examples/ang.off delete mode 100755 examples/bad.chans create mode 100644 examples/config_gen_script/generic_example.config create mode 100755 examples/config_gen_script/generic_example.config_gen delete mode 100755 examples/mythen.config delete mode 100755 examples/receiver.config delete mode 100755 examples/remove_shm.sh delete mode 100755 examples/scripts/HeaderBeforeAfter.awk delete mode 100755 examples/scripts/ScanScript.awk delete mode 100755 examples/scripts/ScriptBeforeAfter.awk delete mode 100755 examples/scripts/StartStopScript.awk delete mode 100755 examples/two_no_receiver.config diff --git a/examples/ang.off b/examples/ang.off deleted file mode 100755 index 819a60667..000000000 --- a/examples/ang.off +++ /dev/null @@ -1,24 +0,0 @@ - module 0 center 6.395E+02 +- 0.00E+00 conversion 6.5660E-05 +- 7.10E-09 offset 0.00000 +- 0.00015 - module 1 center 6.395E+02 +- 0.00E+00 conversion 6.5650E-05 +- 7.09E-09 offset 5.00211 +- 0.00015 - module 2 center 6.395E+02 +- 0.00E+00 conversion 6.5625E-05 +- 7.09E-09 offset 10.00733 +- 0.00015 - module 3 center 6.395E+02 +- 0.00E+00 conversion 6.5618E-05 +- 7.09E-09 offset 15.00742 +- 0.00015 - module 4 center 6.395E+02 +- 0.00E+00 conversion 6.5642E-05 +- 7.15E-09 offset 20.00620 +- 0.00015 - module 5 center 6.395E+02 +- 0.00E+00 conversion 6.5612E-05 +- 7.09E-09 offset 25.00281 +- 0.00015 - module 6 center 6.395E+02 +- 0.00E+00 conversion 6.5623E-05 +- 6.93E-09 offset 30.00704 +- 0.00015 - module 7 center 6.395E+02 +- 0.00E+00 conversion 6.5605E-05 +- 7.10E-09 offset 34.99715 +- 0.00015 - module 8 center 6.395E+02 +- 0.00E+00 conversion 6.5643E-05 +- 7.21E-09 offset 39.99533 +- 0.00015 - module 9 center 6.395E+02 +- 0.00E+00 conversion 6.5638E-05 +- 7.09E-09 offset 44.99969 +- 0.00015 - module 10 center 6.395E+02 +- 0.00E+00 conversion 6.5638E-05 +- 6.94E-09 offset 49.99859 +- 0.00015 - module 11 center 6.395E+02 +- 0.00E+00 conversion 6.5644E-05 +- 7.10E-09 offset 54.99499 +- 0.00015 - module 12 center 6.395E+02 +- 0.00E+00 conversion 6.5618E-05 +- 7.09E-09 offset 59.99120 +- 0.00015 - module 13 center 6.395E+02 +- 0.00E+00 conversion 6.5607E-05 +- 7.11E-09 offset 64.98880 +- 0.00015 - module 14 center 6.395E+02 +- 0.00E+00 conversion 6.5609E-05 +- 7.09E-09 offset 69.98205 +- 0.00015 - module 15 center 6.395E+02 +- 0.00E+00 conversion 6.5611E-05 +- 7.09E-09 offset 74.98379 +- 0.00015 - module 16 center 6.395E+02 +- 0.00E+00 conversion 6.5619E-05 +- 4.72E-09 offset 79.98559 +- 0.00015 - module 17 center 6.395E+02 +- 0.00E+00 conversion 6.5604E-05 +- 7.09E-09 offset 84.98376 +- 0.00015 - module 18 center 6.395E+02 +- 0.00E+00 conversion 6.5605E-05 +- 7.09E-09 offset 89.98307 +- 0.00015 - module 19 center 6.395E+02 +- 0.00E+00 conversion 6.5616E-05 +- 7.09E-09 offset 94.98907 +- 0.00015 - module 20 center 6.395E+02 +- 0.00E+00 conversion 6.5634E-05 +- 7.08E-09 offset 99.97965 +- 0.00015 - module 21 center 6.395E+02 +- 0.00E+00 conversion 6.5608E-05 +- 4.16E-09 offset 104.99732 +- 0.00016 - module 22 center 6.395E+02 +- 0.00E+00 conversion 6.5608E-05 +- 7.09E-09 offset 109.98646 +- 0.00015 - module 23 center 6.395E+02 +- 0.00E+00 conversion 6.5649E-05 +- 7.09E-09 offset 114.98765 +- 0.00015 diff --git a/examples/bad.chans b/examples/bad.chans deleted file mode 100755 index 6e7db22a2..000000000 --- a/examples/bad.chans +++ /dev/null @@ -1,5 +0,0 @@ -15 -1528 -5000 -6513 - diff --git a/examples/config_gen_script/generic_example.config b/examples/config_gen_script/generic_example.config new file mode 100644 index 000000000..9f34ef551 --- /dev/null +++ b/examples/config_gen_script/generic_example.config @@ -0,0 +1,39 @@ +hostname hostname1+hostname2+hostname3+hostname55+ +header_var1 wow +header_var2 great +header_var3 very nice + +0:counter1 100 +0:counter2 1024 +0:counter3 1500 +0:forallmodules val_mod1 +0:constant1 const1 +0:constant2 const2 +0:constant3 const3 /path/to/something + +1:counter1 101 +1:counter2 1036 +1:counter3 1503 +1:forallmodules val_mod2 +1:constant1 const1 +1:constant2 const2 +1:constant3 const3 /path/to/something + +2:counter1 102 +2:counter2 1048 +2:counter3 1506 +2:forallmodules val_mod3 +2:constant1 const1 +2:constant2 const2 +2:constant3 const3 /path/to/something + +3:counter1 103 +3:counter2 1060 +3:counter3 1509 +3:forallmodules val_mod4 +3:constant1 const1 +3:constant2 const2 +3:constant3 const3 /path/to/something + +footer1 foot1 +footer2 somethingelseathebottom diff --git a/examples/config_gen_script/generic_example.config_gen b/examples/config_gen_script/generic_example.config_gen new file mode 100755 index 000000000..fc703169b --- /dev/null +++ b/examples/config_gen_script/generic_example.config_gen @@ -0,0 +1,47 @@ +#!/bin/bash + +# local variables +a_variable=/path/to/something + +# HOSTNAMES is special +# Beside of the hostname line it also defines the amount of modules +# for the body part +# take care for the last space +HOSTNAMES="hostname1 hostname2 hostname3 hostname55 " + +## header contains constant values at the beginning of the file +header=( +header_var1="wow" +header_var2="great" +header_var3="very nice" +) + +## the body part is for each half module +# counters will count automatically +# the number behind ':' indicates the incrementation value + +counters=( +counter1="100:1" +counter2="1024:12" +counter3="1500:3" +) + +# constant values +constants=( +constant1="const1" +constant2="const2" +constant3="const3 ${a_variable}" +) + +# lists contains space separated lists each value for each half module +lists=( +forallmodules="val_mod1 val_mod2 val_mod3 val_mod4" +) + + +## footer contains constant values for the end of the file +footer=( +footer1=foot1 +footer2=somethingelseathebottom +) + diff --git a/examples/mythen.config b/examples/mythen.config deleted file mode 100755 index 3390c61c8..000000000 --- a/examples/mythen.config +++ /dev/null @@ -1,32 +0,0 @@ -type Mythen+ -0:hostname mcs1x21 -0:port 1952 -0:stopport 1953 -0:settingsdir /afs/psi.ch/user/b/bergamaschi -0:outdir /afs/psi.ch/user/b/bergamaschi -0:angdir 1.000000 -0:moveflag 1.000000 -0:lock 0 -0:caldir /afs/psi.ch/user/b/bergamaschi -0:ffdir /afs/psi.ch/user/b/bergamaschi -0:nmod 1 -0:waitstates 13 -0:setlength 3 -0:clkdivider 6 -0:extsig:0 gate_in_active_high -0:extsig:1 trigger_in_rising_edge -0:extsig:2 off -0:extsig:3 off -master -1 -sync none -outdir /afs/psi.ch/user/b/bergamaschi -ffdir /afs/psi.ch/user/b/bergamaschi -headerbefore none -headerafter none -headerbeforepar none -headerafterpar none -badchannels none -angconv none -globaloff 0.000000 -binsize 0.001000 -threaded 1 diff --git a/examples/receiver.config b/examples/receiver.config deleted file mode 100755 index fa4586e14..000000000 --- a/examples/receiver.config +++ /dev/null @@ -1 +0,0 @@ -dataport 1955 diff --git a/examples/remove_shm.sh b/examples/remove_shm.sh deleted file mode 100755 index 439bc839c..000000000 --- a/examples/remove_shm.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/csh -f -#set l = `ipcs -m | grep "$USER"| cut -c12-19` -set l = `ipcs -m | cut -c0-10` -foreach s ( $l ) - echo $s - ipcrm -M $s -end -#if ($#l != 0 ) -echo $#l shared memory\(s\) for $user removed - diff --git a/examples/scripts/HeaderBeforeAfter.awk b/examples/scripts/HeaderBeforeAfter.awk deleted file mode 100755 index 9b1354471..000000000 --- a/examples/scripts/HeaderBeforeAfter.awk +++ /dev/null @@ -1,142 +0,0 @@ -#! /bin/awk -f - -# this is an awk script to start a run -# you first need to run inimodule.awk to initialize -# the pattern, set Vc and set the trimbits -# - -##################################################################### -# revision history # -##################################################################### -# 31.10.2001 first version # -##################################################################### -# # -# Bernd Schmitt # -# # -# bernd.schmitt@psi.ch # -# # -##################################################################### -# # -# modifications: # -# # -# 1.3.2002 BS adapted for use with DCB # -# # -# 25.5.2002 BS adapted to new convert program # -# # -# 29.5.2002 sleep -> usleep for meas. time , TS # -# # -##################################################################### - -BEGIN { - -# initialize variables - NPAR=3 - - PAR[1]="nrun" - PAR[2]="fn" - PAR[3]="par" - -# initialize default values - - - - PARVAL[1] = 100 - PARVAL[2] = "microstrip_july2007" - PARVAL[3]=0 - - - - - - printf("\n\nnumber of command line arguments: %i (incl. command)\n\n", ARGC); - -# read command line defined variables - if (ARGC>1) { - printf("\n\nnumber of command line arguments: %i (incl. command)\n\n", ARGC); - for (i=1; i<=ARGC; i++) { - printf("%s \n", ARGV[i]); - nsplit=split(ARGV[i],array,"=") - VAR = array[1]; - VAL = array[2]; - - for (j=1; j<=NPAR; j++) { - if ( VAR==PAR[j] ) { - PARVAL[j] = VAL - } - } - } - } - run=PARVAL[1] - fn=PARVAL[2] - par=PARVAL[3] - - -# print command line arguments - for (i=1; i<=NPAR; i++){ - printf("\t... %2i.\t%7s = %s\n", i, PAR[i], PARVAL[i] ); - } - printf("\n\n"); - -# generate parameter file - - fnamep=fn".parab" - printf("header before\n")>> fnamep - system("date >>"fnamep) - printf("run=%i \n", run ) >> fnamep - -#print detector parameters to file - if (par==1) { - - command="sls_detector_get exptime| awk -F \" \" '{print $2}'" - command | getline var - printf("acquisition time = %11.6f second(s)\n", var) >> fnamep - - command="sls_detector_get settings| awk -F \" \" '{print $2}'" - command | getline var - printf("settings = %s\n", var) >> fnamep; - - command="sls_detector_get threshold| awk -F \" \" '{print $2}'" - command | getline var - printf("threshold energy = %d eV\n", var) >> fnamep; - - command="sls_detector_get badchannels| awk -F \" \" '{print $2}'" - command | getline var - printf("bad channel list = %s\n",var) >> fnamep; - - - command="sls_detector_get angconv| awk -F \" \" '{print $2}'" - command | getline var - printf("angle calibration conversion = %s\n",var) >> fnamep; - - - command="sls_detector_get globaloff| awk -F \" \" '{print $2}'" - command | getline var - printf("beamline offset = %f deg\n", var) >> fnamep; - - command="sls_detector_get fineoff| awk -F \" \" '{print $2}'" - command | getline var - printf("fine offset = %f deg\n", var) >> fnamep; - - command="sls_detector_get flatfield| awk -F \" \" '{print $2}'" - command | getline var - printf("Flat field corrections = %s\n",var) >> fnamep; - - command="sls_detector_get ratecorr| awk -F \" \" '{print $2}'" - command | getline var - printf("Dead time corrections tau = %d ns\n",var) >> fnamep; - - } - - -#print beamline parameters to file - -#read detector position - system("caget X04SA-ES2-TH2:RO.RBV >>"fnamep) -#read I0 - system("caget X04SA-ES2-SC:CH6>>"fnamep) -} - - - - - diff --git a/examples/scripts/ScanScript.awk b/examples/scripts/ScanScript.awk deleted file mode 100755 index 7617e340c..000000000 --- a/examples/scripts/ScanScript.awk +++ /dev/null @@ -1,87 +0,0 @@ -#! /bin/awk -f - -# this is an awk script to start a run -# you first need to run inimodule.awk to initialize -# the pattern, set Vc and set the trimbits -# - -##################################################################### -# revision history # -##################################################################### -# 31.10.2001 first version # -##################################################################### -# # -# Bernd Schmitt # -# # -# bernd.schmitt@psi.ch # -# # -##################################################################### -# # -# modifications: # -# # -# 1.3.2002 BS adapted for use with DCB # -# # -# 25.5.2002 BS adapted to new convert program # -# # -# 29.5.2002 sleep -> usleep for meas. time , TS # -# # -##################################################################### - -BEGIN { - -# initialize variables - NPAR=4 - - PAR[1]="nrun" - PAR[2]="fn" - PAR[3]="var" - PAR[4]="par" - - -# initialize default values - PARVAL[1] = 100 - PARVAL[2] = "myfname" - PARVAL[3] = 0 - PARVAL[2] = "none" - - - -# read command line defined variables - if (ARGC>1) { - printf("\n\nnumber of command line arguments: %i (incl. command)\n\n", ARGC); - for (i=1; i<=ARGC; i++) { - - nsplit=split(ARGV[i],array,"=") - VAR = array[1]; - VAL = array[2]; - - for (j=1; j<=NPAR; j++) { - if ( VAR==PAR[j] ) { - PARVAL[j] = VAL - } - } - } - } - - run=PARVAL[1] - fn=PARVAL[2] - var=PARVAL[3] - par=PARVAL[4] - - - - -# print command line arguments - for (i=1; i<=NPAR; i++){ - printf("\t... %2i.\t%7s = %s\n", i, PAR[i], PARVAL[i] ); - } - -#execute you command hereafter e.g. change temperature etc. - - -} - - - - - diff --git a/examples/scripts/ScriptBeforeAfter.awk b/examples/scripts/ScriptBeforeAfter.awk deleted file mode 100755 index 14838e280..000000000 --- a/examples/scripts/ScriptBeforeAfter.awk +++ /dev/null @@ -1,100 +0,0 @@ -#! /bin/awk -f - -# this is an awk script to start a run -# you first need to run inimodule.awk to initialize -# the pattern, set Vc and set the trimbits -# - -##################################################################### -# revision history # -##################################################################### -# 31.10.2001 first version # -##################################################################### -# # -# Bernd Schmitt # -# # -# bernd.schmitt@psi.ch # -# # -##################################################################### -# # -# modifications: # -# # -# 1.3.2002 BS adapted for use with DCB # -# # -# 25.5.2002 BS adapted to new convert program # -# # -# 29.5.2002 sleep -> usleep for meas. time , TS # -# # -##################################################################### - -BEGIN { - -# initialize variables - NPAR=7 - - PAR[1]="nrun" - PAR[2]="fn" - PAR[3]="par" - PAR[4]="sv0" - PAR[5]="sv1" - PAR[6]="p0" - PAR[7]="p1" - -# initialize default values - PARVAL[1] = 100 - PARVAL[2] = "myfname" - PARVAL[3] = 1 - PARVAL[4] = 0 - PARVAL[5] = 0 - PARVAL[6] = "none" - PARVAL[7] = "none" - - - -# read command line defined variables - if (ARGC>1) { - printf("\n\nnumber of command line arguments: %i (incl. command)\n\n", ARGC); - for (i=1; i<=ARGC; i++) { - - nsplit=split(ARGV[i],array,"=") - VAR = array[1]; - VAL = array[2]; - - for (j=1; j<=NPAR; j++) { - if ( VAR==PAR[j] ) { - PARVAL[j] = VAL - } - } - } - } - - run=PARVAL[1] - fn=PARVAL[2] - "par"PAR[3]= - sv0=PAR[4] - sv1=PAR[5] - p0=PAR[6] - p1=PAR[7] - - - -# print command line arguments - for (i=1; i<=NPAR; i++){ - printf("\t... %2i.\t%7s = %s\n", i, PAR[i], PARVAL[i] ); - } -# printf("\n\n"); - # system("close_shutter_g95") - -# execute your actions hereafter - if (par==1) { - #open shutter - } else { - #close shutter - } - -} - - - - - diff --git a/examples/scripts/StartStopScript.awk b/examples/scripts/StartStopScript.awk deleted file mode 100755 index f8e53917c..000000000 --- a/examples/scripts/StartStopScript.awk +++ /dev/null @@ -1,79 +0,0 @@ -#! /bin/awk -f - -# this is an awk script to start a run -# you first need to run inimodule.awk to initialize -# the pattern, set Vc and set the trimbits -# - -##################################################################### -# revision history # -##################################################################### -# 31.10.2001 first version # -##################################################################### -# # -# Bernd Schmitt # -# # -# bernd.schmitt@psi.ch # -# # -##################################################################### -# # -# modifications: # -# # -# 1.3.2002 BS adapted for use with DCB # -# # -# 25.5.2002 BS adapted to new convert program # -# # -# 29.5.2002 sleep -> usleep for meas. time , TS # -# # -##################################################################### - -BEGIN { - -# initialize variables - NPAR=2 - - PAR[1]="nrun" - PAR[2]="par" - - -# initialize default values - PARVAL[1] = 100 - PARVAL[2] = "none" - - - -# read command line defined variables - if (ARGC>1) { - printf("\n\nnumber of command line arguments: %i (incl. command)\n\n", ARGC); - for (i=1; i<=ARGC; i++) { - - nsplit=split(ARGV[i],array,"=") - VAR = array[1]; - VAL = array[2]; - - for (j=1; j<=NPAR; j++) { - if ( VAR==PAR[j] ) { - PARVAL[j] = VAL - } - } - } - } - - run=PARVAL[1] - par=PARVAL[2] - - - - -# print command line arguments - for (i=1; i<=NPAR; i++){ - printf("\t... %2i.\t%7s = %s\n", i, PAR[i], PARVAL[i] ); - } -#execute action hereafter - -} - - - - - diff --git a/examples/two_no_receiver.config b/examples/two_no_receiver.config deleted file mode 100755 index 18718ad64..000000000 --- a/examples/two_no_receiver.config +++ /dev/null @@ -1,64 +0,0 @@ -#####Any line with a # is not read###### - -#type Gotthard+ -hostname bchip007+bchip009+ - -#0:hostname bchip007 -#0:port 1952 -#0:stopport 1953 -#0:rx_tcpport 1956 -0:settingsdir /home/l_msdetect/dhanya/slsDetectorsPackage/settingsdir/gotthard -0:angdir 1.000000 -0:moveflag 0.000000 -0:lock 0 -0:caldir /home/l_msdetect/dhanya/slsDetectorsPackage/settingsdir/gotthard -0:ffdir /home/l_msdetect -0:extsig:0 off -0:extsig:1 off -0:extsig:2 off -0:extsig:3 off -#0:detectorip 10.1.1.2 -#0:detectormac 00:aa:bb:cc:dd:ee -#0:rx_udpport 50001 -#0:rx_udpip 10.1.1.1 -#0:rx_hostname 129.129.202.134 -0:outdir /data/speedt -0:vhighvoltage 120 - - -#1:hostname bchip009 -#1:port 1952 -#1:stopport 1953 -1:rx_tcpport 1957 -1:settingsdir /home/l_msdetect/dhanya/slsDetectorsPackage/settingsdir/gotthard -1:angdir 1.000000 -1:moveflag 0.000000 -1:lock 0 -1:caldir /home/l_msdetect/dhanya/slsDetectorsPackage/settingsdir/gotthard -1:ffdir /home/l_msdetect -1:extsig:0 off -1:extsig:1 off -1:extsig:2 off -1:extsig:3 off -#1:detectorip 10.1.2.2 -#1:detectormac 00:aa:bb:cc:dd:ee -#1:rx_udpport 50004 -#1:rx_udpip 10.1.2.1 -#1:rx_hostname 129.129.202.134 -1:outdir /data/speedt -1:vhighvoltage 120 - - -master -1 -sync none -outdir /data/speedt -ffdir /home/l_msdetect -headerbefore none -headerafter none -headerbeforepar none -headerafterpar none -badchannels none -angconv none -globaloff 0.000000 -binsize 0.001000 -threaded 1 From e2ef043e040becea668a8e9301a801b45e46a962 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Fri, 24 May 2019 16:31:25 +0200 Subject: [PATCH 46/76] removed old configure file --- configure | 58 ------------------------------------------------------- 1 file changed, 58 deletions(-) delete mode 100755 configure diff --git a/configure b/configure deleted file mode 100755 index a58728f9f..000000000 --- a/configure +++ /dev/null @@ -1,58 +0,0 @@ -##!/bin/bash - -: ${INSTALLROOT=$PWD} -read -p "Installation directory [default:\"$INSTALLROOT\"]:" -e t3 -if [ -z "$t3" ] -then -echo -else - INSTALLROOT=$t3 -fi -echo "INSTALLROOT will be \"$INSTALLROOT\"" -export INSTALLROOT - -: ${BINDIR="bin"} -read -p "Binaries directory [default:\"$BINDIR\"]:" -e t4 -if [ -z "$t4" ] -then - BINDIR=$INSTALLROOT/$BINDIR -else - BINDIR=$INSTALLROOT/$t4 -fi -echo "BINDIR will be \"$BINDIR\"" -export BINDIR - -: ${LIBDIR="bin"} -read -p "Libraries directory [default:\"$LIBDIR\"]:" -e t5 -if [ -z "$t5" ] -then - LIBDIR=$INSTALLROOT/$LIBDIR -else - LIBDIR=$INSTALLROOT/$t5 -fi -echo "LIBDIR will be \"$LIBDIR\"" -export LIBDIR - -: ${INCDIR="include"} -read -p "Includes directory [default:\"$INCDIR\"]:" -e t6 -if [ -z "$t6" ] -then - INCDIR=$INSTALLROOT/$INCDIR -else - INCDIR=$INSTALLROOT/$t6 -fi -echo "INCDIR will be \"$INCDIR\"" -export INCDIR - -: ${DOCDIR="doc"} -read -p "Documentation directory [default:\"$DOCDIR\"]:" -e t7 -if [ -z "$t7" ] -then - DOCDIR=$INSTALLROOT/$DOCDIR -else - DOCDIR=$INSTALLROOT/$t7 -fi -echo "DOCDIR will be \"$DOCDIR\"" -export DOCDIR - - From 8ebc0f2644e08a1930c32ee027ae005c1da387bb Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Mon, 27 May 2019 11:28:59 +0200 Subject: [PATCH 47/76] uniqe ptr for receiver --- slsReceiverSoftware/include/slsReceiverTCPIPInterface.h | 5 +++-- slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h b/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h index 77ea28485..9a39e1578 100755 --- a/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h +++ b/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h @@ -10,7 +10,8 @@ class MySocketTCP; class ServerInterface; -class slsReceiverImplementation; +// class slsReceiverImplementation; +#include "slsReceiverImplementation.h" #include "ServerSocket.h" @@ -306,7 +307,7 @@ class slsReceiverTCPIPInterface : private virtual slsDetectorDefs { detectorType myDetectorType; /** slsReceiverBase object */ - slsReceiverImplementation *receiver{nullptr}; + std::unique_ptr receiver{nullptr}; /** Function List */ int (slsReceiverTCPIPInterface::*flist[NUM_REC_FUNCTIONS])(sls::ServerInterface2& socket); diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp index 2e3344d2b..076f152b9 100755 --- a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp +++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp @@ -583,7 +583,7 @@ int slsReceiverTCPIPInterface::set_detector_type(sls::ServerInterface2 &socket){ } if(ret == OK) { if(receiver == nullptr){ - receiver = new slsReceiverImplementation(); + receiver = sls::make_unique(); } myDetectorType = arg; ret = receiver->setDetectorType(myDetectorType); From 7fdab08256eacde39bd8bb5047fd0b23d689b36e Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Mon, 27 May 2019 11:30:54 +0200 Subject: [PATCH 48/76] ctb receiver fix: extract in 8 bit batches instead of 32 for less padding --- slsReceiverSoftware/src/DataProcessor.cpp | 24 +++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/slsReceiverSoftware/src/DataProcessor.cpp b/slsReceiverSoftware/src/DataProcessor.cpp index 1b5721083..d115d1fd6 100755 --- a/slsReceiverSoftware/src/DataProcessor.cpp +++ b/slsReceiverSoftware/src/DataProcessor.cpp @@ -515,18 +515,18 @@ void DataProcessor::RearrangeDbitData(char* buf) { const int numSamples = (ctbDigitalDataBytes / sizeof(uint64_t)); const int digOffset = FIFO_HEADER_NUMBYTES + sizeof(sls_receiver_header) + (*ctbAnalogDataBytes); - // ceil as numResult32Bits could be decimal - const int numResult32Bits = ceil((double)(numSamples * (*ctbDbitList).size()) / 32.00); - uint32_t result[numResult32Bits]; - memset(result, 0, numResult32Bits * sizeof(uint32_t)); + // ceil as numResult8Bits could be decimal + const int numResult8Bits = ceil((double)(numSamples * (*ctbDbitList).size()) / 8.00); + uint8_t result[numResult8Bits]; + memset(result, 0, numResult8Bits * sizeof(uint8_t)); + uint8_t* dest = result; - uint32_t* dest = result; auto* source = (uint64_t*)(buf + digOffset + (*ctbDbitOffset)); // loop through digital bit enable vector int bitoffset = 0; for (auto bi : (*ctbDbitList)) { - // where numbits * numsamples is not a multiple of 32 + // where numbits * numsamples is not a multiple of 8 if (bitoffset != 0) { bitoffset = 0; ++dest; @@ -534,12 +534,12 @@ void DataProcessor::RearrangeDbitData(char* buf) { // loop through the frame digital data for (auto ptr = source; ptr < (source + numSamples);) { - // get selected bit from each 32 bit - uint32_t bit = (*ptr++ >> bi) & 1; + // get selected bit from each 8 bit + uint8_t bit = (*ptr++ >> bi) & 1; *dest |= bit << bitoffset; ++bitoffset; - // extract destination in 32 bit batches - if (bitoffset == 32) { + // extract destination in 8 bit batches + if (bitoffset == 8) { bitoffset = 0; ++dest; } @@ -548,8 +548,8 @@ void DataProcessor::RearrangeDbitData(char* buf) { // copy back to buf and update size - memcpy(buf + digOffset, result, numResult32Bits * sizeof(uint32_t)); - (*((uint32_t*)buf)) = numResult32Bits * sizeof(uint32_t); + memcpy(buf + digOffset, result, numResult8Bits * sizeof(uint8_t)); + (*((uint32_t*)buf)) = numResult8Bits * sizeof(uint8_t); } /** eiger specific */ From 54a396065d738a91e19577b827b461e4b2e2ad57 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil <33750417+thattil@users.noreply.github.com> Date: Mon, 27 May 2019 14:08:41 +0200 Subject: [PATCH 49/76] ctb versioning bug fix --- slsSupportLib/include/versionAPI.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/slsSupportLib/include/versionAPI.h b/slsSupportLib/include/versionAPI.h index 689b78438..9624620cb 100644 --- a/slsSupportLib/include/versionAPI.h +++ b/slsSupportLib/include/versionAPI.h @@ -6,6 +6,5 @@ #define APIRECEIVER 0x190405 #define APIGUI 0x190405 #define APIEIGER 0x190516 -#define APICTB 0x190516 - +#define APICTB 0x190514 #define APIJUNGFRAU 0x190517 From e4367c9ab10b3c215f76b6f8066b0fb6a40adbe4 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Mon, 27 May 2019 14:20:40 +0200 Subject: [PATCH 50/76] checking for nullptr --- .../src/slsReceiverTCPIPInterface.cpp | 219 ++++++++++++++---- 1 file changed, 177 insertions(+), 42 deletions(-) diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp index 076f152b9..8041289f4 100755 --- a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp +++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp @@ -111,7 +111,7 @@ void slsReceiverTCPIPInterface::startTCPServer() { while (true) { try { auto socket = server->accept(); - socket.setReceiveTimeout(10000); + socket.setReceiveTimeout(static_cast(5E6)); ret = decode_function(socket); // if tcp command was to exit server @@ -423,6 +423,8 @@ int slsReceiverTCPIPInterface::update_client(sls::ServerInterface2 &socket) { // no arg, check receiver is null socket.receiveArg(ret, mess, nullptr, 0); + if(server == nullptr) + NullObjectError(ret, mess); socket.sendResult(false, ret, nullptr, 0, mess); if (ret == FAIL) @@ -617,9 +619,12 @@ int slsReceiverTCPIPInterface::set_detector_hostname(sls::ServerInterface2 &sock char retval[MAX_STR_LENGTH] = {0}; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, hostname,MAX_STR_LENGTH) == FAIL) + socket.receiveArg(ret, mess, hostname, MAX_STR_LENGTH); + if(server == nullptr){ + NullObjectError(ret, mess); return FAIL; - + } + // base object not null if (ret == OK) { // set @@ -696,8 +701,11 @@ int slsReceiverTCPIPInterface::setup_udp(sls::ServerInterface2 &socket){ char retvals[2][MAX_STR_LENGTH]{}; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, args, sizeof(args)) == FAIL) + socket.receiveArg(ret, mess, args, sizeof(args)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } // base object not null if (ret == OK) { @@ -826,8 +834,11 @@ int slsReceiverTCPIPInterface::set_timer(sls::ServerInterface2 &socket) { int64_t retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, &index, sizeof(index)) == FAIL) + socket.receiveArg(ret, mess, &index, sizeof(index)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } // base object not null if (ret == OK) { @@ -931,8 +942,11 @@ int slsReceiverTCPIPInterface::set_dynamic_range(sls::ServerInterface2 &socket) int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, &dr, sizeof(dr)) == FAIL) + socket.receiveArg(ret, mess, &dr, sizeof(dr)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } // base object not null if (ret == OK) { @@ -986,8 +1000,11 @@ int slsReceiverTCPIPInterface::set_streaming_frequency(sls::ServerInterface2 &so int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, &index, sizeof(index)) == FAIL) + socket.receiveArg(ret, mess, &index, sizeof(index)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } // base object not null if (ret == OK) { @@ -1019,6 +1036,9 @@ int slsReceiverTCPIPInterface::get_status(sls::ServerInterface2 &socket){ // no arg, check receiver is null socket.receiveArg(ret, mess, nullptr, 0); + if(receiver == nullptr){ + NullObjectError(ret, mess); + } if (ret == OK) { FILE_LOG(logDEBUG1) << "Getting Status"; @@ -1038,7 +1058,9 @@ int slsReceiverTCPIPInterface::start_receiver(sls::ServerInterface2 &socket){ // no arg, and check receiver is null socket.receiveArg(ret, mess, nullptr, 0); - + if(receiver == nullptr){ + NullObjectError(ret, mess); + } // receiver is not null if (ret == OK) { // only set @@ -1070,7 +1092,9 @@ int slsReceiverTCPIPInterface::stop_receiver(sls::ServerInterface2 &socket){ // no arg, and check receiver is null socket.receiveArg(ret, mess, nullptr, 0); - + if(receiver == nullptr){ + NullObjectError(ret, mess); + } // receiver is not null if (ret == OK) { // only set @@ -1102,8 +1126,11 @@ int slsReceiverTCPIPInterface::set_file_dir(sls::ServerInterface2 &socket) { char retval[MAX_STR_LENGTH] = {0}; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, fPath, sizeof(fPath)) == FAIL) + socket.receiveArg(ret, mess, fPath, sizeof(fPath)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } // base object not null if (ret == OK) { @@ -1134,8 +1161,11 @@ int slsReceiverTCPIPInterface::set_file_name(sls::ServerInterface2 &socket) { char retval[MAX_STR_LENGTH] = {0}; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, fName, sizeof(fName)) == FAIL) + socket.receiveArg(ret, mess, fName, sizeof(fName)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } // base object not null if (ret == OK) { @@ -1166,8 +1196,11 @@ int slsReceiverTCPIPInterface::set_file_index(sls::ServerInterface2 &socket) { int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, &index, sizeof(index)) == FAIL) + socket.receiveArg(ret, mess, &index, sizeof(index)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } // base object not null if (ret == OK) { @@ -1196,6 +1229,9 @@ int slsReceiverTCPIPInterface::get_frame_index(sls::ServerInterface2 &socket){ // no arg, check receiver is null socket.receiveArg(ret, mess, nullptr, 0); + if(receiver == nullptr){ + NullObjectError(ret, mess); + } if (ret == OK) { FILE_LOG(logDEBUG1) << "Getting frame index"; @@ -1214,6 +1250,9 @@ int slsReceiverTCPIPInterface::get_frames_caught(sls::ServerInterface2 &socket){ // no arg, check receiver is null socket.receiveArg(ret, mess, nullptr, 0); + if(receiver == nullptr){ + NullObjectError(ret, mess); + } if (ret == OK) { FILE_LOG(logDEBUG1) << "Getting frames caught"; @@ -1231,6 +1270,9 @@ int slsReceiverTCPIPInterface::reset_frames_caught(sls::ServerInterface2 &socket // no arg, and check receiver is null socket.receiveArg(ret, mess, nullptr, 0); + if(receiver == nullptr){ + NullObjectError(ret, mess); + } // receiver is not null if (ret == OK) { @@ -1253,8 +1295,11 @@ int slsReceiverTCPIPInterface::enable_file_write(sls::ServerInterface2 &socket){ int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, &enable, sizeof(enable)) == FAIL) + socket.receiveArg(ret, mess, &enable, sizeof(enable)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } // base object not null if (ret == OK) { @@ -1283,8 +1328,11 @@ int slsReceiverTCPIPInterface::enable_master_file_write(sls::ServerInterface2 &s int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, &enable, sizeof(enable)) == FAIL) + socket.receiveArg(ret, mess, &enable, sizeof(enable)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } // base object not null if (ret == OK) { @@ -1312,8 +1360,11 @@ int slsReceiverTCPIPInterface::enable_overwrite(sls::ServerInterface2 &socket) { int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, &index, sizeof(index)) == FAIL) + socket.receiveArg(ret, mess, &index, sizeof(index)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } // base object not null if (ret == OK) { @@ -1342,8 +1393,11 @@ int slsReceiverTCPIPInterface::enable_tengiga(sls::ServerInterface2 &socket) { int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, &val, sizeof(val)) == FAIL) + socket.receiveArg(ret, mess, &val, sizeof(val)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } if (myDetectorType != EIGER && myDetectorType != CHIPTESTBOARD && myDetectorType != MOENCH) functionNotImplemented(); @@ -1375,8 +1429,11 @@ int slsReceiverTCPIPInterface::set_fifo_depth(sls::ServerInterface2 &socket) { int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, &value, sizeof(value)) == FAIL) + socket.receiveArg(ret, mess, &value, sizeof(value)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } // base object not null if (ret == OK) { @@ -1409,8 +1466,11 @@ int slsReceiverTCPIPInterface::set_activate(sls::ServerInterface2 &socket) { int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, &enable, sizeof(enable)) == FAIL) + socket.receiveArg(ret, mess, &enable, sizeof(enable)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } if (myDetectorType != EIGER) functionNotImplemented(); @@ -1442,9 +1502,11 @@ int slsReceiverTCPIPInterface::set_data_stream_enable(sls::ServerInterface2 &soc int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, &index, sizeof(index)) == FAIL) + socket.receiveArg(ret, mess, &index, sizeof(index)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; - + } // base object not null if (ret == OK) { // set @@ -1472,8 +1534,11 @@ int slsReceiverTCPIPInterface::set_streaming_timer(sls::ServerInterface2 &socket int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, &index, sizeof(index)) == FAIL) + socket.receiveArg(ret, mess, &index, sizeof(index)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } // base object not null if (ret == OK) { @@ -1502,8 +1567,11 @@ int slsReceiverTCPIPInterface::set_flipped_data(sls::ServerInterface2 &socket){ int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, args, sizeof(args)) == FAIL) + socket.receiveArg(ret, mess, args, sizeof(args)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } if (myDetectorType != EIGER) functionNotImplemented(); @@ -1535,8 +1603,11 @@ int slsReceiverTCPIPInterface::set_file_format(sls::ServerInterface2 &socket) { fileFormat f = GET_FILE_FORMAT; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, &f, sizeof(f)) == FAIL) + socket.receiveArg(ret, mess, &f, sizeof(f)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } // base object not null if (ret == OK) { @@ -1565,8 +1636,11 @@ int slsReceiverTCPIPInterface::set_detector_posid(sls::ServerInterface2 &socket) int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, &arg, sizeof(arg)) == FAIL) + socket.receiveArg(ret, mess, &arg, sizeof(arg)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } // base object not null if (ret == OK) { @@ -1595,8 +1669,11 @@ int slsReceiverTCPIPInterface::set_multi_detector_size(sls::ServerInterface2 &so int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, arg, sizeof(arg)) == FAIL) + socket.receiveArg(ret, mess, arg, sizeof(arg)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } // base object not null if (ret == OK) { @@ -1630,8 +1707,11 @@ int slsReceiverTCPIPInterface::set_streaming_port(sls::ServerInterface2 &socket) int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, &port, sizeof(port)) == FAIL) + socket.receiveArg(ret, mess, &port, sizeof(port)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } // base object not null if (ret == OK) { @@ -1660,8 +1740,11 @@ int slsReceiverTCPIPInterface::set_streaming_source_ip(sls::ServerInterface2 &so char retval[MAX_STR_LENGTH] = {0}; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, arg, MAX_STR_LENGTH) == FAIL) + socket.receiveArg(ret, mess, arg, MAX_STR_LENGTH); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } // base object not null if (ret == OK) { @@ -1687,8 +1770,11 @@ int slsReceiverTCPIPInterface::set_silent_mode(sls::ServerInterface2 &socket) { int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, &value, sizeof(value)) == FAIL) + socket.receiveArg(ret, mess, &value, sizeof(value)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } // base object not null if (ret == OK) { @@ -1717,8 +1803,11 @@ int slsReceiverTCPIPInterface::enable_gap_pixels(sls::ServerInterface2 &socket) int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, &enable, sizeof(enable)) == FAIL) + socket.receiveArg(ret, mess, &enable, sizeof(enable)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } if (myDetectorType != EIGER) functionNotImplemented(); @@ -1749,6 +1838,9 @@ int slsReceiverTCPIPInterface::restream_stop(sls::ServerInterface2 &socket){ // no arg, and check receiver is null socket.receiveArg(ret, mess, nullptr, 0); + if(receiver == nullptr){ + NullObjectError(ret, mess); + } // receiver is not null if (ret == OK) { @@ -1781,8 +1873,11 @@ int slsReceiverTCPIPInterface::set_additional_json_header(sls::ServerInterface2 char retval[MAX_STR_LENGTH] = {0}; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, arg, sizeof(arg)) == FAIL) + socket.receiveArg(ret, mess, arg, sizeof(arg)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } // base object not null if (ret == OK) { @@ -1808,6 +1903,9 @@ int slsReceiverTCPIPInterface::get_additional_json_header(sls::ServerInterface2 // no arg, check receiver is null socket.receiveArg(ret, mess, nullptr, 0); + if(receiver == nullptr){ + NullObjectError(ret, mess); + } // base object not null if (ret == OK) { @@ -1827,8 +1925,11 @@ int slsReceiverTCPIPInterface::set_udp_socket_buffer_size(sls::ServerInterface2 int64_t retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, &index, sizeof(index)) == FAIL) + socket.receiveArg(ret, mess, &index, sizeof(index)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } // base object not null if (ret == OK) { @@ -1862,6 +1963,9 @@ int slsReceiverTCPIPInterface::get_real_udp_socket_buffer_size(sls::ServerInterf // no arg, check receiver is null socket.receiveArg(ret, mess, nullptr, 0); + if(receiver == nullptr){ + NullObjectError(ret, mess); + } if (ret == OK) { FILE_LOG(logDEBUG1) << "Getting actual UDP buffer size"; @@ -1879,8 +1983,11 @@ int slsReceiverTCPIPInterface::set_frames_per_file(sls::ServerInterface2 &socket int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, &index, sizeof(index)) == FAIL) + socket.receiveArg(ret, mess, &index, sizeof(index)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } // base object not null if (ret == OK) { @@ -1907,8 +2014,10 @@ int slsReceiverTCPIPInterface::check_version_compatibility(sls::ServerInterface2 memset(mess, 0, sizeof(mess)); int64_t arg = -1; // get args, return if socket crashed - if (socket.receiveArg(ret, mess, &arg, sizeof(arg)) == FAIL) + socket.receiveArg(ret, mess, &arg, sizeof(arg)); + if (ret == FAIL) return FAIL; + FILE_LOG(logDEBUG1) << "Checking versioning compatibility with value " << arg; int64_t client_requiredVersion = arg; int64_t rx_apiVersion = APIRECEIVER; @@ -1948,8 +2057,11 @@ int slsReceiverTCPIPInterface::set_discard_policy(sls::ServerInterface2 &socket) int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, &index, sizeof(index)) == FAIL) + socket.receiveArg(ret, mess, &index, sizeof(index)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } // base object not null if (ret == OK) { @@ -1978,8 +2090,11 @@ int slsReceiverTCPIPInterface::set_padding_enable(sls::ServerInterface2 &socket) int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, &index, sizeof(index)) == FAIL) + socket.receiveArg(ret, mess, &index, sizeof(index)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } // base object not null if (ret == OK) { @@ -2009,8 +2124,11 @@ int slsReceiverTCPIPInterface::set_deactivated_padding_enable(sls::ServerInterfa int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, &enable, sizeof(enable)) == FAIL) + socket.receiveArg(ret, mess, &enable, sizeof(enable)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } if (myDetectorType != EIGER) functionNotImplemented(); @@ -2040,8 +2158,11 @@ int slsReceiverTCPIPInterface::set_readout_flags(sls::ServerInterface2 &socket) readOutFlags retval = GET_READOUT_FLAGS; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, &arg, sizeof(arg)) == FAIL) + socket.receiveArg(ret, mess, &arg, sizeof(arg)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } if (myDetectorType == JUNGFRAU || myDetectorType == GOTTHARD || myDetectorType == MOENCH) functionNotImplemented(); @@ -2073,11 +2194,14 @@ int slsReceiverTCPIPInterface::set_adc_mask(sls::ServerInterface2 &socket) { uint32_t retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, &arg, sizeof(arg)) == FAIL) + socket.receiveArg(ret, mess, &arg, sizeof(arg)); + if(receiver == nullptr){ + NullObjectError(ret, mess); return FAIL; + } // base object not null - else if (ret == OK) { + if (ret == OK) { if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting ADC enable mask: " << arg; receiver->setADCEnableMask(arg); @@ -2098,7 +2222,11 @@ int slsReceiverTCPIPInterface::set_dbit_list(sls::ServerInterface2 &socket) { memset(mess, 0, sizeof(mess)); sls::FixedCapacityContainer args; if (socket.receiveArg(ret, mess, &args, sizeof(args)) == FAIL) { - return FAIL; + if(receiver == nullptr){ + NullObjectError(ret, mess); + } + return FAIL; + } else if (ret == OK) { FILE_LOG(logDEBUG1) << "Setting DBIT list"; for (auto &it : args) { @@ -2124,7 +2252,9 @@ int slsReceiverTCPIPInterface::get_dbit_list(sls::ServerInterface2 &socket) { // no arg, check receiver is null socket.receiveArg(ret, mess, nullptr, 0); - + if(receiver == nullptr){ + NullObjectError(ret, mess); + } // base object not null if (ret == OK) { retval = receiver->getDbitList(); @@ -2141,8 +2271,13 @@ int slsReceiverTCPIPInterface::set_dbit_offset(sls::ServerInterface2 &socket) { int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (socket.receiveArg(ret, mess, &arg, sizeof(arg)) == FAIL) + if (socket.receiveArg(ret, mess, &arg, sizeof(arg)) == FAIL){ + if(receiver == nullptr){ + NullObjectError(ret, mess); + } return FAIL; + } + // base object not null else if (ret == OK) { From d3646f0ac5115d987ad4c75e2a5d41486a9c8b14 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Mon, 27 May 2019 14:33:17 +0200 Subject: [PATCH 51/76] pinned conda-build version --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0bbc8d6bf..81b60efea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,7 +25,8 @@ install: - conda config --add channels slsdetectorgroup - conda update conda - conda update --all - - conda install conda-build anaconda-client + - conda install conda-build=3.17 + - conda install anaconda-client - conda install conda-verify # Useful for debugging any issues with conda From 2c2fb7358c6efa6b7cd588e2ff5d5a44d4cb34c2 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Mon, 27 May 2019 15:04:13 +0200 Subject: [PATCH 52/76] jungfrau board 2 adc defines, full speed limitation for old boards --- .../jungfrauDetectorServer/RegisterDefs.h | 32 +++-------- .../bin/jungfrauDetectorServer_developer | Bin 120136 -> 120584 bytes .../slsDetectorFunctionList.c | 53 +++++++++++++++--- .../slsDetectorServer_defs.h | 20 ++++--- .../slsDetectorFunctionList.h | 1 + .../slsDetectorServer_funcs.c | 7 +++ slsSupportLib/include/versionAPI.h | 2 +- 7 files changed, 73 insertions(+), 42 deletions(-) diff --git a/slsDetectorServers/jungfrauDetectorServer/RegisterDefs.h b/slsDetectorServers/jungfrauDetectorServer/RegisterDefs.h index e25b1942f..948fb9fe0 100755 --- a/slsDetectorServers/jungfrauDetectorServer/RegisterDefs.h +++ b/slsDetectorServers/jungfrauDetectorServer/RegisterDefs.h @@ -303,10 +303,9 @@ #define SAMPLE_DGTL_DECMT_FACTOR_OFST (12) #define SAMPLE_DGTL_DECMT_FACTOR_MSK (0x00000003 << SAMPLE_DGTL_DECMT_FACTOR_OFST) -// 1 = full speed, 2 = half speed, 4 = quarter speed -#define SAMPLE_DECMT_FACTOR_1_VAL ((0x0 << SAMPLE_DGTL_DECMT_FACTOR_OFST) & SAMPLE_DGTL_DECMT_FACTOR_MSK) -#define SAMPLE_DECMT_FACTOR_2_VAL ((0x1 << SAMPLE_DGTL_DECMT_FACTOR_OFST) & SAMPLE_DGTL_DECMT_FACTOR_MSK) -#define SAMPLE_DECMT_FACTOR_4_VAL ((0x2 << SAMPLE_DGTL_DECMT_FACTOR_OFST) & SAMPLE_DGTL_DECMT_FACTOR_MSK) +#define SAMPLE_DECMT_FACTOR_FULL_VAL ((0x0 << SAMPLE_DGTL_DECMT_FACTOR_OFST) & SAMPLE_DGTL_DECMT_FACTOR_MSK) +#define SAMPLE_DECMT_FACTOR_HALF_VAL ((0x1 << SAMPLE_DGTL_DECMT_FACTOR_OFST) & SAMPLE_DGTL_DECMT_FACTOR_MSK) +#define SAMPLE_DECMT_FACTOR_QUARTER_VAL ((0x2 << SAMPLE_DGTL_DECMT_FACTOR_OFST) & SAMPLE_DGTL_DECMT_FACTOR_MSK) /** Vref Comp Mod Register */ #define VREF_COMP_MOD_REG (0x5C << MEM_MAP_SHIFT) @@ -393,45 +392,30 @@ #define SET_TRIGGER_DELAY_LSB_REG (0x70 << MEM_MAP_SHIFT) #define SET_TRIGGER_DELAY_MSB_REG (0x71 << MEM_MAP_SHIFT) -/* Module Coordinates Register 0 */ -#define COORD_0_REG (0x7C << MEM_MAP_SHIFT) - -#define COORD_0_Y_OFST (0) -#define COORD_0_Y_MSK (0x0000FFFF << COORD_0_Y_OFST) -#define COORD_0_X_OFST (16) -#define COORD_0_X_MSK (0x0000FFFF << COORD_0_X_OFST) - -/* Module Coordinates Register 1 */ -#define COORD_1_REG (0x7D << MEM_MAP_SHIFT) - -#define COORD_0_Z_OFST (0) -#define COORD_0_Z_MSK (0x0000FFFF << COORD_0_Z_OFST) - /** Module row coordinates */ -/*#define COORD_ROW_REG (0x7C << MEM_MAP_SHIFT) +#define COORD_ROW_REG (0x7C << MEM_MAP_SHIFT) #define COORD_ROW_OUTER_OFST (0) #define COORD_ROW_OUTER_MSK (0x0000FFFF << COORD_ROW_OUTER_OFST) #define COORD_ROW_INNER_OFST (16) #define COORD_ROW_INNER_MSK (0x0000FFFF << COORD_ROW_INNER_OFST) -*/ + /** Module column coordinates */ -/*#define COORD_COL_REG (0x7D << MEM_MAP_SHIFT) +#define COORD_COL_REG (0x7D << MEM_MAP_SHIFT) #define COORD_COL_OUTER_OFST (0) #define COORD_COL_OUTER_MSK (0x0000FFFF << COORD_COL_OUTER_OFST) #define COORD_COL_INNER_OFST (16) #define COORD_COL_INNER_MSK (0x0000FFFF << COORD_COL_INNER_OFST) -*/ + /** Module column coordinates */ -/*#define COORD_RESERVED_REG (0x7E << MEM_MAP_SHIFT) +#define COORD_RESERVED_REG (0x7E << MEM_MAP_SHIFT) #define COORD_RESERVED_OUTER_OFST (0) #define COORD_RESERVED_OUTER_MSK (0x0000FFFF << COORD_RESERVED_OUTER_OFST) #define COORD_RESERVED_INNER_OFST (16) #define COORD_RESERVED_INNER_MSK (0x0000FFFF << COORD_RESERVED_INNER_OFST) -*/ /* ASIC Control Register */ #define ASIC_CTRL_REG (0x7F << MEM_MAP_SHIFT) diff --git a/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer b/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer index 4ed0aa93cc99c6c020c29704c1b22141716868f5..565e857f338f5b9b2421888657b78e5d84159811 100755 GIT binary patch delta 47076 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 {F~9H#AII>A>=6Di74vZ!Zoj|NH8Dw^4@oi$ zmtg^3!<*QJmE9grcxb~5cnP;-6^bhp@uzQqNpe3X;kbL^$(Rh88j>M7I1}f@BvVBG zCnE9@Js}x!F(#A6p_A{$G>*u@3j)Nfh7yI42}Oo`JJMW%6SN{5b8!8a??mB$*dtGD`)sCg3VuEwnd8eTJy- zF+LIE8_Tb!3+c`BhwU->zH;CHOxoB#?2x`7eO20=dDtm^N&31Q-61!+WqTdv*#bQ)2U%~v(P{m7Tg|K9{sMn-TnY1b8Qpzo@ z4q<6+3@>g7;l)x7%vb*cG~2&xRs6u@{=q2q*kSYSu=#&tmgV16pj?59raNbnx=Bm) zc8T7m3RGGsp!{4w`Gt5;W1Ehhtv{Pw9a6d2Y+G!0E*_2}(5zc*)-7hqVwNn)QprTL zV=b{`ExChtReDLKT(vZVrJ2Z;OQ)jQz0~Y}v5FzpcmmDt!imD>$+!lK@C=@_ZVS6T z^oXM;iKCyzT%3ct{IV{;yc26;SjEs)4E?Ef_fzXGT^d5V9IxSx82)}<2!Ef4ZP*^e z>d7Ij&PFa@&E@|vGK7B^gAI5n`ad6ie2CWVn(ZE{P|w!r+0SN#@UxlNj4kN>&%9r& z#M&afj8|fKg`ux7^p#_HB8DQKDB_7Ch7~cas0+K@19W7aj;uR^N3kCV+y}P04^(dR zaKXbR7lH*Y1dDJj7ULs)Y}{C0!t#eGtfs!XK218sBreY3i=v57^&+>O1 zCSo<#Vh>()ap0NPc;>YZ=k{xzE)HC}flD{&=>|RB$RithWFyyZ*?!La2lp@4O%v@pLD^{aH)n%>#+fOtdz&z;ITJ&?2QxH=Av;j{7u+=%Ee)! zi$gvdt8!yiK7fNUY?&9r7Gt`Fi??v`mV5XhhOLDmY)v<1f0F#9lCw^7R+~E8)cL_! zNBIQI#;N!`&O%jvpsEj2xE$I10h>QqkDKr?9*JRiozJZMVi>RQyFohRRWEZ;Esec>531&fiVMjgTT@D@6+Mo*C6@1ws!>2c1VaSR*B1LK|^eB&Kh z;~iMzog?F&BjYtN{$>pS`@}&vDkftKLo${DQ*(#Lo!vxKeDa= z=(Cti|1u=gHSm+Fko=@RCVw?AB!6YBGiNzY<~v5lIz}eP|C z7*fTM9h0TAQ3E?PQ1!_B$I>~{GjJ!?#PD_q;q54$D{bNLVE7J(zs=CM8M-4+dZDxi z-_DXgBYh5g@S?rBise*%gI@>S0BaKOW18K=wm zJQ|W3L-Njm0)q;0T{YM3S|HydWbiHq*XVJL9@iMw8pB#0<+DrdTITlxJdP*5x3^c@ z+jrfRzU5*+(ZznU`}-t&bFI}}tKnJ=*H&Y#0y0#~P;IQLjaBtkypB9k%@ftFcno{- zwu?W{?B4B5?)-F^7ThX5U^(~;eWq?@J9tvYk7jwkAPVt1=M)ovBljqqX=8sj=+ zyt_?-c4@AzRHScMF! zW5}L7;K#)gA@*D6p4>ds(=*0=Ii# z?tKLs!#&2Zp2zBWtlr$HH#h1#u+#5Vey>)}nC~^_dl@y3zIj~2>v+?rj2xdbX5f5WfNQZBx%gc!K47d580&+E=AfZD$iRaP zJoo_neW~DqMjmMV67Ty$;rGLSKcJlh+Bujh-$?8KAd3&O_~4+8CfIQ9W1oWS72Jg8 zM58%zSiZyZ9X^St+>iIUA0NOYc+{5#h8<Nc6a9`KFc?Cs~;{)qy16+KkZ!+sp_ z{#oy*NHg>yLmy@Nb}wJwRA*$4GtikgwA@)|-yUY)9<~!JYh*YogR^Mp4jFdhpdW@f z61F=Ms_-cKeVm)ZxJ!;61;^Jo417w@S}xrxeay!14mRO{Gi|0bE!SD5q0t%|Ejk#z z8S8K#I*LX+ipJ-KS9YZKRSal#Q51_{HbWdFEQa$ z@~7la&BEDY{25~Wna-*XXH}`Lq~*yBOXckiLy~#PIoI_+{9MU1E3>ezgg|x)qO!;U|jWCu0k?3f#~ZsNYS3=6OudxYkNLi02}z?glTsF!GWZQ1dV`1F=)g{~yOp`w z$}BGssuyA_9uuNRA$kU?XN!8av||Sj;GkHgC_EFkmYhxhSF(9X<$+svoX>4ASvH!9 zI2-3;A*NAl2eo$a8s4zsw@#=&^*ecg_NIBnap42p@0f0O>3wqBl&-as6He4yNIn+LEUtbdNPtc%)8_FOzCFN z%H&mh-cD8Y^tqNAsD+Nv32LKu>Y&a_e{|7hx}Z$x2gK!>QASeDvA%A}M@DU(trrA$hh%9KJWg;ENo z6iO+SdRnNJj!_$(piXM1j*Mh!A*E>z6;TOkWT{4$YGkQKmiEv^x=dH-8r`7YjAVtn zR&-IfnYcp66*8`nafOU4WLzQRil-TG(;d1?_viuj(*O--Br5|&%AiadNnJAD$}Y?t2(Xfw5rppO)HX?Ev=cfCeoTnYa*?Qv?kJ;NNXak ziL@rts!yvvt@?G#sDKJ7O>3x#N=RGlw6#uK>$J6QyFpl|@H&OpJuR%!b!;nEd9lii zRbI@PVtGpM&|Mm!do)N7s6Qhqldnv^GWp8XRi>V@+vN8$^_Ho#tebl1B3-5{bj=`? z-Jo95K$!;0RK6umMN~qi#NsU#R86&{S6epFcB;xq-i(w*6KOJK(^Sf!Od3gJGLots zT1fdcgDP|VF^@D>r9f37X}n4URdZ+=&7?dkAdOblQav%OicwVzs5(Z?)IzPaof?SY zRn>HeO6UZ2(`CA25mw#s&`Y#1by62yq$|`$?e-6ao8)QozDXrb$~4K_ByS^w z8a3Rg!Nzi`B6T-bWF&_t($n9RZB(vNosHKrUQ7J%b4jDh4oAwQku-*~C_}{q8A)?C oEu<2vr4yur=E02Q7n3QUH28}{)IsX}g>pwUdPKP+8>r#`09|xVUH||9 diff --git a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c index 463bea38d..6922261ef 100755 --- a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c @@ -997,6 +997,11 @@ void setNumberofUDPInterfaces(int val) { } } +int getNumberofUDPInterfaces() { + // return 2 if enabled, else 1 + return ((bus_r(CONFIG_REG) | CONFIG_OPRTN_MDE_2_X_10GbE_MSK) ? 2 : 1); +} + void selectPrimaryInterface(int val) { uint32_t addr = CONFIG_REG; @@ -1169,20 +1174,50 @@ int configureMAC(int numInterfaces, int selInterface, int setDetectorPosition(int pos[]) { int ret = OK; - FILE_LOG(logDEBUG1, ("Setting detector position: (%d, %d)\n", pos[X], pos[Y])); + int innerPos[2] = {pos[X], pos[Y]}; + int outerPos[2] = {pos[X], pos[Y]}; + int numInterfaces = getNumberofUDPInterfaces(); - bus_w(COORD_0_REG, bus_r(COORD_0_REG) & (~(COORD_0_X_MSK))); - bus_w(COORD_0_REG, bus_r(COORD_0_REG) | ((pos[X] << COORD_0_X_OFST) & COORD_0_X_MSK)); - if ((bus_r(COORD_0_REG) & COORD_0_X_MSK) != ((pos[X] << COORD_0_X_OFST) & COORD_0_X_MSK)) + if (numInterfaces == 1) { + FILE_LOG(logDEBUG1, ("Setting detector position: (%d, %d)\n", innerPos[X], innerPos[Y])); + } + else { + ++outerPos[X]; + FILE_LOG(logDEBUG1, ("Setting detector position:\n" + " inner top(%d, %d), outer bottom(%d, %d)\n" + , innerPos[X], innerPos[Y], outerPos[X], outerPos[Y])); + } + + // row + //outer + uint32_t addr = COORD_ROW_REG; + bus_w(addr, (bus_r(addr) &~COORD_ROW_OUTER_MSK) | ((outerPos[X] << COORD_ROW_OUTER_OFST) & COORD_ROW_OUTER_MSK)); + if (((bus_r(addr) & COORD_ROW_OUTER_MSK) >> COORD_ROW_OUTER_OFST) != outerPos[X]) + ret = FAIL; + // inner + bus_w(addr, (bus_r(addr) &~COORD_ROW_INNER_MSK) | ((innerPos[X] << COORD_ROW_INNER_OFST) & COORD_ROW_INNER_MSK)); + if (((bus_r(addr) & COORD_ROW_INNER_MSK) >> COORD_ROW_INNER_OFST) != innerPos[X]) ret = FAIL; - bus_w(COORD_0_REG, bus_r(COORD_0_REG) & (~(COORD_0_Y_MSK))); - bus_w(COORD_0_REG, bus_r(COORD_0_REG) | ((pos[Y] << COORD_0_Y_OFST) & COORD_0_Y_MSK)); - if ((bus_r(COORD_0_REG) & COORD_0_Y_MSK) != ((pos[Y] << COORD_0_Y_OFST) & COORD_0_Y_MSK)) + // col + //outer + addr = COORD_COL_REG; + bus_w(addr, (bus_r(addr) &~COORD_COL_OUTER_MSK) | ((outerPos[Y] << COORD_COL_OUTER_OFST) & COORD_COL_OUTER_MSK)); + if (((bus_r(addr) & COORD_COL_OUTER_MSK) >> COORD_COL_OUTER_OFST) != outerPos[Y]) + ret = FAIL; + // inner + bus_w(addr, (bus_r(addr) &~COORD_COL_INNER_MSK) | ((innerPos[Y] << COORD_COL_INNER_OFST) & COORD_COL_INNER_MSK)); + if (((bus_r(addr) & COORD_COL_INNER_MSK) >> COORD_COL_INNER_OFST) != innerPos[Y]) ret = FAIL; if (ret == OK) { - FILE_LOG(logINFO, ("Position set to [%d, %d]\n", pos[X], pos[Y])); + if (numInterfaces == 1) { + FILE_LOG(logINFO, ("Position set to [%d, %d]\n", innerPos[X], innerPos[Y])); + } + else { + FILE_LOG(logINFO, (" Inner (top) position set to [%d, %d]\n", innerPos[X], innerPos[Y])); + FILE_LOG(logINFO, (" Outer (bottom) position set to [%d, %d]\n", outerPos[X], outerPos[Y])); + } } return ret; } @@ -1384,6 +1419,8 @@ void setAdcPhase(int val, int degrees){ ALTERA_PLL_SetPhaseShift(phase, 1, 0); adcPhase = valShift; + + alignDeserializer(); } int getPhase(degrees) { diff --git a/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_defs.h b/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_defs.h index 18ab6eb82..98cdbe596 100755 --- a/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_defs.h +++ b/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_defs.h @@ -88,17 +88,19 @@ enum NETWORKINDEX { TXN_FRAME, FLOWCTRL_10G }; #define MAX_STORAGE_CELL_DLY_NS_VAL ((ASIC_CTRL_EXPSRE_TMR_MSK >> ASIC_CTRL_EXPSRE_TMR_OFST) * ASIC_CTRL_EXPSRE_TMR_STEPS) #define ACQ_TIME_MIN_CLOCK (2) -#define SAMPLE_ADC_FULL_SPEED (SAMPLE_ADC_HALF_SPEED) -#define SAMPLE_ADC_HALF_SPEED (SAMPLE_DECMT_FACTOR_2_VAL + SAMPLE_DGTL_SAMPLE_0_VAL + SAMPLE_ADC_DECMT_FACTOR_0_VAL + SAMPLE_ADC_SAMPLE_0_VAL) /* 0x1000 */ -#define SAMPLE_ADC_QUARTER_SPEED (SAMPLE_DECMT_FACTOR_4_VAL + SAMPLE_DGTL_SAMPLE_8_VAL + SAMPLE_ADC_DECMT_FACTOR_1_VAL + SAMPLE_ADC_SAMPLE_0_VAL) /* 0x2810 */ +#define BOARD_VERSION_2_VAL (0x3F) -#define ADC_OFST_FULL_SPEED_VAL (0x20)//(0x1f) //(0x20) -#define ADC_OFST_HALF_SPEED_VAL (0x20)//(0x1f) //(0x20) -#define ADC_OFST_QUARTER_SPEED_VAL (0x0f) //(0x0f) +#define SAMPLE_ADC_FULL_SPEED (SAMPLE_ADC_SAMPLE_0_VAL + SAMPLE_ADC_DECMT_FACTOR_0_VAL + SAMPLE_DGTL_SAMPLE_3_VAL + SAMPLE_DECMT_FACTOR_FULL_VAL) // 0x300 +#define SAMPLE_ADC_HALF_SPEED (SAMPLE_ADC_SAMPLE_0_VAL + SAMPLE_ADC_DECMT_FACTOR_1_VAL + SAMPLE_DGTL_SAMPLE_6_VAL + SAMPLE_DECMT_FACTOR_HALF_VAL) // 0x1610 +#define SAMPLE_ADC_QUARTER_SPEED (SAMPLE_ADC_SAMPLE_0_VAL + SAMPLE_ADC_DECMT_FACTOR_3_VAL + SAMPLE_DGTL_SAMPLE_14_VAL + SAMPLE_DECMT_FACTOR_QUARTER_VAL) // 0x2e30 -#define ADC_PHASE_FULL_SPEED (0x2D) //45 -#define ADC_PHASE_HALF_SPEED (0x2D) //45 -#define ADC_PHASE_QUARTER_SPEED (0x2D) //45 +#define ADC_OFST_FULL_SPEED_VAL (0xF) +#define ADC_OFST_HALF_SPEED_VAL (0xB) +#define ADC_OFST_QUARTER_SPEED_VAL (0x7) + +#define ADC_PHASE_FULL_SPEED (0x1E) //30 +#define ADC_PHASE_HALF_SPEED (0x1E) //30 +#define ADC_PHASE_QUARTER_SPEED (0x1E) //30 #define ADC_PORT_INVERT_VAL (0x5A5A5A5A)//(0x453b2a9c) #define MAX_PHASE_SHIFTS (160) diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h b/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h index c18fec0dc..85eef8e34 100755 --- a/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h +++ b/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h @@ -216,6 +216,7 @@ int getExtSignal(); void calcChecksum(mac_conf* mac, int sourceip, int destip); #elif JUNGFRAUD void setNumberofUDPInterfaces(int val); +int getNumberofUDPInterfaces(); void selectPrimaryInterface(int val); void setupHeader(int iRxEntry, enum interfaceType type, uint32_t destip, uint64_t destmac, uint32_t destport, uint64_t sourcemac, uint32_t sourceip, uint32_t sourceport); void calcChecksum(udp_header* udp); diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c index 3689a6061..a9e2736fd 100755 --- a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c +++ b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c @@ -2007,6 +2007,13 @@ int set_speed(int file_des) { FILE_LOG(logERROR,(mess)); } #endif +#ifdef JUNGFRAUD + if (ret == OK && ind == CLOCK_DIVIDER && val == FULL_SPEED && getHardwareVersionNumber() != BOARD_VERSION_2_VAL) { + ret = FAIL; + strcpy(mess, "Full speed not implemented for this board version.\n"); + FILE_LOG(logERROR,(mess)); + } +#endif if (ret == OK) { // set diff --git a/slsSupportLib/include/versionAPI.h b/slsSupportLib/include/versionAPI.h index 689b78438..c0d8472a4 100644 --- a/slsSupportLib/include/versionAPI.h +++ b/slsSupportLib/include/versionAPI.h @@ -8,4 +8,4 @@ #define APIEIGER 0x190516 #define APICTB 0x190516 -#define APIJUNGFRAU 0x190517 +#define APIJUNGFRAU 0x190527 From 7e43472b7b7907a6f8bdfd2c6656a532695e6edf Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Mon, 27 May 2019 16:29:56 +0200 Subject: [PATCH 53/76] minor help editing --- slsDetectorSoftware/src/slsDetectorCommand.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/slsDetectorSoftware/src/slsDetectorCommand.cpp b/slsDetectorSoftware/src/slsDetectorCommand.cpp index 34923a256..e19bfc67c 100755 --- a/slsDetectorSoftware/src/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp @@ -1665,7 +1665,7 @@ slsDetectorCommand::slsDetectorCommand(multiSlsDetector *det) { ++i; /*! \page network - - selinterface [n] sets/gets the 1st or the 2nd interface to use to stream data out of the detector. Options: 1, 2. Effective only when \c numinterfaces is 1. JUNGFRAU only. \c Returns \c (int) + - selinterface [n] sets/gets the 1st (inner) or the 2nd (outer) interface to use to stream data out of the detector. Options: 1, 2. Effective only when \c numinterfaces is 1. JUNGFRAU only. \c Returns \c (int) */ descrToFuncMap[i].m_pFuncName = "selinterface"; descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdNetworkParameter; @@ -3065,7 +3065,7 @@ std::string slsDetectorCommand::helpNetworkParameter(int action) { os << "rx_udpport port \n sets receiver udp port to port" << std::endl; os << "rx_udpport2 port \n sets receiver udp port to port. For Eiger and Jungfrau, it is the second half module and for other detectors, same as rx_udpport" << std::endl; os << "numinterfaces n \n sets the number of interfaces to n used to stream out from the detector. Options: 1, 2. JUNGFRAU only. " << std::endl; - os << "selinterface n \n sets the 1st or the 2nd interface to use to stream data out of the detector. Options: 1, 2. Effective only when numinterfaces is 1. JUNGFRAU only. " << std::endl; + os << "selinterface n \n sets the 1st (inner) or the 2nd (outer) interface to use to stream data out of the detector. Options: 1, 2. Effective only when numinterfaces is 1. JUNGFRAU only. " << std::endl; os << "txndelay_left port \n sets detector transmission delay of the left port" << std::endl; os << "txndelay_right port \n sets detector transmission delay of the right port" << std::endl; os << "txndelay_frame port \n sets detector transmission delay of the entire frame" << std::endl; From 14dd753397b578af4081afe5ff958196a413f687 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Mon, 27 May 2019 16:59:42 +0200 Subject: [PATCH 54/76] updated build nr --- conda-recepie/meta.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conda-recepie/meta.yaml b/conda-recepie/meta.yaml index c929d0122..68077a462 100755 --- a/conda-recepie/meta.yaml +++ b/conda-recepie/meta.yaml @@ -7,7 +7,7 @@ source: - path: .. build: - number: 0 + number: 1 rpaths: - lib/ From a0f697ce71aa72d2d856771f5f4f673a0a2d2414 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Tue, 28 May 2019 10:31:36 +0200 Subject: [PATCH 55/76] jungfrau feature change: outer is default and connects to bottom, inner is secondary but connects to top --- .../bin/jungfrauDetectorServer_developer | Bin 120584 -> 120820 bytes .../slsDetectorFunctionList.c | 40 ++++++++++++------ slsDetectorSoftware/src/slsDetector.cpp | 22 ++++------ .../src/slsDetectorCommand.cpp | 28 ++++++------ .../src/slsReceiverTCPIPInterface.cpp | 29 +++---------- slsSupportLib/include/versionAPI.h | 2 +- 6 files changed, 57 insertions(+), 64 deletions(-) diff --git a/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer b/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer index 565e857f338f5b9b2421888657b78e5d84159811..9c684a8a49f44a07c2e8c1637e3944d9200c632b 100755 GIT binary patch delta 37749 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%0DS0Z-xcu}|Tc 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 delta 37346 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 XV#2u^+A-#wx;c~1shc~FVZP#j6;ObG diff --git a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c index 6922261ef..8934cb5a3 100755 --- a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c @@ -1005,16 +1005,16 @@ int getNumberofUDPInterfaces() { void selectPrimaryInterface(int val) { uint32_t addr = CONFIG_REG; - // inner (user input: 1) - if (val == 1) { - FILE_LOG(logINFOBLUE, ("Setting Primary Interface: 1 (Inner)\n")); - bus_w(addr, bus_r(addr) | CONFIG_INNR_PRIMRY_INTRFCE_MSK); - } - // outer (user input: 2) - else { - FILE_LOG(logINFOBLUE, ("Setting Primary Interface: 2 (Outer)\n")); + // inner (user input: 0) + if (val == 0) { + FILE_LOG(logINFOBLUE, ("Setting Primary Interface: 0 (Outer)\n")); bus_w(addr, bus_r(addr) &~ CONFIG_INNR_PRIMRY_INTRFCE_MSK); } + // outer (user input: 1) + else { + FILE_LOG(logINFOBLUE, ("Setting Secondary Interface: 1 (Inner)\n")); + bus_w(addr, bus_r(addr) | CONFIG_INNR_PRIMRY_INTRFCE_MSK); + } } void setupHeader(int iRxEntry, enum interfaceType type, uint32_t destip, uint64_t destmac, uint32_t destport, uint64_t sourcemac, uint32_t sourceip, uint32_t sourceport) { @@ -1104,7 +1104,7 @@ int configureMAC(int numInterfaces, int selInterface, FILE_LOG(logINFO, ("\t#Interfaces : %d\n", numInterfaces)); FILE_LOG(logINFO, ("\tInterface : %d\n\n", selInterface)); - FILE_LOG(logINFO, ("\tInner\n")); + FILE_LOG(logINFO, ("\tOuter %s\n", (numInterfaces == 2) ? "(Bottom)": "")); FILE_LOG(logINFO, ("\tSource IP : %d.%d.%d.%d \t\t(0x%08x)\n", (sourceip>>24)&0xff,(sourceip>>16)&0xff,(sourceip>>8)&0xff,(sourceip)&0xff, sourceip)); FILE_LOG(logINFO, ("\tSource MAC : %02x:%02x:%02x:%02x:%02x:%02x \t(0x%010llx)\n", @@ -1130,7 +1130,7 @@ int configureMAC(int numInterfaces, int selInterface, FILE_LOG(logINFO, ("\tDest. Port : %d \t\t\t(0x%08x)\n\n",udpport, udpport)); uint32_t sourceport2 = DEFAULT_TX_UDP_PORT + 1; - FILE_LOG(logINFO, ("\tOuter\n")); + FILE_LOG(logINFO, ("\tInner %s\n", (numInterfaces == 2) ? "(Top)": "Not used")); FILE_LOG(logINFO, ("\tSource IP2 : %d.%d.%d.%d \t\t(0x%08x)\n", (sourceip2>>24)&0xff,(sourceip2>>16)&0xff,(sourceip2>>8)&0xff,(sourceip2)&0xff, sourceip2)); FILE_LOG(logINFO, ("\tSource MAC2 : %02x:%02x:%02x:%02x:%02x:%02x \t(0x%010llx)\n", @@ -1157,10 +1157,22 @@ int configureMAC(int numInterfaces, int selInterface, // default one rxr entry (others not yet implemented in client yet) int iRxEntry = 0; - // top - setupHeader(iRxEntry, INNER, destip, destmac, udpport, sourcemac, sourceip, sourceport); - // bottom - setupHeader(iRxEntry, OUTER, destip2, destmac2, udpport2, sourcemac2, sourceip2, sourceport2); + + if (numInterfaces == 2) { + // bottom + setupHeader(iRxEntry, OUTER, destip, destmac, udpport, sourcemac, sourceip, sourceport); + // top + setupHeader(iRxEntry, INNER, destip2, destmac2, udpport2, sourcemac2, sourceip2, sourceport2); + } + // single interface + else { + // default + if (selInterface == 0) { + setupHeader(iRxEntry, OUTER, destip, destmac, udpport, sourcemac, sourceip, sourceport); + } else { + setupHeader(iRxEntry, INNER, destip, destmac, udpport, sourcemac, sourceip, sourceport); + } + } setNumberofUDPInterfaces(numInterfaces); selectPrimaryInterface(selInterface); diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index 58ebf45e1..7215bd856 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -338,7 +338,7 @@ void slsDetector::initializeDetectorStructure(detectorType type) { shm()->detectorIP2 = DEFAULT_DET_MAC2; shm()->numUDPInterfaces = 1; - shm()->selectedUDPInterface = 1; + shm()->selectedUDPInterface = 0; shm()->rxOnlineFlag = OFFLINE_FLAG; shm()->tenGigaEnable = 0; shm()->flippedData[X] = 0; @@ -2092,7 +2092,7 @@ int slsDetector::selectUDPInterface(int n) { if (shm()->myDetectorType != JUNGFRAU) { throw RuntimeError("Cannot select an interface for this detector"); } - shm()->selectedUDPInterface = (n > 1 ? 2 : 1); + shm()->selectedUDPInterface = (n == 0 ? 0 : 1); if (strcmp(shm()->rxHostname, "none") == 0) { FILE_LOG(logDEBUG1) << "Receiver hostname not set yet"; } else if (setUDPConnection() == FAIL) { @@ -2349,7 +2349,7 @@ int64_t slsDetector::getReceiverRealUDPSocketBufferSize() { int slsDetector::setUDPConnection() { int ret = FAIL; - char args[6][MAX_STR_LENGTH]{}; + char args[5][MAX_STR_LENGTH]{}; char retvals[2][MAX_STR_LENGTH]{}; FILE_LOG(logDEBUG1) << "Setting UDP Connection"; @@ -2366,9 +2366,8 @@ int slsDetector::setUDPConnection() { shm()->rxUDPIP = HostnameToIp(shm()->rxHostname); } } - // jungfrau 2 interfaces or (1 interface and 2nd interface), copy udpip if - // udpip2 empty - if (shm()->numUDPInterfaces == 2 || shm()->selectedUDPInterface == 2) { + // jungfrau 2 interfaces, copy udpip if udpip2 empty + if (shm()->numUDPInterfaces == 2) { if (shm()->rxUDPIP2 == 0) { shm()->rxUDPIP2 = shm()->rxUDPIP; } @@ -2376,15 +2375,12 @@ int slsDetector::setUDPConnection() { // copy arguments to args[][] snprintf(args[0], sizeof(args[0]), "%d", shm()->numUDPInterfaces); - snprintf(args[1], sizeof(args[1]), "%d", shm()->selectedUDPInterface); - sls::strcpy_safe(args[2], getReceiverUDPIP().str()); - sls::strcpy_safe(args[3], getReceiverUDPIP2().str()); - snprintf(args[4], sizeof(args[4]), "%d", shm()->rxUDPPort); - snprintf(args[5], sizeof(args[5]), "%d", shm()->rxUDPPort2); + sls::strcpy_safe(args[1], getReceiverUDPIP().str()); + sls::strcpy_safe(args[2], getReceiverUDPIP2().str()); + snprintf(args[3], sizeof(args[3]), "%d", shm()->rxUDPPort); + snprintf(args[4], sizeof(args[4]), "%d", shm()->rxUDPPort2); FILE_LOG(logDEBUG1) << "Receiver Number of UDP Interfaces: " << shm()->numUDPInterfaces; - FILE_LOG(logDEBUG1) << "Receiver Selected Interface: " - << shm()->selectedUDPInterface; FILE_LOG(logDEBUG1) << "Receiver udp ip address: " << shm()->rxUDPIP; FILE_LOG(logDEBUG1) << "Receiver udp ip address2: " << shm()->rxUDPIP2; FILE_LOG(logDEBUG1) << "Receiver udp port: " << shm()->rxUDPPort; diff --git a/slsDetectorSoftware/src/slsDetectorCommand.cpp b/slsDetectorSoftware/src/slsDetectorCommand.cpp index e19bfc67c..3303439f9 100755 --- a/slsDetectorSoftware/src/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp @@ -1581,7 +1581,7 @@ slsDetectorCommand::slsDetectorCommand(multiSlsDetector *det) { ++i; /*! \page network - - rx_udpip2 [ip] sets/gets the ip address of the second receiver UDP interface where the data from the bottom half module of the detector will be streamed to. Normally used for single detectors (Can be multi-detector). Used if different from eth0. JUNGFRAU only. \c Returns \c (string) + - rx_udpip2 [ip] sets/gets the ip address of the second receiver UDP interface where the data from the top half module of the detector will be streamed to. Normally used for single detectors (Can be multi-detector). Used if different from eth0. JUNGFRAU only. \c Returns \c (string) */ descrToFuncMap[i].m_pFuncName = "rx_udpip2"; descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdNetworkParameter; @@ -1595,7 +1595,7 @@ slsDetectorCommand::slsDetectorCommand(multiSlsDetector *det) { ++i; /*! \page network - - rx_udpmac2 [mac] sets/gets the mac address of the second receiver UDP interface where the data from the bottom half module of the detector will be streamed to. Normally used for single detectors (Can be multi-detector). JUNGFRAU only.\c Returns \c (string) + - rx_udpmac2 [mac] sets/gets the mac address of the second receiver UDP interface where the data from the top half module of the detector will be streamed to. Normally used for single detectors (Can be multi-detector). JUNGFRAU only.\c Returns \c (string) */ descrToFuncMap[i].m_pFuncName = "rx_udpmac2"; descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdNetworkParameter; @@ -1609,7 +1609,7 @@ slsDetectorCommand::slsDetectorCommand(multiSlsDetector *det) { ++i; /*! \page network - - rx_udpport2 [port] sets/gets the second port of the receiver UDP interface where the data from the second half of the detector will be streamed to. Use single-detector command. Used for EIGERand JUNGFRAU only. \c Returns \c (int) + - rx_udpport2 [port] sets/gets the second port of the receiver UDP interface where the data from the second half of the detector will be streamed to. Use single-detector command. For Eiger, it is the right half and for Jungfrau, it is the top half module. \c Returns \c (int) */ descrToFuncMap[i].m_pFuncName = "rx_udpport2"; descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdNetworkParameter; @@ -1637,35 +1637,35 @@ slsDetectorCommand::slsDetectorCommand(multiSlsDetector *det) { ++i; /*! \page network - - detectormac2 [mac] sets/gets the mac address of the second half of the detector UDP interface from where the bottom half module of the detector will stream data. Use single-detector command. Normally unused. JUNGFRAU only. \c Returns \c (string) + - detectormac2 [mac] sets/gets the mac address of the second half of the detector UDP interface from where the top half module of the detector will stream data. Use single-detector command. Normally unused. JUNGFRAU only. \c Returns \c (string) */ descrToFuncMap[i].m_pFuncName = "detectormac2"; descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdNetworkParameter; ++i; /*! \page network - - detectorip [ip] sets/gets the ip address of the detector UDP interface from where the bottom half of the detector will stream data. Use single-detector command. Keep in same subnet as rx_udpip (if rx_udpip specified). \c Returns \c (string) + - detectorip [ip] sets/gets the ip address of the detector UDP interface from where the detector will stream data. Use single-detector command. Keep in same subnet as rx_udpip (if rx_udpip specified). \c Returns \c (string) */ descrToFuncMap[i].m_pFuncName = "detectorip"; descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdNetworkParameter; ++i; /*! \page network - - detectorip2 [ip] sets/gets the ip address of the second half of the detector UDP interface from where the bottom half of the detector will stream data. Use single-detector command. Keep in same subnet as rx_udpip2 (if rx_udpip2 specified). JUNGFRAU only. \c Returns \c (string) + - detectorip2 [ip] sets/gets the ip address of the top half of the detector UDP interface from where the top half of the detector will stream data. Use single-detector command. Keep in same subnet as rx_udpip2 (if rx_udpip2 specified). JUNGFRAU only. \c Returns \c (string) */ descrToFuncMap[i].m_pFuncName = "detectorip2"; descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdNetworkParameter; ++i; /*! \page network - - numinterfaces [n] sets/gets the number of interfaces used to stream out from the detector. Options: 1, 2. JUNGFRAU only. \c Returns \c (int) + - numinterfaces [n] sets/gets the number of interfaces used to stream out from the detector. Options: 1(default), 2. JUNGFRAU only. \c Returns \c (int) */ descrToFuncMap[i].m_pFuncName = "numinterfaces"; descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdNetworkParameter; ++i; /*! \page network - - selinterface [n] sets/gets the 1st (inner) or the 2nd (outer) interface to use to stream data out of the detector. Options: 1, 2. Effective only when \c numinterfaces is 1. JUNGFRAU only. \c Returns \c (int) + - selinterface [n] sets/gets interface to use to stream data out of the detector. Options: 0 (outer, default), 1(inner). Effective only when \c numinterfaces is 1. JUNGFRAU only. \c Returns \c (int) */ descrToFuncMap[i].m_pFuncName = "selinterface"; descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdNetworkParameter; @@ -3063,9 +3063,9 @@ std::string slsDetectorCommand::helpNetworkParameter(int action) { os << "rx_udpmac mac \n sets receiver udp mac to mac" << std::endl; os << "rx_udpmac2 mac \n sets receiver udp mac of 2nd udp interface to mac. Jungfrau only." << std::endl; os << "rx_udpport port \n sets receiver udp port to port" << std::endl; - os << "rx_udpport2 port \n sets receiver udp port to port. For Eiger and Jungfrau, it is the second half module and for other detectors, same as rx_udpport" << std::endl; - os << "numinterfaces n \n sets the number of interfaces to n used to stream out from the detector. Options: 1, 2. JUNGFRAU only. " << std::endl; - os << "selinterface n \n sets the 1st (inner) or the 2nd (outer) interface to use to stream data out of the detector. Options: 1, 2. Effective only when numinterfaces is 1. JUNGFRAU only. " << std::endl; + os << "rx_udpport2 port \n sets receiver udp port to port. For Eiger, it is the right half and for Jungfrau, it is the top half module and for other detectors, same as rx_udpport" << std::endl; + os << "numinterfaces n \n sets the number of interfaces to n used to stream out from the detector. Options: 1 (default), 2. JUNGFRAU only. " << std::endl; + os << "selinterface n \n sets interface to use to stream data out of the detector. Options: 0 (outer, default), 1(inner). Effective only when numinterfaces is 1. JUNGFRAU only. " << std::endl; os << "txndelay_left port \n sets detector transmission delay of the left port" << std::endl; os << "txndelay_right port \n sets detector transmission delay of the right port" << std::endl; os << "txndelay_frame port \n sets detector transmission delay of the entire frame" << std::endl; @@ -3103,9 +3103,9 @@ std::string slsDetectorCommand::helpNetworkParameter(int action) { os << "rx_udpip \n gets receiver udp mac " << std::endl; os << "rx_udpip2 \n gets receiver udp mac of 2nd udp interface. Jungfrau only" << std::endl; os << "rx_udpport \n gets receiver udp port " << std::endl; - os << "rx_udpport2 \n gets receiver udp port of 2nd udp interface. For Eiger and Jungfrau, it is the second half module and for other detectors, same as rx_udpport" << std::endl; - os << "numinterfaces \n gets the number of interfaces to n used to stream out from the detector. Options: 1, 2. JUNGFRAU only. " << std::endl; - os << "selinterface \n gets the interface selected to use to stream data out of the detector. Options: 1, 2. Effective only when numinterfaces is 1. JUNGFRAU only. " << std::endl; + os << "rx_udpport2 \n gets receiver udp port of 2nd udp interface. For Eiger, it is the right half and for Jungfrau, it is the top half module and for other detectors, same as rx_udpport" << std::endl; + os << "numinterfaces \n gets the number of interfaces to n used to stream out from the detector. Options: 1 (default), 2. JUNGFRAU only. " << std::endl; + os << "selinterface \n gets interface to use to stream data out of the detector. Options: 0 (outer, default), 1(inner). Effective only when numinterfaces is 1. JUNGFRAU only. " << std::endl; os << "txndelay_left \n gets detector transmission delay of the left port" << std::endl; os << "txndelay_right \n gets detector transmission delay of the right port" << std::endl; os << "txndelay_frame \n gets detector transmission delay of the entire frame" << std::endl; diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp index 24e5b31af..0c7701cb6 100755 --- a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp +++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp @@ -731,7 +731,7 @@ int slsReceiverTCPIPInterface::set_roi() { int slsReceiverTCPIPInterface::setup_udp(){ ret = OK; memset(mess, 0, sizeof(mess)); - char args[6][MAX_STR_LENGTH] = {{""}, {""}, {""}, {""}, {""}, {""}}; + char args[][MAX_STR_LENGTH] = {{""}, {""}, {""}, {""}, {""}}; char retvals[2][MAX_STR_LENGTH] = {{""}, {""}}; // get args, return if socket crashed, ret is fail if receiver is not null @@ -746,18 +746,10 @@ int slsReceiverTCPIPInterface::setup_udp(){ //setup interfaces count int numInterfaces = atoi(args[0]) > 1 ? 2 : 1; - int selInterface = atoi(args[1]) > 1 ? 2 : 1; - - char* ip1 = args[2]; - char* ip2 = args[3]; - uint32_t port1 = atoi(args[4]); - uint32_t port2 = atoi(args[5]); - - // using the 2nd interface only - if (myDetectorType == JUNGFRAU && numInterfaces == 1 && selInterface == 2) { - ip1 = ip2; - port1 = port2; - } + char* ip1 = args[1]; + char* ip2 = args[2]; + uint32_t port1 = atoi(args[3]); + uint32_t port2 = atoi(args[4]); // 1st interface receiver->setUDPPortNumber(port1); @@ -794,15 +786,8 @@ int slsReceiverTCPIPInterface::setup_udp(){ strcpy(mess,"failed to get mac adddress to listen to\n"); FILE_LOG(logERROR) << mess; } else { - // using the 2nd interface only - if (myDetectorType == JUNGFRAU && numInterfaces == 1 && selInterface == 2) { - strcpy(retvals[1],temp.c_str()); - FILE_LOG(logINFO) << "Receiver MAC Address: " << retvals[1]; - } - else { - strcpy(retvals[0],temp.c_str()); - FILE_LOG(logINFO) << "Receiver MAC Address: " << retvals[0]; - } + strcpy(retvals[0],temp.c_str()); + FILE_LOG(logINFO) << "Receiver MAC Address: " << retvals[0]; } } } diff --git a/slsSupportLib/include/versionAPI.h b/slsSupportLib/include/versionAPI.h index 63760ae97..fbaf24be5 100644 --- a/slsSupportLib/include/versionAPI.h +++ b/slsSupportLib/include/versionAPI.h @@ -7,5 +7,5 @@ #define APIGUI 0x190405 #define APIEIGER 0x190516 #define APICTB 0x190514 -#define APIJUNGFRAU 0x190527 +#define APIJUNGFRAU 0x190528 From 6a81e779c1620ada10c28b8dc558dbc677f8527f Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Tue, 28 May 2019 11:35:41 +0200 Subject: [PATCH 56/76] replaced server with receiver bug --- slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp index 8041289f4..e43c6fe22 100755 --- a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp +++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp @@ -423,7 +423,7 @@ int slsReceiverTCPIPInterface::update_client(sls::ServerInterface2 &socket) { // no arg, check receiver is null socket.receiveArg(ret, mess, nullptr, 0); - if(server == nullptr) + if(receiver == nullptr) NullObjectError(ret, mess); socket.sendResult(false, ret, nullptr, 0, mess); From 57170b1c80f4e5c43210d4b604399fd3b6424561 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Tue, 28 May 2019 12:12:05 +0200 Subject: [PATCH 57/76] pinned conda build --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0bbc8d6bf..81b60efea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,7 +25,8 @@ install: - conda config --add channels slsdetectorgroup - conda update conda - conda update --all - - conda install conda-build anaconda-client + - conda install conda-build=3.17 + - conda install anaconda-client - conda install conda-verify # Useful for debugging any issues with conda From 82308daf7b20717a3112e73ab3a3c3db3f067be2 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Tue, 28 May 2019 12:28:44 +0200 Subject: [PATCH 58/76] jungfrau server bug fix: vref adc voltage overwritten by default for ctb --- .../bin/jungfrauDetectorServer_developer | Bin 120820 -> 120820 bytes slsDetectorServers/slsDetectorServer/AD9257.h | 9 ++++----- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer b/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer index 9c684a8a49f44a07c2e8c1637e3944d9200c632b..6ac75d33c30b90cea690916be1a74cd6c143dddf 100755 GIT binary patch delta 17546 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 diff --git a/slsDetectorServers/slsDetectorServer/AD9257.h b/slsDetectorServers/slsDetectorServer/AD9257.h index 52e9f3d1a..97cf67526 100755 --- a/slsDetectorServers/slsDetectorServer/AD9257.h +++ b/slsDetectorServers/slsDetectorServer/AD9257.h @@ -295,9 +295,12 @@ void AD9257_Configure(){ // vref #ifdef GOTTHARDD FILE_LOG(logINFO, ("\tVref default at 2.0\n")); + AD9257_SetVrefVoltage(AD9257_VREF_DEFAULT_VAL, 0); #else FILE_LOG(logINFO, ("\tVref 1.33\n")); - AD9257_Set(AD9257_VREF_REG, AD9257_VREF_1_33_VAL); + //AD9257_Set(AD9257_VREF_REG, AD9257_VREF_1_33_VAL); + AD9257_SetVrefVoltage(AD9257_VREF_1_33_VAL, 0); + #endif // no test mode @@ -310,8 +313,4 @@ void AD9257_Configure(){ FILE_LOG(logINFO, ("\tMixed bit frequency test mode\n")); AD9257_Set(AD9257_TEST_MODE_REG, AD9257_TST_MXD_BT_FRQ_VAL); #endif - - // set default value again (to remember the value set) - AD9257_SetVrefVoltage(AD9257_VREF_DEFAULT_VAL, 0); - } From 938e1e87ffd8f326ab47edf7b3e51d8542518da3 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Tue, 28 May 2019 12:31:19 +0200 Subject: [PATCH 59/76] bugfix: vref adc voltage --- .../bin/ctbDetectorServer_developer | Bin 151744 -> 152112 bytes slsSupportLib/include/versionAPI.h | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer b/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer index f0f2fbc3f31dfb94b993919227c37321c7ecdb13..7484330e71afedb7f0b4f1af80e2058ef3facc5e 100755 GIT binary patch delta 67483 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 diff --git a/slsSupportLib/include/versionAPI.h b/slsSupportLib/include/versionAPI.h index fbaf24be5..8aa2e449e 100644 --- a/slsSupportLib/include/versionAPI.h +++ b/slsSupportLib/include/versionAPI.h @@ -6,6 +6,6 @@ #define APIRECEIVER 0x190405 #define APIGUI 0x190405 #define APIEIGER 0x190516 -#define APICTB 0x190514 #define APIJUNGFRAU 0x190528 +#define APICTB 0x190528 From e64f57ecaca400a7e0713e2520666449a250fb2b Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Tue, 28 May 2019 13:12:43 +0200 Subject: [PATCH 60/76] receiver --- slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp index e43c6fe22..b844bfdf5 100755 --- a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp +++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp @@ -620,7 +620,7 @@ int slsReceiverTCPIPInterface::set_detector_hostname(sls::ServerInterface2 &sock // get args, return if socket crashed, ret is fail if receiver is not null socket.receiveArg(ret, mess, hostname, MAX_STR_LENGTH); - if(server == nullptr){ + if(receiver == nullptr){ NullObjectError(ret, mess); return FAIL; } From 8f4009bfb668d9d1ce352a04e7d970e89a54b58a Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Tue, 28 May 2019 13:27:43 +0200 Subject: [PATCH 61/76] WIP --- slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp | 3 ++- slsSupportLib/include/DataSocket.h | 6 +++--- slsSupportLib/src/DataSocket.cpp | 8 ++++---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp index b844bfdf5..c408f0bef 100755 --- a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp +++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp @@ -111,7 +111,8 @@ void slsReceiverTCPIPInterface::startTCPServer() { while (true) { try { auto socket = server->accept(); - socket.setReceiveTimeout(static_cast(5E6)); + constexpr int time_us = 5000000; + socket.setReceiveTimeout(time_us); ret = decode_function(socket); // if tcp command was to exit server diff --git a/slsSupportLib/include/DataSocket.h b/slsSupportLib/include/DataSocket.h index 87de7d39d..05f008bba 100755 --- a/slsSupportLib/include/DataSocket.h +++ b/slsSupportLib/include/DataSocket.h @@ -18,9 +18,9 @@ class DataSocket { int getSocketId() const { return socketId_; } - size_t sendData(const void *buffer, size_t size); - size_t receiveData(void *buffer, size_t size); - ssize_t read(void *buffer, size_t size); + int sendData(const void *buffer, size_t size); + int receiveData(void *buffer, size_t size); + int read(void *buffer, size_t size); int setTimeOut(int t_seconds); int setReceiveTimeout(int us); void close(); diff --git a/slsSupportLib/src/DataSocket.cpp b/slsSupportLib/src/DataSocket.cpp index 9a70c5c19..a38d821d4 100755 --- a/slsSupportLib/src/DataSocket.cpp +++ b/slsSupportLib/src/DataSocket.cpp @@ -40,7 +40,7 @@ DataSocket &DataSocket::operator=(DataSocket &&move) noexcept { return *this; } -size_t DataSocket::receiveData(void *buffer, size_t size) { +int DataSocket::receiveData(void *buffer, size_t size) { size_t dataRead = 0; while (dataRead < size) { dataRead += @@ -50,7 +50,7 @@ size_t DataSocket::receiveData(void *buffer, size_t size) { return dataRead; } -ssize_t DataSocket::read(void *buffer, size_t size){ +int DataSocket::read(void *buffer, size_t size){ return ::read(getSocketId(), reinterpret_cast(buffer), size); } @@ -63,8 +63,8 @@ int DataSocket::setReceiveTimeout(int us) { } -size_t DataSocket::sendData(const void *buffer, size_t size) { - size_t dataSent = 0; +int DataSocket::sendData(const void *buffer, size_t size) { + int dataSent = 0; while (dataSent < size) { dataSent += write(getSocketId(), reinterpret_cast(buffer) + dataSent, From 8c112efdb3c0c584fde49633409a259ab067d5a2 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Tue, 28 May 2019 14:14:08 +0200 Subject: [PATCH 62/76] jungfrau bug fix: setting clkdivider also set adcphase: break inswitch --- .../bin/jungfrauDetectorServer_developer | Bin 120820 -> 120820 bytes .../slsDetectorFunctionList.c | 8 +++++--- slsSupportLib/include/versionAPI.h | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer b/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer index 6ac75d33c30b90cea690916be1a74cd6c143dddf..40b4e315f68a8dfa5dec84d4f80654f30d0a2b88 100755 GIT binary patch delta 15784 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 delta 15736 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 diff --git a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c index 8934cb5a3..d667d1349 100755 --- a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c @@ -519,8 +519,10 @@ void setSpeed(enum speedVariable ind, int val, int mode) { switch(ind) { case CLOCK_DIVIDER: setClockDivider(val); + break; case ADC_PHASE: setAdcPhase(val, mode); + break; default: return; } @@ -1337,7 +1339,7 @@ void setClockDivider(int val) { FILE_LOG(logINFO, ("\tSet ADC Ofst Reg to 0x%x\n", bus_r(ADC_OFST_REG))); setAdcPhase(ADC_PHASE_FULL_SPEED, 0); - FILE_LOG(logINFO, ("\tSet ADC Phase Reg to 0x%x\n", ADC_PHASE_FULL_SPEED)); + FILE_LOG(logINFO, ("\tSet ADC Phase Reg to %d\n", ADC_PHASE_FULL_SPEED)); break; case HALF_SPEED: @@ -1353,7 +1355,7 @@ void setClockDivider(int val) { FILE_LOG(logINFO, ("\tSet ADC Ofst Reg to 0x%x\n", bus_r(ADC_OFST_REG))); setAdcPhase(ADC_PHASE_HALF_SPEED, 0); - FILE_LOG(logINFO, ("\tSet ADC Phase Reg to 0x%x\n", ADC_PHASE_HALF_SPEED)); + FILE_LOG(logINFO, ("\tSet ADC Phase Reg to %d\n", ADC_PHASE_HALF_SPEED)); break; case QUARTER_SPEED: @@ -1369,7 +1371,7 @@ void setClockDivider(int val) { FILE_LOG(logINFO, ("\tSet ADC Ofst Reg to 0x%x\n", bus_r(ADC_OFST_REG))); setAdcPhase(ADC_PHASE_QUARTER_SPEED, 0); - FILE_LOG(logINFO, ("\tSet ADC Phase Reg to 0x%x\n", ADC_PHASE_QUARTER_SPEED)); + FILE_LOG(logINFO, ("\tSet ADC Phase Reg to %d\n", ADC_PHASE_QUARTER_SPEED)); break; } diff --git a/slsSupportLib/include/versionAPI.h b/slsSupportLib/include/versionAPI.h index 8aa2e449e..08ceab081 100644 --- a/slsSupportLib/include/versionAPI.h +++ b/slsSupportLib/include/versionAPI.h @@ -7,5 +7,5 @@ #define APIGUI 0x190405 #define APIEIGER 0x190516 -#define APIJUNGFRAU 0x190528 #define APICTB 0x190528 +#define APIJUNGFRAU 0x190528 From daa82b91a9641ae20e8daf878e6ba7107ac9bcf4 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Tue, 28 May 2019 14:44:46 +0200 Subject: [PATCH 63/76] removed comment --- slsReceiverSoftware/include/slsReceiverTCPIPInterface.h | 1 - 1 file changed, 1 deletion(-) diff --git a/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h b/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h index 9a39e1578..19b13b3b4 100755 --- a/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h +++ b/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h @@ -10,7 +10,6 @@ class MySocketTCP; class ServerInterface; -// class slsReceiverImplementation; #include "slsReceiverImplementation.h" #include "ServerSocket.h" From f7aedf7711ee81e4be19dd967a6c06c81872e45b Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Tue, 28 May 2019 16:56:15 +0200 Subject: [PATCH 64/76] client bug fix: typo in command line, get returned rx_udpip instead of rx_udpip2, same with mac --- slsDetectorSoftware/src/slsDetectorCommand.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/slsDetectorSoftware/src/slsDetectorCommand.cpp b/slsDetectorSoftware/src/slsDetectorCommand.cpp index 3303439f9..a9e9c9b99 100755 --- a/slsDetectorSoftware/src/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp @@ -2913,7 +2913,7 @@ std::string slsDetectorCommand::cmdNetworkParameter(int narg, const char * const if (action == PUT_ACTION) { myDet->setReceiverUDPIP2(args[1], detPos); } - return myDet->getReceiverUDPIP(detPos); + return myDet->getReceiverUDPIP2(detPos); } else if (cmd == "rx_udpmac") { if (action == PUT_ACTION) { myDet->setReceiverUDPMAC(args[1], detPos); @@ -2923,7 +2923,7 @@ std::string slsDetectorCommand::cmdNetworkParameter(int narg, const char * const if (action == PUT_ACTION) { myDet->setReceiverUDPMAC2(args[1], detPos); } - return myDet->getReceiverUDPMAC(detPos); + return myDet->getReceiverUDPMAC2(detPos); } else if (cmd == "rx_udpport") { if (action == PUT_ACTION) { if (!(sscanf(args[1], "%d", &i))) { From aa2bcfa308a83509192462e1c93bd5e27fa932fb Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Tue, 28 May 2019 17:07:34 +0200 Subject: [PATCH 65/76] fixed setup udp --- .../src/slsReceiverTCPIPInterface.cpp | 59 ++++--------------- slsSupportLib/include/logger.h | 4 +- slsSupportLib/src/ServerInterface2.cpp | 12 +++- 3 files changed, 22 insertions(+), 53 deletions(-) diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp index 0ed492b13..5cb082b2f 100755 --- a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp +++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp @@ -109,6 +109,7 @@ void slsReceiverTCPIPInterface::startTCPServer() { int ret = OK; server = sls::make_unique(portNumber); while (true) { + FILE_LOG(logDEBUG1) << "Start accept loop"; try { auto socket = server->accept(); constexpr int time_us = 5000000; @@ -422,8 +423,6 @@ int slsReceiverTCPIPInterface::update_client(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); - // no arg, check receiver is null - socket.receiveArg(ret, mess, nullptr, 0); if(receiver == nullptr) NullObjectError(ret, mess); socket.sendResult(false, ret, nullptr, 0, mess); @@ -698,15 +697,16 @@ int slsReceiverTCPIPInterface::set_roi(sls::ServerInterface2 &socket) { int slsReceiverTCPIPInterface::setup_udp(sls::ServerInterface2 &socket){ ret = OK; memset(mess, 0, sizeof(mess)); - char args[6][MAX_STR_LENGTH]{}; + char args[5][MAX_STR_LENGTH]{}; char retvals[2][MAX_STR_LENGTH]{}; // get args, return if socket crashed, ret is fail if receiver is not null socket.receiveArg(ret, mess, args, sizeof(args)); - if(receiver == nullptr){ + if (receiver == nullptr){ NullObjectError(ret, mess); return FAIL; } + // base object not null if (ret == OK) { @@ -716,18 +716,10 @@ int slsReceiverTCPIPInterface::setup_udp(sls::ServerInterface2 &socket){ //setup interfaces count int numInterfaces = atoi(args[0]) > 1 ? 2 : 1; - int selInterface = atoi(args[1]) > 1 ? 2 : 1; - - char* ip1 = args[2]; - char* ip2 = args[3]; - uint32_t port1 = atoi(args[4]); - uint32_t port2 = atoi(args[5]); - - // using the 2nd interface only - if (myDetectorType == JUNGFRAU && numInterfaces == 1 && selInterface == 2) { - ip1 = ip2; - port1 = port2; - } + char* ip1 = args[1]; + char* ip2 = args[2]; + uint32_t port1 = atoi(args[3]); + uint32_t port2 = atoi(args[4]); // 1st interface receiver->setUDPPortNumber(port1); @@ -764,15 +756,8 @@ int slsReceiverTCPIPInterface::setup_udp(sls::ServerInterface2 &socket){ strcpy(mess,"failed to get mac adddress to listen to\n"); FILE_LOG(logERROR) << mess; } else { - // using the 2nd interface only - if (myDetectorType == JUNGFRAU && numInterfaces == 1 && selInterface == 2) { - strcpy(retvals[1],temp.c_str()); - FILE_LOG(logINFO) << "Receiver MAC Address: " << retvals[1]; - } - else { - strcpy(retvals[0],temp.c_str()); - FILE_LOG(logINFO) << "Receiver MAC Address: " << retvals[0]; - } + strcpy(retvals[0],temp.c_str()); + FILE_LOG(logINFO) << "Receiver MAC Address: " << retvals[0]; } } } @@ -829,7 +814,6 @@ int slsReceiverTCPIPInterface::setup_udp(sls::ServerInterface2 &socket){ - int slsReceiverTCPIPInterface::set_timer(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); @@ -1037,17 +1021,13 @@ int slsReceiverTCPIPInterface::get_status(sls::ServerInterface2 &socket){ memset(mess, 0, sizeof(mess)); enum runStatus retval = ERROR; - // no arg, check receiver is null - socket.receiveArg(ret, mess, nullptr, 0); if(receiver == nullptr){ NullObjectError(ret, mess); } if (ret == OK) { FILE_LOG(logDEBUG1) << "Getting Status"; - std::cout << "kalas\n"; retval = receiver->getStatus(); - std::cout << "puff\n"; FILE_LOG(logDEBUG1) << "Status:" << runStatusType(retval); } return socket.sendResult(true, ret, &retval, sizeof(retval), mess); @@ -1059,8 +1039,6 @@ int slsReceiverTCPIPInterface::start_receiver(sls::ServerInterface2 &socket){ ret = OK; memset(mess, 0, sizeof(mess)); - // no arg, and check receiver is null - socket.receiveArg(ret, mess, nullptr, 0); if(receiver == nullptr){ NullObjectError(ret, mess); } @@ -1093,8 +1071,7 @@ int slsReceiverTCPIPInterface::stop_receiver(sls::ServerInterface2 &socket){ ret = OK; memset(mess, 0, sizeof(mess)); - // no arg, and check receiver is null - socket.receiveArg(ret, mess, nullptr, 0); + if(receiver == nullptr){ NullObjectError(ret, mess); } @@ -1230,8 +1207,6 @@ int slsReceiverTCPIPInterface::get_frame_index(sls::ServerInterface2 &socket){ memset(mess, 0, sizeof(mess)); int retval = -1; - // no arg, check receiver is null - socket.receiveArg(ret, mess, nullptr, 0); if(receiver == nullptr){ NullObjectError(ret, mess); } @@ -1251,8 +1226,6 @@ int slsReceiverTCPIPInterface::get_frames_caught(sls::ServerInterface2 &socket){ memset(mess, 0, sizeof(mess)); int retval = -1; - // no arg, check receiver is null - socket.receiveArg(ret, mess, nullptr, 0); if(receiver == nullptr){ NullObjectError(ret, mess); } @@ -1271,8 +1244,6 @@ int slsReceiverTCPIPInterface::reset_frames_caught(sls::ServerInterface2 &socket ret = OK; memset(mess, 0, sizeof(mess)); - // no arg, and check receiver is null - socket.receiveArg(ret, mess, nullptr, 0); if(receiver == nullptr){ NullObjectError(ret, mess); } @@ -1839,8 +1810,6 @@ int slsReceiverTCPIPInterface::restream_stop(sls::ServerInterface2 &socket){ ret = OK; memset(mess, 0, sizeof(mess)); - // no arg, and check receiver is null - socket.receiveArg(ret, mess, nullptr, 0); if(receiver == nullptr){ NullObjectError(ret, mess); } @@ -1904,8 +1873,6 @@ int slsReceiverTCPIPInterface::get_additional_json_header(sls::ServerInterface2 memset(mess, 0, sizeof(mess)); char retval[MAX_STR_LENGTH] = {0}; - // no arg, check receiver is null - socket.receiveArg(ret, mess, nullptr, 0); if(receiver == nullptr){ NullObjectError(ret, mess); } @@ -1964,8 +1931,6 @@ int slsReceiverTCPIPInterface::get_real_udp_socket_buffer_size(sls::ServerInterf memset(mess, 0, sizeof(mess)); int64_t retval = -1; - // no arg, check receiver is null - socket.receiveArg(ret, mess, nullptr, 0); if(receiver == nullptr){ NullObjectError(ret, mess); } @@ -2253,8 +2218,6 @@ int slsReceiverTCPIPInterface::get_dbit_list(sls::ServerInterface2 &socket) { memset(mess, 0, sizeof(mess)); sls::FixedCapacityContainer retval; - // no arg, check receiver is null - socket.receiveArg(ret, mess, nullptr, 0); if(receiver == nullptr){ NullObjectError(ret, mess); } diff --git a/slsSupportLib/include/logger.h b/slsSupportLib/include/logger.h index 541da95b0..8de0c2f49 100755 --- a/slsSupportLib/include/logger.h +++ b/slsSupportLib/include/logger.h @@ -17,8 +17,8 @@ #endif #ifndef FILELOG_MAX_LEVEL -// #define FILELOG_MAX_LEVEL logINFO -#define FILELOG_MAX_LEVEL logDEBUG5 +#define FILELOG_MAX_LEVEL logINFO +// #define FILELOG_MAX_LEVEL logDEBUG5 #endif diff --git a/slsSupportLib/src/ServerInterface2.cpp b/slsSupportLib/src/ServerInterface2.cpp index 2eab250f5..44c53782b 100644 --- a/slsSupportLib/src/ServerInterface2.cpp +++ b/slsSupportLib/src/ServerInterface2.cpp @@ -1,5 +1,5 @@ #include "ServerInterface2.h" - +#include namespace sls { int ServerInterface2::sendResult(bool update, int ret, void *retval, @@ -24,9 +24,15 @@ int ServerInterface2::sendResult(bool update, int ret, void *retval, int ServerInterface2::receiveArg(int &ret, char *mess, void *arg, int sizeofArg) { - if (sizeofArg && receiveData(arg, sizeofArg) < 0) + assert(sizeofArg > 0); + int bytes_read = read(arg, sizeofArg); + if (bytes_read == sizeofArg) { + return defs::OK; + } else { + FILE_LOG(logERROR) << "Read: " << bytes_read << " instead of " + << sizeofArg; return defs::FAIL; - return defs::OK; + } } } // namespace sls From a008c2b2c8ba23777b8f74b12907d80c93d29b02 Mon Sep 17 00:00:00 2001 From: Anna Bergamaschi Date: Tue, 28 May 2019 17:15:59 +0200 Subject: [PATCH 66/76] added ctbGui --- ctbGui/Makefile.root5 | 44 + ctbGui/Makefile.root6 | 45 + ctbGui/ctbAcquisition.cpp | 2058 ++++++++++++++++++ ctbGui/ctbAcquisition.h | 234 ++ ctbGui/ctbAdcs.cpp | 710 ++++++ ctbGui/ctbAdcs.h | 151 ++ ctbGui/ctbDacs.cpp | 251 +++ ctbGui/ctbDacs.h | 74 + ctbGui/ctbGui.cpp | 161 ++ ctbGui/ctbLinkDef.h | 15 + ctbGui/ctbMain.cpp | 709 ++++++ ctbGui/ctbMain.h | 126 ++ ctbGui/ctbPattern.cpp | 1263 +++++++++++ ctbGui/ctbPattern.h | 176 ++ ctbGui/ctbPowers.cpp | 243 +++ ctbGui/ctbPowers.h | 72 + ctbGui/ctbSignals.cpp | 548 +++++ ctbGui/ctbSignals.h | 118 + ctbGui/ctbSlowAdcs.cpp | 185 ++ ctbGui/ctbSlowAdcs.h | 75 + slsDetectorSoftware/include/detectorData.h | 24 +- slsDetectorSoftware/src/multiSlsDetector.cpp | 10 +- 22 files changed, 7290 insertions(+), 2 deletions(-) create mode 100644 ctbGui/Makefile.root5 create mode 100644 ctbGui/Makefile.root6 create mode 100755 ctbGui/ctbAcquisition.cpp create mode 100755 ctbGui/ctbAcquisition.h create mode 100755 ctbGui/ctbAdcs.cpp create mode 100755 ctbGui/ctbAdcs.h create mode 100755 ctbGui/ctbDacs.cpp create mode 100755 ctbGui/ctbDacs.h create mode 100755 ctbGui/ctbGui.cpp create mode 100755 ctbGui/ctbLinkDef.h create mode 100755 ctbGui/ctbMain.cpp create mode 100755 ctbGui/ctbMain.h create mode 100755 ctbGui/ctbPattern.cpp create mode 100755 ctbGui/ctbPattern.h create mode 100644 ctbGui/ctbPowers.cpp create mode 100644 ctbGui/ctbPowers.h create mode 100755 ctbGui/ctbSignals.cpp create mode 100755 ctbGui/ctbSignals.h create mode 100644 ctbGui/ctbSlowAdcs.cpp create mode 100644 ctbGui/ctbSlowAdcs.h diff --git a/ctbGui/Makefile.root5 b/ctbGui/Makefile.root5 new file mode 100644 index 000000000..767f32281 --- /dev/null +++ b/ctbGui/Makefile.root5 @@ -0,0 +1,44 @@ + + +INCS=ctbMain.h ctbDacs.h ctbPattern.h ctbSignals.h ctbAdcs.h ctbAcquisition.h ctbPowers.h ctbSlowAdcs.h +SRC= $(SRC:.h=.cpp) ctbDict.cpp +LINKDEF=ctbLinkDef.h +ZMQLIB=../slsReceiverSoftware/include +LIBRARYCBF=$(CBFLIBDIR)/lib/*.o + +INCDIR=-I../slsReceiverSoftware/include/ -I../slsDetectorSoftware/include/ -I../slsSupportLib/include/ -I../slsDetectorCalibration -I../slsDetectorCalibration/dataStructures -I$(CBFLIBDIR)/include -I../slsDetectorCalibration/interpolations +LDFLAG=-L../bin -lSlsDetector -lSlsSupport -L/usr/lib64/ -lpthread -lm -lstdc++ -lzmq -pthread -lrt -ltiff -L$(ZMQLIB) -L$(CBFLIBDIR)/lib/ -std=c++11 +# +MAIN=ctbGui.cpp + +DESTDIR?=../bin + + +OBJS = $(SRC:.cpp=.o) $(MAIN:.cpp=.o) + +all: $(DESTDIR)/ctbGui + + +doc: + cd manual && make DESTDIR=$(DESTDIR) + +htmldoc: + cd manual && make html DESTDIR=$(DESTDIR) + +ctbDict.cpp: $(INCS) $(LINKDEF) + rootcint -f ctbDict.cpp -c $(INCS) $(LINKDEF) + +%.o : %.cpp + echo $@ + g++ -DMYROOT `root-config --cflags --glibs` -lMinuit -DCTB $(LDFLAG) -o $@ -c $< $(INCDIR) +#$(CXX) -o $@ -c $< $(INCLUDES) $(DFLAGS) -fPIC $(EPICSFLAGS) -lpthread #$(FLAGS) + + + +$(DESTDIR)/ctbGui: $(OBJS) $(LINKDEF) + g++ -DMYROOT `root-config --cflags --glibs` -lMinuit -DCTB $(LDFLAG) -o ctbGui $(INCDIR) $(OBJS) ../slsDetectorCalibration/tiffIO.cpp + mv ctbGui $(DESTDIR) + +clean: + rm -f $(DESTDIR)/ctbGui *.o ctbDict.* $(OBJS) + diff --git a/ctbGui/Makefile.root6 b/ctbGui/Makefile.root6 new file mode 100644 index 000000000..c80b29fed --- /dev/null +++ b/ctbGui/Makefile.root6 @@ -0,0 +1,45 @@ + + +INCS=ctbMain.h ctbDacs.h ctbPattern.h ctbSignals.h ctbAdcs.h ctbAcquisition.h ctbPowers.h ctbSlowAdcs.h +SRC= $(INCS:.h=.cpp) ctbDict.cpp +LINKDEF=ctbLinkDef.h +#ctbActions.h +ZMQLIB=../slsReceiverSoftware/include +LIBRARYCBF=$(CBFLIBDIR)/lib/*.o + +INCDIR=-I../slsReceiverSoftware/include/ -I../slsDetectorSoftware/include/ -I../slsSupportLib/include/ -I../slsDetectorCalibration -I../slsDetectorCalibration/dataStructures -I$(CBFLIBDIR)/include -I../slsDetectorCalibration/interpolations +LDFLAG=-L../bin -lSlsDetector -lSlsSupport -L/usr/lib64/ -lpthread -lm -lstdc++ -lzmq -pthread -lrt -ltiff -L$(ZMQLIB) -L$(CBFLIBDIR)/lib/ -std=c++11 +# +MAIN=ctbGui.cpp + +DESTDIR?=../bin + + +OBJS = $(SRC:.cpp=.o) $(MAIN:.cpp=.o) + +all: $(DESTDIR)/ctbGui + + +doc: + cd manual && make DESTDIR=$(DESTDIR) + +htmldoc: + cd manual && make html DESTDIR=$(DESTDIR) + +ctbDict.cpp: $(INCS) $(LINKDEF) + rootcling -f ctbDict.cpp -c $(INCS) $(LINKDEF) + +%.o : %.cpp + echo $@ + g++ -DMYROOT `root-config --cflags --glibs` -lMinuit -DCTB $(LDFLAG) -o $@ -c $< $(INCDIR) +#$(CXX) -o $@ -c $< $(INCLUDES) $(DFLAGS) -fPIC $(EPICSFLAGS) -lpthread #$(FLAGS) + + + +$(DESTDIR)/ctbGui: $(OBJS) $(LINKDEF) + g++ -DMYROOT `root-config --cflags --glibs` -lMinuit -DCTB $(LDFLAG) -o ctbGui $(INCDIR) $(OBJS) ../slsDetectorCalibration/tiffIO.cpp + mv ctbGui $(DESTDIR) + +clean: + rm -f $(DESTDIR)/ctbGui *.o ctbDict.* $(OBJS) + diff --git a/ctbGui/ctbAcquisition.cpp b/ctbGui/ctbAcquisition.cpp new file mode 100755 index 000000000..af4c1e257 --- /dev/null +++ b/ctbGui/ctbAcquisition.cpp @@ -0,0 +1,2058 @@ +//#define TESTADC + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include + +#include "ctbAcquisition.h" +#include "multiSlsDetector.h" +#include "sls_detector_defs.h" +#include "ctbMain.h" +#include "moench03CtbData.h" +#include "moench03TCtbData.h" +#include "moench03T1CtbData.h" +#include "moench03CommonMode.h" +#include "moench02CtbData.h" +//#include "jungfrau10ModuleData.h" +#include "moenchCommonMode.h" +#include "singlePhotonDetector.h" +#include "Mythen3_01_jctbData.h" +#include "Mythen3_02_jctbData.h" +#include "adcSar2_jctbData.h" +#include "detectorData.h" + +using namespace std; + + + + +ctbAcquisition::ctbAcquisition(TGVerticalFrame *page, multiSlsDetector *det) : TGGroupFrame(page,"Acquisition",kVerticalFrame), myDet(det), myCanvas(NULL), globalPlot(0), nAnalogSamples(1), nDigitalSamples(1), dataStructure(NULL), photonFinder(NULL), cmSub(0), dBitMask(0xffffffffffffffff) { + + adcFit=NULL; + bitPlot=NULL; + countsFit=NULL; + + page->AddFrame(this,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); + MapWindow(); + + TGHorizontalFrame *hframe=new TGHorizontalFrame(this, 800,50); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); + hframe->MapWindow(); + + char tit[100]; + + cout << "outfile "<< endl; + + cFileSave= new TGCheckButton(hframe, "Output file: "); + hframe->AddFrame(cFileSave,new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX, 5, 5, 5, 5)); + cFileSave->MapWindow(); + cFileSave->SetTextJustify(kTextRight); + cFileSave->Connect("Toggled(Bool_t)","ctbAcquisition",this,"setFsave(Bool_t)"); + + + eFname = new TGTextEntry(hframe, (myDet->getFileName()).c_str()); + + hframe->AddFrame(eFname,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 5, 5, 5, 5)); + eFname->MapWindow(); + eFname->Resize(150,30); + + eFname->Connect("ReturnPressed()","ctbAcquisition",this,"setFname()"); + + + TGLabel *label=new TGLabel(hframe,"index: "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + label->MapWindow(); + label->SetTextJustify(kTextRight); + + + eFindex = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELNoLimits); + hframe->AddFrame( eFindex,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eFindex->MapWindow(); + eFindex->Resize(150,30); + TGTextEntry *e= eFindex->TGNumberEntry::GetNumberEntry(); + e->Connect("ReturnPressed()","ctbAcquisition",this,"setFindex()"); + + + + + cout << "outdir "<< endl; + + + hframe=new TGHorizontalFrame(this, 800,50); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); + hframe->MapWindow(); + + label=new TGLabel(hframe,"Output directory: "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + label->MapWindow(); + label->SetTextJustify(kTextRight); + + + + eOutdir = new TGTextEntry(hframe, (myDet->getFilePath()).c_str()); + + hframe->AddFrame(eOutdir,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 5, 5, 5, 5)); + eOutdir->MapWindow(); + eOutdir->Resize(150,30); + + + eOutdir->Connect("ReturnPressed()","ctbAcquisition",this,"setOutdir()"); + + hframe=new TGHorizontalFrame(this, 800,50); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); + hframe->MapWindow(); + + + cout << "meas "<< endl; +label=new TGLabel(hframe,"Number of Measurements (fake): "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + label->MapWindow(); + label->SetTextJustify(kTextRight); + + + eMeasurements = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELNoLimits); + hframe->AddFrame( eMeasurements,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eMeasurements->MapWindow(); + eMeasurements->Resize(150,30); + eMeasurements->SetNumber(1); + e= eMeasurements->TGNumberEntry::GetNumberEntry(); + e->Connect("ReturnPressed()","ctbAcquisition",this,"setMeasurements()"); + + + + +hframe=new TGHorizontalFrame(this, 800,50); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); + hframe->MapWindow(); + + + + + cout << "pattern "<< endl; + + + + + cCompile= new TGCheckButton(hframe, "Compile"); + hframe->AddFrame(cCompile,new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX, 5, 5, 5, 5)); + cCompile->MapWindow(); + cCompile->SetOn(); + // cCompile->Connect("Toggled(Bool_t)","ctbAcquisition",this,"setFsave(Bool_t)"); + + + cLoad= new TGTextButton(hframe, "Load"); + hframe->AddFrame(cLoad,new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX, 5, 5, 5, 5)); + cLoad->MapWindow(); + cLoad->Connect("Clicked()","ctbAcquisition",this,"loadPattern()"); + + +// cRun= new TGCheckButton(hframe, "Run"); +// hframe->AddFrame(cRun,new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX, 5, 5, 5, 5)); +// cRun->MapWindow(); +// // cCompile->Connect("Toggled(Bool_t)","ctbAcquisition",this,"setFsave(Bool_t)"); + + + + + + + bStatus=new TGTextButton(hframe, "Start"); + hframe->AddFrame(bStatus,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 5, 5, 5, 5)); + bStatus->MapWindow(); + bStatus->Connect("Clicked()","ctbAcquisition",this,"toggleAcquisition()"); + + + + + + cout << "plot "<< endl; + + hframe=new TGHorizontalFrame(this, 800,50); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); + hframe->MapWindow(); + + + + + label=new TGLabel(hframe,"Plot: "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + label->MapWindow(); + label->SetTextJustify(kTextRight); + + + + + + + TGButtonGroup *bgPlot = new TGButtonGroup(hframe); + // horizontal->SetTitlePos(TGGroupFrame::kCenter); + rbPlotOff=new TGRadioButton(hframe, "No plot"); + rbWaveform=new TGRadioButton(hframe, "Waveform"); + rbDistribution=new TGRadioButton(hframe, "Distribution"); + rb2D=new TGRadioButton(hframe, "Image"); + // rbScan=new TGRadioButton(hframe, "Scan"); + + cbDetType=new TGComboBox(hframe); + // enum {MOENCH03, MOENCH02, ADCSAR2, MYTHEN301, MYTHEN302, MAXDET}; + cbDetType->AddEntry("MOENCH03", MOENCH03); + cbDetType->AddEntry("MOENCH02", MOENCH02); + // cbDetType->AddEntry("JUNGFRAU1.0", 2); + //cbDetType->AddEntry("MOENCH03 T", iiii++); + //cbDetType->AddEntry("MOENCH03", iiii++); + cbDetType->AddEntry("MYTHEN3 0.1", MYTHEN301); + cbDetType->AddEntry("ADCSAR2", ADCSAR2); + cbDetType->AddEntry("MYTHEN3 0.2", MYTHEN302); + + cbDetType->SetHeight(20); + cbDetType->Select(0); + + bgPlot->Insert(rbPlotOff,0); + bgPlot->Insert(rbWaveform,1); + bgPlot->Insert(rbDistribution,2); + bgPlot->Insert(rb2D,3); + // bgPlot->Insert(rbScan,4); + + bgPlot->Connect("Clicked(Int_t)", "ctbAcquisition", this, "changePlot(Int_t)"); + // hframe->AddFrame(bgPlot, new TGLayoutHints(kLHintsExpandX)); + + cbDetType->Connect("Selected(Int_t)", "ctbAcquisition",this, "changeDetector(Int_t)"); + hframe->AddFrame(rbPlotOff, new TGLayoutHints(kLHintsTop | kLHintsExpandX)); + hframe->AddFrame(rbWaveform, new TGLayoutHints(kLHintsTop | kLHintsExpandX)); + hframe->AddFrame(rbDistribution, new TGLayoutHints(kLHintsTop | kLHintsExpandX)); + hframe->AddFrame(rb2D, new TGLayoutHints(kLHintsTop | kLHintsExpandX)); + // hframe->AddFrame(rbScan, new TGLayoutHints(kLHintsTop | kLHintsExpandX)); + hframe->AddFrame(cbDetType, new TGLayoutHints(kLHintsTop | kLHintsExpandX| kLHintsExpandY)); + + + bgPlot->SetExclusive(kTRUE); + rbWaveform->SetOn(); + rbPlotOff->MapWindow(); + rbWaveform->MapWindow(); + rbDistribution->MapWindow(); + rb2D->MapWindow(); + // rbScan->MapWindow(); + cbDetType->MapWindow(); + + + + + cout << "off "<< endl; + + + hframe=new TGHorizontalFrame(this, 800,50); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); + hframe->MapWindow(); + + + + label=new TGLabel(hframe,"Serial offset:"); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + label->MapWindow(); + label->SetTextJustify(kTextRight); + + + eSerOff=new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELLimitMinMax,0,16535); + hframe->AddFrame(eSerOff,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eSerOff->MapWindow();; + eSerOff->SetNumber(5); + e= eSerOff->TGNumberEntry::GetNumberEntry(); + eSerOff->Connect("ValueSet(Long_t)","ctbAcquisition",this,"ChangeSerialOffset(Long_t)"); + e->Connect("ReturnPressed()","ctbAcquisition",this,"ChangeSerialOffset()"); + + + label=new TGLabel(hframe,"N counters:"); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + label->MapWindow(); + label->SetTextJustify(kTextRight); + + + eNumCount=new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELLimitMinMax,0,16535); + hframe->AddFrame(eNumCount,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eNumCount->MapWindow();; + eNumCount->SetNumber(64*3); + e= eNumCount->TGNumberEntry::GetNumberEntry(); + eNumCount->Connect("ValueSet(Long_t)","ctbAcquisition",this,"ChangeNumberOfChannels(Long_t)"); + e->Connect("ReturnPressed()","ctbAcquisition",this,"ChangeNumberOfChannels()"); + + + + cout << "dr "<< endl; + + label=new TGLabel(hframe,"Dynamic Range:"); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + label->MapWindow(); + label->SetTextJustify(kTextRight); + + + eDynRange=new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELLimitMinMax,0,16535); + hframe->AddFrame(eDynRange,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eDynRange->MapWindow();; + eDynRange->SetNumber(24); + e= eDynRange->TGNumberEntry::GetNumberEntry(); + eDynRange->Connect("ValueSet(Long_t)","ctbAcquisition",this,"ChangeDynamicRange(Long_t)"); + e->Connect("ReturnPressed()","ctbAcquisition",this,"ChangeDynamicRange()"); + + + + + + + + hframe=new TGHorizontalFrame(this, 800,50); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); + hframe->MapWindow(); + + + + label=new TGLabel(hframe,"Pedestal "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + label->MapWindow(); + label->SetTextJustify(kTextRight); + + + + cbGetPedestal= new TGCheckButton(hframe, "Acquire"); + hframe->AddFrame(cbGetPedestal,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + cbGetPedestal->MapWindow(); + + cbSubtractPedestal= new TGCheckButton(hframe, "Subtract"); + hframe->AddFrame(cbSubtractPedestal,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + cbSubtractPedestal->MapWindow(); + + + cbSubtractPedestal->Connect("Toggled(Bool_t)","ctbAcquisition",this,"TogglePedSub(Bool_t)"); + + cbCommonMode= new TGCheckButton(hframe, "Common Mode"); + hframe->AddFrame(cbCommonMode,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + cbCommonMode->MapWindow(); + + + cbCommonMode->Connect("Toggled(Bool_t)","ctbAcquisition",this,"ToggleCommonMode(Bool_t)"); + + + bResetPedestal= new TGTextButton(hframe, "Reset"); + hframe->AddFrame(bResetPedestal,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + bResetPedestal->MapWindow(); + + + bResetPedestal->Connect("Clicked()","ctbAcquisition",this,"resetPedestal()"); + + + + + + hframe=new TGHorizontalFrame(this, 800,50); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); + hframe->MapWindow(); + + + cMinMaxRaw=new TGCheckButton(hframe,"Raw data "); + hframe->AddFrame(cMinMaxRaw,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + cMinMaxRaw->MapWindow(); + cMinMaxRaw->Connect("Toggled(Bool_t)","ctbAcquisition",this,"ChangeHistoLimitsRaw(Bool_t)"); + + + + + label=new TGLabel(hframe,"Min: "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + label->MapWindow(); + label->SetTextJustify(kTextRight); + + + eMinRaw=new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELLimitMinMax,0,16535); + hframe->AddFrame(eMinRaw,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eMinRaw->MapWindow();; + eMinRaw->SetNumber(0); + e= eMinRaw->TGNumberEntry::GetNumberEntry(); + eMinRaw->Connect("ValueSet(Long_t)","ctbAcquisition",this,"ChangeHistoLimitsRaw(Long_t)"); + e->Connect("ReturnPressed()","ctbAcquisition",this,"ChangeHistoLimitsRaw()"); + + + label=new TGLabel(hframe,"Max: "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + label->MapWindow(); + label->SetTextJustify(kTextRight); + + + + + eMaxRaw=new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELLimitMinMax,0,16535); + hframe->AddFrame(eMaxRaw,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eMaxRaw->MapWindow();; + eMaxRaw->SetNumber(16535); + + e= eMaxRaw->TGNumberEntry::GetNumberEntry(); + eMaxRaw->Connect("ValueSet(Long_t)","ctbAcquisition",this,"ChangeHistoLimitsRaw(Long_t)"); + e->Connect("ReturnPressed()","ctbAcquisition",this,"ChangeHistoLimitsRaw()"); + + + hframe=new TGHorizontalFrame(this, 800,50); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); + hframe->MapWindow(); + + + + cMinMaxPedSub=new TGCheckButton(hframe,"Pedestal Subtracted "); + hframe->AddFrame(cMinMaxPedSub,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + cMinMaxPedSub->MapWindow(); + cMinMaxPedSub->Connect("Toggled(Bool_t)","ctbAcquisition",this,"ChangeHistoLimitsPedSub(Bool_t)"); + + + label=new TGLabel(hframe,"Min: "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + label->MapWindow(); + label->SetTextJustify(kTextRight); + + + eMinPedSub=new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEAAnyNumber, + TGNumberFormat::kNELLimitMinMax,-16535,16535); + hframe->AddFrame(eMinPedSub,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eMinPedSub->MapWindow();; + eMinPedSub->SetNumber(-100); + + e= eMinPedSub->TGNumberEntry::GetNumberEntry(); + + eMinPedSub->Connect("ValueSet(Long_t)","ctbAcquisition",this,"ChangeHistoLimitsPedSub(Long_t)"); + e->Connect("ReturnPressed()","ctbAcquisition",this,"ChangeHistoLimitsPedSub()"); + + + label=new TGLabel(hframe,"Max: "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + label->MapWindow(); + label->SetTextJustify(kTextRight); + + + eMaxPedSub=new TGNumberEntry(hframe,0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEAAnyNumber, + TGNumberFormat::kNELLimitMinMax,-16535,16535); + hframe->AddFrame(eMaxPedSub,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eMaxPedSub->MapWindow();; + eMaxPedSub->SetNumber(100); + + + e= eMaxPedSub->TGNumberEntry::GetNumberEntry(); + eMaxPedSub->Connect("ValueSet(Long_t)","ctbAcquisition",this,"ChangeHistoLimitsPedSub(Long_t)"); + e->Connect("ReturnPressed()","ctbAcquisition",this,"ChangeHistoLimitsPedSub()"); + + + hframe=new TGHorizontalFrame(this, 800,50); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); + hframe->MapWindow(); + + + + + + TGTextButton *b= new TGTextButton(hframe, "Fit Panel ADC:"); + hframe->AddFrame(b,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + b->MapWindow(); + + + b->Connect("Clicked()","ctbAcquisition",this,"FitADC()"); + + + eFitADC=new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELLimitMinMax,0,31); + hframe->AddFrame( eFitADC,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eFitADC->MapWindow();; + + + + hframe=new TGHorizontalFrame(this, 800,50); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); + hframe->MapWindow(); + + + + + + b= new TGTextButton(hframe, "Plot bit:"); + hframe->AddFrame(b,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + b->MapWindow(); + + + b->Connect("Clicked()","ctbAcquisition",this,"plotBit()"); + + + eBitPlot=new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELLimitMinMax,0,64); + hframe->AddFrame( eBitPlot,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eBitPlot->MapWindow();; + + + + + + hframe=new TGHorizontalFrame(this, 800,50); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); + hframe->MapWindow(); + + + + label=new TGLabel(hframe,"X "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + label->MapWindow(); + label->SetTextJustify(kTextRight); + + + label=new TGLabel(hframe," "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + lClickX=label; + + + + label=new TGLabel(hframe,"Y "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + label->MapWindow(); + label->SetTextJustify(kTextRight); + + + + label=new TGLabel(hframe," "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + lClickY=label; + + + label=new TGLabel(hframe,"Value "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + label->MapWindow(); + label->SetTextJustify(kTextRight); + + + + + + label=new TGLabel(hframe," "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + lClickValue=label; + + + + + + + + b= new TGTextButton(hframe, "Refresh"); + hframe->AddFrame(b,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + b->MapWindow(); + + + b->Connect("Clicked()","ctbAcquisition",this,"Draw()"); + + + + + + + + + + + acqThread = new TThread("acqThread", + ctbAcquisition::ThreadHandle,(void*)this); + // acqThread->Run(); + cout <<"Registering progress callback" << endl; + try { + myDet->registerProgressCallback(&progressCallback,(void*)this); + } catch (...) { + cout << "Do nothing for this error" << endl; + } + + cout <<"Registering data callback" << endl; + try{ + myDet->registerDataCallback(&dataCallback, (void*)this); + } catch (...) { + cout << "Do nothing for this error" << endl; + } + + cout <<"Done" << endl; + + // mgAdcs=new TMultiGraph(); + adcStack=new THStack(); + TH1F *h; + int nSamples=nAnalogSamples; + + for (int i=0; iSetLineColor(i+1); + h->SetLineWidth(2); + adcStack->Add(h); + adcHisto[i]=h; + plotFlag[i]=0; + // h->SetMinimum(-1); + // h->SetMaximum(16385); + } + + + // mgAdcs=new TMultiGraph(); + // bitStack=new THStack(); + bitStack=adcStack; + TH1F *hb; + for (int i=0; iSetLineColor(i+1); + hb->SetLineWidth(2); + bitStack->Add(hb); + bitHisto[i]=hb; + bitOffset[i]=0; + bitPlotFlag[i]=0; + // h->SetMinimum(-1); + // h->SetMaximum(16385); + } + + + countsStack=new THStack(); + TH1F *h1; + for (int i=0; iSetLineColor(i+1); + h1->SetFillColor(i+1); + h1->SetLineWidth(2); + countsStack->Add(h1); + countsHisto[i]=h1; + } + + int nx,ny; + int csize=3; + int nsigma=5; + + dataStructure=NULL; + commonMode=NULL; + photonFinder=NULL; + h2DMap=NULL; + //h2Scan=NULL; + h1DMap=NULL; + + changeDetector(cbDetType->GetSelected()); + + + + // display could be updated with TTimer instead of with histogramfillthread: + // plotTimer= new TTimer("ctbAcquisition::Draw()",100); + + + // plotTimer->Connect("TurnOff()", "ctbAcquisition", this, "Draw()"); +} + + + + +void ctbAcquisition::canvasClicked() { + int event = gPad->GetEvent(); + if (event != 11) return; + TObject *select = gPad->GetSelected(); + if (!select) return; + + if (select->InheritsFrom("TH2")) { + TH2* hh=(TH2*)select; + + + + + int px = gPad->GetEventX(); + int py = gPad->GetEventY(); + Float_t upy = gPad->AbsPixeltoY(py); + Float_t y = gPad->PadtoY(upy); + Float_t upx = gPad->AbsPixeltoX(px); + Float_t x = gPad->PadtoY(upx); + + + // cout << "x: " << x << " y: " << y << " " << hh->GetBinContent(hh->GetXaxis()->FindBin(x), hh->GetYaxis()->FindBin(y)) << endl; + + + lClickX->SetText(hh->GetXaxis()->FindBin(x)-1); + lClickY->SetText( hh->GetYaxis()->FindBin(y)-1); + lClickValue->SetText(hh->GetBinContent(hh->GetXaxis()->FindBin(x), hh->GetYaxis()->FindBin(y))); + + + + + + + } else if (select->InheritsFrom("TH1")) { + + TH1* h1=(TH1*)select; + int px = gPad->GetEventX(); + Float_t upx = gPad->AbsPixeltoX(px); + Float_t x = gPad->PadtoY(upx); + + + // cout << "x: " << x << " y: " << y << " " << hh->GetBinContent(hh->GetXaxis()->FindBin(x), hh->GetYaxis()->FindBin(y)) << endl; + + + lClickX->SetText(h1->GetXaxis()->FindBin(x)-1); + lClickY->SetText(" "); + lClickValue->SetText(h1->GetBinContent(h1->GetXaxis()->FindBin(x))); + + + + + + } else// if ((select->ClassName())=="THStack") { + { + + + int px = gPad->GetEventX(); + int py = gPad->GetEventY(); + Float_t upy = gPad->AbsPixeltoY(py); + Float_t y = gPad->PadtoY(upy); + Float_t upx = gPad->AbsPixeltoX(px); + Float_t x = gPad->PadtoY(upx); + + + lClickX->SetText(x); + lClickY->SetText(y); + lClickValue->SetText(""); + + + + } + +} + + + + + + +void ctbAcquisition::setCanvas(TCanvas* c) { + myCanvas=c; + myCanvas->cd(); + myCanvas->AddExec("dynamic",Form("((ctbAcquisition*)0x%x)->canvasClicked()",this)); + // myCanvas->AddExec("ex","canvasClicked()"); +} +int ctbAcquisition::dataCallback(detectorData *data, int index, int dum, void* pArgs) { + + return ((ctbAcquisition*)pArgs)->plotData(data,index); +} + + +int ctbAcquisition::plotData(detectorData *data, int index) { + + /* +****************************************************************** +When selecting dbit +amount of data is nadc * nasamples * 16 bit + ndbitlist * ndsamples (bits) +order of data +analog: +sample0 (adc0 + adc1 +...) +sample1 (adc0 + adc1 +...) +digital: +dbit0 (sample0 + sample1 ...) +dbit1 (sample0 + sample1..) + +when setting dbit to all +amount of data: nadc * nasamples * 16 bit + 8 * ndsamples * 64 bit +what you had before.. +except analog first, then digital +analog: +sample0 (adc0 + adc1 +...) +sample1 (adc0 + adc1 +...) +digital: +sample0 (dbit0 + dbit1 +...) +sample1 (dbit0 + dbit1 +...)if (cmd == "rx_dbitlist") { + + myDet->setReceiverOnline(ONLINE_FLAG, detPos); + + if (action == PUT_ACTION) { + std::vector dbitlist; + + // if not all digital bits enabled + if (std::string(args[1]) != "all") { + for (int i = 1; i < narg; ++i) { + int temp = 0; + if (!sscanf(args[i], "%d", &temp)) + return std::string("Could not scan dbitlist value ") + + std::string(args[i]); + if (temp < 0 || temp > 63) + return std::string("dbitlist value should be between 0 and 63 ") + + std::string(args[i]); + dbitlist.push_back(temp); + } + if (dbitlist.size() > 64) { + return std::string("Max number of values for dbitlist is 64 "); + } + } + + myDet->setReceiverDbitList(dbitlist, detPos); + } + +****************************************************************** +*/ + + // cout << "plot data" << endl; + + + // cout <<"global plot is " << globalPlot << endl; + cout << "*******************************************" <progressIndex << " npoints:" << data->npoints << " npy: " << data->npy << " " << data->fileName << " bytes: " << data->databytes << " dr:"<< data->dynamicRange << " fi: " << data ->fileIndex << endl; + if (globalPlot || cbGetPedestal->IsOn()) { + //#ifdef TESTADC + // cout <<"------"<< index << " " << ip << " " << data->npoints << endl; + //#endif + int ig=0; + int i, ii, ich=0, ib, vv; + // TList *l= adcStack->GetHists(); + // TList *l1= countsStack->GetHists(); + TH1F *h; + TH1F *h1; + TH1F *hb; + int nb, x,y; + double ped=0; + int vv1,vv2; + int dsize=-1; + short unsigned int **val=NULL; + int nx=1, ny=1, jj; + short unsigned int *va; + if (dataStructure) { + dataStructure->getDetectorSize(nx,ny); + cout << "Data structure: " << dataStructure << " size " << nx << " " << ny << endl; + } + + i=0; + int nadc; + int ndbit; + + + + + + + if (adclist.empty()) + nadc=32; + else + nadc=adclist.size(); + + if (dbitlist.empty()) { + ndbit=64; + dBitOffset=0; + } else + ndbit=dbitlist.size(); + + dsize=nadc*2*nAnalogSamples+ndbit*(nDigitalSamples-dBitOffset/8)/8; + + cout << "dataBytes is " << data->databytes << " expected " << dsize << endl; + + cout << "*******************************************" <getChannel(i);//*((uint16_t*)(data->cvalues+i*2));// + + // cout << "asample " << ip << " adc " << ig << " " << i << " " << aval << endl; + + ped=0; + + + + if (dataStructure) { + dataStructure->getPixel(i,x,y); + + + + if (cbGetPedestal->IsOn()) { + if (photonFinder) { + photonFinder->addToPedestal(aval,x,y); + } + } + + if (plotFlag[ig]) { + + if (cbSubtractPedestal->IsOn()) { + if (photonFinder) { + ped=photonFinder->getPedestal(x,y,cmSub); + } + } + + + //normal filling except when deserializer + if (h2DMap) + h2DMap->SetBinContent(x+1,y+1,aval-ped); + if (h1DMap){ + h1DMap->SetBinContent(x+1,aval-ped); + // cout << "plotting 1D " << endl; + } + // if (h2Scan) { + // //cout << "plotting Scan " << endl; + // h2Scan->SetBinContent((x+1)+y*nx,iScanStep+1,data->getChannel(i)-ped); + // } else + // cout << "No scan (analog)" << endl; + } + } + + + + + //if (enableFlag[ig]) { + h=adcHisto[ig]; + h1=countsHisto[ig]; + //} + + if (plotFlag[ig]) { + // cout << data->getChannel(i) << endl; + h->SetBinContent(ip+1,aval-ped); + h1->Fill(aval-ped); + } + + i++; + } + + } + + char *d_data= data->cvalues+2*nadc*nAnalogSamples; + char dval; + + + /**** Digital Samples ****/ + + + + if (dataStructure) { + + val=dataStructure->getData(d_data); + + if (val) { + if (h2DMap) { + for (x=0; xSetBinContent(x+1,y+1,val[y][x]); + } + } + } + if (h1DMap){ + for (x=0; xSetBinContent(x+1,val[0][x]); + // cout << dec << x << " " << val[0][x] << endl; + } + } + // if (h2Scan) { + // for (x=0; xSetBinContent((x+1)+y*nx,iScanStep+1,val[y][x]); + // } + // } + // } else + // cout << "No scan (digital)" << endl; + + for (y=0; yGetHists()->Contains(hb)==0) cout << "ERROR!" << endl; + //#define ADCSAR2 +// #ifdef ADCSAR2 +// if (ib==0) vv1=dval; +// if (ib==16) vv2=dval; +// cout << ib << " " << hex << vv << dec << endl; +// #endif + if (dval&(1<<(ib%8))) + hb->SetBinContent(ip+1,1+bitOffset[ib]); + else + hb->SetBinContent(ip+1,bitOffset[ib]); + } + } + +// #ifdef ADCSAR2 +// //this is a deserializer similar to MYTHEN! +// hb=bitHisto[0]; +// int adcvalue=0; +// // int startbit= ig; +// for (int jj=0;jj<8;jj++){ +// adcvalue=adcvalue+ (((vv1>>(jj*2)) & 0x1)<<(jj)); +// } +// for (int jj=0;jj<4;jj++){ +// adcvalue=adcvalue+ (((vv2>>(jj*2)) & 0x1)<<(jj+8)); +// } +// hb->SetBinContent(ip+1, adcvalue); +// printf(" %d 0x%x 0x%x adc=%d \n", i, vv1, vv2, adcvalue); +// #endif + } + } + } else { + ii=0; + int iii=0; + int nb=dbitlist.size(); + for (const auto &value : dbitlist) { + ib=value; + hb=bitHisto[ib]; + cout << dec <SetBinContent(iii,1+bitOffset[ib]); + else + hb->SetBinContent(iii,bitOffset[ib]); + iii++; + } + } + } + ii++; + } + } + + Draw(); + // iScanStep++; + if (photonFinder) + photonFinder->newFrame(); + return i; +} + return 0; + +} + +void ctbAcquisition::Draw(){ + if (globalPlot) { + // TThread::Lock(); + cout << "Draw" << endl; + if (myCanvas && globalPlot!=0) { + myCanvas->cd(); + myCanvas->Modified(); + myCanvas->Update(); + } + // TThread::UnLock(); + } + +} + + + +void ctbAcquisition::changePlot(){ + if (rbPlotOff->IsOn()) { + globalPlot=0; + } else { + globalPlot=0; + for (int ii=0; iiIsOn()) + if (adcStack) + adcStack->Draw("NOSTACK"); + else + cout << "adcStack is NULL" << endl; + else if (rbDistribution->IsOn()) + if (countsStack) + countsStack->Draw("NOSTACK"); + else + cout << "countsStack is NULL" << endl; + else if (rb2D->IsOn()) { + if (h2DMap) + h2DMap->Draw("colz"); + else if (h1DMap) + h1DMap->Draw(); + else + cout << "h2DMap and h1DMap are NULL" << endl; + } // else if (rbScan->IsOn()) { + // if (h2Scan) + // h2Scan->Draw("colz"); + // else + // cout << "h2Scan is NULL" << endl; + // } + } + Draw(); + +} + + + + + +void ctbAcquisition::changeDetector(){ + // cout << "change detector " << i << " old " << cbDetType->GetSelected() << endl; + + if (dataStructure) delete dataStructure; + if (commonMode) delete commonMode; + if (photonFinder) delete photonFinder; + if (h2DMap) delete h2DMap; + if (h1DMap) delete h1DMap; + // if (h2Scan) delete h2Scan; + h2DMap=NULL; + h1DMap=NULL; + // h2Scan=NULL; + photonFinder=NULL; + dataStructure=NULL; + commonMode=NULL; + TH2F *h2DMapOld=h2DMap; + // TH2F *h2ScanOld=h2Scan; + TH1F *h1DMapOld=h1DMap; + int dim=2; + int nx,ny; + int csize=3; + int nsigma=5; + commonModeSubtraction* cm=0; + eNumCount->SetState(kFALSE); + eDynRange->SetState(kFALSE); + eSerOff->SetState(kFALSE); + if (rb2D->IsOn() ) {//|| rbScan->IsOn() + switch (cbDetType->GetSelected()) { + case MOENCH03: + cout << "MOENCH 0.3 T1!" << endl; + dataStructure=new moench03T1CtbData(); + commonMode=new moench03CommonMode(); + break; + // case 1: + // cout << "************** T!!!!!!!!!!" << endl; + // dataStructure=new moench03TCtbData(); + // commonMode=new moench03CommonMode(); + // break; + case MOENCH02: + cout << "MOENCH 0.2" << endl; + dataStructure=new moench02CtbData(); + commonMode=new moenchCommonMode(); + break; + // case 2: + // dataStructure=new jungfrau10ModuleData(); + // commonMode=new commonModeSubtraction(); + // break; + // case 3: + // cout << "************** Flat!!!!!!!!!!" << endl; + // dataStructure=new moench03CtbData(); + // commonMode=new moench03CommonMode(); + // break; + case MYTHEN301: + cout << "MYTHEN 3 0.1" << endl; + dataStructure=new mythen3_01_jctbData(eNumCount->GetIntNumber(),eDynRange->GetIntNumber(),eSerOff->GetIntNumber()); + //( int nch=64*3,int dr=24, int off=5) + eNumCount->SetState(kTRUE); + eDynRange->SetState(kTRUE); + eSerOff->SetState(kTRUE); + commonMode=NULL; + dim=1; + break; + case ADCSAR2: + //adcsar2 + dataStructure=new adcSar2_jctbData(); + //need to use configurable number of counters, offset or dynamic range? + commonMode=NULL; + dim=1; + break; + + case MYTHEN302: + cout << "MYTHEN 3 0.2" << endl; + dataStructure=new mythen3_02_jctbData(eNumCount->GetIntNumber(),eDynRange->GetIntNumber(),eSerOff->GetIntNumber()); + //( int nch=64*3,int dr=24, int off=5) + eNumCount->SetState(kTRUE); + eDynRange->SetState(kTRUE); + eSerOff->SetState(kTRUE); + commonMode=NULL; + dim=1; + break; + default: + dataStructure=NULL; + commonMode=NULL; + } + if (cbCommonMode->IsOn()) cm=commonMode; + } + + if (dataStructure) { + photonFinder=new singlePhotonDetector(dataStructure,csize,nsigma,1,cm); //sign is positive - should correct with ADC mask, no common mode + //photonFinder=new singlePhotonDetector(dataStructure,csize,nsigma,1,cm); //sign is positive - should correct with ADC mask, no common mode + dataStructure->getDetectorSize(nx,ny); + // cout << "h size is " << nx << " " << ny << endl; + int ymax=ny, xmax=nx; + // if (ny>500) {ny=ny/2;} + // if (nx>500) {nx=nx/2;} + cout << "*** " << nx << " " << ny << endl; + if (rb2D->IsOn()) { + if (ny>1) { + h2DMap=new TH2F("h2dmap","",nx,0,xmax,ny,0,ymax); + h2DMap->SetStats(kFALSE); + cout << "Created h2DMap"<< endl; + } else { + h1DMap=new TH1F("h1dmap","",nx,0,xmax); + h1DMap->SetStats(kFALSE); + cout << "Created h1DMap"<< endl; + } + } // else if (rbScan->IsOn()) { + // int nsteps=0;//myDet->getScanSteps(0); + // double stepmin=0, stepmax=1; + // if (nsteps>0) { + // stepmin=myDet->getScanStep(0,0); + // stepmax=myDet->getScanStep(0,nsteps-1); + // } + // cout << "************ creating scan histogram " << nx*ny << " " << nsteps << " " << stepmin << " " << stepmax << endl; + // if (nsteps<1) nsteps=1; + // double hmin=stepmin, hmax=stepmax; + // if (stepmin>stepmax) { + // hmin=stepmax; + // hmax=stepmin; + // } + // h2Scan=new TH2F("h2scan","",nx*ny,0,nx*ny,nsteps,hmin,hmax); + // } + + } + + + cout << "done " << endl; +} + + + +void ctbAcquisition::changeDetector(int i){ + changePlot(); + changeDetector(); +} + +void ctbAcquisition::changePlot(int i){ + changePlot(); + changeDetector(); +} + + + +void ctbAcquisition::setGraph(int i ,int en, Pixel_t col) { + char name[100]; + // TList *l= mgAdcs->GetListOfGraphs(); + sprintf(name,"adc%d",i); + + // TList *l= adcStack->GetHists(); + TH1F *h=adcHisto[i];//(TH1F*)l->At(i);; + TH1F *h1=countsHisto[i];//(TH1F*)(countsStack->GetHists()->At(i)); + if (en) { + plotFlag[i]=1; + h->SetLineColor(TColor::GetColor(col)); + h1->SetLineColor(TColor::GetColor(col)); + h1->SetFillColor(TColor::GetColor(col)); + + if (adcStack->GetHists()) + // if (adcStack->GetHists()->GetEntries()) + if (adcStack->GetHists()->Contains(h)==0) + adcStack->Add(h); + + if (countsStack->GetHists()) + if (countsStack->GetHists()->Contains(h1)==0) + countsStack->Add(h1); + + cout << "Enable plot " << i << " color " << col << endl; + } else { + cout << "Disable plot " << i << endl; + plotFlag[i]=0; + if (adcStack->GetHists()) + // if (adcStack->GetHists()->GetEntries()) + if (adcStack->GetHists()->Contains(h)) + adcStack->RecursiveRemove(h); + if (countsStack->GetHists()) + if (countsStack->GetHists()->Contains(h1)) + countsStack->RecursiveRemove(h1); + } + cout << countsStack->GetHists()->GetEntries() << endl; + + cout << "Number of histos " << adcStack->GetHists()->GetEntries() << endl; + + changePlot(); + + // globalPlot=0; + // for (int ii=0; iiGetListOfGraphs(); + sprintf(name,"bit%d",i); + // TList *l= adcStack->GetHists(); + TH1F *h=bitHisto[i];//(TH1F*)l->At(i);; + if (en) { + //cout<< "enabling plot of bit "<SetLineColor(TColor::GetColor(col)); + if (bitStack->GetHists()) + //if (bitStack->GetHists()->GetEntries()) + if (bitStack->GetHists()->Contains(h)==0) + bitStack->Add(h); + + + cout << "Enable bit plot " << i << " color " << col << endl; + } else { + cout << "Disable bit plot " << i << endl; + bitPlotFlag[i]=0; + if (bitStack->GetHists()) + // if (bitStack->GetHists()->GetEntries()) + if (bitStack->GetHists()->Contains(h)) + bitStack->RecursiveRemove(h); + } + cout << "Number of histos " << bitStack->GetHists()->GetEntries() << endl; + + changePlot(); + + float off=0; + for (int ii=0; iisetFilePath(eOutdir->GetText()); + } catch (...) { + cout << "Do nothing for this error" << endl; + } +// // cout << "setting dac! "<< id << endl; + +// myDet->setDAC(dacsEntry->GetIntNumber(), (slsDetectorDefs::dacIndex)id, dacsUnit->IsOn()); + +// getValue(); + +} + +void ctbAcquisition::setFname() { + try { + myDet->setFileName(eFname->GetText()); + } catch (...) { + cout << "Do nothing for this error" << endl; + } +// int val=myDet->setDAC(-1, (slsDetectorDefs::dacIndex)id, dacsUnit->IsOn()); +// char s[100]; + +// sprintf(s,"%d",val); + +// dacsValue->SetText(s); + + +// return val; + +} + +void ctbAcquisition::setFindex() { + + try { + myDet->setFileIndex(eFindex->GetNumber()); +} catch (...) { + cout << "Do nothing for this error" << endl; + } + +} + + +void ctbAcquisition::setFsave(Bool_t b) { + try { + myDet->setFileWrite(b); + } catch (...) { + cout << "Do nothing for this error" << endl; + } + eFname->SetState(b); + eOutdir->SetState(b); + +} + +void ctbAcquisition::update() { + + + eFname->SetText((myDet->getFileName()).c_str()); + eOutdir->SetText((myDet->getFilePath()).c_str()); + eFindex->SetNumber(myDet->getFileIndex()); + cFileSave->SetOn(myDet->getFileWrite()); + eFname->SetState(cFileSave->IsOn()); + eOutdir->SetState(cFileSave->IsOn()); + eFindex->SetState(cFileSave->IsOn()); + // eMeasurements->SetNumber(myDet->setTimer(slsDetectorDefs::MEASUREMENTS_NUMBER,-1)); + setAnalogSamples(myDet->setTimer(slsDetectorDefs::ANALOG_SAMPLES,-1)); + setDigitalSamples(myDet->setTimer(slsDetectorDefs::DIGITAL_SAMPLES,-1)); + roMode=myDet->setReadOutFlags(); + setReadoutMode(roMode); + //nChannels=myDet->getTotalNumberOfChannels(); + updateChans(); + + if (dataStructure) { + cout << cbDetType->GetSelected()<< endl; + if (cbDetType->GetSelected()==MYTHEN301 || cbDetType->GetSelected()==MYTHEN302){ + cout << "settings deserialiation parameters for MYTHEN" << endl; + mythen3_01_jctbData* ms=(mythen3_01_jctbData*)dataStructure; + eSerOff->SetNumber( ms->setSerialOffset(-1)); + eDynRange->SetNumber( ms->setDynamicRange(-1)); + eNumCount->SetNumber( ms->setNumberOfCounters(-1)); + } + + } + dBitOffset=myDet->getReceiverDbitOffset(); + + // char aargs[10][100]; + // char *args[10]; + // for (int i=0; i<10; i++) + // args[i]=aargs[i]; + + // string retval; + // sprintf(args[0],"adcdisable"); + // slsDetectorCommand *cmd=new slsDetectorCommand(myDet); + // retval=cmd->executeLine(1,args,slsDetectorDefs::GET_ACTION); + // delete cmd; + // int mask; + // sscanf(retval.c_str(),"adcdisable %d",&mask); + // for (int i=0; iGetState()==1 || acqThread->GetState()==6) { + + + if (cCompile->IsOn()) { + sprintf(fname,"%s %s",patternCompiler,patternFile); + cout << "Compile: " << fname << endl; + strcpy(currdir,gSystem->pwd()); + + std::size_t found = string(patternCompiler).rfind('/'); + if (found!=std::string::npos) + gSystem->cd(string(patternCompiler).substr(0,found).c_str()); + + gSystem->cd(cdir); + system(fname); + gSystem->cd(currdir); + } + + if (string(patternCompiler).rfind(".pat")!=std::string::npos) + strcpy(fname,patternFile); + else if (string(patternCompiler).rfind(".npat")!=std::string::npos) + strcpy(fname,patternFile); + else + sprintf(fname,"%sat",patternFile); + + cout << "Load: " << fname << endl; + try { + myDet->retrieveDetectorSetup(fname); + } catch (...) { + cout << "Do nothing for this error" << endl; + } + } +} + + +void ctbAcquisition::toggleAcquisition() { + + + if (acqThread->GetState()==1 || acqThread->GetState()==6) { + /** update all infos useful for the acquisition! */ + + setAnalogSamples(myDet->setTimer(slsDetectorDefs::ANALOG_SAMPLES,-1)); + setDigitalSamples(myDet->setTimer(slsDetectorDefs::DIGITAL_SAMPLES,-1)); + dBitOffset=myDet->getReceiverDbitOffset(); + roMode=myDet->setReadOutFlags(); + setReadoutMode(roMode); + + + + // iScanStep=0; + + cout << "Run" << endl; + bStatus->SetText("Stop"); + ip=0; + for (int i=0; iGetListOfFunctions()) + adcHisto[i]->GetListOfFunctions()->Delete(); + + adcHisto[i]->Reset(); + + if (countsHisto[i]->GetListOfFunctions()) + countsHisto[i]->GetListOfFunctions()->Delete(); + countsHisto[i]->Reset(); + // ((TH1F*)adcStack->GetHists()->At(i))->Reset(); + // ((TH1F*)countsStack->GetHists()->At(i))->Reset(); + } + for (int i=0; iReset(); + } + cout << "reset 2d" << endl;; + if (h2DMap) h2DMap->Reset(); + cout << "reset 1d" << endl;; + if (h1DMap) h1DMap->Reset(); + cout << "done" << endl;; + // if (h2Scan) h2Scan->Reset(); + // cout << "reset 1d" << endl;; + // if (rbWaveform->IsOn()) +// adcStack->Draw("NOSTACK"); +// else if (rbDistribution->IsOn()) +// countsStack->Draw("NOSTACK"); +// else if (rb2D->IsOn()) +// h2DMap->Draw("colz"); + + // cout << "timer" << endl; + changePlot(); + + // plotTimer->TurnOn(); + // cout << "thread" << endl; + acqThread->Run(); + StopFlag=0; + + + + + + } else { + StopFlag=1; + try { + myDet->stopAcquisition(); + } catch (...) { + cout << "Do nothing for this error" << endl; + } + stop=1; + bStatus->SetText("Start"); + // acqThread->Kill(); + } +} + +void ctbAcquisition::acquisitionFinished() { + bStatus->SetText("Start"); + cout << "finished " << endl; + // plotTimer->TurnOff(); + Draw(); +} + +void ctbAcquisition::startAcquisition(){ + cout << "Detector started " <GetNumber()<< endl; + stop=0; + for (int im=0; imGetNumber(); im++) { + try { + myDet->acquire(); + } catch (...) { + cout << "Do nothing for this error" << endl; + } + cout << im << endl; + if (stop) break; + } + +} + +void* ctbAcquisition::ThreadHandle(void *arg) +{ + ctbAcquisition *acq = static_cast(arg); + int i=0; + + acq->startAcquisition(); + acq->acquisitionFinished(); + + +} + + int ctbAcquisition::progressCallback(double f,void* arg) { + + + // ctbAcquisition *acq = static_cast(arg); + + + cout << "*********" << f << "*******" << endl; + + + + + } + +void ctbAcquisition::setPatternFile(const char* t) { + + + cout << "New pattern is " << t << endl; + + strcpy(patternFile,t); + } + +void ctbAcquisition::setPatternCompiler(const char* t) { + + + cout << "New compiler is " << t << endl; + strcpy(patternCompiler,t); + + } +void ctbAcquisition::setMeasurements() { + + + + // myDet->setTimer(slsDetectorDefs::MEASUREMENTS_NUMBER,eMeasurements->GetNumber()); + + + +} + +void ctbAcquisition::setAnalogSamples(int n) { + + + cout<< "Set number of analog samples to " << dec<< n << endl; + if (n>0 && n<8192) + nAnalogSamples=n; + + // TList *l= adcStack->GetHists(); + TH1 *h; + // if (l) { + for (int i=0; iAt(i); + if (h) { + + h->SetBins(nAnalogSamples,0,nAnalogSamples); + } + } + + h=adcStack->GetHistogram(); + if (h) + h->SetBins(nAnalogSamples,0,nAnalogSamples); +} + + + +void ctbAcquisition::setDigitalSamples(int n) { + + + cout<< "Set number of digital samples to " << dec<< n << endl; + if (n>0 && n<8192) + nDigitalSamples=n; + + TH1 *h; + for (int i=0; iAt(i); + if (h) { + + h->SetBins(nDigitalSamples,0,nDigitalSamples); + } + + } + // cout<< "histos resized " << dec<< h->GetNbinsX() << endl; + + h=bitStack->GetHistogram(); + if (h) + h->SetBins(nDigitalSamples,0,nDigitalSamples); + +} + +void ctbAcquisition::setReadoutMode(int f) { + + roMode=f; + slsDetectorDefs::readOutFlags flags=(slsDetectorDefs::readOutFlags)f; + if (flags&slsDetectorDefs::DIGITAL_ONLY) { + nAnalogSamples=0; + adclist.clear(); + } else if (flags&slsDetectorDefs::ANALOG_AND_DIGITAL) { + ; + } + else { + nDigitalSamples=0; + dbitlist.clear(); + } + + // for (int i=0; i dbl; + try { + dbl = myDet->getReceiverDbitList(); + } catch (...) { + cout << "Do nothing for this error" << endl; + } + dbitlist.clear(); + if (dbl.empty()) + ; + else { + for (const auto &value : dbl) + dbitlist.push_back(value); + } + uint32_t reg; + try { + reg=myDet->getADCEnableMask(); + } catch (...) { + cout << "Do nothing for this error" << endl; + } + /* adc updated */ + adclist.clear(); + // // updateChans(); + if (reg!=0xffffffff) { + for (int i=0; inewDataSet(); + }; + +} + +void ctbAcquisition::ToggleCommonMode(Bool_t b) { + if (photonFinder) { + if (b) { + photonFinder->setCommonModeSubtraction(commonMode); + cmSub=1; + cout << "Enable common mode" << endl; + } else { + photonFinder->setCommonModeSubtraction(NULL); + cmSub=0; + cout << "Disable common mode" << endl; + } + } + +} + + +void ctbAcquisition::TogglePedSub(Bool_t b) { + if (b) { + ChangeHistoLimitsPedSub(); + } else { + ChangeHistoLimitsRaw(); + } + +} + + +void ctbAcquisition::FitADC() { + int iadc=eFitADC->GetNumber(); + if (iadc<0 || iadc>=NADCS) return; + cout << "fit panel for adc " << eFitADC->GetNumber() << endl; + if (rbWaveform->IsOn()) { + if (adcHisto[iadc]==NULL) return; + new TCanvas("Cadcfit"); + if (adcFit) { + delete adcFit; + adcFit=NULL; + } + adcFit=(TH1F*)(adcHisto[iadc]->Clone("adcfit")); + adcFit->Draw(); + adcFit->FitPanel(); + + } else if (rbDistribution->IsOn()) { + if (countsHisto[iadc]==NULL) return; + new TCanvas("Ccountsfit"); + + if (countsFit) { + delete countsFit; + countsFit=NULL; + } + + countsFit=(TH1F*)(countsHisto[iadc]->Clone("countsfit")); + countsFit->Draw(); + countsFit->FitPanel(); + } +} + + +void ctbAcquisition::plotBit() { + int iadc=eBitPlot->GetNumber(); + if (iadc<0 || iadc>=NSIGNALS) return; + cout << "plot panel for bit " << eBitPlot->GetNumber() << endl; + if (bitHisto[iadc]==NULL) return; + new TCanvas("Cbitplot"); + if (bitPlot) { + delete bitPlot; + bitPlot=NULL; + } + bitPlot=(TH1F*)(bitHisto[iadc]->Clone("bitplot")); + bitPlot->Draw(); +} + + + + + + + + + + +void ctbAcquisition::ChangeSerialOffset(Long_t a){ + ChangeSerialOffset(); +}; + + +void ctbAcquisition::ChangeDynamicRange(Long_t a){ + ChangeDynamicRange(); +}; + +void ctbAcquisition::ChangeNumberOfChannels(Long_t a){ + ChangeNumberOfChannels(); +}; + + + +void ctbAcquisition::ChangeSerialOffset(){ + if (dataStructure) { + + cout << cbDetType->GetSelected()<< endl; + if (cbDetType->GetSelected()==MYTHEN301 || cbDetType->GetSelected()==MYTHEN302 ){ + cout << "settings offsets for MYTHEN" << endl; + mythen3_01_jctbData* ms=(mythen3_01_jctbData*)dataStructure; + ms->setSerialOffset(eSerOff->GetIntNumber()); + + } + } +}; + + +void ctbAcquisition::ChangeDynamicRange(){ + if (dataStructure) { + + cout << cbDetType->GetSelected()<< endl; + if (cbDetType->GetSelected()==MYTHEN301 || cbDetType->GetSelected()==MYTHEN302){ + cout << "settings dynamic range for MYTHEN" << endl; + mythen3_01_jctbData* ms=(mythen3_01_jctbData*)dataStructure; + ms->setDynamicRange(eDynRange->GetIntNumber()); + + } + } +}; + +void ctbAcquisition::ChangeNumberOfChannels(){ + if (dataStructure) { + cout << cbDetType->GetSelected()<< endl; + if (cbDetType->GetSelected()==MYTHEN301 || cbDetType->GetSelected()==MYTHEN302){ + cout << "settings number of channels for MYTHEN" << endl; + mythen3_01_jctbData* ms=(mythen3_01_jctbData*)dataStructure; + ms->setNumberOfCounters(eNumCount->GetIntNumber()); + + } + } +}; + + + +void ctbAcquisition::ChangeHistoLimitsPedSub(Long_t a){ + ChangeHistoLimitsPedSub(); +}; + + +void ctbAcquisition::ChangeHistoLimitsRaw(Long_t a){ + ChangeHistoLimitsRaw(); +} + +void ctbAcquisition::ChangeHistoLimitsPedSub(Bool_t a){ + ChangeHistoLimitsPedSub(); +}; + + +void ctbAcquisition::ChangeHistoLimitsRaw(Bool_t a){ + ChangeHistoLimitsRaw(); +} + + +void ctbAcquisition::ChangeHistoLimitsPedSub(){ + + cout << "set Limits ped sub hist " << eMinPedSub->GetNumber() << " " << eMaxPedSub->GetNumber() << endl; + + if (eMinPedSub->GetNumber()>eMaxPedSub->GetNumber()) + return; + + if (cbSubtractPedestal->IsOn()) { + if (cMinMaxPedSub->IsOn()) { + adcStack->SetMaximum( eMaxPedSub->GetNumber()); + adcStack->SetMinimum( eMinPedSub->GetNumber()); + if (h2DMap) { + h2DMap->SetMaximum( eMaxPedSub->GetNumber()); + h2DMap->SetMinimum( eMinPedSub->GetNumber()); + } + if (h1DMap) { + h1DMap->SetMaximum( eMaxPedSub->GetNumber()); + h1DMap->SetMinimum( eMinPedSub->GetNumber()); + } + if (countsStack->GetHistogram()) + countsStack->GetHistogram()->GetXaxis()->SetRangeUser(eMinPedSub->GetNumber(), eMaxPedSub->GetNumber()); + } else { + if (adcStack->GetHistogram()) + adcStack->GetHistogram()->GetYaxis()->UnZoom(); + if (h2DMap) { + h2DMap->GetZaxis()->UnZoom(); + } + if (h1DMap) { + h1DMap->GetYaxis()->UnZoom(); + } + if (countsStack->GetHistogram()) + countsStack->GetHistogram()->GetXaxis()->UnZoom(); + } + } + + +}; + + +void ctbAcquisition::ChangeHistoLimitsRaw(){ + + cout << "set Limits raw hist " << eMinRaw->GetNumber() << " " << eMaxRaw->GetNumber() << endl; + if (eMinRaw->GetNumber()>eMaxRaw->GetNumber()) + return; + + if (cbSubtractPedestal->IsOn()==0) { + if (cMinMaxRaw->IsOn()) { + adcStack->SetMaximum( eMaxRaw->GetNumber()); + adcStack->SetMinimum( eMinRaw->GetNumber()); + if (h2DMap) { + h2DMap->SetMaximum( eMaxRaw->GetNumber()); + h2DMap->SetMinimum( eMinRaw->GetNumber()); + } + if (h1DMap) { + h1DMap->SetMaximum( eMaxRaw->GetNumber()); + h1DMap->SetMinimum( eMinRaw->GetNumber()); + } + if (countsStack->GetHistogram()) + countsStack->GetHistogram()->GetXaxis()->SetRangeUser(eMinRaw->GetNumber(), eMaxRaw->GetNumber()); + } else { + + if (adcStack->GetHistogram()) + adcStack->GetHistogram()->GetYaxis()->UnZoom(); + if (h2DMap) { + h2DMap->GetZaxis()->UnZoom(); + } + + if (h1DMap) { + h1DMap->GetYaxis()->UnZoom(); + } + if (countsStack->GetHistogram()) + countsStack->GetHistogram()->GetXaxis()->UnZoom(); + + } + } + +} diff --git a/ctbGui/ctbAcquisition.h b/ctbGui/ctbAcquisition.h new file mode 100755 index 000000000..01d3964e4 --- /dev/null +++ b/ctbGui/ctbAcquisition.h @@ -0,0 +1,234 @@ +#ifndef CTBACQUISITION_H +#define CTBACQUISITION_H +#include + +#include "ctbAdcs.h" +#include "ctbSignals.h" +#include "ctbPattern.h" +class TGTextEntry; +class TGLabel; +class TGNumberEntry; +class TGCheckButton; +class TThread; +class TGraph; +class TMultiGraph; +class THStack; +class TGButtonGroup; +class TGRadioButton; +class TGComboBox; +class TTimer; +class TCanvas; +class TH2F; +class TH1F; +class TGLabel; +class TGTextButton; + +class multiSlsDetector; +class detectorData; + +template class slsDetectorData; +class singlePhotonDetector; +//class singlePhotonDetector; +class commonModeSubtraction; + +#include +#include +using namespace std; + +class ctbAcquisition : public TGGroupFrame { + + + enum {MOENCH03, MOENCH02, ADCSAR2, MYTHEN301, MYTHEN302}; + + + private: + TGTextEntry *eOutdir; + TGTextEntry *eFname; + TGNumberEntry *eFindex; + TGCheckButton *cFileSave; + + + TGNumberEntry *eSerOff; + TGNumberEntry *eDynRange; + TGNumberEntry *eNumCount; + + + TGNumberEntry *eFitADC; + TGNumberEntry *eBitPlot; + TGNumberEntry *eMinRaw; + TGNumberEntry *eMaxRaw; + TGNumberEntry *eMinPedSub; + TGNumberEntry *eMaxPedSub; + TGCheckButton *cMinMaxRaw; + TGCheckButton *cMinMaxPedSub; + + + + + TGNumberEntry *eMeasurements; + + + + TGTextButton *bStatus; + // TGTextButton + TGCheckButton *cCompile; + TGTextButton *cLoad; + // TGCheckButton *cRun; + + TThread *acqThread; + + + THStack *adcStack; + THStack *bitStack; + THStack *countsStack; + + + TH1F *adcHisto[NADCS]; + TH1F *countsHisto[NADCS]; + + TH1F *bitHisto[NSIGNALS]; + float bitOffset[NSIGNALS]; + + // int enableFlag[NADCS+4]; + int roMode; + + int dBitOffset; + + + + TH1F *adcFit; + TH1F *bitPlot; + TH1F *countsFit; + + + + TH2F *h2DMap; // for 2D detectors + TH1F *h1DMap; //for 1D detectors + + // TH2F *h2Scan; // for 2D detectors + // TMultiGraph *mgAdcs; + // TH1I *plotAdc[NADCS]; + + + multiSlsDetector* myDet; + + int plotFlag[NADCS]; + int bitPlotFlag[NSIGNALS]; + + int ip; + // int nChannels; + // int chanEnable; + //int nADCs; + + std::vector dbitlist; + std::vector adclist; + + TGButtonGroup *bgPlot;// = new TGVButtonGroup(main_frame); + TGRadioButton *rbPlotOff; + TGRadioButton *rbWaveform; + TGRadioButton *rbDistribution; + TGRadioButton *rb2D; + // TGRadioButton *rbScan; + TGComboBox *cbDetType; + TGCheckButton *cbGetPedestal; + TGCheckButton *cbSubtractPedestal; + TGCheckButton *cbCommonMode; + TGTextButton *bResetPedestal; + + TGLabel *lClickX; + TGLabel *lClickY; + TGLabel *lClickValue; + + + TCanvas *myCanvas; + TTimer *plotTimer; + + char patternFile[10000]; + char patternCompiler[10000]; + + int globalPlot; + + int nAnalogSamples, nDigitalSamples; + // int iScanStep; + + slsDetectorData *dataStructure; + singlePhotonDetector *photonFinder; + //singlePhotonDetector *photonFinder; + commonModeSubtraction *commonMode; + int cmSub; + + int stop; + + uint64_t dBitMask; + + + + public: + ctbAcquisition(TGVerticalFrame*, multiSlsDetector*); + void setOutdir(); + void setFname(); + void setMeasurements(); + void setFsave(Bool_t); + void changePlot(Int_t); + void changeDetector(Int_t); + void changePlot(); + void changeDetector(); + void setFindex(); + void Draw(); + void setCanvas(TCanvas*); + + void toggleAcquisition(); + void loadPattern(); + static void* ThreadHandle(void *arg); + void update(); + void acquisitionFinished(); + // string getParameters(); + + void setGraph (int i ,int en, Pixel_t col); + void setBitGraph (int i ,int en, Pixel_t col); + void startAcquisition(); + static int progressCallback(double,void*); + static int dataCallback(detectorData*, int,int, void*); + int StopFlag; + + int plotData(detectorData*, int); + + void setPatternFile(const char* t); + + void setPatternCompiler(const char* t); + + void setAnalogSamples(int); + void setDigitalSamples(int); + + void setADCEnable(Int_t); + void setDbitEnable(Int_t); + void setReadoutMode(int); + void updateChans(); + + void resetPedestal(); + + void ToggleCommonMode(Bool_t); + void TogglePedSub(Bool_t); + void ChangeHistoLimitsPedSub(Long_t ); + void ChangeHistoLimitsRaw(Long_t); + void ChangeHistoLimitsPedSub( ); + void ChangeHistoLimitsRaw(); + void ChangeHistoLimitsPedSub(Bool_t ); + void ChangeHistoLimitsRaw(Bool_t); + + + void ChangeSerialOffset(); + void ChangeSerialOffset(Long_t); + void ChangeNumberOfChannels(); + void ChangeNumberOfChannels(Long_t); + void ChangeDynamicRange(); + void ChangeDynamicRange(Long_t); + + + void canvasClicked(); + void FitADC(); + void plotBit(); + ClassDef(ctbAcquisition,0) +}; + +#endif diff --git a/ctbGui/ctbAdcs.cpp b/ctbGui/ctbAdcs.cpp new file mode 100755 index 000000000..927b8de3a --- /dev/null +++ b/ctbGui/ctbAdcs.cpp @@ -0,0 +1,710 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ctbAdcs.h" +#include "multiSlsDetector.h" +#include "slsDetectorCommand.h" + +using namespace std; + + + +ctbAdc::ctbAdc(TGVerticalFrame *page, int i, multiSlsDetector *det) + : TGHorizontalFrame(page, 800,800), id(i), myDet(det) { + + TGHorizontalFrame *hframe=this; + char tit[100]; + + page->AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + hframe->MapWindow(); + + + + + + sprintf(tit, "ADC%d", id); + + sAdcLabel= new TGLabel(hframe, tit); + hframe->AddFrame(sAdcLabel,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + sAdcLabel->MapWindow(); + sAdcLabel->SetTextJustify(kTextLeft); + + + + + + + sAdcInvert= new TGCheckButton(hframe, "Inv"); + hframe->AddFrame( sAdcInvert,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + sAdcInvert->MapWindow(); + sAdcInvert->Connect("Toggled(Bool_t)","ctbAdc",this,"ToggledInvert(Bool_t)"); + + + sAdcEnable= new TGCheckButton(hframe, "En"); + hframe->AddFrame( sAdcEnable,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + sAdcEnable->MapWindow(); + // sAdcEnable->SetOn(kTRUE); + // sAdcEnable->SetEnabled(kFALSE); + sAdcEnable->Connect("Toggled(Bool_t)","ctbAdc",this,"ToggledEnable(Bool_t)"); + + + + sAdcPlot= new TGCheckButton(hframe, "Plot"); + hframe->AddFrame( sAdcPlot,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + sAdcPlot->MapWindow(); + + + sAdcPlot->Connect("Toggled(Bool_t)","ctbAdc",this,"ToggledPlot(Bool_t)"); + + + + fColorSel = new TGColorSelect(hframe, id+1, 0); + + fColorSel->Connect("ColorSelected(Pixel_t)","ctbAdc",this,"ColorChanged(Pixel_t)"); + hframe->AddFrame(fColorSel, new TGLayoutHints(kLHintsTop | + kLHintsLeft, 2, 0, 2, 2)); + + + fColorSel->SetColor(TColor::Number2Pixel(id+1)); + // sprintf(tit,"adc%d",id); +// gADC=new TGraph(); +// gADC->SetName(tit); +// gADC->SetLineColor(id+1); +// gADC->SetMarkerColor(id+1); + + + +}; +Pixel_t ctbAdc::getColor(){ + return fColorSel->GetColor(); +} +Bool_t ctbAdc::getEnabled(){ + return getPlot(); +} +Bool_t ctbAdc::getPlot(){ + return sAdcPlot->IsOn(); +} +Bool_t ctbAdc::getInverted(){ + return sAdcInvert->IsOn(); +} + +Bool_t ctbAdc::getEnable(){ + return sAdcEnable->IsOn(); +} + + + +void ctbAdc::setInverted(Bool_t b){ + // cout << id << "set enabled " << b << endl; + if (b) + sAdcInvert->SetOn(kTRUE,kTRUE); + else + sAdcInvert->SetOn(kFALSE,kTRUE); + +} + + +void ctbAdc::setEnable(Bool_t b){ + // cout << id << "set enabled " << b << endl; + if (b) + sAdcEnable->SetOn(kTRUE,kFALSE); + else + sAdcEnable->SetOn(kFALSE,kFALSE); + +} + + + + + +void ctbAdc::setAdcAlias(char *tit, int plot, int color) { + if (tit) + sAdcLabel->SetText(tit); + if (plot>0) + sAdcPlot->SetOn(kTRUE,kTRUE); + else if (plot==0) + sAdcPlot->SetOn(kFALSE,kTRUE); + if (color>=0) + fColorSel->SetColor(color); + fColorSel->SetEnabled(sAdcPlot->IsOn()); +} + + +string ctbAdc::getAdcAlias() { + + char line[1000]; + sprintf(line,"ADC%d %s %d %x\n",id,sAdcLabel->GetText()->Data(),sAdcPlot->IsOn(),fColorSel->GetColor()); + return string(line); +} + +void ctbAdc::update() { + + + //Emit("ToggledAdcEnable(Int_t)", id); + +} + + +void ctbAdc::ToggledPlot(Bool_t b){ + + // Long_t mask=b<SetEnabled(kTRUE); + else + fColorSel->SetEnabled(kFALSE); + + // fColorSel->SetEnabled(sAdcPlot->IsOn()); + Emit("ToggledAdcPlot(Int_t)", id); + +} + + + +void ctbAdc::ToggledInvert(Bool_t b){ + + + // fColorSel->SetEnabled(sAdcPlot->IsOn()); + Emit("ToggledAdcInvert(Int_t)", id); + +} + + + +void ctbAdc::ToggledEnable(Bool_t b){ + + + fColorSel->SetEnabled(sAdcPlot->IsOn()); + Emit("ToggledAdcEnable(Int_t)", id); + +} + + + + + + +void ctbAdc::ColorChanged(Pixel_t) { + + Emit("ToggledAdcPlot(Int_t)", id); + +} + +void ctbAdc::ToggledAdcPlot(Int_t b){ + + + Emit("ToggledAdcPlot(Int_t)", id); + +} + +void ctbAdc::ToggledAdcInvert(Int_t b){ + + + Emit("ToggledAdcInvert(Int_t)", id); + +} + +void ctbAdc::ToggledAdcEnable(Int_t b){ + + + Emit("ToggledAdcEnable(Int_t)", id); + +} + + + + +void ctbAdc::setEnabled(Bool_t b){ + // cout << id << "set enabled " << b << endl; + if (b) + sAdcPlot->SetOn(kTRUE,kFALSE); + else + sAdcPlot->SetOn(kFALSE,kFALSE); + +} + + + + + + + + + + +ctbAdcs::ctbAdcs(TGVerticalFrame *page, multiSlsDetector *det) + : TGGroupFrame(page,"Adcs",kVerticalFrame), myDet(det) { + + + SetTitlePos(TGGroupFrame::kLeft); + page->AddFrame(this,new TGLayoutHints( kLHintsTop | kLHintsExpandX , 10,10,10,10)); + MapWindow(); + + char tit[100]; + + + TGHorizontalFrame* hframe=new TGHorizontalFrame(this, 800,800); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + hframe->MapWindow(); + + + + + int idac=0; + + + + + + TGHorizontalFrame* hhframe=new TGHorizontalFrame(this, 800,800); + AddFrame(hhframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + hhframe->MapWindow(); + + TGVerticalFrame *vframe; + + + + + for (idac=0; idacAddFrame(vframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + vframe->MapWindow(); + + + + } + + sAdc[idac]=new ctbAdc(vframe,idac,myDet); + + + sAdc[idac]->Connect("ToggledAdcPlot(Int_t)","ctbAdcs",this,"ToggledAdcPlot(Int_t)"); + sAdc[idac]->Connect("ToggledAdcInvert(Int_t)","ctbAdcs",this,"ToggledAdcInvert(Int_t)"); + sAdc[idac]->Connect("ToggledAdcEnable(Int_t)","ctbAdcs",this,"ToggledAdcEnable(Int_t)"); + + } + + hframe=new TGHorizontalFrame(this, 800,800); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + hframe->MapWindow(); + + + bCheckHalf[0]=new TGTextButton(hframe, "All 0-15"); + hframe->AddFrame(bCheckHalf[0],new TGLayoutHints(kLHintsTop | kLHintsExpandX, 5, 5, 5, 5)); + bCheckHalf[0]->MapWindow(); + bCheckHalf[0]->Connect("Clicked()","ctbAdcs",this,"CheckHalf0()"); + + + bRemoveHalf[0]=new TGTextButton(hframe, "None 0-15"); + hframe->AddFrame(bRemoveHalf[0],new TGLayoutHints(kLHintsBottom | kLHintsExpandX, 5, 5, 5, 5)); + bRemoveHalf[0]->MapWindow(); + bRemoveHalf[0]->Connect("Clicked()","ctbAdcs",this,"RemoveHalf0()"); + + + bCheckHalf[1]=new TGTextButton(hframe, "All 16-23"); + hframe->AddFrame(bCheckHalf[1],new TGLayoutHints(kLHintsTop | kLHintsExpandX, 5, 5, 5, 5)); + bCheckHalf[1]->MapWindow(); + bCheckHalf[1]->Connect("Clicked()","ctbAdcs",this,"CheckHalf1()"); + // bCheckAll->Connect("Clicked()","ctbAdcs",this,"CheckAll()"); + + + bRemoveHalf[1]=new TGTextButton(hframe, "None 16-23"); + hframe->AddFrame(bRemoveHalf[1],new TGLayoutHints(kLHintsBottom | kLHintsExpandX, 5, 5, 5, 5)); + bRemoveHalf[1]->MapWindow(); + bRemoveHalf[1]->Connect("Clicked()","ctbAdcs",this,"RemoveHalf1()"); + // bRemoveAll->Connect("Clicked()","ctbAdcs",this,"RemoveAll()"); + + + + + hframe=new TGHorizontalFrame(this, 800,800); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + hframe->MapWindow(); + + + bCheckAll=new TGTextButton(hframe, "All"); + hframe->AddFrame(bCheckAll,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 5, 5, 5, 5)); + bCheckAll->MapWindow(); + bCheckAll->Connect("Clicked()","ctbAdcs",this,"CheckAll()"); + + + bRemoveAll=new TGTextButton(hframe, "None"); + hframe->AddFrame(bRemoveAll,new TGLayoutHints(kLHintsBottom | kLHintsExpandX, 5, 5, 5, 5)); + bRemoveAll->MapWindow(); + bRemoveAll->Connect("Clicked()","ctbAdcs",this,"RemoveAll()"); + + + + hframe=new TGHorizontalFrame(this, 800,50); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + hframe->MapWindow(); + + + TGLabel *label= new TGLabel(hframe, "Inversion mask: "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + eInversionMask = new TGNumberEntry(hframe, 0, 16,999, TGNumberFormat::kNESHex, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELNoLimits); + + hframe->AddFrame(eInversionMask,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eInversionMask->MapWindow(); + eInversionMask->Resize(150,30); + eInversionMask->SetState(kFALSE); + + + hframe=new TGHorizontalFrame(this, 800,50); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + hframe->MapWindow(); + + + label= new TGLabel(hframe, "Enable mask: "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + eEnableMask = new TGNumberEntry(hframe, 0, 16,999, TGNumberFormat::kNESHex, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELNoLimits); + + hframe->AddFrame(eEnableMask,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eEnableMask->MapWindow(); + eEnableMask->Resize(150,30); + eEnableMask->SetState(kFALSE); + +} + + +int ctbAdcs::setEnable(int reg) { + + // char aargs[10][100]; + // char *args[10]; + string retval; + int retreg; + + // for (int i=0; i<10; i++) args[i]=aargs[i]; + + // sprintf(args[0],"adcenable"); + // sprintf(args[1],"%x",reg); + // slsDetectorCommand *cmd=new slsDetectorCommand(myDet); + // if (reg>-1) { + // retval=cmd->executeLine(1,args,slsDetectorDefs::PUT_ACTION); + // } + if (reg>-1) { + try { + myDet->setADCEnableMask(reg); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + + } + // retval=cmd->executeLine(1,args,slsDetectorDefs::GET_ACTION); + // cout <<"enable: " << retval << endl;; + // delete cmd; + + // sscanf(retval.c_str(),"%x",&retreg); + try { + retreg=myDet->getADCEnableMask(); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + + eEnableMask->SetHexNumber(retreg); + + return retreg; +} + +int ctbAdcs::setInvert(int reg) { + + // char aargs[10][100]; + // char *args[10]; + string retval; + int retreg; + + // for (int i=0; i<10; i++) args[i]=aargs[i]; + + //sprint// f(args[0],"adcinvert"); + // sprintf(args[1],"%x",reg); + // slsDetectorCommand *cmd=new slsDetectorCommand(myDet); + + if (reg>-1) { + try { + myDet->setADCInvert(reg); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + + //retval=cmd->executeLine(1,args,slsDetectorDefs::PUT_ACTION); + } + try { + retreg=myDet->getADCInvert(); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + + // retval=cmd->executeLine(1,args,slsDetectorDefs::GET_ACTION); + // cout <<"invert: " << retval << endl;; + // delete cmd; + + // sscanf(retval.c_str(),"%x",&retreg); + eInversionMask->SetHexNumber(retreg); + return retreg; +} + + + +void ctbAdcs::update() { + Int_t invreg;//=myDet->readRegister(67);//(120); + Int_t disreg;//=myDet->readRegister(120);//(94); + // for (int i=0; i<10; i++) + // args[i]=aargs[i]; + + // string retval; + // sprintf(args[0],"adcenable"); + // slsDetectorCommand *cmd=new slsDetectorCommand(myDet); + // retval=cmd->executeLine(1,args,slsDetectorDefs::GET_ACTION); + // delete cmd; + // // cout << retval << endl; + + // sscanf(retval.c_str(),"adcenable %x",&disreg); + + // eInversionMask->SetHexNumber(invreg); + // eEnableMask->SetHexNumber(disreg); + + disreg=setEnable(); + invreg=setInvert(); + + + for (int is=0; issetAdcAlias(NULL,-1,-1); + if (invreg & (1<setInverted(kTRUE); + else + sAdc[is]->setInverted(kFALSE); + + if (disreg & (1<setEnable(kTRUE); + else + sAdc[is]->setEnable(kFALSE); + + + } + + Emit("AdcEnable(Int_t)", disreg); + +} +string ctbAdcs::getAdcParameters() { + + ostringstream line; + + line << "reg "<< hex << setInvert() << "# ADC invert reg" << dec << endl; + line << "reg "<< hex << setEnable() << " # ADC enable reg"<< dec << endl; + // line << "reg "<< hex << 67 << " " << myDet->readRegister(67) << "# ADC invert reg" << dec << endl; + // line << "reg "<< hex << 120 << " " << myDet->readRegister(120) << " # ADC enable reg"<< dec << endl; + // // line << "reg "<< hex << 94 << " " << myDet->readRegister(94) << " # ADC enable reg"<< dec << endl; + return line.str(); + +} + + +void ctbAdcs::CheckAll() { + + + for (int is=0; issetEnabled(kTRUE); +} + + +void ctbAdcs::RemoveAll() { + + + for (int is=0; issetEnabled(kFALSE); +} + + + +void ctbAdcs::CheckHalf0() { + + + for (int is=0; issetEnabled(kTRUE); +} + + +void ctbAdcs::RemoveHalf0() { + + + for (int is=0; issetEnabled(kFALSE); +} + +void ctbAdcs::CheckHalf1() { + + + for (int is=NADCS/2; issetEnabled(kTRUE); +} + + +void ctbAdcs::RemoveHalf1() { + + + for (int is=NADCS/2; issetEnabled(kFALSE); +} + + +// TGraph* ctbAdcs::getGraph(int i) { + +// if (i>=0 && igetGraph(); +// return NULL; +// } + +int ctbAdcs::setAdcAlias(string line) { + + int is=-1, plot=0, color=-1; + char tit[100]; + int narg=sscanf(line.c_str(),"ADC%d %s %d %x",&is,tit,&plot, &color); + if (narg<2) + return -1; + if (narg!=3) + color=-1; + if (is>=0 && issetAdcAlias(tit,plot,color); + } + return is; + +} + +string ctbAdcs::getAdcAlias() { + + ostringstream line; + + for (int is=0; isgetAdcAlias(); + + return line.str(); +} + + +void ctbAdcs::ToggledAdcPlot(Int_t b){ + + + Emit("ToggledAdcPlot(Int_t)", b); + +} + +void ctbAdcs::AdcEnable(Int_t b){ + Emit("AdcEnable(Int_t)", b); +} + + +void ctbAdcs::ToggledAdcEnable(Int_t b){ + + + Int_t oreg=setEnable();//myDet->readRegister(67); + Int_t m=1<getEnable()) + oreg|=m; + else + oreg&=~m; + +// cout << dec << sizeof(Long64_t) << " " << mask << " " << hex << m << " ioreg " << oreg << endl; + + setEnable(oreg);//)writeRegister(67, oreg); + //oreg=setEnable();//myDet->readRegister(67); + + + Emit("AdcEnable(Int_t)", oreg); + //cout << "enable!" << endl; + // Emit("ToggledAdcPlot(Int_t)", b); + +} + + +void ctbAdcs::ToggledAdcInvert(Int_t b){ + + // char val[1000]; + Int_t oreg=setInvert();//myDet->readRegister(67); + Int_t m=1<getInverted()) + oreg|=m; + else + oreg&=~m; + +// cout << dec << sizeof(Long64_t) << " " << mask << " " << hex << m << " ioreg " << oreg << endl; + + setInvert(oreg);//)writeRegister(67, oreg); + // oreg=setInvert();//myDet->readRegister(67); + +// cout << dec << sizeof(Long64_t) << " " << mask << " " << hex << m << " ioreg " << oreg << endl; + + //sprintf(val,"%X",oreg); + //eInversionMask->SetHexNumber(oreg); +} + + + + + +Pixel_t ctbAdcs::getColor(int i){ + if (i>=0 && igetColor(); +} + +Bool_t ctbAdcs::getEnabled(int i){ + if (i>=0 && igetEnabled(); + +} + +Bool_t ctbAdcs::getEnable(int i){ + if (i>=0 && igetEnable(); + +} + +Bool_t ctbAdcs::getPlot(int i){ + if (i>=0 && igetPlot(); + +} diff --git a/ctbGui/ctbAdcs.h b/ctbGui/ctbAdcs.h new file mode 100755 index 000000000..7fe136188 --- /dev/null +++ b/ctbGui/ctbAdcs.h @@ -0,0 +1,151 @@ + + + +#ifndef CTBADCS_H +#define CTBADCS_H +#include + + +#define NADCS 32 + +class TRootEmbeddedCanvas; +class TGButtonGroup; +class TGVerticalFrame; +class TGHorizontalFrame; +class TGTextEntry; +class TGLabel; +class TGNumberEntry; +class TH2F; +class TGComboBox; +class TGCheckButton; +class TGColorSelect; +class TColor; + +class THStack; +class TGraphErrors; +class TGTextButton; +class TGTab; + +class TGraph; + +class multiSlsDetector; + +#include +using namespace std; + +class ctbAdc : public TGHorizontalFrame { + + + private: + + + TGLabel *sAdcLabel; + TGCheckButton *sAdcEnable; + TGCheckButton *sAdcPlot; + TGCheckButton *sAdcInvert; + + TGColorSelect *fColorSel; + + // TGraph *gADC; + + int id; + multiSlsDetector *myDet; + + public: + ctbAdc(TGVerticalFrame *page, int i, multiSlsDetector *det); + + + void setAdcAlias(char *tit, int plot, int color); + string getAdcAlias(); + void ToggledAdcPlot(Int_t b); + void ToggledAdcEnable(Int_t b); + void ToggledAdcInvert(Int_t b); + + + void ToggledPlot(Bool_t b); + void ToggledEnable(Bool_t b); + void ToggledInvert(Bool_t b); + void ColorChanged(Pixel_t); + void setEnabled(Bool_t b); + Bool_t getEnabled(); + // TGraph *getGraph(); + void update(); + + Pixel_t getColor(); + + Bool_t getEnable(); + void setEnable(Bool_t); + Bool_t getInverted(); + Bool_t getPlot(); + void setInverted(Bool_t); + + ClassDef(ctbAdc,0) + }; + + + +class ctbAdcs : public TGGroupFrame { +private: + + ctbAdc *sAdc[NADCS]; + multiSlsDetector *myDet; + + + TGTextButton *bCheckAll; + TGTextButton *bRemoveAll; + TGTextButton *bCheckHalf[2]; + TGTextButton *bRemoveHalf[2]; + TGNumberEntry *eInversionMask; + TGNumberEntry *eEnableMask; + + +/* TGTextButton *bPlotSelected; */ +/* TGNumberEntry *eMinX; */ +/* TGNumberEntry *eMaxX; */ +/* TGNumberEntry *eMinY; */ +/* TGNumberEntry *eMaxY; */ + + + +/* TGTextButton *bGetPixel; */ +/* TGNumberEntry *ePixelX; */ +/* TGNumberEntry *ePixelY; */ +/* TGLabel *lPixelValue; */ + +public: + + ctbAdcs(TGVerticalFrame *page, multiSlsDetector *det); + int setAdcAlias(string line); + string getAdcAlias(); + string getAdcParameters(); + void ToggledAdcPlot(Int_t); + void ToggledAdcInvert(Int_t); + void ToggledAdcEnable(Int_t); + void AdcEnable(Int_t b); + // TGraph *getGraph(int i); + void CheckAll(); + void RemoveAll(); + void update(); + + int setInvert(int reg=-1); + int setEnable(int reg=-1); + + + Pixel_t getColor(int i); + Bool_t getEnabled(int i); + Bool_t getPlot(int i); + Bool_t getEnable(int i); + + void CheckHalf0(); + void RemoveHalf0(); + + void CheckHalf1(); + void RemoveHalf1(); + + + ClassDef(ctbAdcs,0) +}; + +#endif + + diff --git a/ctbGui/ctbDacs.cpp b/ctbGui/ctbDacs.cpp new file mode 100755 index 000000000..afb137567 --- /dev/null +++ b/ctbGui/ctbDacs.cpp @@ -0,0 +1,251 @@ + +#include +#include +#include + +#include +#include +#include +#include + +#include "ctbDacs.h" +#include "multiSlsDetector.h" +#include "sls_detector_defs.h" + +using namespace std; + + + + + +ctbDac::ctbDac(TGGroupFrame *page, int idac, multiSlsDetector *det) : TGHorizontalFrame(page, 800,50) , id(idac), myDet(det) { + + + TGHorizontalFrame *hframe=this; + + page->AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + MapWindow(); + + char tit[100]; + + + sprintf(tit, "DAC %d:",idac); + + dacsLabel= new TGCheckButton(hframe, tit);// new TGLabel(hframe, tit); + dacsLabel->SetOn(kTRUE, kTRUE); + + dacsLabel->Connect("Toggled(Bool_t)","ctbDac",this,"setOn(Bool_t)"); + + + hframe->AddFrame(dacsLabel,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + dacsLabel->MapWindow(); + dacsLabel->SetTextJustify(kTextLeft); + + + dacsEntry = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELLimitMinMax, + 0, 65535); + + hframe->AddFrame(dacsEntry,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 5, 5, 5, 5)); + dacsEntry->MapWindow(); + dacsEntry->Resize(150,30); + + + dacsUnit= new TGCheckButton(hframe, "mV"); + // if (idac!=slsDetectorDefs::ADC_VPP) { + hframe->AddFrame( dacsUnit,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + dacsUnit->MapWindow(); + if (idac==slsDetectorDefs::ADC_VPP) { + dacsUnit->SetEnabled(kFALSE); + hframe->HideFrame(dacsUnit); + dacsUnit->MapWindow(); + cout << "hiding!" << endl; + } + if (idac==slsDetectorDefs::HIGH_VOLTAGE) { + dacsUnit->SetText("V"); + dacsUnit->SetOn(kTRUE,kTRUE); + dacsUnit->SetEnabled(kFALSE); + } + //} + + + + sprintf(tit, "xxx"); + dacsValue= new TGLabel(hframe, tit); + hframe->AddFrame( dacsValue,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + dacsValue->MapWindow(); + dacsValue->SetTextJustify(kTextLeft); + + TGTextEntry *e=dacsEntry->TGNumberEntry::GetNumberEntry(); + e->Connect("ReturnPressed()","ctbDac",this,"setValue()"); + // e->Connect("ValueSet(Long_t)","ctbDac",this,"setValue(Long_t)"); + dacsEntry->Connect("ValueSet(Long_t)","ctbDac",this,"setValue(Long_t)"); + // cout << "(((((((((((((((((((((((((((((((" << dacsEntry->GetListOfSignals()->At(0)->IsA() << endl; + + +} + + + +int ctbDac::setLabel(char *tit, int mv) { + if(tit) + dacsLabel->SetText(tit); + if (mv==1) + dacsUnit->SetOn(kTRUE,kTRUE); + else if (mv==0) + dacsUnit->SetOn(kFALSE,kTRUE); + // else if (mv==2) { + // ;} + // else if (mv==3) + // ; + return id; + +} + +string ctbDac::getLabel() { + + ostringstream line; + line << dacsLabel->GetText() << " " << dacsUnit->IsOn() << endl; + + // line << "DAC" << dec << id << " " << dacsUnit->IsOn() << endl; + + return line.str(); + +} + + +void ctbDac::setValue(Long_t a) {setValue();} + +void ctbDac::setValue() { + + + + cout << "setting dac! "<< id << " value " << dacsEntry->GetIntNumber() << " units " << dacsUnit->IsOn() << endl; + try { + myDet->setDAC(dacsEntry->GetIntNumber(), (slsDetectorDefs::dacIndex)id, dacsUnit->IsOn()); } catch (...) { + cout << "Do nothing for this error" << endl; + } + + getValue(); + +} + +void ctbDac::setOn(Bool_t b) { + + + + // cout << "setting dac! "<< id << endl; + + if ( dacsLabel->IsOn()) { + setValue(); + } else { + try { + myDet->setDAC(-100, (slsDetectorDefs::dacIndex)id, 0); + } catch (...) { + cout << "Do nothing for this error" << endl; + } + } + getValue(); + +} + +int ctbDac::getValue() { + int val; + try { + val=myDet->setDAC(-1,(slsDetectorDefs::dacIndex)id, dacsUnit->IsOn()); + } catch (...) { + cout << "Do nothing for this error" << endl; + } + char s[100]; + cout << "dac " << id << " " << val << endl; + sprintf(s,"%d",val); + dacsValue->SetText(s); + if (val>=0) { + dacsLabel->SetOn(kTRUE); + } else { + dacsLabel->SetOn(kFALSE); + } + + + return val; + +} + + + + + +ctbDacs::ctbDacs(TGVerticalFrame *page, multiSlsDetector *det) : TGGroupFrame(page,"DACs",kVerticalFrame) , myDet(det){ + + + SetTitlePos(TGGroupFrame::kLeft); + page->AddFrame(this,new TGLayoutHints( kLHintsTop | kLHintsExpandX , 10,10,10,10)); + MapWindow(); + + // cout << "window mapped " << endl; + + for (int idac=0; idacsetLabel("ADC Vpp",2); + dacs[NDACS+1]->setLabel("High Voltage",3); + +} + + +int ctbDacs::setDacAlias(string line) { + + int is=-1, mv=0; + char tit[100]; + int narg=sscanf(line.c_str(),"DAC%d %s %d",&is,tit,&mv); + if (narg<2) + return -1; + if (is>=0 && issetLabel(tit,mv); + return is; + +} + +string ctbDacs::getDacAlias() { + ostringstream line; + + for (int i=0; igetLabel() << endl; + return line.str(); + +} + + + + + +string ctbDacs::getDacParameters() { + + + ostringstream line; + + for (int i=0; igetValue << endl; + line << "dac:" << i << " " << dacs[i]->getValue() << endl; + } + return line.str(); + + +} + + + +void ctbDacs::update() { + + for (int idac=0; idacgetValue(); + } + + + +} diff --git a/ctbGui/ctbDacs.h b/ctbGui/ctbDacs.h new file mode 100755 index 000000000..ff921fa6b --- /dev/null +++ b/ctbGui/ctbDacs.h @@ -0,0 +1,74 @@ + + +#ifndef CTBDACS_H +#define CTBDACS_H +#include + + +#define NDACS 18 +//#define NDACS 16 + + +class TGTextEntry; +class TGLabel; +class TGNumberEntry; +class TGCheckButton; + + +class multiSlsDetector; + +#include +using namespace std; + + +class ctbDac : public TGHorizontalFrame { + + + protected: + // TGLabel *dacsLabel; + TGNumberEntry *dacsEntry; + TGCheckButton *dacsUnit; + TGCheckButton *dacsLabel; + TGLabel *dacsValue; + int id; + + multiSlsDetector* myDet; + public: + ctbDac(TGGroupFrame*, int , multiSlsDetector*); + void setValue(); + void setValue(Long_t); + int getValue(); + void setOn(Bool_t); + + int setLabel(char *tit, int mv); + string getLabel(); + + + + ClassDef(ctbDac,0) +}; + +class ctbDacs : public TGGroupFrame { +private: + + + + ctbDac *dacs[NDACS+2]; + + multiSlsDetector* myDet; + +public: + ctbDacs(TGVerticalFrame *page, multiSlsDetector*); + + int setDacAlias(string line); + // int setDacAlias(string line); + string getDacAlias(); + string getDacParameters(); + + void update(); + + ClassDef(ctbDacs,0) +}; + +#endif + diff --git a/ctbGui/ctbGui.cpp b/ctbGui/ctbGui.cpp new file mode 100755 index 000000000..e5df8b6db --- /dev/null +++ b/ctbGui/ctbGui.cpp @@ -0,0 +1,161 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +#include "multiSlsDetector.h" +#include "sls_detector_defs.h" +//#include "sls_receiver_defs.h" +#include "ctbMain.h" +using namespace std; + + +int main(int argc, char **argv) { + + + string afname, cfname, pfname; + int id=0; + + int af=0, cf=0, pf=0; + + + cout << " *** " << argc << endl; + for (int ia=0; iasetOnline(slsDetectorDefs::ONLINE_FLAG); + + //cout << id << " " << myDet << " " << myDet->setOnline() << endl; + if (cf) { + myDet->readConfigurationFile(cfname); + } else + cout << "No config file specified" << endl; + + cout << "aa" << endl; + + cout << "Created multi detector id " << id << " hostname " << myDet->getHostname() << endl; + + + cout << "bb" << endl; + if (pf) { + myDet->retrieveDetectorSetup(pfname); + } else + cout << "No parameter file specified" << endl; + + + + + + /***********Create GUI stuff *******************/ + TApplication theApp("App",&argc,argv); + + + gStyle->SetDrawBorder(0); + gStyle->SetCanvasColor(kWhite); + gStyle->SetCanvasDefH(800); + gStyle->SetCanvasDefW(800); + gStyle->SetCanvasBorderMode(0); + gStyle->SetPadBorderMode(0); + gStyle->SetPaintTextFormat("5.2f"); + gStyle->SetLineWidth(2); + gStyle->SetTextSize(1.1); + gStyle->SetLabelSize(0.04,"xy"); + gStyle->SetTitleSize(0.05,"xy"); + gStyle->SetTitleOffset(1.0,"x"); + gStyle->SetTitleOffset(1.1,"y"); + gStyle->SetPadTopMargin(0.15); + gStyle->SetPadRightMargin(0.15); + gStyle->SetPadBottomMargin(0.15); + gStyle->SetPadLeftMargin(0.15); + gStyle->SetLegendBorderSize(1); + gStyle->SetFrameBorderMode(0); + gStyle->SetFrameFillColor(kWhite); + // gStyle->SetLegendFillColor(kWhite); + gStyle->SetTitleFillColor(kWhite); + gStyle->SetFillColor(kWhite); + gStyle->SetStatFontSize(0.03); + gStyle->SetStatBorderSize(1); + gStyle->SetStatFormat("6.4g"); + gStyle->SetStatX(0.95); + gStyle->SetStatY(0.95); + gStyle->SetStatW(0.2); + gStyle->SetStatH(0.2); + gStyle->SetTitleX(0.1); + gStyle->SetTitleY(0.95); + gStyle->SetTitleBorderSize(0); + gStyle->SetTitleFontSize(0.05); + gROOT->SetStyle("Default"); + + + TColor::InitializeColors(); + const Int_t NRGBs = 5; + const Int_t NCont = 90; + + Double_t stops[NRGBs] = { 0.00, 0.34, 0.61, 0.84, 1.00 }; + Double_t red[NRGBs] = { 0.00, 0.00, 0.87, 1.00, 0.51 }; + Double_t green[NRGBs] = { 0.00, 0.81, 1.00, 0.20, 0.00 }; + Double_t blue[NRGBs] = { 0.51, 1.00, 0.12, 0.00, 0.00 }; + TColor::CreateGradientColorTable(NRGBs, stops, red, green, blue, NCont); + gStyle->SetNumberContours(NCont); + + + gROOT->ForceStyle(); + ctbMain *mf=new ctbMain(gClient->GetRoot(),myDet); + + cout << " *** " << argc << endl; + for (int ia=0; ialoadAlias(afname); + else + cout << "no alias specified" << endl; + + theApp.Run(); + + return 0; +} diff --git a/ctbGui/ctbLinkDef.h b/ctbGui/ctbLinkDef.h new file mode 100755 index 000000000..dd61a0bba --- /dev/null +++ b/ctbGui/ctbLinkDef.h @@ -0,0 +1,15 @@ +#pragma link C++ class ctbMain; +#pragma link C++ class ctbDacs; +#pragma link C++ class ctbDac; +#pragma link C++ class ctbSignals; +#pragma link C++ class ctbSignal; +#pragma link C++ class ctbAdc; +#pragma link C++ class ctbAdcs; +#pragma link C++ class ctbLoop; +#pragma link C++ class ctbWait; +#pragma link C++ class ctbPattern; +#pragma link C++ class ctbAcquisition; +#pragma link C++ class ctbPower; +#pragma link C++ class ctbPowers; +#pragma link C++ class ctbSlowAdc; +#pragma link C++ class ctbSlowAdcs; diff --git a/ctbGui/ctbMain.cpp b/ctbGui/ctbMain.cpp new file mode 100755 index 000000000..f66560aa4 --- /dev/null +++ b/ctbGui/ctbMain.cpp @@ -0,0 +1,709 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +//#include +//#include + + + + + + + +#include +#include +#include +#include + +#include "multiSlsDetector.h" +#include "ctbMain.h" +#include "ctbDacs.h" +#include "ctbSlowAdcs.h" +#include "ctbPowers.h" +#include "ctbSignals.h" +#include "ctbPattern.h" +#include "ctbAdcs.h" +#include "ctbAcquisition.h" +//#include "ctbActions.h" + +using namespace std; + + + +ctbMain::ctbMain(const TGWindow *p, multiSlsDetector *det) + : TGMainFrame(p,800,800), pwrs(NULL), senses(NULL) { + + myDet=det; + + Connect("CloseWindow()", "ctbMain", this, "CloseWindow()"); + + + + + +// fMenuDock = new TGDockableFrame(this); +// AddFrame(fMenuDock, new TGLayoutHints(kLHintsExpandX, 0, 0, 1, 0)); +// fMenuDock->SetWindowName("GuiTest Menu"); + + fMenuBarLayout = new TGLayoutHints(kLHintsTop | kLHintsExpandX); + fMenuBarItemLayout = new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 4, 0, 0); + fMenuBarHelpLayout = new TGLayoutHints(kLHintsTop | kLHintsRight); + + fMenuFile = new TGPopupMenu(gClient->GetRoot()); + int im=0; + + fMenuFile->AddEntry("Open Alias", im++); + fMenuFile->AddEntry("Save Alias", im++); + fMenuFile->AddSeparator(); + fMenuFile->AddEntry("Open Parameters", im++); + fMenuFile->AddEntry("Save Parameters", im++); + fMenuFile->AddSeparator(); + fMenuFile->AddEntry("Open Configuration", im++); + fMenuFile->AddEntry("Save Configuration", im++); + fMenuFile->AddSeparator(); + fMenuFile->AddEntry("Open Pattern", im++); + fMenuFile->AddEntry("Save Pattern", im++); + fMenuFile->AddSeparator(); + fMenuFile->AddEntry("Exit", im++); + + fMenuFile->Connect("Activated(Int_t)", "ctbMain", this, + "HandleMenu(Int_t)"); + + + i_dacs=-1; + i_pwrs=-1; + i_senses=-1; + i_sig=-1; + i_adcs=-1; + i_pat=-1; + i_acq=-1; + + int i_page=0; + + + + + + + + + + + + + + + + + + TGVerticalFrame *vframe=new TGVerticalFrame(this, 800,1200); //main frame + + + + fMenuBar = new TGMenuBar(vframe, 1, 1, kHorizontalFrame); + fMenuBar->AddPopup("&File", fMenuFile, fMenuBarItemLayout); +// fMenuBar->AddPopup("&Test", fMenuTest, fMenuBarItemLayout); +// fMenuBar->AddPopup("&View", fMenuView, fMenuBarItemLayout); +// fMenuBar->AddPopup("&Help", fMenuHelp, fMenuBarHelpLayout); + + vframe->AddFrame(fMenuBar, fMenuBarLayout); + + TGHorizontalFrame* hpage=new TGHorizontalFrame(vframe, 800,1200); //horizontal frame. Inside there should be the tab and the canvas + mtab=new TGTab(hpage, 1500, 1200); //tab! + // page=new TGVerticalFrame(mtab, 1500,1200); + + cout << "DACS" << endl; + + TGCompositeFrame *tf = mtab->AddTab("DACs"); + TGVerticalFrame *page=new TGVerticalFrame(tf, 1500,1200); + tf->AddFrame(page, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1)); + dacs=new ctbDacs(page, myDet); + i_dacs=i_page++; + + + cout << "power " << endl; + tf = mtab->AddTab("Power Supplies"); + page=new TGVerticalFrame(tf, 1500,1200); + tf->AddFrame(page, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1)); + pwrs=new ctbPowers(page, myDet); + + i_pwrs=i_page++; + + cout << "sense " << endl; + tf = mtab->AddTab("Sense"); + page=new TGVerticalFrame(tf, 1500,1200); + tf->AddFrame(page, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1)); + senses=new ctbSlowAdcs(page, myDet); + + i_senses=i_page++; + + + + cout << "signals " << endl; + tf = mtab->AddTab("Signals"); + page=new TGVerticalFrame(tf, 1500,1200); + tf->AddFrame(page, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1)); + sig=new ctbSignals(page, myDet); + sig->Connect("ToggledSignalPlot(Int_t)","ctbMain",this,"setSignalPlot(Int_t)"); + + i_sig=i_page++; + + cout << "adcs " << endl; + tf = mtab->AddTab("ADCs"); + page=new TGVerticalFrame(tf, 1500,1200); + tf->AddFrame(page, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1)); + adcs=new ctbAdcs(page, myDet); + adcs->Connect("ToggledAdcPlot(Int_t)","ctbMain",this,"setADCPlot(Int_t)"); + adcs->Connect("AdcEnable(Int_t)","ctbMain",this,"setADCEnable(Int_t)"); + i_adcs=i_page++; + + + cout << "pattern" << endl; + + tf = mtab->AddTab("Pattern"); + page=new TGVerticalFrame(tf, 1500,1200); + tf->AddFrame(page, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1)); + pat=new ctbPattern(page, myDet); + pat->Connect("patternFileChanged(const char*)","ctbMain",this,"setPatternFile(const char*)"); + pat->Connect("patternCompilerChanged(const char*)","ctbMain",this,"setPatternCompiler(const char*)"); + pat->Connect("analogSamplesChanged(const int)","ctbMain",this,"setAnalogSamples(int)"); + pat->Connect("digitalSamplesChanged(const int)","ctbMain",this,"setDigitalSamples(int)"); + pat->Connect("readoutModeChanged(int)","ctbMain",this,"setReadoutMode(int)"); + + i_pat=i_page++; + + cout << "acquisition" << endl; + + tf = mtab->AddTab("Acquisition"); + page=new TGVerticalFrame(tf, 1500,1200); + tf->AddFrame(page, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1)); + acq=new ctbAcquisition(page, myDet); + + + i_acq=i_page++; + + + // cout << "actions" << endl; + // tf = mtab->AddTab("Actions"); + // page=new TGVerticalFrame(tf, 1500,1200); + // tf->AddFrame(page, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1)); + // actions=new ctbActions(page, myDet); + + + // i_actions=i_page++; + + + + cout << "tabs finished" << endl; + + hpage->AddFrame(mtab,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1)); + + vframe->AddFrame(hpage,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1)); + + AddFrame(vframe,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1)); + vframe->MapWindow(); + hpage->MapWindow(); + mtab->MapWindow(); + page->MapWindow(); + + // Sets window name and shows the main frame + cout << "dockabel" << endl; + TGDockableFrame *fdock=new TGDockableFrame(hpage); + hpage->AddFrame(fdock, new TGLayoutHints(kLHintsBottom | kLHintsCenterX | kLHintsExpandX | kLHintsExpandY, 10,10,10,10)); + fdock->MapWindow(); + + cout << "canvas" << endl; +// // Creates widgets of the example + + + fEcanvas = new TRootEmbeddedCanvas ("Ecanvas",fdock,800,800);//hpage,800,800); + //fEcanvas = new TRootEmbeddedCanvas ("Ecanvas",this,800,800);//hpage,800,800); + // fEcanvas->Resize(); + // fEcanvas->GetCanvas()->Update(); + //AddFrame(fEcanvas, new TGLayoutHints(kLHintsBottom | kLHintsCenterX | kLHintsExpandX | kLHintsExpandY, 10,10,10,10)); + + // // hpage-> + fdock->AddFrame(fEcanvas, new TGLayoutHints(kLHintsBottom | kLHintsCenterX | kLHintsExpandX | kLHintsExpandY, 10,10,10,10)); + + + fEcanvas->MapWindow(); + + acq->setCanvas(getCanvas()); + + + + hpage->MapSubwindows(); + mtab->Connect("Selected(Int_t)","ctbMain",this,"tabSelected(Int_t)"); + + + + cout << "connect mtab" << endl; + + + setReadoutMode(pat->getReadoutMode()); + setADCEnable(adcs->setEnable()); + setAnalogSamples(pat->getAnalogSamples()); + setDigitalSamples(pat->getDigitalSamples()); + + tabSelected(0); + + SetWindowName("CTB Gui"); + MapSubwindows(); + Resize(1500,1200); + + MapWindow(); +} + +void ctbMain::CloseWindow() { + gApplication->Terminate(); +} + +TCanvas* ctbMain::getCanvas() { + return fEcanvas->GetCanvas(); +} + + + +void ctbMain::HandleMenu(Int_t id) +{ + // Handle menu items. + + + + + switch (id) { + + case 0: // fMenuFile->AddEntry("Open Alias", im++); + cout << "Open Alias" << endl; + { + static TString dir("."); + TGFileInfo fi; + //fi.fFileTypes = filetypes; + fi.fIniDir = StrDup(dir); + printf("fIniDir = %s\n", fi.fIniDir); + new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fi); + printf("Open file: %s (dir: %s)\n", fi.fFilename); + // dir = fi.fIniDir; + if (fi.fFilename) + loadAlias(fi.fFilename); + } + break; + + case 1: // fMenuFile->AddEntry("Save Alias", im++); + cout << "Save Alias" << endl; + { + static TString dir("."); + TGFileInfo fi; + //fi.fFileTypes = filetypes; + fi.fIniDir = StrDup(dir); + printf("fIniDir = %s\n", fi.fIniDir); + new TGFileDialog(gClient->GetRoot(), this, kFDSave, &fi); + printf("Save file: %s (dir: %s)\n", fi.fFilename); + // dir = fi.fIniDir; + if (fi.fFilename) + saveAlias(fi.fFilename); + } + break; + + case 2: //fMenuFile->AddEntry("Open Parameters", im++); + cout << "Open Parameters" << endl; + { + static TString dir("."); + TGFileInfo fi; + //fi.fFileTypes = filetypes; + fi.fIniDir = StrDup(dir); + printf("fIniDir = %s\n", fi.fIniDir); + new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fi); + printf("Open file: %s (dir: %s)\n", fi.fFilename, fi.fIniDir); + // dir = fi.fIniDir; + if (fi.fFilename) + loadParameters(fi.fFilename); + } + break; + + case 3: //fMenuFile->AddEntry("Save Parameters", im++); + cout << "Save Parameters" << endl; + { + static TString dir("."); + TGFileInfo fi; + //fi.fFileTypes = filetypes; + fi.fIniDir = StrDup(dir); + printf("fIniDir = %s\n", fi.fIniDir); + new TGFileDialog(gClient->GetRoot(), this, kFDSave, &fi); + printf("Open file: %s (dir: %s)\n", fi.fFilename, fi.fIniDir); + // dir = fi.fIniDir; + if (fi.fFilename) + saveParameters(fi.fFilename); + } + break; + + case 4: // fMenuFile->AddEntry("Open Configuration", im++); + cout << "Open configuration" << endl; + { + static TString dir("."); + TGFileInfo fi; + //fi.fFileTypes = filetypes; + fi.fIniDir = StrDup(dir); + printf("fIniDir = %s\n", fi.fIniDir); + new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fi); + printf("Open file: %s (dir: %s)\n", fi.fFilename, fi.fIniDir); + // dir = fi.fIniDir; + if (fi.fFilename) + loadConfiguration(fi.fFilename); + } + break; + + case 5: // fMenuFile->AddEntry("Save Configuration", im++); + cout << "Save configuration" << endl; + { + static TString dir("."); + TGFileInfo fi; + //fi.fFileTypes = filetypes; + fi.fIniDir = StrDup(dir); + printf("fIniDir = %s\n", fi.fIniDir); + new TGFileDialog(gClient->GetRoot(), this, kFDSave, &fi); + printf("Open file: %s (dir: %s)\n", fi.fFilename, fi.fIniDir); + // dir = fi.fIniDir; + if (fi.fFilename) + saveConfiguration(fi.fFilename); + } + break; + + case 6: //fMenuFile->AddEntry("Open Pattern", im++); + cout << "Open pattern" << endl; + { + static TString dir("."); + TGFileInfo fi; + //fi.fFileTypes = filetypes; + fi.fIniDir = StrDup(dir); + printf("fIniDir = %s\n", fi.fIniDir); + new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fi); + printf("Open file: %s (dir: %s)\n", fi.fFilename, fi.fIniDir); + // dir = fi.fIniDir; + if (fi.fFilename) + loadParameters(fi.fFilename); + } + break; + + case 7: //fMenuFile->AddEntry("Save Pattern", im++); + cout << "Save pattern" << endl; + { + static TString dir("."); + TGFileInfo fi; + //fi.fFileTypes = filetypes; + fi.fIniDir = StrDup(dir); + printf("fIniDir = %s\n", fi.fIniDir); + new TGFileDialog(gClient->GetRoot(), this, kFDSave, &fi); + printf("Open file: %s (dir: %s)\n", fi.fFilename, fi.fIniDir); + // dir = fi.fIniDir; + if (fi.fFilename) + saveParameters(fi.fFilename); + } + break; + + case 8: // fMenuFile->AddEntry("Exit", im++); + CloseWindow(); + + default: + printf("Menu item %d selected\n", id); + break; + } +} + + + +int ctbMain::setADCPlot(Int_t i) { + + // cout << "ADC " << i << " plot or color toggled" << endl; + // acq->setGraph(i,adcs->getGraph(i)); + acq->setGraph(i,adcs->getEnabled(i),adcs->getColor(i)); + +} + + +int ctbMain::setSignalPlot(Int_t i) { + + // cout << "ADC " << i << " plot or color toggled" << endl; + // acq->setGraph(i,adcs->getGraph(i)); + acq->setBitGraph(i,sig->getPlot(i),sig->getColor(i)); + +} + + + +int ctbMain::loadConfiguration(string fname) { + + myDet->readConfigurationFile(fname); + +// string line; +// int i; +// ifstream myfile (fname.c_str()); +// if (myfile.is_open()) +// { +// while ( getline (myfile,line) ) +// { + + + +// } +// myfile.close(); +// } + +// else cout << "Unable to open file"; + + return 0; + +} + + + + + +int ctbMain::saveConfiguration(string fname) { + + + myDet->writeConfigurationFile(fname); + // string line; +// int i; +// ofstream myfile (fname.c_str()); +// if (myfile.is_open()) +// { + + +// myfile.close(); +// } + +// else cout << "Unable to open file"; + + return 0; + +} + + + + + + + +int ctbMain::loadParameters(string fname) { + + myDet->retrieveDetectorSetup(fname); + +// string line; +// int i; +// ifstream myfile (fname.c_str()); +// if (myfile.is_open()) +// { +// while ( getline (myfile,line) ) +// { + + + +// } +// myfile.close(); +// } + +// else cout << "Unable to open file"; + + return 0; + +} + + + + + +int ctbMain::saveParameters(string fname) { + + + string line; + int i; + myDet->dumpDetectorSetup(fname); +// ofstream myfile (fname.c_str()); +// if (myfile.is_open()) +// { + +// myfile << dacs->getDacParameters(); +// myfile << sig->getSignalParameters(); +// myfile << adcs->getAdcParameters(); + +// myfile.close(); +// } + +// else cout << "Unable to open file"; + + return 0; + +} + + + + + +int ctbMain::loadAlias(string fname) { + + + string line; + char aaaa[1000]; + int i; + ifstream myfile (fname.c_str()); + if (myfile.is_open()) + { + while ( getline (myfile,line) ) + { + // cout << line ; + if (sscanf(line.c_str(),"BIT%d",&i)>0) { + //cout << "*******" << line<< endl; + sig->setSignalAlias(line); + // cout << line ; + } else if (sscanf(line.c_str(),"DAC%d",&i)>0) { + dacs->setDacAlias(line); + // cout << "+++++++++" << line<< endl; + } else if (sscanf(line.c_str(),"ADC%d",&i)>0) { + adcs->setAdcAlias(line); + // cout << "---------" << line<< endl; + } // else + // cout << "<<<<<<<" << line << endl; + else if (sscanf(line.c_str(),"PAT%s",aaaa)>0) { + pat->setPatternAlias(line); + // cout << "---------" << line<< endl; + } else if (sscanf(line.c_str(),"V%s",&i)>0) { + if (pwrs) pwrs->setPwrAlias(line); + // cout << "+++++++++" << line<< endl; + } else if (sscanf(line.c_str(),"SENSE%d",&i)>0) { + if (senses) senses->setSlowAdcAlias(line); + // cout << "+++++++++" << line<< endl; + } + + } + myfile.close(); + } + + else cout << "Unable to open file"; + + return 0; + +} + + + + + +int ctbMain::saveAlias(string fname) { + + + string line; + int i; + ofstream myfile (fname.c_str()); + if (myfile.is_open()) + { + //while ( getline (myfile,line) ) + // { + // cout << line ; + //if (sscanf(line.c_str(),"BIT%d",&i)>0) { + //cout << "*******" << line<< endl; + myfile << sig->getSignalAlias(); + // cout << line ; + // } else if (sscanf(line.c_str(),"DAC%d",&i)>0) { + myfile << dacs->getDacAlias(); + if (pwrs) myfile << pwrs->getPwrAlias(); + if (senses) myfile << senses->getSlowAdcAlias(); + // cout << "+++++++++" << line<< endl; + // } else if (sscanf(line.c_str(),"ADC%d",&i)>0) { + myfile << adcs->getAdcAlias(); + // cout << "---------" << line<< endl; + // } // else + // cout << "<<<<<<<" << line << endl; + myfile << pat->getPatternAlias(); + + //} + myfile.close(); + } + + else cout << "Unable to open file"; + + return 0; + +} + + + + + + + + + + + +void ctbMain::tabSelected(Int_t i) { + + // cout << "Selected tab " << i << endl; + // cout << "Current tab is " << mtab->GetCurrent() << endl; + + if (i==i_dacs) dacs->update(); + else if (i==i_pwrs) pwrs->update(); + else if (i==i_senses) ;//senses->update(); + else if (i==i_sig) sig->update(); + else if (i==i_adcs) adcs->update(); + else if (i==i_pat) pat->update(); + else if (i==i_acq) acq->update(); + else if (i==i_acq) acq->update(); + // else if (i==i_actions) actions->update(); + else cout << "Unknown tab " << i << endl; + + +} + +void ctbMain::setPatternFile(const char* t) { + acq->setPatternFile(t); + +} + +void ctbMain::setPatternCompiler(const char* t) { + acq->setPatternCompiler(t); + + +} + +void ctbMain::setAnalogSamples(const int n) { + acq->setAnalogSamples(n); + + +} + +void ctbMain::setDigitalSamples(const int n) { + acq->setDigitalSamples(n); + + +} + +void ctbMain::setReadoutMode(int flags) { + acq->setReadoutMode(flags); +} + +void ctbMain::setADCEnable(Int_t reg){ + acq->setADCEnable(reg); +} diff --git a/ctbGui/ctbMain.h b/ctbGui/ctbMain.h new file mode 100755 index 000000000..f3fb51574 --- /dev/null +++ b/ctbGui/ctbMain.h @@ -0,0 +1,126 @@ +#ifndef CTBMAIN_H +#define CTBMAIN_H +#include + + +class TRootEmbeddedCanvas; +class TGButtonGroup; +class TGVerticalFrame; +class TGHorizontalFrame; +class TGTextEntry; +class TGLabel; +class TGNumberEntry; +class TH2F; +class TGComboBox; +class TGCheckButton; + +class THStack; +class TGraphErrors; +class TGTextButton; +class TGTab; + +class TGMenuBar; +class TGPopupMenu; +class TGDockableFrame; +class TGLayoutHints; +class TGCanvas; +class TCanvas; + +class ctbDacs; +class ctbSlowAdcs; +class ctbPowers; + + +class ctbSignals; + +class multiSlsDetector; + +class ctbPattern; +class ctbAdcs; +class ctbAcquisition; +//class ctbActions; + +#include +using namespace std; + +class ctbMain : public TGMainFrame { +private: + + + multiSlsDetector *myDet; + + + + TRootEmbeddedCanvas *fEcanvas; + TRootEmbeddedCanvas *fModulecanvas; + TGButtonGroup *br; + + TGTab *mtab; + + + ctbDacs *dacs; + int i_dacs; + + ctbPowers *pwrs; + int i_pwrs; + + ctbSlowAdcs *senses; + int i_senses; + + + ctbSignals *sig; + int i_sig; + + + ctbAdcs *adcs; + int i_adcs; + + + ctbPattern *pat; + int i_pat; + + ctbAcquisition *acq; + int i_acq; + + // ctbActions *actions; + int i_actions; + + TGDockableFrame *fMenuDock; + + TGMenuBar *fMenuBar; + TGPopupMenu *fMenuFile, *fMenuTest, *fMenuView, *fMenuHelp; + TGPopupMenu *fCascadeMenu, *fCascade1Menu, *fCascade2Menu; + TGPopupMenu *fMenuNew1, *fMenuNew2; + TGLayoutHints *fMenuBarLayout, *fMenuBarItemLayout, *fMenuBarHelpLayout; + TGCanvas *myCanvas; + + +public: + ctbMain(const TGWindow *p, multiSlsDetector *det); + + + int loadAlias(string fname); + int saveAlias(string fname); + int loadParameters(string fname); + int saveParameters(string fname); + int loadConfiguration(string fname); + int saveConfiguration(string fname); + void tabSelected(Int_t); + int setADCPlot(Int_t); + int setSignalPlot(Int_t); + void CloseWindow(); + + void setPatternFile(const char* t); + + void setPatternCompiler(const char* t); + void setAnalogSamples(const int); + void setDigitalSamples(const int); + void setReadoutMode(int); + void setADCEnable(Int_t); + + void HandleMenu(Int_t); + TCanvas* getCanvas(); + ClassDef(ctbMain,0) +}; + +#endif diff --git a/ctbGui/ctbPattern.cpp b/ctbGui/ctbPattern.cpp new file mode 100755 index 000000000..4823f8570 --- /dev/null +++ b/ctbGui/ctbPattern.cpp @@ -0,0 +1,1263 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ctbPattern.h" +#include "multiSlsDetector.h" + +using namespace std; + + + + + +ctbLoop::ctbLoop(TGGroupFrame *page, int i, multiSlsDetector *det) : TGHorizontalFrame(page, 800,800), id(i), myDet(det) { + + TGHorizontalFrame *hframe=this; + + char tit[100]; + + page->AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + MapWindow(); + + + + + + sprintf(tit, "Loop %d Repetitions: ", id); + + TGLabel *label= new TGLabel(hframe, tit); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + + + eLoopNumber = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELNoLimits); + hframe->AddFrame( eLoopNumber,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eLoopNumber->MapWindow(); + eLoopNumber->Resize(150,30); + TGTextEntry *e= eLoopNumber->TGNumberEntry::GetNumberEntry(); + e->Connect("ReturnPressed()","ctbLoop",this,"setNLoops()"); + + + + + sprintf(tit, "Start Address: "); + + label= new TGLabel(hframe, tit); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + + + eLoopStartAddr = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESHex, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELLimitMinMax, + 0, 1024); + hframe->AddFrame( eLoopStartAddr,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eLoopStartAddr->MapWindow(); + eLoopStartAddr->Resize(150,30); + + // eLoopStartAddr->SetState(kFALSE); + + label= new TGLabel(hframe, "Stop Address: "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + + + + eLoopStopAddr = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESHex, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELLimitMinMax, + 0, 1024); + hframe->AddFrame( eLoopStopAddr,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eLoopStopAddr->MapWindow(); + eLoopStopAddr->Resize(150,30); + + + + // eLoopStopAddr->SetState(kFALSE); + + + + + + +} + +void ctbLoop::setNLoops() { + + int start, stop, n; + + + start=-1; + stop=-1; + n=eLoopNumber->GetNumber(); + try{ + myDet->setPatternLoops(id,start, stop,n); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + + +} + + + +void ctbLoop::update() { + + int start, stop, n; + + std::array loop; + + try { + loop=myDet->getPatternLoops(id); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + + + eLoopStartAddr->SetHexNumber(loop[0]); + eLoopStopAddr->SetHexNumber(loop[1]); + eLoopNumber->SetNumber(loop[2]); +} + + + +ctbWait::ctbWait(TGGroupFrame *page, int i, multiSlsDetector *det) : TGHorizontalFrame(page, 800,800), id(i), myDet(det) { + + char tit[100]; + TGHorizontalFrame *hframe=this; + page->AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + MapWindow(); + + + + sprintf(tit, "Wait %d (run clk): ", id); + + TGLabel *label= new TGLabel(hframe, tit); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + + + eWaitTime = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELNoLimits); + hframe->AddFrame( eWaitTime,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eWaitTime->MapWindow(); + eWaitTime->Resize(150,30); + TGTextEntry *e= eWaitTime->TGNumberEntry::GetNumberEntry(); + e->Connect("ReturnPressed()","ctbWait",this,"setWaitTime()"); + + + + sprintf(tit, "Wait Address: "); + + label= new TGLabel(hframe, tit); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + + + eWaitAddr = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESHex, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELLimitMinMax, + 0, 1024); + hframe->AddFrame( eWaitAddr,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eWaitAddr->MapWindow(); + eWaitAddr->Resize(150,30); + + // eWaitAddr->SetState(kFALSE); + +} + + + +void ctbWait::setWaitTime() { + + + Long64_t t=eWaitTime->GetNumber(); + try{ + t=myDet->setPatternWaitTime(id,t); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } +} + + + +void ctbWait::update() { + + int start, stop, n, addr; + + Long64_t t=-1; + try{ + + t=myDet->setPatternWaitTime(id,t); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + try{ + addr=myDet->setPatternWaitAddr(id,-1); + + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + eWaitAddr->SetHexNumber(addr); + eWaitTime->SetNumber(t); + +} + + + + + + + + + +ctbPattern::ctbPattern(TGVerticalFrame *page, multiSlsDetector *det) + : TGGroupFrame(page,"Pattern",kVerticalFrame), myDet(det) { + + + SetTitlePos(TGGroupFrame::kLeft); + page->AddFrame(this,new TGLayoutHints( kLHintsTop | kLHintsExpandX , 10,10,10,10)); + MapWindow(); + + + char tit[100]; + + + TGHorizontalFrame* hframe=new TGHorizontalFrame(this, 800,800); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + hframe->MapWindow(); + + + sprintf(tit, "Run Clock Frequency (MHz): "); + + TGLabel *label= new TGLabel(hframe, tit); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + + + eRunClkFreq = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELLimitMinMax, + 0, 400); + hframe->AddFrame( eRunClkFreq,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eRunClkFreq->MapWindow(); + eRunClkFreq->Resize(150,30); + TGTextEntry *e= eRunClkFreq->TGNumberEntry::GetNumberEntry(); + e->Connect("ReturnPressed()","ctbPattern",this,"setRunFreq()"); + + + + + + hframe=new TGHorizontalFrame(this, 800,800); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + hframe->MapWindow(); + + + + + sprintf(tit, "ADC Clock Frequency (MHz): "); + + label= new TGLabel(hframe, tit); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + + + eAdcClkFreq = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELLimitMinMax, + 0, 40); + hframe->AddFrame( eAdcClkFreq,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eAdcClkFreq->MapWindow(); + eAdcClkFreq->Resize(150,30); + e= eAdcClkFreq->TGNumberEntry::GetNumberEntry(); + e->Connect("ReturnPressed()","ctbPattern",this,"setAdcFreq()"); + + + + + sprintf(tit, "DBIT Clock Frequency (MHz): "); + + label= new TGLabel(hframe, tit); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + + + eDBitClkFreq = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELLimitMinMax, + 0, 400); + hframe->AddFrame( eDBitClkFreq,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eDBitClkFreq->MapWindow(); + eDBitClkFreq->Resize(150,30); + e= eDBitClkFreq->TGNumberEntry::GetNumberEntry(); + e->Connect("ReturnPressed()","ctbPattern",this,"setDBitFreq()"); + + + + + + + + + + + hframe=new TGHorizontalFrame(this, 800,800); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + hframe->MapWindow(); + + + + + label= new TGLabel(hframe, "ADC Clock Phase (a.u.): "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + + + + eAdcClkPhase = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEAAnyNumber, + TGNumberFormat::kNELLimitMinMax, + -255, 255); + hframe->AddFrame( eAdcClkPhase,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eAdcClkPhase->MapWindow(); + eAdcClkPhase->Resize(150,30); + e= eAdcClkPhase->TGNumberEntry::GetNumberEntry(); + e->Connect("ReturnPressed()","ctbPattern",this,"setAdcPhase()"); + + + + + label= new TGLabel(hframe, "DBit Clock Phase (a.u.): "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + + + + eDBitClkPhase = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEAAnyNumber, + TGNumberFormat::kNELLimitMinMax, + -255, 255); + hframe->AddFrame( eDBitClkPhase,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eDBitClkPhase->MapWindow(); + eDBitClkPhase->Resize(150,30); + e= eDBitClkPhase->TGNumberEntry::GetNumberEntry(); + e->Connect("ReturnPressed()","ctbPattern",this,"setDBitPhase()"); + + +// label= new TGLabel(hframe, " Phase (0.15ns step): "); +// hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); +// label->MapWindow(); +// label->SetTextJustify(kTextLeft); + + + + + +// eRunClkPhase = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, +// TGNumberFormat::kNEANonNegative, +// TGNumberFormat::kNELLimitMinMax, +// 0, 200); +// hframe->AddFrame( eRunClkPhase,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); +// eRunClkPhase->MapWindow(); +// eRunClkPhase->Resize(150,30); +// e= eRunClkPhase->TGNumberEntry::GetNumberEntry(); +// e->Connect("ReturnPressed()","ctbPattern",this,"setRunPhase()"); + + + + + + hframe=new TGHorizontalFrame(this, 800,800); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + hframe->MapWindow(); + + + + + label= new TGLabel(hframe, "Adc pipeline: "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + + + + eAdcPipeline = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELLimitMinMax, + 0, 64); + hframe->AddFrame( eAdcPipeline,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eAdcPipeline->MapWindow(); + eAdcPipeline->Resize(150,30); + e= eAdcPipeline->TGNumberEntry::GetNumberEntry(); + e->Connect("ReturnPressed()","ctbPattern",this,"setAdcPipeline()"); + + + + + + + label= new TGLabel(hframe, "DBIT pipeline: "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + + + + eDBitPipeline = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELLimitMinMax, + 0, 64); + hframe->AddFrame( eDBitPipeline,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eDBitPipeline->MapWindow(); + eDBitPipeline->Resize(150,30); + e= eDBitPipeline->TGNumberEntry::GetNumberEntry(); + e->Connect("ReturnPressed()","ctbPattern",this,"setDBitPipeline()"); + + + + + + + + + hframe=new TGHorizontalFrame(this, 800,800); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + hframe->MapWindow(); + + + sprintf(tit, "Number of cycles: "); + + label= new TGLabel(hframe, tit); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + + + eCycles = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELNoLimits); + hframe->AddFrame( eCycles,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eCycles->MapWindow(); + eCycles->Resize(150,30); + e= eCycles->TGNumberEntry::GetNumberEntry(); + e->Connect("ReturnPressed()","ctbPattern",this,"setCycles()"); + + + sprintf(tit, "Number of measurements: "); + + label= new TGLabel(hframe, tit); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + + + eMeasurements = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELNoLimits); + hframe->AddFrame( eMeasurements,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eMeasurements->MapWindow(); + eMeasurements->Resize(150,30); + e= eMeasurements->TGNumberEntry::GetNumberEntry(); + e->Connect("ReturnPressed()","ctbPattern",this,"setMeasurements()"); + + + hframe=new TGHorizontalFrame(this, 800,800); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + hframe->MapWindow(); + + + sprintf(tit, "Number of frames: "); + + label= new TGLabel(hframe, tit); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + + + eFrames = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELNoLimits); + hframe->AddFrame( eFrames,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eFrames->MapWindow(); + eFrames->Resize(150,30); + e= eFrames->TGNumberEntry::GetNumberEntry(); + e->Connect("ReturnPressed()","ctbPattern",this,"setFrames()"); + + + label= new TGLabel(hframe, " Period (s): "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + + + + ePeriod = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESReal, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELNoLimits); + hframe->AddFrame( ePeriod,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + ePeriod->MapWindow(); + ePeriod->Resize(150,30); + e= ePeriod->TGNumberEntry::GetNumberEntry(); + e->Connect("ReturnPressed()","ctbPattern",this,"setPeriod()"); + + + + + + + hframe=new TGHorizontalFrame(this, 800,800); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + hframe->MapWindow(); + + + sprintf(tit, "Start Address: "); + + label= new TGLabel(hframe, tit); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + + + eStartAddr = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESHex, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELLimitMinMax, + 0, 1024); + hframe->AddFrame( eStartAddr,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eStartAddr->MapWindow(); + eStartAddr->Resize(150,30); + + eStartAddr->SetState(kFALSE); + + label= new TGLabel(hframe, "Stop Address: "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + + + + eStopAddr = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESHex, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELLimitMinMax, + 0, 1024); + hframe->AddFrame( eStopAddr,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eStopAddr->MapWindow(); + eStopAddr->Resize(150,30); + + + + + eStopAddr->SetState(kFALSE); + + + + + + + int idac=0; + for (idac=0; idacMapWindow(); + + + + label= new TGLabel(hframe, "Compiler: "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + + + patternCompiler=new TGTextEntry(hframe,"generate.sh"); + hframe->AddFrame(patternCompiler,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + patternCompiler->MapWindow(); + // patternCompiler->SetTextJustify(kTextLeft); + patternCompiler->Connect("ReturnPressed()","ctbPattern",this,"setCompiler()"); + + + browseCompiler=new TGTextButton(hframe,"Browse"); + hframe->AddFrame(browseCompiler,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + browseCompiler->MapWindow(); + // patternCompiler->SetTextJustify(kTextLeft); + browseCompiler->Connect("Clicked()","ctbPattern",this,"chooseCompiler()"); + + + + + hframe=new TGHorizontalFrame(this, 800,800); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + hframe->MapWindow(); + + + label= new TGLabel(hframe, "Pattern: "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + patternFile=new TGTextEntry(hframe,"file.p"); + hframe->AddFrame(patternFile,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + patternFile->MapWindow(); + patternFile->Connect("ReturnPressed()","ctbPattern",this,"setFile()"); + // patternFile->SetTextJustify(kTextLeft); + + + + browseFile=new TGTextButton(hframe,"Browse"); + hframe->AddFrame(browseFile,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + browseFile->MapWindow(); + // patternCompiler->SetTextJustify(kTextLeft); + browseFile->Connect("Clicked()","ctbPattern",this,"choosePattern()"); + + + + + hframe=new TGHorizontalFrame(this, 800,800); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + hframe->MapWindow(); + + + sprintf(tit, "Samples per frame - "); + + label= new TGLabel(hframe, tit); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + sprintf(tit, "Analog: "); + + label= new TGLabel(hframe, tit); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + + eAnalogSamples = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELLimitMinMax, + 1, 8192); + hframe->AddFrame( eAnalogSamples,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eAnalogSamples->MapWindow(); + eAnalogSamples->Resize(150,30); + e= eAnalogSamples->TGNumberEntry::GetNumberEntry(); + e->Connect("ReturnPressed()","ctbPattern",this,"setAnalogSamples()"); + + sprintf(tit, "Digital: "); + + label= new TGLabel(hframe, tit); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + + eDigitalSamples = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELLimitMinMax, + 1, 8192); + hframe->AddFrame( eDigitalSamples,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eDigitalSamples->MapWindow(); + eDigitalSamples->Resize(150,30); + e= eDigitalSamples->TGNumberEntry::GetNumberEntry(); + e->Connect("ReturnPressed()","ctbPattern",this,"setDigitalSamples()"); + + + hframe=new TGHorizontalFrame(this, 800,800); + AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + hframe->MapWindow(); + + + sprintf(tit, "Read Out Mode: "); + + label= new TGLabel(hframe, tit); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + cbAnalog= new TGCheckButton(hframe, "Analog"); + hframe->AddFrame(cbAnalog,new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX, 5, 5, 5, 5)); + cbAnalog->MapWindow(); + cbAnalog->SetTextJustify(kTextRight); + cbAnalog->Connect("Toggled(Bool_t)","ctbPattern",this,"setReadoutMode(Bool_t)"); + + cbDigital= new TGCheckButton(hframe, "Digital"); + hframe->AddFrame(cbDigital,new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX, 5, 5, 5, 5)); + cbDigital->MapWindow(); + cbDigital->SetTextJustify(kTextRight); + cbDigital->Connect("Toggled(Bool_t)","ctbPattern",this,"setReadoutMode(Bool_t)"); + + + + +} + +void ctbPattern::update() { + + int start, stop, n, addr; + + Long_t t; + + + try { + n=myDet->setSpeed(slsDetectorDefs::CLOCK_DIVIDER,-1,0); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + + eRunClkFreq->SetNumber(n); + + try { + n=myDet->setSpeed(slsDetectorDefs::ADC_CLOCK,-1,0); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + + eAdcClkFreq->SetNumber(n); + + try { + n=myDet->setSpeed(slsDetectorDefs::ADC_PHASE,-1,0); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + + eAdcClkPhase->SetNumber(n); + + try { + n=myDet->setSpeed(slsDetectorDefs::ADC_PIPELINE,-1,0); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + + + eAdcPipeline->SetNumber(n); + + try { + n=myDet->setSpeed(slsDetectorDefs::DBIT_CLOCK,-1,0); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + + + eDBitClkFreq->SetNumber(n); + + try { + n=myDet->setSpeed(slsDetectorDefs::DBIT_PHASE,-1,0); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + + + eDBitClkPhase->SetNumber(n); +try { + myDet->setSpeed(slsDetectorDefs::DBIT_PIPELINE,0,-1); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + eDBitPipeline->SetNumber(n); + +try { + n=myDet->setTimer(slsDetectorDefs::FRAME_NUMBER,-1); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + + eFrames->SetNumber(n); + + +try { + n=myDet->setTimer(slsDetectorDefs::FRAME_PERIOD,-1); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + + + + ePeriod->SetNumber(((Double_t)n)*1E-9); + + try { + n=myDet->setTimer(slsDetectorDefs::CYCLES_NUMBER,-1); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + + eCycles->SetNumber(n); + + + try { + myDet->setTimer(slsDetectorDefs::MEASUREMENTS_NUMBER,-1); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + + eMeasurements->SetNumber(n); + + start=-1; + stop=-1; + n=-1; + std::array loop; + + try { + loop=myDet->getPatternLoops(-1); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + + eStartAddr->SetHexNumber(loop[0]); + eStopAddr->SetHexNumber(loop[1]); + + for (int iloop=0; iloopupdate(); + + } + + for (int iwait=0; iwaitupdate(); + } + + getAnalogSamples(); + getDigitalSamples(); + getReadoutMode(); + +} +void ctbPattern::setFile() { + patternFileChanged(patternFile->GetText()); + +} + + +void ctbPattern::setCompiler() { + patternCompilerChanged(patternCompiler->GetText()); +} + + +void ctbPattern::patternFileChanged(const char* t){ + Emit("patternFileChanged(const char*)", t); +} + + +void ctbPattern::patternCompilerChanged(const char* t){ + Emit("patternCompilerChanged(const char*)", t); + +} + + +void ctbPattern::setPatternAlias(string line){ + char fname[10000]; + if (sscanf(line.c_str(),"PATCOMPILER %s",fname)) { + patternCompiler->SetText(fname); + patternCompilerChanged(patternCompiler->GetText()); + } else if (sscanf(line.c_str(),"PATFILE %s",fname)) { + patternFile->SetText(fname); + patternFileChanged(patternFile->GetText()); + } +} + + +string ctbPattern::getPatternAlias() { + char line[100000]; + sprintf("PATCOMPILER %s\nPATFILE %s\n",patternCompiler->GetText(),patternFile->GetText()); +} + + +void ctbPattern::chooseCompiler() { + static TString dir("."); + TGFileInfo fi; + //fi.fFileTypes = filetypes; + fi.fIniDir = StrDup(dir); + printf("fIniDir = %s\n", fi.fIniDir); + new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fi); + printf("Open file: %s (dir: %s)\n", fi.fFilename, fi.fIniDir); + // dir = fi.fIniDir; + if (fi.fFilename) { + patternCompiler->SetText(fi.fFilename); + patternCompilerChanged(patternCompiler->GetText()); + } +} + + +void ctbPattern::choosePattern() { + static TString dir("."); + TGFileInfo fi; + //fi.fFileTypes = filetypes; + fi.fIniDir = StrDup(dir); + printf("fIniDir = %s\n", fi.fIniDir); + new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fi); + printf("Open file: %s (dir: %s)\n", fi.fFilename, fi.fIniDir); + // dir = fi.fIniDir; + if (fi.fFilename) { + patternFile->SetText(fi.fFilename); + patternFileChanged(patternFile->GetText()); + } + +} + + +string ctbPattern::getCompiler() { + return string(patternCompiler->GetText()); + +} + +string ctbPattern::getPatternFile() { + return string(patternFile->GetText()); + +} + +void ctbPattern::setFrames() { + try { + myDet->setTimer(slsDetectorDefs::FRAME_NUMBER,eFrames->GetNumber()); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } +} + +void ctbPattern::setCycles() { + try { + myDet->setTimer(slsDetectorDefs::CYCLES_NUMBER,eFrames->GetNumber()); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } +} + +void ctbPattern::setMeasurements() { + try { + myDet->setTimer(slsDetectorDefs::MEASUREMENTS_NUMBER,eFrames->GetNumber()); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } +} + + + + +void ctbPattern::setPeriod() { + try { + myDet->setTimer(slsDetectorDefs::FRAME_PERIOD,ePeriod->GetNumber()*1E9); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } +} + + + + +void ctbPattern::setAdcFreq() { + try { + myDet->setSpeed(slsDetectorDefs::ADC_CLOCK,eAdcClkFreq->GetNumber(),0); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } +} +void ctbPattern::setRunFreq() { + try{ + myDet->setSpeed(slsDetectorDefs::CLOCK_DIVIDER,eRunClkFreq->GetNumber(),0); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + +} +void ctbPattern::setDBitFreq() { + // cout <<"Not setting dbit frequency to " << eDBitClkFreq->GetNumber()<< endl; + try { + myDet->setSpeed(slsDetectorDefs::DBIT_CLOCK,eDBitClkFreq->GetNumber(),0); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + +} +void ctbPattern::setAdcPhase() { + try { + myDet->setSpeed(slsDetectorDefs::ADC_PHASE,eAdcClkPhase->GetNumber(),0); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + +} + +void ctbPattern::setDBitPhase() { + // cout <<"Not setting dbit phase to " << eDBitClkPhase->GetNumber()<< endl; + try { + myDet->setSpeed(slsDetectorDefs::DBIT_PHASE,eDBitClkPhase->GetNumber(),0); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + +} + + +void ctbPattern::setAdcPipeline() { + try { + myDet->setSpeed(slsDetectorDefs::ADC_PIPELINE,eAdcPipeline->GetNumber(),0); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } +} + + +void ctbPattern::setDBitPipeline() { + // cout <<"Not setting dbit pipeline to " << eDBitPipeline->GetNumber() << endl; + try { + myDet->setSpeed(slsDetectorDefs::DBIT_PIPELINE,eDBitPipeline->GetNumber(),0); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } +} + + +void ctbPattern::setAnalogSamples() { + try { + myDet->setTimer(slsDetectorDefs::ANALOG_SAMPLES,eAnalogSamples->GetNumber()); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + analogSamplesChanged(eAnalogSamples->GetNumber()); +} + +void ctbPattern::setDigitalSamples() { + try { + myDet->setTimer(slsDetectorDefs::DIGITAL_SAMPLES,eDigitalSamples->GetNumber()); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + digitalSamplesChanged(eDigitalSamples->GetNumber()); +} + +void ctbPattern::setReadoutMode(Bool_t) { + // cout << "Set readout mode to be implemented" << endl; + slsDetectorDefs::readOutFlags flags; + if (cbAnalog->IsOn() && cbDigital->IsOn()) flags=slsDetectorDefs::ANALOG_AND_DIGITAL; + else if (~cbAnalog->IsOn() && cbDigital->IsOn()) flags=slsDetectorDefs::DIGITAL_ONLY; + else if (cbAnalog->IsOn() && ~cbDigital->IsOn()) flags=slsDetectorDefs::NORMAL_READOUT; + else flags=slsDetectorDefs::GET_READOUT_FLAGS; + try { + myDet->setReadOutFlags(flags); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + cout << "Set readout flags " << hex << flags << dec << endl; + getReadoutMode(); + // myDet->setTimer(slsDetectorDefs::SAMPLES_CTB,eSamples->GetNumber()); + //samplesChanged(eSamples->GetNumber()); +} + +void ctbPattern::readoutModeChanged(int flags) { + Emit("readoutModeChanged(Int_t)",(int)flags); + +} + +int ctbPattern::getReadoutMode() { + // cout << "Get readout mode to be implemented" << endl; + slsDetectorDefs::readOutFlags flags; + try { + flags=(slsDetectorDefs::readOutFlags) myDet->setReadOutFlags(); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + + cout << "++++++++++++++++++++"<< hex << flags << dec << endl; + if (flags&slsDetectorDefs::ANALOG_AND_DIGITAL) { + cout << "analog and digital" << hex << slsDetectorDefs::ANALOG_AND_DIGITAL << dec<< endl; + cbAnalog->SetOn(kTRUE); + cbDigital->SetOn(kTRUE); + } else if (flags&slsDetectorDefs::DIGITAL_ONLY) { + cout << "digital only" << hex << slsDetectorDefs::DIGITAL_ONLY << dec << endl; + cbAnalog->SetOn(kFALSE); + cbDigital->SetOn(kTRUE); + }// else if (flags==slsDetectorDefs::NORMAL_READOUT) { + // cbAnalog->SetOn(kTRUE); + // cbDigital->SetOn(kFALSE); + // } + else { + cout << "analog only" << endl; + flags=slsDetectorDefs::NORMAL_READOUT; + cbAnalog->SetOn(kTRUE); + cbDigital->SetOn(kFALSE); + } + + Emit("readoutModeChanged(int)",(int)flags); + return (int)flags; + + // myDet->setTimer(slsDetectorDefs::SAMPLES_CTB,eSamples->GetNumber()); + //samplesChanged(eSamples->GetNumber()); +} + +int ctbPattern::getAnalogSamples() { + int n; + try { + n=(myDet->setTimer(slsDetectorDefs::ANALOG_SAMPLES,-1)); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + eAnalogSamples->SetNumber((Double_t)n); + Emit("analogSamplesChanged(const int)", eAnalogSamples->GetNumber()); + return eAnalogSamples->GetNumber(); +} + +int ctbPattern::getDigitalSamples() { + int n; + try { + + n=(myDet->setTimer(slsDetectorDefs::DIGITAL_SAMPLES,-1)); + } catch (...) { + + cout << "Do nothing for this error" << endl; + } + + eDigitalSamples->SetNumber(((Double_t)n)); + Emit("digitalSamplesChanged(const int)", eDigitalSamples->GetNumber()); + return eDigitalSamples->GetNumber(); +} + + + +void ctbPattern::analogSamplesChanged(const int t){ + Emit("analogSamplesChanged(const int)", t); +} + +void ctbPattern::digitalSamplesChanged(const int t){ + Emit("digitalSamplesChanged(const int)", t); +} diff --git a/ctbGui/ctbPattern.h b/ctbGui/ctbPattern.h new file mode 100755 index 000000000..fdfc0412b --- /dev/null +++ b/ctbGui/ctbPattern.h @@ -0,0 +1,176 @@ +#ifndef CTBPATTERN_H +#define CTBPATTERN_H +#include + + +#define NLOOPS 3 +#define NWAITS 3 +#define NADCS 32 +#define PATLEN 1024 + +class TRootEmbeddedCanvas; +class TGButtonGroup; +class TGVerticalFrame; +class TGHorizontalFrame; +class TGTextEntry; +class TGLabel; +class TGNumberEntry; +class TH2F; +class TGComboBox; +class TGCheckButton; +class TGTextEntry; +class TGCheckButton; + +class THStack; +class TGraphErrors; +class energyCalibration; +class TGTextButton; +class TGTab; + +class multiSlsDetector; + + +#include +using namespace std; + + + +class ctbLoop : public TGHorizontalFrame { + + + private: + + TGNumberEntry *eLoopStartAddr; + TGNumberEntry *eLoopStopAddr; + TGNumberEntry *eLoopNumber; + + int id; + + multiSlsDetector *myDet; + + public: + ctbLoop(TGGroupFrame *page, int i,multiSlsDetector *det); + + void setNLoops(); + void update(); + + ClassDef(ctbLoop,0) + }; + +class ctbWait : public TGHorizontalFrame { + + + private: + + TGNumberEntry *eWaitAddr; + TGNumberEntry *eWaitTime; + + int id; + + multiSlsDetector *myDet; + + public: + ctbWait(TGGroupFrame *page, int i,multiSlsDetector *det); + + void setWaitTime(); + void update(); + + ClassDef(ctbWait,0) + }; + + + + + + + +class ctbPattern : public TGGroupFrame { +private: + + + TGNumberEntry *eAdcClkFreq; + TGNumberEntry *eRunClkFreq; + TGNumberEntry *eDBitClkFreq; + TGNumberEntry *eAdcClkPhase; + TGNumberEntry *eDBitClkPhase; + //TGNumberEntry *eRunClkPhase; + + TGNumberEntry *eStartAddr; + TGNumberEntry *eStopAddr; + TGNumberEntry *eFrames; + TGNumberEntry *ePeriod; + TGNumberEntry *eCycles; + TGNumberEntry *eMeasurements; + TGNumberEntry *eAdcPipeline; + TGNumberEntry *eDBitPipeline; + + ctbLoop *eLoop[NLOOPS]; + ctbWait *eWait[NWAITS]; + + TGTextEntry *patternCompiler; + TGTextEntry *patternFile; + + TGTextButton *browseCompiler; + TGTextButton *browseFile; + + + TGNumberEntry *eAnalogSamples; + TGNumberEntry *eDigitalSamples; + + TGCheckButton *cbAnalog; + TGCheckButton *cbDigital; + + char pat[PATLEN*8]; + + multiSlsDetector *myDet; + +public: + + ctbPattern(TGVerticalFrame *page, multiSlsDetector *det); + + void update(); + void setAdcFreq(); + void setRunFreq(); + void setDBitFreq(); + void setAdcPhase(); + void setDBitPhase(); + // void setRunPhase(); + void setAdcPipeline(); + void setDBitPipeline(); + void setFrames(); + void setCycles(); + void setMeasurements(); + void setPeriod(); + + + void chooseCompiler(); + void choosePattern(); + + string getCompiler(); + string getPatternFile(); + + void setPatternAlias(string); + string getPatternAlias(); + + + int getAnalogSamples(); + void setAnalogSamples(); + int getDigitalSamples(); + void setDigitalSamples(); + void setReadoutMode(Bool_t); + int getReadoutMode(); + + + void setFile(); + void setCompiler(); + void patternFileChanged(const char*); + void patternCompilerChanged(const char*); + void analogSamplesChanged(const int t); + void digitalSamplesChanged(const int t); + void readoutModeChanged(int); + + + ClassDef(ctbPattern,0) +}; + +#endif diff --git a/ctbGui/ctbPowers.cpp b/ctbGui/ctbPowers.cpp new file mode 100644 index 000000000..1e4f8d170 --- /dev/null +++ b/ctbGui/ctbPowers.cpp @@ -0,0 +1,243 @@ +#include + + +#include +#include +#include +#include + +#include +#include +#include + +#include "ctbDacs.h" +#include "ctbPowers.h" +#include "multiSlsDetector.h" +#include "sls_detector_defs.h" + +using namespace std; + + + +ctbPower::ctbPower(TGGroupFrame* f, int i, multiSlsDetector* d) + : ctbDac(f, i, d) +{ + cout << "****************************************************************power " << i << endl; + dacsUnit->SetOn(kTRUE); + dacsUnit->SetEnabled(kFALSE); + int ii=0; + + switch(i) { + case slsDetectorDefs::V_POWER_IO: + dacsLabel->SetText("VIO"); + ii=slsDetectorDefs::I_POWER_IO; + break; + case slsDetectorDefs::V_POWER_A: + dacsLabel->SetText("VA"); + ii=slsDetectorDefs::I_POWER_A; + break; + case slsDetectorDefs::V_POWER_B: + dacsLabel->SetText("VB"); + ii=slsDetectorDefs::I_POWER_B; + break; + case slsDetectorDefs::V_POWER_C: + dacsLabel->SetText("VC"); + ii=slsDetectorDefs::I_POWER_C; + break; + case slsDetectorDefs::V_POWER_D: + dacsLabel->SetText("VD"); + ii=slsDetectorDefs::I_POWER_D; + break; + case slsDetectorDefs::V_POWER_CHIP: + dacsLabel->SetText("VCHIP"); + dacsLabel->SetEnabled(kFALSE); + ii=-1; + break; + default: + dacsLabel->SetText("Bad index"); + ii=-1; + break; + }; + + // ctbSlowAdc *vm=new ctbSlowAdc(f,i,d); + // vm->setLabel("V: "); + // if (ii>=0) { + // ctbSlowAdc *im=new ctbSlowAdc(f,ii,d); + // im->setLabel("I: "); + // } + + TGTextEntry *e=dacsEntry->TGNumberEntry::GetNumberEntry(); + e->Disconnect ("ReturnPressed()"); + e->Disconnect ("ValueSet(Long_t)"); + + e->Connect("ReturnPressed()","ctbPower",this,"setValue()"); + dacsEntry->Connect("ValueSet(Long_t)","ctbPower",this,"setValue(Long_t)"); + }; + + +string ctbPower::getLabel() { + + ostringstream line; + switch (id) { + case slsDetectorDefs::V_POWER_IO: + line << "VIO"; + break; + case slsDetectorDefs::V_POWER_A: + line << "VA"; + break; + case slsDetectorDefs::V_POWER_B: + line << "VB"; + break; + case slsDetectorDefs::V_POWER_C: + line << "VC"; + break; + case slsDetectorDefs::V_POWER_D: + line << "VD"; + break; + case slsDetectorDefs::V_POWER_CHIP: + line << "VCHIP"; + break; + default: + line << "VBAD"; + break; + + } + line << " " << dacsLabel->GetText() << endl; + return line.str(); + +} + + +void ctbPower::setValue(Long_t a) {cout << "ssssssssss" << endl; ctbPower::setValue();} +void ctbPower::setValue() { + + + cout << "***************************Setting power " << dacsEntry->GetIntNumber() << " " << (slsDetectorDefs::dacIndex)id <<" " << 1 << endl; + myDet->setDAC(dacsEntry->GetIntNumber(), (slsDetectorDefs::dacIndex)id, 1); + + getValue(); + +} + + +int ctbPower::getValue() { + + int val=myDet->setDAC(-1, (slsDetectorDefs::dacIndex)id, 1); + char s[100]; + cout << "****************************Getting power " << val << " " << (slsDetectorDefs::dacIndex)id <<" " << 1 << endl; + sprintf(s,"%d",val); + dacsValue->SetText(s); + if (val>0) { + if (id!=slsDetectorDefs::V_POWER_CHIP) + dacsLabel->SetOn(kTRUE); + } else { + dacsLabel->SetOn(kFALSE); + } + + + return val; + +} + + + +ctbPowers::ctbPowers(TGVerticalFrame* page, multiSlsDetector* det) : TGGroupFrame(page,"Power Supplies",kVerticalFrame) , myDet(det){ + + + SetTitlePos(TGGroupFrame::kLeft); + page->AddFrame(this,new TGLayoutHints( kLHintsTop | kLHintsExpandX , 10,10,10,10)); + MapWindow(); + + // cout << "window mapped " << endl; + + for (int idac=0; idacsetLabel(tit,1); + is=0; + } + + if (sscanf(line.c_str(),"VB %s",tit)) { + dacs[1]->setLabel(tit,1); + is=1; + } + + if (sscanf(line.c_str(),"VC %s",tit)) { + dacs[2]->setLabel(tit,1); + is=2; + } + + if (sscanf(line.c_str(),"VD %s",tit)) { + dacs[3]->setLabel(tit,1); + is=3; + } + + if (sscanf(line.c_str(),"VIO %s",tit)) { + dacs[4]->setLabel(tit,1); + is=4; + } + + if (sscanf(line.c_str(),"VCHIP %s",tit)) { + dacs[5]->setLabel(tit,1); + is=5; + } + + return is; + +} + +string ctbPowers::getPwrAlias() { + + ostringstream line; + + for (int i=0; igetLabel() << endl; + return line.str(); + +} + + + + +string ctbPowers::getPwrParameters() { + + + ostringstream line; + line << "v_a" << " " << dacs[0]->getValue() << " mv" << endl; + line << "v_b" << " " << dacs[1]->getValue() << " mv" << endl; + line << "v_c" << " " << dacs[2]->getValue() << " mv" << endl; + line << "v_d" << " " << dacs[3]->getValue() << " mv" << endl; + line << "v_io" << " " << dacs[4]->getValue() << " mv" << endl; + line << "v_chip" << " " << dacs[5]->getValue() << " mv" << endl; + // for (int i=0; igetValue << endl; + // line << "dac:" << i << " " << dacs[i]->getValue() << endl; + // } + return line.str(); + + +} + + + +void ctbPowers::update() { + + for (int idac=0; idacgetValue(); + + } + + +} diff --git a/ctbGui/ctbPowers.h b/ctbGui/ctbPowers.h new file mode 100644 index 000000000..3cd84d2bb --- /dev/null +++ b/ctbGui/ctbPowers.h @@ -0,0 +1,72 @@ +#ifndef CTBPOWERS_H +#define CTBPOWERS_H + +#include + +#ifndef CTB +#define NPOWERS 0 +#else + +#define NPOWERS 6 +#endif + + + + + +class TGTextEntry; +class TGLabel; +class TGNumberEntry; +class TGCheckButton; + + + + +class multiSlsDetector; + + +#include +using namespace std; + + +class ctbPower : public ctbDac { + + + + + public: + + ctbPower(TGGroupFrame* f, int i, multiSlsDetector* d); + + string getLabel(); + + int getValue(); + void setValue(); + void setValue(Long_t); + + ClassDef(ctbPower,0) +}; + + +class ctbPowers : public TGGroupFrame +{ + private: + + ctbPower *dacs[NPOWERS]; + + multiSlsDetector* myDet; + +public: + //ctbPowers(); + ctbPowers(TGVerticalFrame*, multiSlsDetector*); + + int setPwrAlias(string); + string getPwrAlias(); + string getPwrParameters(); + + void update(); + + ClassDef(ctbPowers,0) +}; + +#endif diff --git a/ctbGui/ctbSignals.cpp b/ctbGui/ctbSignals.cpp new file mode 100755 index 000000000..46197b81a --- /dev/null +++ b/ctbGui/ctbSignals.cpp @@ -0,0 +1,548 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "ctbSignals.h" +#include "multiSlsDetector.h" + +using namespace std; + + + +//#define DEFAULTFN "run_0.encal" + + +ctbSignal::ctbSignal(TGFrame *page, int i, multiSlsDetector *det) + : TGHorizontalFrame(page, 800,50), myDet(det), id(i), hsig(NULL) { + + + TGHorizontalFrame *hframe=this; + char tit[100]; + + + + sprintf(tit, "BIT%d ",id); + + sLabel= new TGLabel(hframe, tit); + hframe->AddFrame( sLabel,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + sLabel->MapWindow(); + sLabel->SetTextJustify(kTextLeft); + + + + sOutput= new TGCheckButton(hframe, "Out"); + hframe->AddFrame( sOutput,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + sOutput->MapWindow(); + + + sOutput->Connect("Toggled(Bool_t)","ctbSignal",this,"ToggledOutput(Bool_t)"); + + sDbitList= new TGCheckButton(hframe, "DB List"); + hframe->AddFrame( sDbitList,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + sDbitList->MapWindow(); + + sDbitList->Connect("Toggled(Bool_t)","ctbSignal",this,"ToggledDbitList(Bool_t)"); + + + sPlot= new TGCheckButton(hframe, "Plot"); + hframe->AddFrame( sPlot,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + sPlot->MapWindow(); + + sPlot->Connect("Toggled(Bool_t)","ctbSignal",this,"ToggledPlot(Bool_t)"); + + fColorSel = new TGColorSelect(hframe, id+1, 0); + fColorSel->Connect("ColorSelected(Pixel_t)","ctbSignal",this,"ColorChanged(Pixel_t)"); + hframe->AddFrame(fColorSel, new TGLayoutHints(kLHintsTop | + kLHintsLeft, 2, 0, 2, 2)); + + + fColorSel->SetColor(TColor::Number2Pixel(id+1)); + + + ToggledOutput(kFALSE); + + + ToggledPlot(kFALSE); + + // if (id==63) { +// sOutput->SetOn(kTRUE); +// sOutput->SetEnabled(kFALSE); +// } +// #ifdef CTB +// if (id==62) { +// sOutput->SetOn(kTRUE); +// sOutput->SetEnabled(kFALSE); +// } + +// // if (id>=32 && id<48) +// // fixOutput(1); +// // else if (id>=48 && id<64) +// // fixOutput(0); + +// #endif +} +int ctbSignal::setSignalAlias(char *tit, int plot, int col) { + + if (tit) + sLabel->SetText(tit); + + if (plot>0) { + sPlot->SetOn(kTRUE,kTRUE); + } else if (plot==0) + sPlot->SetOn(kFALSE,kTRUE); + + if (col>=0) + fColorSel->SetColor(col);//TColor::Number2Pixel(col+1)); + + fColorSel->SetEnabled(sPlot->IsOn()); + return 0; + +} + +string ctbSignal::getSignalAlias() { + + + ostringstream oss; + oss << "BIT" << dec << id << " " << sLabel->GetText()->Data() << " " << sPlot->IsOn() << hex << " " << fColorSel->GetColor() << endl; + return oss.str(); + + + + +} +int ctbSignal::setOutput(Long64_t r) { + + + // cout << hex << r << dec <SetOn(kTRUE,kTRUE); + else + sOutput->SetOn(kFALSE,kTRUE); + + return sOutput->IsOn(); + +} + +int ctbSignal::fixOutput(int i) { + + if (i) { + sPlot->SetOn(kFALSE); + //sClock->SetOn(kFALSE,kTRUE); + sOutput->SetOn(kTRUE); + // sPlot->SetEnabled(kFALSE); + // sClock->SetEnabled(kTRUE); + } else { + sOutput->SetOn(kFALSE,kTRUE); + // sClock->SetOn(kFALSE); + // sClock->SetEnabled(kFALSE); + sPlot->SetEnabled(kTRUE); + } + sOutput->SetEnabled(kFALSE); + return 0; + +} + +int ctbSignal::setDbitList(Long64_t r) { + + Long64_t mask=((Long64_t)1<SetOn(kTRUE,kFALSE); + else + sDbitList->SetOn(kFALSE,kFALSE); + + return sDbitList->IsOn(); + +} + +int ctbSignal::isDbitList() { return sDbitList->IsOn();} +int ctbSignal::isOutput() { return sOutput->IsOn();} +int ctbSignal::isPlot() { return sPlot->IsOn();} +Pixel_t ctbSignal::getColor(){return fColorSel->GetColor();} + +void ctbSignal::ToggledOutput(Bool_t b) { + Long_t mask=b<SetEnabled(kTRUE); + sPlot->SetOn(kFALSE); + // sPlot->SetEnabled(kFALSE); + fColorSel->SetEnabled(kFALSE); + } else { + // sClock->SetEnabled(kFALSE); + // sClock->SetOn(kFALSE); + sPlot->SetEnabled(kTRUE); + if ( sPlot->IsOn()) + fColorSel->SetEnabled(kFALSE); + else + fColorSel->SetEnabled(kTRUE); + } + + +} + +void ctbSignal::ToggledDbitList(Bool_t b){ + Long_t mask=id; + ToggledSignalDbitList(mask); +} + + +void ctbSignal::ToggledPlot(Bool_t b){ + Long_t mask=b<SetEnabled(b); +} + +void ctbSignal::ColorChanged(Pixel_t p){ + ToggledSignalPlot(id); +} + + +void ctbSignal::ToggledSignalOutput(Int_t b) { + cout << "Toggle signal " << id << " " << b << " " << sOutput->IsOn() <AddFrame(this,new TGLayoutHints( kLHintsTop | kLHintsExpandX , 10,10,10,10)); + MapWindow(); + + + TGHorizontalFrame *hframe; + char tit[100]; + + TGHorizontalFrame* hhframe=new TGHorizontalFrame(this, 800,800); + AddFrame(hhframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + hhframe->MapWindow(); + + TGVerticalFrame *vframe; + + + + + int idac=0; + for (idac=0; idacAddFrame(vframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + vframe->MapWindow(); + } + + + signals[idac]=new ctbSignal(vframe,idac,myDet); + signals[idac]->Connect("ToggledSignalOutput(Int_t)","ctbSignals",this,"ToggledOutReg(Int_t)"); + signals[idac]->Connect("ToggledSignalDbitList(Int_t)","ctbSignals",this,"ToggledDbitList(Int_t)"); + signals[idac]->Connect("ToggledSignalPlot(Int_t)","ctbSignals",this,"ToggledPlot(Int_t)"); + + vframe->AddFrame(signals[idac],new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + signals[idac]->MapWindow(); + + + } + +// #ifdef CTB +// idac=62; +// signals[idac]=new ctbSignal(vframe,idac,myDet); +// vframe->AddFrame(signals[idac],new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); +// signals[idac]->MapWindow(); +// sprintf(tit,"DBIT Latch"); + +// signals[idac]->setSignalAlias(tit,-1,-1); + +// signals[idac]->Connect("ToggledSignalOutput(Int_t)","ctbSignals",this,"ToggledOutReg(Int_t)"); +// signals[idac]->Connect("ToggledSignalDbitList(Int_t)","ctbSignals",this,"ToggledDbitList(Int_t)"); +// signals[idac]->Connect("ToggledSignalPlot(Int_t)","ctbSignals",this,"ToggledPlot(Int_t)"); + + +// #endif + + + // idac=63; + // signals[idac]=new ctbSignal(vframe,idac,myDet); + // vframe->AddFrame(signals[idac],new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + // signals[idac]->MapWindow(); + // sprintf(tit,"ADC Latch"); + + // signals[idac]->setSignalAlias(tit,-1,-1); + + // signals[idac]->Connect("ToggledSignalOutput(Int_t)","ctbSignals",this,"ToggledOutReg(Int_t)"); + // signals[idac]->Connect("ToggledSignalDbitList(Int_t)","ctbSignals",this,"ToggledDbitList(Int_t)"); + // signals[idac]->Connect("ToggledSignalPlot(Int_t)","ctbSignals",this,"ToggledPlot(Int_t)"); + + + hframe=new TGHorizontalFrame(vframe, 800,50); + vframe->AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + hframe->MapWindow(); + + + TGLabel *label= new TGLabel(hframe, "IO Control Register: "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + eIOCntrlRegister = new TGNumberEntry(hframe, 0, 16,999, TGNumberFormat::kNESHex, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELNoLimits); + + hframe->AddFrame(eIOCntrlRegister,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eIOCntrlRegister->MapWindow(); + eIOCntrlRegister->Resize(150,30); + + + + + hframe=new TGHorizontalFrame(vframe, 800,50); + vframe->AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + hframe->MapWindow(); + + + label= new TGLabel(hframe, "DBit Offset: "); + hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); + label->MapWindow(); + label->SetTextJustify(kTextLeft); + + + eDbitOffset = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, + TGNumberFormat::kNEANonNegative, + TGNumberFormat::kNELNoLimits); + + hframe->AddFrame(eDbitOffset,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); + eDbitOffset->MapWindow(); + eDbitOffset->Resize(150,30); + + + TGTextEntry *e= eDbitOffset->TGNumberEntry::GetNumberEntry(); + e->Connect("ReturnPressed()","ctbSignals",this,"setDbitOffset()"); + + e->Connect("ValueSet(Long_t)","ctbSignals",this,"setDbitOffset(Long_t)"); +} + + + + +int ctbSignals::setSignalAlias(string line) { + + int is=-1, plot=0, col=-1; + char tit[100]; + int narg=sscanf(line.c_str(),"BIT%d %s %d %d",&is,tit,&plot,&col); + if (narg<2) + return -1; + if (is>=0 && issetSignalAlias(tit,plot,col); + } + return is; + +} + +string ctbSignals::getSignalAlias() { + + ostringstream oss; + for (int is=0; isgetSignalAlias() << endl; + + + return oss.str(); + +} + + +void ctbSignals::update() { + Long64_t oreg=myDet->setPatternIOControl();//setCTBWord(-1,-1); + // Long64_t creg=myDet->setPatternClockControl();//setCTBWord(-2,-1); + + + char val[1000]; + cout << hex << oreg << dec << endl; + // cout << hex << creg << dec << endl; + + sprintf(val,"%llX",oreg); + // eIOCntrlRegister->SetHexNumber(oreg); + + + for (int idac=0; idacsetOutput(oreg); + + } + + Long64_t mask; + std::vector dbitlist=myDet->getReceiverDbitList(); + if (dbitlist.empty()) + for (int is=0; is<64; is++) { + signals[is]->setDbitList(1); + } + else { + for (int is=0; is<64; is++) signals[is]->setDbitList(0); + for (const auto &value : dbitlist) { + signals[value]->setDbitList(1); + } + } + + + eDbitOffset->SetNumber(myDet->getReceiverDbitOffset()); + +} + + +string ctbSignals::getSignalParameters() { + + + ostringstream line; + line << "patioctrl " << hex << myDet->setPatternIOControl() << dec << endl;//setCTBWord(-1,-1) + return line.str(); + + +} + +void ctbSignals::ToggledOutReg(Int_t mask) { + + char val[1000]; + Long64_t oreg=myDet->setPatternIOControl();//setCTBWord(-1,-1); + Long64_t m=((Long64_t)1)<isOutput()) { + cout << " or " << m ; + oreg|=m; + } else { + cout << " not " << ~m ; + oreg&=~m; + } + cout << " after " << oreg << endl; + + myDet->setPatternIOControl(oreg);//setCTBWord(-1,oreg); + oreg=myDet->setPatternIOControl();//myDet->setCTBWord(-1,-1); + + cout << dec << sizeof(Long64_t) << " " << mask << " " << hex << m << " ioreg " << oreg << endl; + + sprintf(val,"%llX",oreg); + // eIOCntrlRegister->SetHexNumber(oreg); + eIOCntrlRegister->SetText(val); + // eIOCntrlRegister->SetNumber(oreg); + +} + + + +void ctbSignals::ToggledDbitList(Int_t mask){ + + + + cout << "************* Here" << endl; + + + + std::vector new_dbitlist; + std::vector old_dbitlist=myDet->getReceiverDbitList(); + + char val[1000]; + Long64_t m=((Long64_t)1)<isDbitList()) + ; + else { + int ns=0; + for (int is=0; is<64; is++) { + if (signals[is]->isDbitList()){ + new_dbitlist.push_back(is); + ns++; + cout << is << " " << ns << endl; + } + } + if (ns>63) new_dbitlist.clear(); + myDet->setReceiverDbitList(new_dbitlist); + } + std::vector dbitlist=myDet->getReceiverDbitList(); + if (dbitlist.empty()) + for (int is=0; is<64; is++) signals[is]->setDbitList(1); + else + for (int is=0; is<64; is++) signals[is]->setDbitList(0); + for (const auto &value : dbitlist) signals[value]->setDbitList(1); + +} + + + + +void ctbSignals::ToggledPlot(Int_t b) { + + Emit("ToggledSignalPlot(Int_t)", b); + +} + + +void ctbSignals::ToggledSignalPlot(Int_t b) { + + Emit("ToggledSignalPlot(Int_t)", b); + +} + + +Pixel_t ctbSignals::getColor(int i){ + if (i>=0 && igetColor(); +} + +int ctbSignals::getPlot(int i){ + if (i>=0 && iisPlot(); +}; + +void ctbSignals::setDbitOffset(Long_t) { + setDbitOffset(); +} +void ctbSignals::setDbitOffset(){ + myDet->setReceiverDbitOffset(eDbitOffset->GetNumber()); +} diff --git a/ctbGui/ctbSignals.h b/ctbGui/ctbSignals.h new file mode 100755 index 000000000..8761b5f1d --- /dev/null +++ b/ctbGui/ctbSignals.h @@ -0,0 +1,118 @@ +#ifndef CTBSIGNALS_H +#define CTBSIGNALS_H +#include + + +#define NSIGNALS 64 + +#define NIOSIGNALS 64 //for moench board was 52 + + +#define ADCLATCH 63 +#define DIGSIGLATCH 62 + + + + +class TGTextEntry; +class TGLabel; +class TGNumberEntry; +class TGCheckButton; +class TH1I; +class TGTextButton; +class TGColorSelect; + + + +class TGNumberEntry; +class multiSlsDetector; +class ctbSignal; + +#include +using namespace std; + +class ctbSignal : public TGHorizontalFrame { + + // RQ_OBJECT("ctbSignal") + +private: + + TGLabel *sLabel; + TGCheckButton *sOutput; + TGCheckButton *sDbitList; + TGCheckButton *sPlot; + TGLabel *sValue; + TGNumberEntry *sEntry; + TGColorSelect *fColorSel; + + multiSlsDetector *myDet; + Int_t id; + + TH1I *hsig; + +public: + + ctbSignal(TGFrame *page, int i, multiSlsDetector *det); + int setSignalAlias(char *tit, int plot, int col); + string getSignalAlias(); + + TH1I *getPlot() {return hsig;}; + int setOutput(Long64_t); + int fixOutput(int); + int setDbitList(Long64_t); + + void ToggledOutput(Bool_t); + void ToggledDbitList(Bool_t); + void ToggledPlot(Bool_t); + void ColorChanged(Pixel_t); + + int isDbitList(); + int isOutput(); + int isPlot(); + Pixel_t getColor(); + + + void ToggledSignalOutput(Int_t); //*SIGNAL* + void ToggledSignalDbitList(Int_t); //*SIGNAL* + void ToggledSignalPlot(Int_t); //*SIGNAL* + + + + ClassDef(ctbSignal,0) +}; + +class ctbSignals : public TGGroupFrame { +private: + + ctbSignal *signals[NSIGNALS]; + + TGNumberEntry *eIOCntrlRegister; + TGNumberEntry *eDbitOffset; + + multiSlsDetector *myDet; + +public: + ctbSignals(TGVerticalFrame *page, multiSlsDetector *det); + int setSignalAlias(string line); + string getSignalAlias(); + + int getPlot(int); + Pixel_t getColor(int); + + void update(); + // void saveParameters(); + string getSignalParameters(); + + //void setDbitList(Int_t); + void setDbitOffset(Long_t); + void setDbitOffset(); + + void ToggledOutReg(Int_t); + void ToggledDbitList(Int_t); + void ToggledPlot(Int_t); + void ToggledSignalPlot(Int_t); //*SIGNAL* + + ClassDef(ctbSignals,0) +}; + +#endif diff --git a/ctbGui/ctbSlowAdcs.cpp b/ctbGui/ctbSlowAdcs.cpp new file mode 100644 index 000000000..4c6d34113 --- /dev/null +++ b/ctbGui/ctbSlowAdcs.cpp @@ -0,0 +1,185 @@ + +#include +#include +#include + +#include +#include +#include +#include + +#include "ctbSlowAdcs.h" +#include "multiSlsDetector.h" +#include "sls_detector_defs.h" + +using namespace std; + + + + +ctbSlowAdc::ctbSlowAdc(TGGroupFrame *page, int idac, multiSlsDetector *det) : TGHorizontalFrame(page, 800,50) , id(idac), myDet(det) { + + + TGHorizontalFrame *hframe=this; + + page->AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); + MapWindow(); + + char tit[100]; + + + sprintf(tit, "SENSE %d:",idac-1000); + + dacsLabel= new TGLabel(hframe, tit);// new TGLabel(hframe, tit); + + + + hframe->AddFrame(dacsLabel,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + dacsLabel->MapWindow(); + dacsLabel->SetTextJustify(kTextLeft); + + + + + sprintf(tit, "xxx"); + dacsValue= new TGLabel(hframe, tit); + hframe->AddFrame( dacsValue,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + dacsValue->MapWindow(); + dacsValue->SetTextJustify(kTextLeft); + + + + TGTextButton *b= new TGTextButton(hframe, "Update"); + hframe->AddFrame( b,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); + b->MapWindow(); + b->SetTextJustify(kTextLeft); + + b->Connect("Clicked()","ctbSlowAdc",this,"getValue()"); + + + +} + + + +int ctbSlowAdc::setLabel(char *tit) { + if(tit) + dacsLabel->SetText(tit); + + + return id; + +} + +string ctbSlowAdc::getLabel() { + + ostringstream line; + line << dacsLabel->GetText() << endl; + + // line << "DAC" << dec << id << " " << dacsUnit->IsOn() << endl; + + return line.str(); + +} + + + +int ctbSlowAdc::getValue() { + + int val=myDet->getADC((slsDetectorDefs::dacIndex)id); + char s[100]; + cout << "adc " << id << " " << val << endl; + sprintf(s,"%d mV",val); + if (id==999) + sprintf(s,"%d °C",val); + dacsValue->SetText(s); + + + + return val; + +} + + + + + + + +ctbSlowAdcs::ctbSlowAdcs(TGVerticalFrame *page, multiSlsDetector *det) : TGGroupFrame(page,"Sense",kVerticalFrame) , myDet(det){ + + + SetTitlePos(TGGroupFrame::kLeft); + page->AddFrame(this,new TGLayoutHints( kLHintsTop | kLHintsExpandX , 10,10,10,10)); + MapWindow(); + + // cout << "window mapped " << endl; + + + for (int idac=0; idacsetLabel("Temperature"); + +} + + + + +int ctbSlowAdcs::setSlowAdcAlias(string line) { + + int is=-1, mv=0; + char tit[100]; + int narg=sscanf(line.c_str(),"SENSE%d %s",&is,tit,&mv); + if (narg<2) + return -1; + if (is>=0 && issetLabel(tit); + return is; + +} + +string ctbSlowAdcs::getSlowAdcAlias() { + + ostringstream line; + + for (int i=0; igetLabel() << endl; + return line.str(); + +} + + + + +string ctbSlowAdcs::getAdcParameters() { + + + ostringstream line; + + for (int i=0; igetValue << endl; + line << "adc:" << i << " " << adcs[i]->getValue() << endl; + } + line << "adc:-1" << adcs[NSLOWADCS]->getValue() << endl; + return line.str(); + + +} + + + +void ctbSlowAdcs::update() { + + + for (int idac=0; idacgetValue(); + + } + + +} diff --git a/ctbGui/ctbSlowAdcs.h b/ctbGui/ctbSlowAdcs.h new file mode 100644 index 000000000..ef25944fa --- /dev/null +++ b/ctbGui/ctbSlowAdcs.h @@ -0,0 +1,75 @@ + + +#ifndef CTBSLOWADCS_H +#define CTBSLOWADCS_H +#include + + +//#define NDACS 16 +#define NSLOWADCS 8 + + + + +class TGTextEntry; +class TGLabel; +class TGNumberEntry; +class TGCheckButton; +class TGTextButton; + + + +class multiSlsDetector; + +#include +using namespace std; + +class ctbSlowAdc : public TGHorizontalFrame { + + + protected: + // TGLabel *dacsLabel; + // TGNumberEntry *dacsEntry; + // TGCheckButton *dacsUnit; + TGLabel *dacsLabel; + TGLabel *dacsValue; + int id; + + multiSlsDetector* myDet; + public: + ctbSlowAdc(TGGroupFrame*, int , multiSlsDetector*); + int getValue(); + + int setLabel(char *tit); + string getLabel(); + + + + ClassDef(ctbSlowAdc,0) +}; + + +class ctbSlowAdcs : public TGGroupFrame { +private: + + + + ctbSlowAdc *adcs[NSLOWADCS+1]; + + multiSlsDetector* myDet; + +public: + ctbSlowAdcs(TGVerticalFrame *page, multiSlsDetector*); + + int setSlowAdcAlias(string line); + // int setDacAlias(string line); + string getSlowAdcAlias(); + string getAdcParameters(); + + void update(); + + ClassDef(ctbSlowAdcs,0) +}; + +#endif + diff --git a/slsDetectorSoftware/include/detectorData.h b/slsDetectorSoftware/include/detectorData.h index 4b91aeba1..cf30bc124 100755 --- a/slsDetectorSoftware/include/detectorData.h +++ b/slsDetectorSoftware/include/detectorData.h @@ -25,7 +25,29 @@ class detectorData { npoints(np), npy(ny), cvalues(cval), databytes(dbytes), dynamicRange(dr), dgainvalues(NULL), fileIndex(file_ind) { strcpy(fileName,fname); - }; + }; + + + int64_t getChannel(int i) { + int off=dynamicRange/8; + if (off==1) { + char val=*(cvalues+i); + return val; + } + if (off==2) { + int16_t val=*((int16_t*)(cvalues+i*off)); + return val; + } + if (off==4) { + int32_t val=*((int32_t*)(cvalues+i*off)); + return val; + } + if (off==8) { + int64_t val=*((int64_t*)(cvalues+i*off)); + return val; + } + return -1; + } /** @short The destructor diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index 76a1b212f..c53db451b 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -3326,7 +3326,10 @@ void multiSlsDetector::readFrameFromReceiver() { uint32_t xoffset = coordX * nPixelsX * bytesPerPixel; uint32_t yoffset = coordY * nPixelsY; uint32_t singledetrowoffset = nPixelsX * bytesPerPixel; - uint32_t rowoffset = nX * singledetrowoffset; + uint32_t rowoffset = nX * singledetrowoffset; + if (getDetectorTypeAsEnum() == CHIPTESTBOARD) { + singledetrowoffset=size; + } FILE_LOG(logDEBUG1) << "Multi Image Info:" "\n\txoffset: " << xoffset << "\n\tyoffset: " << yoffset @@ -3340,7 +3343,11 @@ void multiSlsDetector::readFrameFromReceiver() { (char *)image + (i * singledetrowoffset), singledetrowoffset); } } else { + + for (uint32_t i = 0; i < nPixelsY; ++i) { + std::cout << i << " " << ((yoffset + i) * rowoffset) + xoffset << " " << (i * singledetrowoffset) << " " << singledetrowoffset << std::endl; + memcpy(((char *)multiframe) + ((yoffset + i) * rowoffset) + xoffset, (char *)image + (i * singledetrowoffset), singledetrowoffset); } @@ -3362,6 +3369,7 @@ void multiSlsDetector::readFrameFromReceiver() { } // normal pixels else { + // std::cout << "creating detectorData" << std::endl; thisData = new detectorData(getCurrentProgress(), currentFileName.c_str(), nCompletePixelsX, nCompletePixelsY, multiframe, multisize, dynamicRange, currentFileIndex); From 788ad8d3b6bd2d1d80550763fe899c06edd778c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Fr=C3=B6jdh?= Date: Tue, 28 May 2019 18:01:26 +0200 Subject: [PATCH 67/76] Command proxy (#25) * added cmd proxy * minor * minor * WIP * clean up * added comment --- .../include/multiSlsDetectorClient.h | 13 +++ .../src/sls_detector_client.cpp | 3 - slsSupportLib/include/CmdLineParser.h | 1 + slsSupportLib/include/CmdProxy.h | 100 ++++++++++++++++++ 4 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 slsSupportLib/include/CmdProxy.h diff --git a/slsDetectorSoftware/include/multiSlsDetectorClient.h b/slsDetectorSoftware/include/multiSlsDetectorClient.h index fba5f71f6..7f0eb8352 100755 --- a/slsDetectorSoftware/include/multiSlsDetectorClient.h +++ b/slsDetectorSoftware/include/multiSlsDetectorClient.h @@ -3,6 +3,7 @@ #include #include "CmdLineParser.h" +#include "CmdProxy.h" #include "container_utils.h" #include "string_utils.h" #include "multiSlsDetector.h" @@ -88,6 +89,18 @@ class multiSlsDetectorClient { return; } + + //Call CmdProxy which execute the command if it exists, on success returns an empty string + //If the command is not in CmdProxy but deprecated the new command is returned + sls::CmdProxy proxy(detPtr); + auto cmd = proxy.Call(parser.command(), parser.arguments(), parser.detector_id()); + if (cmd.empty()) + return; + else + parser.setCommand(cmd); + + + // call multi detector command line slsDetectorCommand myCmd(detPtr); std::string answer = myCmd.executeLine(parser.n_arguments()+1, parser.argv().data(), action_, parser.detector_id()); diff --git a/slsDetectorSoftware/src/sls_detector_client.cpp b/slsDetectorSoftware/src/sls_detector_client.cpp index 875950978..b1153a7fc 100755 --- a/slsDetectorSoftware/src/sls_detector_client.cpp +++ b/slsDetectorSoftware/src/sls_detector_client.cpp @@ -26,8 +26,5 @@ int main(int argc, char *argv[]) { #ifdef HELP int action = slsDetectorDefs::HELP_ACTION; #endif - - // if (argc > 1) - // argv++; multiSlsDetectorClient(argc, argv, action); } diff --git a/slsSupportLib/include/CmdLineParser.h b/slsSupportLib/include/CmdLineParser.h index af11254d3..811d88740 100755 --- a/slsSupportLib/include/CmdLineParser.h +++ b/slsSupportLib/include/CmdLineParser.h @@ -14,6 +14,7 @@ class CmdLineParser { int detector_id() const { return detector_id_; }; int n_arguments() const { return arguments_.size(); } const std::string &command() const { return command_; } + void setCommand(std::string cmd){command_ = cmd;} const std::string &executable() const { return executable_; } const std::vector &arguments() const { return arguments_; }; std::vector argv() const; diff --git a/slsSupportLib/include/CmdProxy.h b/slsSupportLib/include/CmdProxy.h new file mode 100644 index 000000000..434a829b4 --- /dev/null +++ b/slsSupportLib/include/CmdProxy.h @@ -0,0 +1,100 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "logger.h" +#include "sls_detector_exceptions.h" + +namespace sls { + +template class CmdProxy { + public: + explicit CmdProxy(T *detectorPtr) : det(detectorPtr) {} + + std::string Call(const std::string &command, + const std::vector &arguments, + int detector_id) { + cmd = command; + args = arguments; + det_id = detector_id; + + ReplaceIfDepreciated(cmd); + + auto it = functions.find(cmd); + if (it != functions.end()) { + std::cout << ((*this).*(it->second))(); + return {}; + } else { + return cmd; + } + } + + bool ReplaceIfDepreciated(std::string &command) { + auto d_it = depreciated_functions.find(command); + if (d_it != depreciated_functions.end()) { + FILE_LOG(logWARNING) + << "WARNING: " << command + << " is depreciated and will be removed. Please migrate to: " + << d_it->second; + command = d_it->second; + return true; + } + return false; + } + + size_t GetFunctionMapSize() const noexcept { return functions.size(); }; + + private: + T *det; + std::string cmd; + std::vector args; + int det_id{-1}; + + using FunctionMap = std::map; + using StringMap = std::map; + + // Initialize maps for translating name and function + FunctionMap functions{{"newfunc", &CmdProxy::NewFunction}}; + + StringMap depreciated_functions{{"oldvrfcmd", "vrf"}, + {"veryveryold", "vcp"}, + {"anothercmd", "vrs"}, + {"this_as_well", "enablefwrite"}}; + + + template std::string ResultToString(const U &ret) { + std::ostringstream os; + if (det_id != -1) + os << det_id << ":"; + os << cmd << " " << ret << "\n"; + return os.str(); + } + + void WrongNumberOfParameters(size_t expected) { + throw RuntimeError("ERROR: Expected " + std::to_string(expected) + + " parameters but got " + std::to_string(args.size()) + + "\n"); + } + + // Mapped functions + + //example + std::string NewFunction() { + if(args.size() == 0){ + std::cout << "This is the new function function\n"; + return ResultToString(det->setExposureTime(-1, true)); + }else if(args.size() == 1){ + std::cout << "Setting exposure time to " << args[0] << "s\n"; + return ResultToString(det->setExposureTime(std::stod(args[0]), true, det_id)); + }else{ + WrongNumberOfParameters(1); + return {}; + } + } +}; + +} // namespace sls From 0f869e1215d4645ca69d0d219cca3084a17b151d Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Tue, 28 May 2019 18:15:15 +0200 Subject: [PATCH 68/76] fixed acquire not working --- .../include/multiSlsDetectorClient.h | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/slsDetectorSoftware/include/multiSlsDetectorClient.h b/slsDetectorSoftware/include/multiSlsDetectorClient.h index 7f0eb8352..7f15703e1 100755 --- a/slsDetectorSoftware/include/multiSlsDetectorClient.h +++ b/slsDetectorSoftware/include/multiSlsDetectorClient.h @@ -92,13 +92,18 @@ class multiSlsDetectorClient { //Call CmdProxy which execute the command if it exists, on success returns an empty string //If the command is not in CmdProxy but deprecated the new command is returned - sls::CmdProxy proxy(detPtr); - auto cmd = proxy.Call(parser.command(), parser.arguments(), parser.detector_id()); - if (cmd.empty()) - return; - else - parser.setCommand(cmd); - + if(action_ != slsDetectorDefs::READOUT_ACTION){ + sls::CmdProxy proxy(detPtr); + auto cmd = proxy.Call(parser.command(), parser.arguments(), parser.detector_id()); + if (cmd.empty()){ + return; + } + else{ + parser.setCommand(cmd); + } + } + + // call multi detector command line From d935e78763d07fcee839aa520fcd1f4fc63e53c7 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Tue, 28 May 2019 18:15:43 +0200 Subject: [PATCH 69/76] clang-format --- .../include/multiSlsDetectorClient.h | 83 ++++++++++--------- 1 file changed, 46 insertions(+), 37 deletions(-) diff --git a/slsDetectorSoftware/include/multiSlsDetectorClient.h b/slsDetectorSoftware/include/multiSlsDetectorClient.h index 7f15703e1..d00f0c314 100755 --- a/slsDetectorSoftware/include/multiSlsDetectorClient.h +++ b/slsDetectorSoftware/include/multiSlsDetectorClient.h @@ -5,10 +5,10 @@ #include "CmdLineParser.h" #include "CmdProxy.h" #include "container_utils.h" -#include "string_utils.h" #include "multiSlsDetector.h" #include "slsDetectorCommand.h" #include "sls_detector_exceptions.h" +#include "string_utils.h" #include #include @@ -22,59 +22,69 @@ inline int dummyCallback(detectorData *d, int p, void *) { class multiSlsDetectorClient { public: - multiSlsDetectorClient(int argc, char *argv[], int action, multiSlsDetector *myDetector = nullptr): - action_(action), - detPtr(myDetector){ + multiSlsDetectorClient(int argc, char *argv[], int action, + multiSlsDetector *myDetector = nullptr) + : action_(action), detPtr(myDetector) { parser.Parse(argc, argv); runCommand(); - } - multiSlsDetectorClient(const std::string& args, int action, multiSlsDetector *myDetector = nullptr): - action_(action), - detPtr(myDetector){ + multiSlsDetectorClient(const std::string &args, int action, + multiSlsDetector *myDetector = nullptr) + : action_(action), detPtr(myDetector) { parser.Parse(args); runCommand(); } - private: - int action_; - CmdLineParser parser; - multiSlsDetector* detPtr = nullptr; - void runCommand(){ + private: + int action_; + CmdLineParser parser; + multiSlsDetector *detPtr = nullptr; + + void runCommand() { bool verify = true; bool update = true; - if (action_ == slsDetectorDefs::PUT_ACTION && parser.n_arguments() == 0) { - std::cout << "Wrong usage - should be: " << parser.executable() << "[id-][pos:]channel arg" << std::endl; + if (action_ == slsDetectorDefs::PUT_ACTION && + parser.n_arguments() == 0) { + std::cout << "Wrong usage - should be: " << parser.executable() + << "[id-][pos:]channel arg" << std::endl; std::cout << std::endl; return; }; - if (action_ == slsDetectorDefs::GET_ACTION && parser.command().empty()) { - std::cout << "Wrong usage - should be: " << parser.executable() << "[id-][pos:]channel arg" << std::endl; + if (action_ == slsDetectorDefs::GET_ACTION && + parser.command().empty()) { + std::cout << "Wrong usage - should be: " << parser.executable() + << "[id-][pos:]channel arg" << std::endl; std::cout << std::endl; return; }; - if (action_ == slsDetectorDefs::READOUT_ACTION && parser.detector_id() != -1) { - std::cout << "detector_id: " << parser.detector_id() << " ,readout of individual detectors is not allowed!" << std::endl; + if (action_ == slsDetectorDefs::READOUT_ACTION && + parser.detector_id() != -1) { + std::cout << "detector_id: " << parser.detector_id() + << " ,readout of individual detectors is not allowed!" + << std::endl; return; } // special commands if (parser.command() == "free") { - multiSlsDetector::freeSharedMemory(parser.multi_id(), parser.detector_id()); + multiSlsDetector::freeSharedMemory(parser.multi_id(), + parser.detector_id()); return; } // get user details without verify sharedMultiSlsDetector version - else if ((parser.command() == "user") && (action_ == slsDetectorDefs::GET_ACTION)) { + else if ((parser.command() == "user") && + (action_ == slsDetectorDefs::GET_ACTION)) { verify = false; update = false; } - //std::cout<<"id:"< localDet; if (detPtr == nullptr) { try { - localDet = sls::make_unique(parser.multi_id(), verify, update); + localDet = sls::make_unique(parser.multi_id(), + verify, update); detPtr = localDet.get(); } catch (const RuntimeError &e) { /*std::cout << e.GetMessage() << std::endl;*/ @@ -89,28 +99,27 @@ class multiSlsDetectorClient { return; } - - //Call CmdProxy which execute the command if it exists, on success returns an empty string - //If the command is not in CmdProxy but deprecated the new command is returned - if(action_ != slsDetectorDefs::READOUT_ACTION){ + // Call CmdProxy which execute the command if it exists, on success + // returns an empty string If the command is not in CmdProxy but + // deprecated the new command is returned + if (action_ != slsDetectorDefs::READOUT_ACTION) { sls::CmdProxy proxy(detPtr); - auto cmd = proxy.Call(parser.command(), parser.arguments(), parser.detector_id()); - if (cmd.empty()){ + auto cmd = proxy.Call(parser.command(), parser.arguments(), + parser.detector_id()); + if (cmd.empty()) { return; - } - else{ + } else { parser.setCommand(cmd); } } - - - // call multi detector command line - slsDetectorCommand myCmd(detPtr); - std::string answer = myCmd.executeLine(parser.n_arguments()+1, parser.argv().data(), action_, parser.detector_id()); + slsDetectorCommand myCmd(detPtr); + std::string answer = + myCmd.executeLine(parser.n_arguments() + 1, parser.argv().data(), + action_, parser.detector_id()); - if (parser.multi_id()!=0) + if (parser.multi_id() != 0) std::cout << parser.multi_id() << '-'; if (parser.detector_id() != -1) std::cout << parser.detector_id() << ':'; From 25541b37f6e23303106b841c576bd78036e7d67c Mon Sep 17 00:00:00 2001 From: Anna Bergamaschi Date: Wed, 29 May 2019 11:38:43 +0200 Subject: [PATCH 70/76] added patternGenerator and slsDteectorCalibration directory in order to compile the ctbGui --- ctbGui/Makefile.root6 | 4 +- ctbGui/patternGenerator/deserializer.cpp | 110 ++ ctbGui/patternGenerator/generate.sh | 30 + ctbGui/patternGenerator/generator.c | 177 +++ ctbGui/patternGenerator/test.p | 201 +++ slsDetectorCalibration/MovingStat.h | 156 +++ slsDetectorCalibration/RunningStat.h | 55 + slsDetectorCalibration/Stat.h | 45 + slsDetectorCalibration/analogDetector.h | 1166 +++++++++++++++++ .../commonModeSubtraction.h | 82 ++ .../commonModeSubtractionNew.h | 116 ++ .../dataStructures/Mythen3_01_jctbData.h | 123 ++ .../dataStructures/Mythen3_02_jctbData.h | 130 ++ .../dataStructures/adcSar2_jctbData.h | 63 + .../dataStructures/chiptestBoardData.h | 89 ++ .../gotthardDoubleModuleDataNew.h | 172 +++ .../dataStructures/gotthardShortModuleData.h | 127 ++ .../dataStructures/moench02CtbData.h | 169 +++ .../dataStructures/moench03CtbData.h | 157 +++ .../dataStructures/moench03T1CtbData.h | 158 +++ .../moench03T1ReceiverDataNew.h | 290 ++++ .../moench03T1ReceiverDataNewRect.h | 321 +++++ .../dataStructures/moench03T1ReorderedData.h | 176 +++ .../dataStructures/moench03T1ZmqDataNew.h | 268 ++++ .../dataStructures/moench03TCtbData.h | 180 +++ .../dataStructures/moench04CtbReceiverData.h | 291 ++++ .../dataStructures/slsDetectorData.h | 338 +++++ .../dataStructures/slsReceiverData.h | 238 ++++ slsDetectorCalibration/doxy.config | 85 ++ slsDetectorCalibration/energyCalibration.h | 462 +++++++ .../gotthardExecutables/Makefile | 14 + .../interpolatingDetector.h | 275 ++++ .../interpolations/eta2InterpolationBase.h | 403 ++++++ .../interpolations/eta3InterpolationBase.h | 294 +++++ .../etaInterpolationAdaptiveBins.h | 285 ++++ .../interpolations/etaInterpolationBase.h | 369 ++++++ .../etaInterpolationCleverAdaptiveBins.h | 263 ++++ .../interpolations/etaInterpolationGlobal.h | 85 ++ .../interpolations/etaInterpolationPosXY.h | 184 +++ .../etaInterpolationRandomBins.h | 417 ++++++ .../interpolations/etaVEL/EVELAlg.C | 678 ++++++++++ .../interpolations/etaVEL/EtaVEL.cpp | 679 ++++++++++ .../interpolations/etaVEL/EtaVEL.h | 164 +++ .../interpolations/etaVEL/EtaVELTr.py | 393 ++++++ .../etaVEL/etaVELInterpolation.cpp | 134 ++ .../etaVEL/etaVELInterpolation.h | 55 + .../interpolations/linearInterpolation.h | 234 ++++ .../interpolations/noInterpolation.h | 104 ++ .../interpolations/slsInterpolation.h | 503 +++++++ slsDetectorCalibration/moench03CommonMode.h | 45 + slsDetectorCalibration/moenchCommonMode.h | 45 + .../moenchExecutables/Makefile.cluster_finder | 34 + .../moenchExecutables/Makefile.zmq | 16 + .../moench03ClusterFinder.cpp | 237 ++++ .../moench03Interpolation.cpp | 249 ++++ .../moench03NoInterpolation.cpp | 170 +++ .../moenchExecutables/moenchPhotonCounter.cpp | 358 +++++ .../moenchExecutables/moenchZmqProcess.cpp | 707 ++++++++++ .../multiThreadedAnalogDetector.h | 568 ++++++++ .../multiThreadedCountingDetector.h | 51 + .../multiThreadedInterpolatingDetector.h | 112 ++ slsDetectorCalibration/pedestalSubtraction.h | 63 + slsDetectorCalibration/singlePhotonDetector.h | 642 +++++++++ slsDetectorCalibration/single_photon_hit.h | 263 ++++ slsDetectorCalibration/tiffIO.cpp | 77 ++ slsDetectorCalibration/tiffIO.h | 36 + this_build_bin_path.sh | 30 + 67 files changed, 15213 insertions(+), 2 deletions(-) create mode 100644 ctbGui/patternGenerator/deserializer.cpp create mode 100755 ctbGui/patternGenerator/generate.sh create mode 100755 ctbGui/patternGenerator/generator.c create mode 100755 ctbGui/patternGenerator/test.p create mode 100755 slsDetectorCalibration/MovingStat.h create mode 100755 slsDetectorCalibration/RunningStat.h create mode 100644 slsDetectorCalibration/Stat.h create mode 100644 slsDetectorCalibration/analogDetector.h create mode 100644 slsDetectorCalibration/commonModeSubtraction.h create mode 100644 slsDetectorCalibration/commonModeSubtractionNew.h create mode 100644 slsDetectorCalibration/dataStructures/Mythen3_01_jctbData.h create mode 100644 slsDetectorCalibration/dataStructures/Mythen3_02_jctbData.h create mode 100644 slsDetectorCalibration/dataStructures/adcSar2_jctbData.h create mode 100644 slsDetectorCalibration/dataStructures/chiptestBoardData.h create mode 100644 slsDetectorCalibration/dataStructures/gotthardDoubleModuleDataNew.h create mode 100644 slsDetectorCalibration/dataStructures/gotthardShortModuleData.h create mode 100644 slsDetectorCalibration/dataStructures/moench02CtbData.h create mode 100644 slsDetectorCalibration/dataStructures/moench03CtbData.h create mode 100644 slsDetectorCalibration/dataStructures/moench03T1CtbData.h create mode 100644 slsDetectorCalibration/dataStructures/moench03T1ReceiverDataNew.h create mode 100644 slsDetectorCalibration/dataStructures/moench03T1ReceiverDataNewRect.h create mode 100644 slsDetectorCalibration/dataStructures/moench03T1ReorderedData.h create mode 100644 slsDetectorCalibration/dataStructures/moench03T1ZmqDataNew.h create mode 100644 slsDetectorCalibration/dataStructures/moench03TCtbData.h create mode 100644 slsDetectorCalibration/dataStructures/moench04CtbReceiverData.h create mode 100644 slsDetectorCalibration/dataStructures/slsDetectorData.h create mode 100644 slsDetectorCalibration/dataStructures/slsReceiverData.h create mode 100644 slsDetectorCalibration/doxy.config create mode 100644 slsDetectorCalibration/energyCalibration.h create mode 100644 slsDetectorCalibration/gotthardExecutables/Makefile create mode 100644 slsDetectorCalibration/interpolatingDetector.h create mode 100644 slsDetectorCalibration/interpolations/eta2InterpolationBase.h create mode 100644 slsDetectorCalibration/interpolations/eta3InterpolationBase.h create mode 100644 slsDetectorCalibration/interpolations/etaInterpolationAdaptiveBins.h create mode 100644 slsDetectorCalibration/interpolations/etaInterpolationBase.h create mode 100644 slsDetectorCalibration/interpolations/etaInterpolationCleverAdaptiveBins.h create mode 100644 slsDetectorCalibration/interpolations/etaInterpolationGlobal.h create mode 100644 slsDetectorCalibration/interpolations/etaInterpolationPosXY.h create mode 100644 slsDetectorCalibration/interpolations/etaInterpolationRandomBins.h create mode 100644 slsDetectorCalibration/interpolations/etaVEL/EVELAlg.C create mode 100644 slsDetectorCalibration/interpolations/etaVEL/EtaVEL.cpp create mode 100644 slsDetectorCalibration/interpolations/etaVEL/EtaVEL.h create mode 100644 slsDetectorCalibration/interpolations/etaVEL/EtaVELTr.py create mode 100644 slsDetectorCalibration/interpolations/etaVEL/etaVELInterpolation.cpp create mode 100644 slsDetectorCalibration/interpolations/etaVEL/etaVELInterpolation.h create mode 100644 slsDetectorCalibration/interpolations/linearInterpolation.h create mode 100644 slsDetectorCalibration/interpolations/noInterpolation.h create mode 100644 slsDetectorCalibration/interpolations/slsInterpolation.h create mode 100644 slsDetectorCalibration/moench03CommonMode.h create mode 100644 slsDetectorCalibration/moenchCommonMode.h create mode 100644 slsDetectorCalibration/moenchExecutables/Makefile.cluster_finder create mode 100644 slsDetectorCalibration/moenchExecutables/Makefile.zmq create mode 100644 slsDetectorCalibration/moenchExecutables/moench03ClusterFinder.cpp create mode 100644 slsDetectorCalibration/moenchExecutables/moench03Interpolation.cpp create mode 100644 slsDetectorCalibration/moenchExecutables/moench03NoInterpolation.cpp create mode 100644 slsDetectorCalibration/moenchExecutables/moenchPhotonCounter.cpp create mode 100644 slsDetectorCalibration/moenchExecutables/moenchZmqProcess.cpp create mode 100644 slsDetectorCalibration/multiThreadedAnalogDetector.h create mode 100644 slsDetectorCalibration/multiThreadedCountingDetector.h create mode 100644 slsDetectorCalibration/multiThreadedInterpolatingDetector.h create mode 100644 slsDetectorCalibration/pedestalSubtraction.h create mode 100644 slsDetectorCalibration/singlePhotonDetector.h create mode 100644 slsDetectorCalibration/single_photon_hit.h create mode 100644 slsDetectorCalibration/tiffIO.cpp create mode 100644 slsDetectorCalibration/tiffIO.h create mode 100755 this_build_bin_path.sh diff --git a/ctbGui/Makefile.root6 b/ctbGui/Makefile.root6 index c80b29fed..2251e5888 100644 --- a/ctbGui/Makefile.root6 +++ b/ctbGui/Makefile.root6 @@ -8,11 +8,11 @@ ZMQLIB=../slsReceiverSoftware/include LIBRARYCBF=$(CBFLIBDIR)/lib/*.o INCDIR=-I../slsReceiverSoftware/include/ -I../slsDetectorSoftware/include/ -I../slsSupportLib/include/ -I../slsDetectorCalibration -I../slsDetectorCalibration/dataStructures -I$(CBFLIBDIR)/include -I../slsDetectorCalibration/interpolations -LDFLAG=-L../bin -lSlsDetector -lSlsSupport -L/usr/lib64/ -lpthread -lm -lstdc++ -lzmq -pthread -lrt -ltiff -L$(ZMQLIB) -L$(CBFLIBDIR)/lib/ -std=c++11 +LDFLAG=-L../build/bin -lSlsDetector -lSlsSupport -L/usr/lib64/ -lpthread -lm -lstdc++ -lzmq -pthread -lrt -ltiff -L$(ZMQLIB) -L$(CBFLIBDIR)/lib/ -std=c++11 # MAIN=ctbGui.cpp -DESTDIR?=../bin +DESTDIR?=../build/bin OBJS = $(SRC:.cpp=.o) $(MAIN:.cpp=.o) diff --git a/ctbGui/patternGenerator/deserializer.cpp b/ctbGui/patternGenerator/deserializer.cpp new file mode 100644 index 000000000..c315ca419 --- /dev/null +++ b/ctbGui/patternGenerator/deserializer.cpp @@ -0,0 +1,110 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) { + + int iarg; + char fname[10000]; + uint64_t word; + int val[64]; + int bit[64]; + FILE *fdin; + + int nb=2; + int off=0; + int ioff=0; + int dr=24; + int idr=0; + int ib=0; + int iw=0; + bit[0]=19; + bit[1]=8; + // for (iarg=0; iarg2) dr=atoi(argv[2]); + if (argc>3) off=atoi(argv[3]); + if (argc>4) { + for (ib=0; ib<64; ib++) { + if (argc>4+ib) { + bit[ib]=atoi(argv[4+ib]); + nb++; + } + } + + } + + idr=0; + for (ib=0; ib +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAXLOOPS 3 +#define MAXTIMERS 3 +#define MAXWORDS 1024 + + + +uint64_t pat=0; +uint64_t iopat=0; +uint64_t clkpat=0; + +int iaddr=0; +int waitaddr[3]={MAXWORDS,MAXWORDS,MAXWORDS}; +int startloopaddr[3]={MAXWORDS,MAXWORDS,MAXWORDS}; +int stoploopaddr[3]={MAXWORDS,MAXWORDS,MAXWORDS}; +int start=0, stop=0; +uint64_t waittime[3]={0,0,0}; +int nloop[3]={0,0,0}; + +char infile[10000], outfile[10000]; + +FILE *fd, *fd1; +uint64_t PAT[MAXWORDS]; + + +int i,ii,iii,j,jj,jjj,pixx,pixy,memx,memy,muxout,memclk,colclk,rowclk,muxclk,memcol,memrow,loopcounter; + +void setstart() { + start=iaddr; +} + +void setstop() { + stop=iaddr; +} + +void setinput(int bit) { + uint64_t mask=1; + mask=mask<>bit; +} + +void setstartloop(int iloop) { + if (iloop>=0 && iloop=0 && iloop=0 && iloop=0 && iloop=0 && iloop=MAXWORDS) printf("ERROR: too many word in the pattern (%d instead of %d)!",iaddr, MAXWORDS); +} + +int parseCommand(int clk, int cmdbit, int cmd, int length) { + int ibit; + clearbit(clk); + for (ibit=0; ibit>ibit)) + setbit(cmdbit); + else + clearbit(cmdbit); + pw(); + /******/ + setbit(clk); + pw(); + /******/ + } +}; + + + +main(void) { + int iloop=0; + fd=fopen(OUTFILE,"w"); +#include INFILE + + fprintf(fd,"patioctrl %016llx\n",iopat); + fprintf(fd,"patclkctrl %016llx\n",clkpat); + fprintf(fd,"patlimits %04x %04x\n",start, stop); + + for (iloop=0; iloop + + +class MovingStat + { + + /** @short approximated moving average structure */ + public: + + + /** constructor + \param nn number of samples parameter to be used + */ + MovingStat(int nn=1000) : n(nn), m_n(0) {} + + /** + clears the moving average number of samples parameter, mean and standard deviation + */ + void Clear() + { + m_n = 0; + m_newM=0; + m_newM2=0; + } + + /** + clears the moving average number of samples parameter, mean and standard deviation + */ + void Set(double val, double rms=0, int m=-1) + { + if (m>=0) m_n = m; else m_n = n; + m_newM=val*m_n; + SetRMS(rms); + } + /** + clears the moving average number of samples parameter, mean and standard deviation + */ + void SetRMS(double rms) + { + if (rms<=0) { + m_newM2=m_newM*m_newM/n; + m_n=0; + } else { + if (m_n>0) + m_newM2=(m_n*rms*rms+m_newM*m_newM/m_n); + else { + m_newM2=(m_n*rms*rms+m_newM*m_newM/n); + m_n=0; + } + } + } + + /** sets number of samples parameter + \param i number of samples parameter to be set + */ + + int SetN(int i) {if (i>=1) n=i; return n;}; + + /** + gets number of samples parameter + \returns actual number of samples parameter + */ + int GetN() {return m_n;}; + + /** calculates the moving average i.e. adds if number of elements is lower than number of samples parameter, pushes otherwise + \param x value to calculate the moving average + */ + inline void Calc(double x) { + if (m_n 0) ? m_newM/m_n : 0.0; + } + + /** returns the squared mean, 0 if no elements are inside + \returns returns the squared average + */ + double M2() const + { + return ( (m_n > 1) ? m_newM2/m_n : 0.0 ); + } + + /** returns the variance, 0 if no elements are inside + \returns returns the variance + */ + inline double Variance() const + { + return ( (m_n > 1) ? (M2()-Mean()*Mean()) : 0.0 ); + } + + /** returns the standard deviation, 0 if no elements are inside + \returns returns the standard deviation + */ + inline double StandardDeviation() const + { + return ( (Variance() > 0) ? sqrt( Variance() ) : -1 ); + } + + private: + int n; /**< number of samples parameter */ + int m_n; /**< current number of elements */ + double m_newM; /**< accumulated average */ + double m_newM2; /**< accumulated squared average */ + }; +#endif diff --git a/slsDetectorCalibration/RunningStat.h b/slsDetectorCalibration/RunningStat.h new file mode 100755 index 000000000..1197ffc0f --- /dev/null +++ b/slsDetectorCalibration/RunningStat.h @@ -0,0 +1,55 @@ + class RunningStat + { + public: + RunningStat() : m_n(0) {} + + void Clear() + { + m_n = 0; + } + + void Push(double x) + { + m_n++; + + // See Knuth TAOCP vol 2, 3rd edition, page 232 + if (m_n == 1) + { + m_oldM = m_newM = x; + m_oldS = 0.0; + } + else + { + m_newM = m_oldM + (x - m_oldM)/m_n; + m_newS = m_oldS + (x - m_oldM)*(x - m_newM); + + // set up for next iteration + m_oldM = m_newM; + m_oldS = m_newS; + } + } + + int NumDataValues() const + { + return m_n; + } + + double Mean() const + { + return (m_n > 0) ? m_newM : 0.0; + } + + double Variance() const + { + return ( (m_n > 1) ? m_newS/(m_n - 1) : 0.0 ); + } + + double StandardDeviation() const + { + return sqrt( Variance() ); + } + + private: + int m_n; + double m_oldM, m_newM, m_oldS, m_newS; + }; diff --git a/slsDetectorCalibration/Stat.h b/slsDetectorCalibration/Stat.h new file mode 100644 index 000000000..196f5bbb7 --- /dev/null +++ b/slsDetectorCalibration/Stat.h @@ -0,0 +1,45 @@ +class Stat + { + public: + + Stat() : n(0), m(0.), m2(0.) {} + + void Clear() + { + n = 0; + m=0; + m2=0; + } + + void Push(double x) + { + + m+=x; + m2+=x*x; + n++; + } + + int NumDataValues() const + { + return n; + } + + double Mean() const + { + return (n > 0) ? m/n : 0.0; + } + + double Variance() const + { + return ( (n >0 ) ? (m2/n-m*m/(n*n)) : 0.0 ); + } + + double StandardDeviation() const + { + return sqrt( Variance() ); + } + + private: + int n; + double m, m2; + }; diff --git a/slsDetectorCalibration/analogDetector.h b/slsDetectorCalibration/analogDetector.h new file mode 100644 index 000000000..49197f0a6 --- /dev/null +++ b/slsDetectorCalibration/analogDetector.h @@ -0,0 +1,1166 @@ +#ifndef ANALOGDETECTOR_H +#define ANALOGDETECTOR_H + +//#include + +#include +#include "slsDetectorData.h" +#include "pedestalSubtraction.h" +#include "commonModeSubtraction.h" +#include "tiffIO.h" +#include "slsInterpolation.h" + + +#ifdef ROOTSPECTRUM +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +using namespace std; + +#ifndef FRAMEMODE_DEF +#define FRAMEMODE_DEF +/** +enum to define the flags of the data set, which are needed to seect the type of processing it should undergo: frame, pedestal, flat +*/ + enum frameMode { eFrame, ePedestal, eFlat }; +/** +enum to define the detector mode +*/ + enum detectorMode { eAnalog, ePhotonCounting, eInterpolating }; +#endif + + +template class analogDetector { + + /** @short class to perform pedestal subtraction etc. for an analog detector */ + + public: + + + + /** + + Constructor (no error checking if datasize and offsets are compatible!) + \param d detector data structure to be used - if null it is assumed that the data are in ordered ip=iy*nx+ix + \param sign is the sign of the data + \param nped number of samples for pedestal averaging + \param cm common mode subtraction algorithm, if any. Defaults to NULL i.e. none + \param nnx detector size in x - must be specified if no data structure is defined, otherwise defaults to the size of the data structure. + \param nny detector size in y - must be specified if no data structure is defined, otherwise defaults to the size of the data structure. + \param gm pointer to tha gain map matrix + + + */ + + + analogDetector(slsDetectorData *d, int sign=1, + commonModeSubtraction *cm=NULL, int nped=1000, int nnx=-1, int nny=-1, double *gm=NULL) : det(d), nx(nnx), ny(nny), stat(NULL), cmSub(cm), iframe(-1), dataSign(sign), gmap(gm), id(0) { + + if (det) + det->getDetectorSize(nx,ny); + + stat=new pedestalSubtraction*[ny]; + for (int i=0; idet; + nx=orig->nx; + ny=orig->ny; + dataSign=orig->dataSign; + iframe=orig->iframe; + gmap=orig->gmap; + cmSub=orig->cmSub; + id=orig->id; + xmin=orig->xmin; + xmax=orig->xmax; + ymin=orig->ymin; + ymax=orig->ymax; + thr=orig->thr; + // nSigma=orig->nSigma; + fMode=orig->fMode; + myFile=orig->myFile; + + + stat=new pedestalSubtraction*[ny]; + for (int i=0; iSetNPedestals(); + //cout << nped << " " << orig->getPedestal(ix,iy) << orig->getPedestalRMS(ix,iy) << endl; + for (int iy=0; iygetPedestal(ix,iy),orig->getPedestalRMS(ix,iy),orig->GetNPedestals(ix,iy)); + } + } + image=new int[nx*ny]; +#ifdef ROOTSPECTRUM + hs=(TH2F*)(orig->hs)->Clone();//new TH2F("hs","hs",(orig->hs)-getNbins,-500,9500,nx*ny,-0.5,nx*ny-0.5); +#ifdef ROOTCLUST + hs3=(TH2F*)(orig->hs3)->Clone();//new TH2F("hs","hs",(orig->hs)-getNbins,-500,9500,nx*ny,-0.5,nx*ny-0.5); + hs5=(TH2F*)(orig->hs5)->Clone();//new TH2F("hs","hs",(orig->hs)-getNbins,-500,9500,nx*ny,-0.5,nx*ny-0.5); + hs7=(TH2F*)(orig->hs7)->Clone();//new TH2F("hs","hs",(orig->hs)-getNbins,-500,9500,nx*ny,-0.5,nx*ny-0.5); + hs9=(TH2F*)(orig->hs9)->Clone();//new TH2F("hs","hs",(orig->hs)-getNbins,-500,9500,nx*ny,-0.5,nx*ny-0.5); +#endif +#endif + + } + + + /** + clone. Must be virtual! + \returns a clone of the original analog detector + */ + virtual analogDetector *Clone() { + return new analogDetector(this); + } + + /** + Gives an id to the structure. For debugging purposes in case of multithreading. + \param i is to be set + \returns current id + */ + int setId(int i){id=i; return id;}; + + /** + Returns id of the structure. For debugging purposes in case of multithreading. + \returns current id + */ + int getId() {return id; }; + /** + Returns data size of the detector data structure + \returns data size of the detector data structurein bytes + */ + int getDataSize(){return det->getDataSize();}; + /** + Returns data size of the detector image matrix + \param nnx reference to image size in x + \param nny reference to image size in y + \param nns reference to number of subpixels for interpolating detector, will always be 1 in this case + \returns number of pixels of the detector image + */ + virtual int getImageSize(int &nnx, int &nny, int &nns){nnx=nx; nny=ny; nns=1; return nx*ny;}; + /** + Returns data size of the detector image matrix + \param nnx reference to pixel size in x + \param nny reference to pixel size in y + \returns number of pixels of the detector image + */ + virtual int getDetectorSize(int &nnx, int &nny){nnx=nx; nny=ny; return nx*ny;}; + + /** + set gain map + \param gm pointer to gain map matrix to be set - NULL unsets + \returns pointer to current gain map + */ + double *setGainMap(double *gm) {gmap=gm; return gmap;}; + + /** + return gain map + \returns pointer to current gain map + */ + double *getGainMap() {return gmap;}; + /** + reads a 32 bit tiff file of the size of the detector and sets its values as gain map for the detector. If file does not exist returns NULL, but does not change gainmap compared to previous settings. + \param imgname complete name of the file containing the gain map data + \returns pointer to current gain map is file reading succeeded, NULL is file reading didn't work. + */ + double *readGainMap(const char * imgname) { + uint32 nnx, nny; + float *gm=ReadFromTiff( imgname, nny, nnx); + if (gm) { + if (gmap) delete [] gmap; + gmap=new double[nnx*nny]; + for (int iy=0; iyClear(); +#ifdef ROOTSPECTRUM + hs->Reset(); +#ifdef ROOTCLUST + hs3->Reset();//new TH2F("hs","hs",(orig->hs)-getNbins,-500,9500,nx*ny,-0.5,nx*ny-0.5); + hs5->Reset();//new TH2F("hs","hs",(orig->hs)-getNbins,-500,9500,nx*ny,-0.5,nx*ny-0.5); + hs7->Reset();//new TH2F("hs","hs",(orig->hs)-getNbins,-500,9500,nx*ny,-0.5,nx*ny-0.5); + hs9->Reset();//new TH2F("hs","hs",(orig->hs)-getNbins,-500,9500,nx*ny,-0.5,nx*ny-0.5); +#endif +#endif + }; + + /** resets the commonModeSubtraction and increases the frame index */ + virtual void newFrame(){iframe++; if (cmSub) cmSub->newFrame();}; + + + /** sets the commonModeSubtraction algorithm to be used + \param cm commonModeSubtraction algorithm to be used (NULL unsets) + \returns pointer to the actual common mode subtraction algorithm + */ + commonModeSubtraction *setCommonModeSubtraction(commonModeSubtraction *cm) {cmSub=cm; return cmSub;}; +/** + gets the commonModeSubtraction algorithm to be used + \returns pointer to the actual common mode subtraction algorithm + */ + commonModeSubtraction *getCommonModeSubtraction() {return cmSub;}; + + + /** + sets the sign of the data + \param sign 1 means positive values for photons, -1 negative, 0 gets + \returns current sign for the data + */ + int setDataSign(int sign=0) {if (sign==1 || sign==-1) dataSign=sign; return dataSign;}; + + + /** + adds value to pedestal (and common mode) for the given pixel + \param val value to be added + \param ix pixel x coordinate + \param iy pixel y coordinate + \param cm 1 adds the value to common mod, 0 skips it. Defaults to 0. - not properly implemented + */ + virtual void addToPedestal(double val, int ix, int iy=0, int cm=0){ + if (ix>=0 && ix=0 && iy0) { + val-= getCommonMode(ix, iy); + } + stat[iy][ix].addToPedestal(val); + /* if (cmSub && cm>0) { */ + /* if (det) if (det->isGood(ix, iy)==0) return; */ + /* cmSub->addToCommonMode(val, ix, iy); */ + /* }; */ + }; + } + + double getCommonMode(int ix, int iy) { + if (cmSub) return cmSub->getCommonMode(ix, iy); + else return 0; + } + + + virtual void addToCommonMode(char *data){ + if (cmSub) { + for (int iy=ymin; iy0) + if (det->isGood(ix,iy)) + addToCommonMode(data, ix, iy); + } + } + //cout << "cm " << getCommonMode(0,0) << " " << getCommonMode(1,0) << endl; + } + } + virtual void addToCommonMode(char *data, int ix, int iy=0){ + if (cmSub) { + if (det) if (det->isGood(ix, iy)==0) return; + if (getNumpedestals(ix,iy)>0){ + cmSub->addToCommonMode(subtractPedestal(data,ix,iy,0), ix, iy); + // cout << ix << " " <=0 && ix=0 && iy0) + return stat[iy][ix].getPedestal()+getCommonMode(ix,iy); + else return stat[iy][ix].getPedestal(); + else return -1; + }; + + + /** + gets pedestal rms (i.e. noise) + \param ix pixel x coordinate + \param iy pixel y coordinate + \returns pedestal rms + */ + virtual double getPedestalRMS(int ix, int iy){ + if (ix>=0 && ix=0 && iy=0 && ix=0 && iy=0 && ix=0 && iy=0 && ix=0 && iySetBinContent(ix+1, iy+1,image[iy*nx+ix]); +#endif + } + } + ret=WriteToTiff(gm, imgname, ny, nx); + delete [] gm; +#ifdef ROOTSPECTRUM + char rootfn[10000]; + sprintf(rootfn,"%s.root",imgname); + TFile *f=new TFile(rootfn,"RECREATE"); + hs->Write("hs"); +#ifdef ROOTCLUST + hs3->Write("hs3"); + hs5->Write("hs5"); + hs7->Write("hs7"); + hs9->Write("hs9"); +#endif + hmap->Write("hmap"); + + + f->Close(); + delete f; + delete hmap; +#endif + return ret; + } +#ifdef ROOTSPECTRUM + TH2F *getSpectrum(){return hs;}; +#endif + /** + write 32bit tiff file containing the pedestals + \param imgname file name to be written + \returns NULL if file writing didn't succed, otherwise a pointer + */ + + virtual void *writePedestals(const char * imgname) { + float *gm=NULL; + void *ret; + gm=new float[nx*ny]; +#ifdef ROOTSPECTRUM + + TH2F *hmap=new TH2F("hmap","hmap",nx, -0.5,nx-0.5, ny, -0.5, ny-0.5); + +#endif + for (int iy=0; iygetCommonMode(); */ + /* else */ + gm[iy*nx+ix]=stat[iy][ix].getPedestal(); +#ifdef ROOTSPECTRUM + hmap->SetBinContent(ix+1, iy+1,gm[iy*nx+ix]); +#endif + } + } + ret=WriteToTiff(gm, imgname, ny, nx); + delete [] gm; + +#ifdef ROOTSPECTRUM + char rootfn[10000]; + sprintf(rootfn,"%s.root",imgname); + TFile *f=new TFile(rootfn,"RECREATE"); + hs->Write("hs"); +#ifdef ROOTCLUST + hs3->Write("hs3"); + hs5->Write("hs5"); + hs7->Write("hs7"); + hs9->Write("hs9"); +#endif + hmap->Write("hmap"); + f->Close(); + delete f; + delete hmap; +#endif + return ret; + } + + /** + read 32bit tiff file containing the pedestals + \param imgname file name to be read + \returns 0 if file reading didn't succed, otherwise 1 + */ + int readPedestals(const char * imgname) { + uint32 nnx, nny; + float *gm=ReadFromTiff( imgname, nny, nnx); + if (nnx>nx) nnx=nx; + if (nny>ny) nny=ny; + + + + if (gm) { + for (int iy=0; iynx) nnx=nx; + if (nny>ny) nny=ny; + + + + if (gm) { + for (int iy=0; iynx) nnx=nx; + if (nny>ny) nny=ny; + if (gm) { + for (int iy=0; iyisGood(ix,iy)) { + addToPedestal(data,ix,iy,1); + //if (ix==10 && iy==10) + // cout <=0 && xmi<=nx) xmin=xmi; + if (xma>=0 && xma<=nx) xmax=xma; + if (xmax=0 && ymi<=ny) ymin=ymi; + if (yma>=0 && yma<=ny) ymax=yma; + if (ymax=0 && ix=0 && iygetValue(data, ix, iy); + else + val=((double*)data)[iy*nx+ix]; + + /* if (ix==10 && iy==10) */ + /* cout << ix << " " << iy << " " << val ; */ + /* if (ix==100 && iy==100) */ + /* cout << ix << " " << iy << " " << val; */ + addToPedestal(val,ix,iy); + /* if (ix==10 && iy==10) */ + /* cout <<" " << getPedestal(ix,iy)<< endl; */ + /* if (ix==100 && iy==100) */ + /* cout << " " << getPedestal(ix,iy)<< endl; */ + } + return ; + + }; + + + /** + Subtracts pedestal from the data array in the region of interest + \param data pointer to the data + \param val pointer where the pedestal subtracted data should be added. If NULL, the internal image is used + \returns pointer to the pedestal subtracted data + */ + // virtual int *subtractPedestal(char *data, int *val=NULL) { + + virtual int *subtractPedestal(char *data, int *val=NULL, int cm=0) { + + newFrame(); + + if (val==NULL) + val=image;//new double[nx*ny]; + + for (int iy=ymin; iyisGood(ix,iy)) + val[iy*nx+ix]+=subtractPedestal(data, ix, iy,cm); + } + } + return val; + }; + + + + + /** + Subtracts pedestal from the data for a selected pixel + \param data pointer to the data + \param ix pixel x coordinate + \param iy pixel y coordinate + \returns pedestal subtracted value + */ + + + + virtual double subtractPedestal(char *data, int ix, int iy=0, int cm=0) { + double g=1.; + double val; + if (ix>=0 && ix=0 && iygetChannel(data, ix, iy)>=0x3fff) */ + /* cout << ix << " " << iy << " " << det->getChannel(data, ix, iy) <getValue(data, ix, iy)-getPedestal(ix,iy,cm))/g; + } else + val= (((double*)data)[iy*nx+ix]-getPedestal(ix,iy))/g; + +#ifdef ROOTSPECTRUM + hs->Fill(val,(iy-ymin)*(xmax-xmin)+(ix-xmin)); +#ifdef ROOTCLUST + double v3=0,v5=0,v7=0,v9=0; + for (int iix=-4; iix<5; iix++) + for (int iiy=-4; iiy<5; iiy++) { + if (det) + val= (dataSign*det->getValue(data, ix+iix, iy+iiy)-getPedestal(ix+iix,iy+iiy,cm))/g; + else + val= (((double*)data)[(iy+iiy)*nx+ix+iix]-getPedestal(ix+iix,iy+iiy,cm))/g; + + if (iix>-4 && iiy>-4 && iix<4 && iiy<4) { + if (iix>-3 && iiy>-3 && iix<3 && iiy<3){ + if (iix>-2 && iiy>-2 && iix<2 && iiy<2){ + v3+=val; + } + v5+=val; + } + v7+=val; + } + v9+=val; + } + hs3->Fill(v3,(iy-ymin)*(xmax-xmin)+(ix-xmin)); + hs5->Fill(v5,(iy-ymin)*(xmax-xmin)+(ix-xmin)); + hs7->Fill(v7,(iy-ymin)*(xmax-xmin)+(ix-xmin)); + hs9->Fill(v9,(iy-ymin)*(xmax-xmin)+(ix-xmin)); + +#endif +#endif + return val; + } + }; + + + /** + sets threshold value for conversion into number of photons + \param t threshold to be set + \returns threshold value + */ + double setThreshold(double t){thr=t; return thr;}; + + /** + gets threshold value for conversion into number of photons + \returns threshold value + */ + double getThreshold(){return thr;}; + /** + converts the data into number of photons for the selected pixel + \param data pointer to the data + \param ix pixel x coordinate + \param iy pixel y coordinate + \returns converted number of photons. If no threshold is set, returns gain converted pedestal subtracted data. + */ + + virtual int getNPhotons(char *data, int ix, int iy=0) { + int nph=0; + double v; + if (ix>=0 && ix=0 && iyFill(v,(iy-ymin)*(xmax-xmin)+(ix-xmin)); */ +/* #endif */ + if (thr>0) { + v+=0.5*thr; + nph=v/thr; + if (nph>0) + return nph; + return 0; + } + return v; + } + return 0; + }; + + /** + converts the data into number of photons for all pixels + \param data pointer to the data + \param nph pointer where the photons should added. If NULL,the internal image is used + \returns pointer to array containing the number of photons + */ + int *getNPhotons(char *data, int *nph=NULL) { + + double val; + if (nph==NULL) + nph=image; + newFrame(); + + addToCommonMode(data); + + for (int iy=ymin; iyisGood(ix,iy)) + nph[iy*nx+ix]+=getNPhotons(data, ix, iy); + } + } + return nph; + + } + + /** + clears the image array + + */ + virtual void clearImage(){ + for (int iy=0; iyReset(); +#ifdef ROOTCLUST + + if (hs3) + hs3->Reset(); + if (hs5) + hs5->Reset(); + if (hs7) + hs7->Reset(); + if (hs9) + hs9->Reset(); +#endif + //cout << "done " << endl; +#endif + }; + + /** sets/gets number of samples for moving average pedestal calculation + \param i number of samples to be set (0 or negative gets) + \returns actual number of samples + */ + int SetNPedestals(int i=-1) { + int ix=0, iy=0; + if (i>0) + for (iy=0; iy=0 && ix=0 && iyisGood(ix,iy)) { + if (ix>=0 && ix=0 && iy *det; /**< slsDetectorData to be used */ + int nx; /**< Size of the detector in x direction */ + int ny; /**< Size of the detector in y direction */ + pedestalSubtraction **stat; /**< pedestalSubtraction class */ + commonModeSubtraction *cmSub;/**< commonModeSubtraction class */ + int dataSign; /**< sign of the data i.e. 1 if photon is positive, -1 if negative */ + int iframe; /**< frame number (not from file but incremented within the dataset every time newFrame is called */ + double *gmap; + int *image; + int id; + //int xmin, xmax, ymin, ymax; int xmin; /**< minimum x of the region of interest */ + int xmin; /**< minimum x of the region of interest */ + int xmax; /**< maximum x of the region of interest */ + int ymin;/**< minimum y of the region of interest */ + int ymax;/**< maximum y of the region of interest */ + double thr; /**< threshold to be used for conversion into number of photons */ + // int nSigma; /**< number of sigma to be used for conversion into number of photons if threshold is undefined */ + frameMode fMode; /**< current detector frame mode */ + detectorMode dMode; /**< current detector frame mode */ + FILE *myFile; /**< file pointer to write to */ +#ifdef ROOTSPECTRUM + TH2F *hs; +#ifdef ROOTCLUST + TH2F *hs3; + TH2F *hs5; + TH2F *hs7; + TH2F *hs9; +#endif +#endif +}; + +#endif diff --git a/slsDetectorCalibration/commonModeSubtraction.h b/slsDetectorCalibration/commonModeSubtraction.h new file mode 100644 index 000000000..0484e6746 --- /dev/null +++ b/slsDetectorCalibration/commonModeSubtraction.h @@ -0,0 +1,82 @@ +#ifndef COMMONMODESUBTRACTION_H +#define COMMONMODESUBTRACTION_H + +#include "MovingStat.h" + + + + +class commonModeSubtraction { + + /** @short class to calculate the common mode of the pedestals based on an approximated moving average*/ + + public: + + /** constructor + \param nn number of samples for the moving average to calculate the average common mode + \param iroi number of regions on which one can calculate the common mode separately. Defaults to 1 i.e. whole detector + + */ + commonModeSubtraction(int nn=1000, int iroi=1) : cmStat(NULL), cmPed(NULL), nCm(NULL), nROI(iroi) {cmStat=new MovingStat[nROI]; for (int i=0; i0) cmStat[i].Calc(cmPed[i]/nCm[i]); + nCm[i]=0; + cmPed[i]=0; + }}; + + /** adds the pixel to the sum of pedestals -- virtual func must be overloaded to define the regions of interest + \param val value to add + \param ix pixel x coordinate + \param iy pixel y coordinate + */ + virtual void addToCommonMode(double val, int ix=0, int iy=0) { + (void) ix; (void) iy; + + //if (isc>=0 && isc0) return cmPed[0]/nCm[0]-cmStat[0].Mean(); + return 0;}; + + + + + + protected: + MovingStat *cmStat; /** + +class commonModeSubtraction { + + /** @short class to calculate the common mode of the pedestals based on an approximated moving average*/ + + public: + + /** constructor + \param nn number of samples for the moving average to calculate the average common mode + \param iroi number of regions on which one can calculate the common mode separately. Defaults to 1 i.e. whole detector + + */ + commonModeSubtraction(int iroi=1, int ns=3) : nROI(iroi), nsigma(ns) { + mean=new double[nROI]; + mean2=new double[nROI]; + nCm=new double[nROI]; + }; + + /** destructor - deletes the moving average(s) and the sum of pedestals calculator(s) */ + virtual ~commonModeSubtraction() {delete [] mean; delete [] mean2; delete [] nCm;}; + + + /** clears the moving average and the sum of pedestals calculation - virtual func*/ + virtual void Clear(){ + for (int i=0; i0) cmStat[i].Calc(cmPed[i]/nCm[i]); + nCm[i]=0; + mean[i]=0; + mean2[i]=0; + }}; + + /** adds the pixel to the sum of pedestals -- virtual func must be overloaded to define the regions of interest + \param val value to add + \param ix pixel x coordinate + \param iy pixel y coordinate + */ + virtual void addToCommonMode(double val, int ix=0, int iy=0) { + + int iroi=getROI(ix,iy); + // if (iroi==0) val=100; + // else val=-100; + // if (isc>=0 && isc=0 && iroi=0 && iroi0) + return mean[iroi]/nCm[iroi]; + } + return 0; + }; + + /** gets the common mode i.e. the difference between the current average sum of pedestals mode and the average pedestal + \param ix pixel x coordinate + \param iy pixel y coordinate + \return the difference between the current average sum of pedestals and the average pedestal + */ + virtual double getCommonModeRMS(int ix=0, int iy=0) { + int iroi=getROI(ix,iy); + if (iroi>=0 && iroi0) + return sqrt(mean2[iroi]/nCm[iroi]-(mean[iroi]/nCm[iroi])*(mean[iroi]/nCm[iroi])); + } + return 0; + }; + + /** + gets the common mode ROI for pixel ix, iy -should be overloaded! + */ + virtual int getROI(int ix, int iy){ (void) ix; (void) iy; return 0;}; + + + + protected: + double *mean; /** { + + + public: + mythen3_01_jctbData( int nch=64*3,int dr=24, int off=5): slsDetectorData(64*3,1,dr*8*nch,NULL,NULL,NULL), dynamicRange(dr), serialOffset(off), frameNumber(0), numberOfCounters(nch) {}; + + virtual void getPixel(int ip, int &x, int &y) {x=-1; y=-1;}; + + virtual short unsigned int getChannel(char *data, int ix, int iy=0) { + int ret=-1; + short unsigned int *val=mythen03_frame(data,dynamicRange,numberOfCounters,serialOffset); + if (ix>=0 && ix=0) frameNumber=f; return frameNumber; }; + virtual int setDynamicRange(int d=-1) {if (d>0 && d<=24) dynamicRange=d; return dynamicRange;}; + virtual int setSerialOffset(int d=-1) {if (d>=0) serialOffset=d; return serialOffset;}; + virtual int setNumberOfCounters(int d=-1) {if (d>=0) numberOfCounters=d; return numberOfCounters;}; + + + private: + + int dynamicRange; + int serialOffset; + int frameNumber; + int numberOfCounters; + + + + +}; + +#endif diff --git a/slsDetectorCalibration/dataStructures/Mythen3_02_jctbData.h b/slsDetectorCalibration/dataStructures/Mythen3_02_jctbData.h new file mode 100644 index 000000000..a76e2cbaf --- /dev/null +++ b/slsDetectorCalibration/dataStructures/Mythen3_02_jctbData.h @@ -0,0 +1,130 @@ +#ifndef MYTHEN302JCTBDATA_H +#define MYTHEN302JCTBDATA_H + + +#include "Mythen3_01_jctbData.h" +//class mythen3_02_jctbData : public slsDetectorData { +class mythen3_02_jctbData : public mythen3_01_jctbData { + + + public: + mythen3_02_jctbData( int nch=64*3,int dr=24, int off=5): mythen3_01_jctbData( nch,dr, off) + //slsDetectorData(64*3,1,dr*8*nch,NULL,NULL,NULL), dynamicRange(dr), serialOffset(off), frameNumber(0), numberOfCounters(nch) + {}; + + /* virtual void getPixel(int ip, int &x, int &y) {x=-1; y=-1;}; */ + + /* virtual short unsigned int getChannel(char *data, int ix, int iy=0) { */ + /* int ret=-1; */ + /* short unsigned int *val=mythen03_frame(data,dynamicRange,numberOfCounters,serialOffset); */ + /* if (ix>=0 && ix=0) frameNumber=f; return frameNumber; }; */ + /* virtual int setDynamicRange(int d=-1) {if (d>0 && d<=24) dynamicRange=d; return dynamicRange;}; */ + /* virtual int setSerialOffset(int d=-1) {if (d>=0) serialOffset=d; return serialOffset;}; */ + /* virtual int setNumberOfCounters(int d=-1) {if (d>=0) numberOfCounters=d; return numberOfCounters;}; */ + + + /* private: */ + + /* int dynamicRange; */ + /* int serialOffset; */ + /* int frameNumber; */ + /* int numberOfCounters; */ + + + + +}; + +#endif diff --git a/slsDetectorCalibration/dataStructures/adcSar2_jctbData.h b/slsDetectorCalibration/dataStructures/adcSar2_jctbData.h new file mode 100644 index 000000000..0b0665aaf --- /dev/null +++ b/slsDetectorCalibration/dataStructures/adcSar2_jctbData.h @@ -0,0 +1,63 @@ +#ifndef ADCSAR2_JCTBDATA_H +#define ADCSAR2_JCTBDATA_H + + +class adcSar2_jctbData : public slsDetectorData { + + + public: + adcSar2_jctbData(int nsamples=1000): slsDetectorData(nsamples,1,nsamples*8,NULL,NULL,NULL){}; + + virtual void getPixel(int ip, int &x, int &y) {x=ip/8; y=1;}; + + virtual short unsigned int getChannel(char *data, int ix, int iy=0) { + int adcvalue=0; + int vv1= *((int16_t*) (data+8*ix)); + int vv2= *((int16_t*) (data+8*ix+2)); + for (int jj=0;jj<8;jj++){ + adcvalue=adcvalue+ (((vv1>>(jj*2)) & 0x1)<<(jj)); + } + for (int jj=0;jj<4;jj++){ + adcvalue=adcvalue+ (((vv2>>(jj*2)) & 0x1)<<(jj+8)); + } + return adcvalue; + }; + + virtual int getFrameNumber(char *buff) {return frameNumber;}; + + virtual char *findNextFrame(char *data, int &ndata, int dsize) { + ndata=dsize; + return data; + } + + virtual char *readNextFrame(ifstream &filebin) { + char *data=NULL; + if (filebin.is_open()) { + data=new char[dataSize]; + filebin.read(data,dataSize); + } + return data; + } + + /* virtual int **getData(char *ptr, int dsize=-1) { */ + /* int **val; */ + /* val=new int*[1]; */ + /* val[0]=mythen03_frame(ptr,dynamicRange,nx,serialOffset); */ + /* return val; */ + + /* } */ + + + + virtual int setFrameNumber(int f=0) {if (f>=0) frameNumber=f; return frameNumber; }; + + private: + + int frameNumber; + + + + +}; + +#endif diff --git a/slsDetectorCalibration/dataStructures/chiptestBoardData.h b/slsDetectorCalibration/dataStructures/chiptestBoardData.h new file mode 100644 index 000000000..0ef633c44 --- /dev/null +++ b/slsDetectorCalibration/dataStructures/chiptestBoardData.h @@ -0,0 +1,89 @@ +#ifndef CHIPTESTDATA_H +#define CHIPTESTDATA_H + +#include "slsDetectorData.h" + +class chiptestBoardData : public slsDetectorData { + + + public: + + /** + chiptestBoard data structure. Works for data acquired using the chiptestBoard. + Inherits and implements slsDetectorData. + + Constructor (no error checking if datasize and offsets are compatible!) + \param npx number of pixels in the x direction + \param npy number of pixels in the y direction (1 for strips) + \param nadc number of adcs + \param offset offset at the beginning of the pattern + \param dMap array of size nx*ny storing the pointers to the data in the dataset (as offset) + \param dMask Array of size nx*ny storing the polarity of the data in the dataset (should be 0 if no inversion is required, 0xffffffff is inversion is required) + \param dROI Array of size nx*ny. The elements are 1s if the channel is good or in the ROI, 0 is bad or out of the ROI. NULL (default) means all 1s. + + */ + chiptestBoardData(int npx, int npy, int nadc, int offset, int **dMap=NULL, uint16_t **dMask=NULL, int **dROI=NULL): slsDetectorData(npx, npy, nadc*(npx*npy)+offset, dMap, dMask, dROI), nAdc(nadc), offSize(offset), iframe(0) {}; // should be? nadc*(npx*npy+offset) + + + + /** + + Returns the frame number for the given dataset. Virtual func: works for slsDetectorReceiver data (also for each packet), but can be overloaded. + \param buff pointer to the dataset + \returns frame number + + */ + + virtual int getFrameNumber(char *buff){(void)buff; return iframe;}; + + + /** + + Loops over a memory slot until a complete frame is found (i.e. all packets 0 to nPackets, same frame number). Can be overloaded for different kind of detectors! + \param data pointer to the memory to be analyzed + \param ndata size of frame returned + \param dsize size of the memory slot to be analyzed + \returns always return the pointer to data (no frame loss!) + */ + + virtual char *findNextFrame(char *data, int &ndata, int dsize) {ndata=dsize;setDataSize(dsize); return data;}; + + /** + Loops over a file stream until a complete frame is found (i.e. all packets 0 to nPackets, same frame number). Can be overloaded for different kind of detectors! + \param filebin input file stream (binary) + \returns pointer to the first packet of the last good frame, NULL if no frame is found or last frame is incomplete + */ + + virtual char *readNextFrame(ifstream &filebin) { + + int afifo_length=0; + uint16_t *afifo_cont; + + if (filebin.is_open()) { + if (filebin.read((char*)&afifo_length,sizeof(uint32_t))) { + setDataSize(afifo_length*nAdc*sizeof(uint16_t)); + afifo_cont=new uint16_t[afifo_length*nAdc]; + if (filebin.read((char*)afifo_cont,afifo_length*sizeof(uint16_t)*nAdc)) { + iframe++; + return (char*)afifo_cont; + } else { + delete [] afifo_cont; + return NULL; + } + } else { + return NULL; + } + } + return NULL; + }; + + private: + const int nAdc; /** { + + private: + const int nModules; + const int offset; + int iframe; + + +public: + + + + /** + Implements the slsReceiverData structure for the gotthard read out by a module i.e. using the slsReceiver + (1x1280 pixels, 2 packets 1286 large etc.) + \param c crosstalk parameter for the output buffer + + */ + + + gotthardDoubleModuleDataNew(int off=24*2, int nmod=2): slsDetectorData(1280*nmod, 1, nmod*(1280*2+off)), nModules(nmod), offset(off),iframe(0) { + + + + +#ifdef BCHIP074_BCHIP075 + cout << "This is a bchip074-bchip075 system " << endl; +#endif + + + uint16_t **dMask; + int **dMap; + int ix, iy; + int ypixels=1; + int xpixels=1280*nmod; + int imod, ipix; + dMask=new uint16_t*[1]; + dMap=new int*[1]; + dMap[0] = new int[1280*nmod]; + dMask[0] = new uint16_t[1280*nmod]; + + for(int ix=0; ix=128*4 && ibad<128*5) || (ibad>=9*128 && ibad<10*128) || (ibad>=(1280+128*4) && ibad=(1280+128*6))) + dataROIMask[0][ix]=0; +#endif + } + + setDataMap(dMap); + setDataMask(dMask); + + }; + + + /** + + Returns the frame number for the given dataset. + \param buff pointer to the dataset + \returns frame number + + */ + + + int getFrameNumber(char *buff){if (offset>=sizeof(sls_detector_header)) return ((sls_detector_header*)buff)->frameNumber; return iframe;};//*((int*)(buff+5))&0xffffff;}; + + + + /** + gets the packets number (last packet is labelled with 0 and is replaced with 40) + \param buff pointer to the memory + \returns packet number + + */ + + int getPacketNumber(char *buff){if (offset>=sizeof(sls_detector_header))return ((sls_detector_header*)buff)->packetNumber;}; + + + + + /** + + 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=0) + fnum=ff; + + if (filebin.is_open()) { + if (filebin.read(data, dataSize) ){ + ff=getFrameNumber(data); + np=getPacketNumber(data); + return data; + } + } + return NULL; + + + + }; + + + + +}; + + + + + +#endif diff --git a/slsDetectorCalibration/dataStructures/gotthardShortModuleData.h b/slsDetectorCalibration/dataStructures/gotthardShortModuleData.h new file mode 100644 index 000000000..4d853c7b0 --- /dev/null +++ b/slsDetectorCalibration/dataStructures/gotthardShortModuleData.h @@ -0,0 +1,127 @@ +#ifndef GOTTHARDSHORTMODULEDATA_H +#define GOTTHARDSHORTMODULEDATA_H +#include "slsReceiverData.h" + + + + + + +class gotthardShortModuleData : public slsReceiverData { +public: + + + + + /** + Implements the slsReceiverData structure for the gotthard short read out by a module i.e. using the slsReceiver + (1x256 pixels, 1 packet 256 large etc.) + \param c crosstalk parameter for the output buffer + + */ + + + gotthardShortModuleData(double c=0): slsReceiverData(xpixels, ypixels, npackets, buffersize), xtalk(c){ + + uint16_t **dMask; + int **dMap; + int ix, iy; + int offset = 2; + + dMask=new uint16_t*[ypixels]; + dMap=new int*[ypixels]; + for (int i = 0; i < ypixels; i++) { + dMap[i] = new int[xpixels]; + dMask[i] = new uint16_t[xpixels]; + } + + for(ix=0; ix::getValue(data, ix, iy); + else + return slsDetectorData::getValue(data, ix, iy)-xtalk*slsDetectorData::getValue(data, ix-1, iy); + }; + + + + /** sets the output buffer crosstalk correction parameter + \param c output buffer crosstalk correction parameter to be set + \returns current value for the output buffer crosstalk correction parameter + + */ + double setXTalk(double c) {xtalk=c; return xtalk;} + + + /** gets the output buffer crosstalk parameter + \returns current value for the output buffer crosstalk correction parameter + */ + double getXTalk() {return xtalk;} + + + + + + + +private: + + double xtalk; /** { + + private: + + int iframe; + // int *xmap, *ymap; + int nadc; + int sc_width; + int sc_height; + + int maplength; + + + + 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 + + */ + + + moench02CtbData(int ns=6400): slsDetectorData(160, 160, ns*2*32, NULL, NULL) , nadc(32), sc_width(40), sc_height(160) { + + + int adc_off[4]={40,0,120,80}; + int adc_nr[4]={8,10,20,22}; + int row, col; + + int isample; + int iadc, iiadc; + int ix, iy; + maplength=this->getDataSize()/2; + //cout << maplength << endl; + + for (iiadc=0; iiadc<4; iiadc++) { + + iadc=adc_nr[iiadc]; + //cout << iiadc << endl; + for (int i=0; i=dataSize) { + cout << "Error: pointer " << dataMap[row][col] << " out of range "<< endl; + } + + } + } + + for (int i=0; i=0){ + xmap[i]=adc_off[iadc]+ix; + ymap[i]=iy; + }else{ + xmap[i]=-1; + ymap[i]=-1; + } + } + iframe=0; + cout << "data struct created" << endl; + }; + + void getPixel(int ip, int &x, int &y) { + if(ip>=0 && ip0) { + iframe++; + //cout << ib/2 << "-" << endl; + //for (int i=0; i { + + private: + + int iframe; + int nadc; + int sc_width; + int sc_height; + 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 + + */ + + + moench03CtbData(int ns=5000): slsDetectorData(400, 400, ns*2*32, NULL, NULL) , nadc(32), sc_width(25), sc_height(200) { + + + int row, col; + + int isample; + int iadc; + int ix, iy; + + int adc_nr[32]={200,225,250,275,300,325,350,375,\ + 0,25,50,75,100,125,150,175,\ + 175,150,125,100,75,50,25,0,\ + 375,350,325,300,275,250,225,200}; + + /* int adc_nr[32]={300,325,350,375,300,325,350,375, \ */ + /* 200,225,250,275,200,225,250,275,\ */ + /* 100,125,150,175,100,125,150,175,\ */ + /* 0,25,50,75,0,25,50,75}; */ + + + for (iadc=0; iadc=2*400*400) + cout << "Error: pointer " << dataMap[row][col] << " out of range "<< endl; + + } + } + for (int i=0; i0) { + iframe++; + // cout << ib << "-" << endl; + return (char*)afifo_cont; + } else { + delete [] afifo_cont; + return NULL; + } + } + return NULL; + }; + + + + +}; + + + +#endif diff --git a/slsDetectorCalibration/dataStructures/moench03T1CtbData.h b/slsDetectorCalibration/dataStructures/moench03T1CtbData.h new file mode 100644 index 000000000..4a99d3746 --- /dev/null +++ b/slsDetectorCalibration/dataStructures/moench03T1CtbData.h @@ -0,0 +1,158 @@ +#ifndef MOENCH03T1CTBDATA_H +#define MOENCH03T1CTBDATA_H +#include "slsDetectorData.h" + + + +class moench03T1CtbData : public slsDetectorData { + + private: + + int iframe; + int nadc; + int sc_width; + int sc_height; + 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 + + */ + + + moench03T1CtbData(int ns=5000): slsDetectorData(400, 400, ns*2*32, NULL, NULL) , nadc(32), sc_width(25), sc_height(200) { + + + int adc_nr[32]={300,325,350,375,300,325,350,375, \ + 200,225,250,275,200,225,250,275,\ + 100,125,150,175,100,125,150,175,\ + 0,25,50,75,0,25,50,75}; + + int row, col; + + int isample; + int iadc; + int ix, iy; + + + + + + for (iadc=0; iadc=2*400*400) + cout << "Error: pointer " << dataMap[row][col] << " out of range "<< endl; + + } + } + int adc4; + for (int i=0; i0) { + iframe++; + // cout << ib << "-" << endl; + return (char*)afifo_cont; + } else { + delete [] afifo_cont; + return NULL; + } + } + return NULL; + }; + + + + +}; + + + +#endif diff --git a/slsDetectorCalibration/dataStructures/moench03T1ReceiverDataNew.h b/slsDetectorCalibration/dataStructures/moench03T1ReceiverDataNew.h new file mode 100644 index 000000000..d3a5e55e1 --- /dev/null +++ b/slsDetectorCalibration/dataStructures/moench03T1ReceiverDataNew.h @@ -0,0 +1,290 @@ +#ifndef MOENCH03T1RECDATANEW_H +#define MOENCH03T1RECDATANEW_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 frameNumber; /**< is the frame number */ + uint32_t expLength; /**< is the subframe number (32 bit eiger) or real time exposure time in 100ns (others) */ + uint32_t packetNumber; /**< is the packet number */ + uint64_t bunchId; /**< is the bunch id from beamline */ + uint64_t timestamp; /**< is the time stamp with 10 MHz clock */ + uint16_t modId; /**< is the unique module id (unique even for left, right, top, bottom) */ + uint16_t xCoord; /**< is the x coordinate in the complete detector system */ + uint16_t yCoord; /**< is the y coordinate in the complete detector system */ + uint16_t zCoord; /**< is the z coordinate in the complete detector system */ + uint32_t debug; /**< is for debugging purposes */ + uint16_t roundRNumber; /**< is the round robin set number */ + uint8_t detType; /**< is the detector type see :: detectorType */ + uint8_t version; /**< is the version number of this structure format */ +#ifndef VERSION_V1 + uint64_t packetCaught[8]; /**< is the version number of this structure format */ +#endif + + } sls_detector_header; + + + + +class moench03T1ReceiverDataNew : public slsDetectorData { + + private: + + int iframe; + int nadc; + int sc_width; + int sc_height; + const int nSamples; + + + 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 + + */ + moench03T1ReceiverDataNew(int ns=5000): slsDetectorData(400, 400, ns*2*32+sizeof(sls_detector_header)), nSamples(ns) { + + int nadc=32; + int sc_width=25; + int sc_height=200; + + int adc_nr[32]={300,325,350,375,300,325,350,375, \ + 200,225,250,275,200,225,250,275,\ + 100,125,150,175,100,125,150,175,\ + 0,25,50,75,0,25,50,75}; + + int row, col; + + int isample; + int iadc; + int ix, iy; + + int npackets=40; + int i; + int adc4(0); + + for (int ip=0; ip=nSamples*2*32) + cout << "Error: pointer " << dataMap[row][col] << " out of range "<< endl; + } + } + } + } + + int ipacket; + int ibyte; + int ii=0; + for (ibyte=0; ibyteframeNumber;};//*((int*)(buff+5))&0xffffff;}; + + /** + + 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 ((sls_detector_header*)buff)->packetNumber;}//((*(((int*)(buff+4))))&0xff)+1;}; + +/* /\** */ + +/* 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){ndata=dsize; setDataSize(dsize); return data;}; */ + + +/* /\** */ + +/* Loops over a file stream until a complete frame is found (i.e. all packets 0 to nPackets, same frame number). Can be overloaded for different kind of detectors! */ +/* \param filebin input file stream (binary) */ +/* \returns pointer to the begin of the last good frame, NULL if no frame is found or last frame is incomplete */ + +/* *\/ */ +/* virtual char *readNextFrame(ifstream &filebin){ */ +/* // int afifo_length=0; */ +/* uint16_t *afifo_cont; */ +/* int ib=0; */ +/* if (filebin.is_open()) { */ +/* afifo_cont=new uint16_t[dataSize/2]; */ +/* while (filebin.read(((char*)afifo_cont)+ib,2)) { */ +/* ib+=2; */ +/* if (ib==dataSize) break; */ +/* } */ +/* if (ib>0) { */ +/* iframe++; */ +/* // cout << ib << "-" << endl; */ +/* return (char*)afifo_cont; */ +/* } else { */ +/* delete [] afifo_cont; */ +/* return NULL; */ +/* } */ +/* } */ +/* return NULL; */ +/* }; */ + + + virtual char *readNextFrame(ifstream &filebin) { + int ff=-1, np=-1; + return readNextFrame(filebin, ff, np); + }; + + virtual char *readNextFrame(ifstream &filebin, int &ff) { + int np=-1; + return readNextFrame(filebin, ff, np); + }; + + virtual 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; + } + + + + + virtual 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 { + + private: + + int iframe; + int nadc; + int sc_width; + int sc_height; + const int nSamples; + + + 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 HOR + moench03T1ReceiverDataNew(int ns=5000): slsDetectorData(800, 200, ns*2*32+sizeof(sls_detector_header)), nSamples(ns) { +#endif +#ifdef VERT + moench03T1ReceiverDataNew(int ns=5000): slsDetectorData(200, 800, ns*2*32+sizeof(sls_detector_header)), nSamples(ns) { +#endif + int nadc=32; + int sc_width=25; + int sc_height=200; + + int adc_nr[32]={300,325,350,375,300,325,350,375, \ + 200,225,250,275,200,225,250,275,\ + 100,125,150,175,100,125,150,175,\ + 0,25,50,75,0,25,50,75}; + + int row, col; + + int isample; + int iadc; + int ix, iy; + + int npackets=40; + int i; + int adc4(0); + int pix; + + + int off=0; +#ifdef OFF_1 + off=1; +#endif + cout << "This is a MOENCH with rectangular pixels!" << endl; + + for (int ip=0; ip=nSamples*2*32+sizeof(sls_detector_header)) + cout << "Error: pointer " << dataMap[row][col] << " out of range "<< endl; + ix=col; + iy=row; +#ifdef HOR + if (row%2==off) { + ix=2*col; + iy=row/2; + } else { + ix=2*col+1; + iy=row/2; + } +#endif + +#ifdef VERT + if (col%2==off) { + ix=col/2; + iy=row*2+1; + } else { + ix=col/2; + iy=row*2; + } +#endif + dataMap[iy][ix]=pix; + } + } + } + } + + /* int ipacket; */ + /* int ibyte; */ + /* int ii=0; */ + /* for (ibyte=0; ibyteframeNumber;};//*((int*)(buff+5))&0xffffff;}; + + /** + + 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 ((sls_detector_header*)buff)->packetNumber;}//((*(((int*)(buff+4))))&0xff)+1;}; + +/* /\** */ + +/* 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){ndata=dsize; setDataSize(dsize); return data;}; */ + + +/* /\** */ + +/* Loops over a file stream until a complete frame is found (i.e. all packets 0 to nPackets, same frame number). Can be overloaded for different kind of detectors! */ +/* \param filebin input file stream (binary) */ +/* \returns pointer to the begin of the last good frame, NULL if no frame is found or last frame is incomplete */ + +/* *\/ */ +/* virtual char *readNextFrame(ifstream &filebin){ */ +/* // int afifo_length=0; */ +/* uint16_t *afifo_cont; */ +/* int ib=0; */ +/* if (filebin.is_open()) { */ +/* afifo_cont=new uint16_t[dataSize/2]; */ +/* while (filebin.read(((char*)afifo_cont)+ib,2)) { */ +/* ib+=2; */ +/* if (ib==dataSize) break; */ +/* } */ +/* if (ib>0) { */ +/* iframe++; */ +/* // cout << ib << "-" << endl; */ +/* return (char*)afifo_cont; */ +/* } else { */ +/* delete [] afifo_cont; */ +/* return NULL; */ +/* } */ +/* } */ +/* return NULL; */ +/* }; */ + + + virtual char *readNextFrame(ifstream &filebin) { + int ff=-1, np=-1; + return readNextFrame(filebin, ff, np); + }; + + virtual char *readNextFrame(ifstream &filebin, int &ff) { + int np=-1; + return readNextFrame(filebin, ff, np); + }; + + virtual 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; + } + + + + + virtual 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 { + + private: + + 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 + + fwrite(&ff, 8, 1,of);//write detector frame number + fwrite(&ifr, 8, 1,of);//write datset frame number + fwrite(data,2,NX*NY,of);//write reordered data + */ + moench03T1ReorderedData(): slsDetectorData(400, 400, 2*400*400+2*8) { + for (int iy=0; iy<400; iy++) + for (int ix=0; ix<400; ix++) + dataMap[iy][ix]=2*8+2*(iy*400+ix); + + int ibyte; + for (ibyte=0; ibyte<8; ibyte++){ + xmap[ibyte]=-1; + ymap[ibyte]=-1; + } + for (ibyte=0; ibyte<400*400; ibyte++){ + xmap[ibyte+8]=ibyte%400; + ymap[ibyte+8]=ibyte/400; + } + + // cout << "data struct created" << endl; + }; + + + + /** + + 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 *((int*)buff);}; + +/* /\** */ + +/* 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){ndata=dsize; setDataSize(dsize); return data;}; */ + + +/* /\** */ + +/* Loops over a file stream until a complete frame is found (i.e. all packets 0 to nPackets, same frame number). Can be overloaded for different kind of detectors! */ +/* \param filebin input file stream (binary) */ +/* \returns pointer to the begin of the last good frame, NULL if no frame is found or last frame is incomplete */ + +/* *\/ */ +/* virtual char *readNextFrame(ifstream &filebin){ */ +/* // int afifo_length=0; */ +/* uint16_t *afifo_cont; */ +/* int ib=0; */ +/* if (filebin.is_open()) { */ +/* afifo_cont=new uint16_t[dataSize/2]; */ +/* while (filebin.read(((char*)afifo_cont)+ib,2)) { */ +/* ib+=2; */ +/* if (ib==dataSize) break; */ +/* } */ +/* if (ib>0) { */ +/* iframe++; */ +/* // cout << ib << "-" << endl; */ +/* return (char*)afifo_cont; */ +/* } else { */ +/* delete [] afifo_cont; */ +/* return NULL; */ +/* } */ +/* } */ +/* return NULL; */ +/* }; */ + + + virtual char *readNextFrame(ifstream &filebin) { + int ff=-1, np=-1; + return readNextFrame(filebin, ff, np); + }; + + virtual char *readNextFrame(ifstream &filebin, int &ff) { + int np=-1; + return readNextFrame(filebin, ff, np); + }; + + virtual 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; + } + + + + + virtual char *readNextFrame(ifstream &filebin, int& ff, int &np, char *data) { + char *retval=0; + int nd; + int fnum = -1; + np=0; + int pn; + + if (ff>=0) + fnum=ff; + + if (filebin.is_open()) { + if (filebin.read(data, dataSize) ){ + ff=getFrameNumber(data); + np=40; + 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 { + + private: + + // int iframe; + int nadc; + int sc_width; + int sc_height; + const int nSamples; + const int offset; + + 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 + + */ + moench03T1ZmqDataNew(int ns=5000): slsDetectorData(400, 400, ns*32*2+sizeof(int)), nSamples(ns), offset(sizeof(int)) { + + int nadc=32; + int sc_width=25; + int sc_height=200; + + int adc_nr[32]={300,325,350,375,300,325,350,375, \ + 200,225,250,275,200,225,250,275,\ + 100,125,150,175,100,125,150,175,\ + 0,25,50,75,0,25,50,75}; + + int row, col; + + int isample; + int iadc; + int ix, iy; + + int npackets=40; + int i; + int adc4(0); + + for (int ip=0; ip=dataSize) + cout << "Error: pointer " << dataMap[row][col] << " out of range "<< endl; + } + } + } + } + + + int ii=0; + + for (i=0; i< dataSize; i++) { + if (i0) { */ +/* iframe++; */ +/* // cout << ib << "-" << endl; */ +/* return (char*)afifo_cont; */ +/* } else { */ +/* delete [] afifo_cont; */ +/* return NULL; */ +/* } */ +/* } */ +/* return NULL; */ +/* }; */ + + + virtual char *readNextFrame(ifstream &filebin) { + int ff=-1, np=-1; + return readNextFrame(filebin, ff, np); + }; + + virtual char *readNextFrame(ifstream &filebin, int &ff) { + int np=-1; + return readNextFrame(filebin, ff, np); + }; + + virtual char *readNextFrame(ifstream &filebin, int& ff, int &np) { + char *data=new char[32*2*nSamples]; + char *d=readNextFrame(filebin, ff, np, data); + if (d==NULL) {delete [] data; data=NULL;} + return data; + } + + + + + virtual char *readNextFrame(ifstream &filebin, int& ff, int &np, char *data) { + char *retval=0; + int nd; + int fnum = -1; + np=0; + int pn; + + + if (ff>=0) + fnum=ff; + + if (filebin.is_open()) { + if (filebin.read(data, 32*2*nSamples) ){ + // iframe++; + //ff=iframe; + 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<32*2*nSamples) ndata=dsize; + else ndata=32*2*nSamples; + return data; + + } + + + + + + + // virtual int setFrameNumber(int ff){iframe=ff}; + + + + + + + + + + +int getPacketNumber(int x, int y) {return 0;}; + +}; + + + + +#endif diff --git a/slsDetectorCalibration/dataStructures/moench03TCtbData.h b/slsDetectorCalibration/dataStructures/moench03TCtbData.h new file mode 100644 index 000000000..5edbdd247 --- /dev/null +++ b/slsDetectorCalibration/dataStructures/moench03TCtbData.h @@ -0,0 +1,180 @@ +#ifndef MOENCH03TCTBDATA_H +#define MOENCH03TCTBDATA_H +#include "slsDetectorData.h" + + + +class moench03TCtbData : public slsDetectorData { + + private: + + int iframe; + int nadc; + int sc_width; + int sc_height; + 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 + + */ + + + moench03TCtbData(int ns=5000): slsDetectorData(400, 400, ns*2*32, NULL, NULL) , nadc(32), sc_width(25), sc_height(200) { + + + int row, col; + + int isample; + int iadc; + int ix, iy; + + + + int adc_nr[32]={300,325,350,375,300,325,350,375, \ + 200,225,250,275,200,225,250,275,\ + 100,125,150,175,100,125,150,175,\ + 0,25,50,75,0,25,50,75}; + + + + /* int adc_nr[32]={200,225,250,275,300,325,350,375,\ */ + /* 0,25,50,75,100,125,150,175,\ */ + /* 175,150,125,100,75,50,25,0,\ */ + /* 375,350,325,300,275,250,225,200}; */ + + + for (iadc=0; iadc=2*400*400) + cout << "Error: pointer " << dataMap[row][col] << " out of range "<< endl; + + } + } + int adc4; + for (int i=0; i0) { + iframe++; + // cout << ib << "-" << endl; + return (char*)afifo_cont; + } else { + delete [] afifo_cont; + return NULL; + } + } + return NULL; + }; + + + + +}; + + + +#endif diff --git a/slsDetectorCalibration/dataStructures/moench04CtbReceiverData.h b/slsDetectorCalibration/dataStructures/moench04CtbReceiverData.h new file mode 100644 index 000000000..a639cf1a7 --- /dev/null +++ b/slsDetectorCalibration/dataStructures/moench04CtbReceiverData.h @@ -0,0 +1,291 @@ +#ifndef MOENCH04RECDATA_H +#define MOENCH04RECDATA_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 frameNumber; /**< is the frame number */ + uint32_t expLength; /**< is the subframe number (32 bit eiger) or real time exposure time in 100ns (others) */ + uint32_t packetNumber; /**< is the packet number */ + uint64_t bunchId; /**< is the bunch id from beamline */ + uint64_t timestamp; /**< is the time stamp with 10 MHz clock */ + uint16_t modId; /**< is the unique module id (unique even for left, right, top, bottom) */ + uint16_t xCoord; /**< is the x coordinate in the complete detector system */ + uint16_t yCoord; /**< is the y coordinate in the complete detector system */ + uint16_t zCoord; /**< is the z coordinate in the complete detector system */ + uint32_t debug; /**< is for debugging purposes */ + uint16_t roundRNumber; /**< is the round robin set number */ + uint8_t detType; /**< is the detector type see :: detectorType */ + uint8_t version; /**< is the version number of this structure format */ + uint64_t packetCaught[8]; /**< is the version number of this structure format */ + + } sls_detector_header; + + + + +class moench04ReceiverData : public slsDetectorData { + + private: + + int iframe; + int nadc; + int sc_width; + int sc_height; + const int aSamples; + const int dSamples; + + + 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 + + */ + moench04ReceiverData(int nas=5000, int nds=0): slsDetectorData(400, 400, nas*2*32+sizeof(sls_detector_header)+nds*8), aSamples(nas), dSamples(nds) { + + int nadc=32; + int sc_width=25; + int sc_height=200; + + int adc_nr[32]={9, 8,11,10,13,12,15,14,1,0,3,2,5,4,7,6,23,22,21,20,19,18,17,16,31,30,29,28,27,26,25,24 }; + + int row, col; + + int isample; + int iadc; + int ix, iy; + + int npackets=40; + int i; + int adc4(0); + + for (int ip=0; ip0) { + row=199-i/sc_width; + } else { + row=200+i/sc_width; + } + dataMap[row][col]=sizeof(sls_detector_header)+(nadc*i+iadc)*2;//+16*(ip+1); + if (dataMap[row][col]<0 || dataMap[row][col]>=nSamples*2*32) + cout << "Error: pointer " << dataMap[row][col] << " out of range "<< endl; + } + } + } + } + + int ipacket; + int ibyte; + int ii=0; + for (ibyte=0; ibyteframeNumber;};//*((int*)(buff+5))&0xffffff;}; + + /** + + 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 ((sls_detector_header*)buff)->packetNumber;}//((*(((int*)(buff+4))))&0xff)+1;}; + +/* /\** */ + +/* 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){ndata=dsize; setDataSize(dsize); return data;}; */ + + +/* /\** */ + +/* Loops over a file stream until a complete frame is found (i.e. all packets 0 to nPackets, same frame number). Can be overloaded for different kind of detectors! */ +/* \param filebin input file stream (binary) */ +/* \returns pointer to the begin of the last good frame, NULL if no frame is found or last frame is incomplete */ + +/* *\/ */ +/* virtual char *readNextFrame(ifstream &filebin){ */ +/* // int afifo_length=0; */ +/* uint16_t *afifo_cont; */ +/* int ib=0; */ +/* if (filebin.is_open()) { */ +/* afifo_cont=new uint16_t[dataSize/2]; */ +/* while (filebin.read(((char*)afifo_cont)+ib,2)) { */ +/* ib+=2; */ +/* if (ib==dataSize) break; */ +/* } */ +/* if (ib>0) { */ +/* iframe++; */ +/* // cout << ib << "-" << endl; */ +/* return (char*)afifo_cont; */ +/* } else { */ +/* delete [] afifo_cont; */ +/* return NULL; */ +/* } */ +/* } */ +/* return NULL; */ +/* }; */ + + + virtual char *readNextFrame(ifstream &filebin) { + int ff=-1, np=-1; + return readNextFrame(filebin, ff, np); + }; + + virtual char *readNextFrame(ifstream &filebin, int &ff) { + int np=-1; + return readNextFrame(filebin, ff, np); + }; + + virtual 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; + } + + + + + virtual 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 +#include +#include + +using namespace std; + + +template +class slsDetectorData { + + protected: + const int nx; /**< Number of pixels in the x direction */ + const int ny; /**< Number of pixels in the y direction */ + int dataSize; /**=0 && ix=0 && iy=0 && ix=0 && iydataSize) dsize=dataSize; + for (int ip=0; ip<(dsize/sizeof(dataType)); ip++) { + getPixel(ip,ix,iy); + if (ix>=0 && ix=0 && iydataSize) dsize=dataSize; + for (int ip=0; ip<(dsize/sizeof(dataType)); ip++) { + getPixel(ip,ix,iy); + if (ix>=0 && ix=0 && iy=0 && ix=0 && iy=0 && dataMap[iy][ix] +#include // exit() +template +class slsReceiverData : public slsDetectorData { + + +public: + + /** + slsReceiver data structure. Works for data acquired using the slsDetectorReceiver subdivided in different packets with headers and footers. + Inherits and implements slsDetectorData. + + Constructor (no error checking if datasize and offsets are compatible!) + \param npx number of pixels in the x direction + \param npy number of pixels in the y direction (1 for strips) + \param np number of packets + \param psize packets size + \param dMap array of size nx*ny storing the pointers to the data in the dataset (as offset) + \param dMask Array of size nx*ny storing the polarity of the data in the dataset (should be 0 if no inversion is required, 0xffffffff is inversion is required) + \param dROI Array of size nx*ny. The elements are 1s if the channel is good or in the ROI, 0 is bad or out of the ROI. NULL (default) means all 1s. + + */ + slsReceiverData(int npx, int npy, int np, int psize, int **dMap=NULL, dataType **dMask=NULL, int **dROI=NULL): slsDetectorData(npx, npy, np*psize, dMap, dMask, dROI), nPackets(np), packetSize(psize) {}; + + + /** + + Returns the frame number for the given dataset. Virtual func: works for slsDetectorReceiver data (also for each packet), but can be overloaded. + \param buff pointer to the dataset + \returns frame number + + */ + + virtual int getFrameNumber(char *buff){return ((*(int*)buff)&(0xffffff00))>>8;}; + + /** + + Returns the packet number for the given dataset. Virtual func: works for slsDetectorReceiver packets, but can be overloaded. + \param buff pointer to the dataset + \returns packet number number + + */ + + virtual int getPacketNumber(char *buff){return (*(int*)buff)&0xff;}; + + + + /** + + Loops over a memory slot until a complete frame is found (i.e. all packets 0 to nPackets, same frame number). Can be overloaded for different kind of detectors! + \param data pointer to the memory to be analyzed + \param ndata size of frame returned + \param dsize size of the memory slot to be analyzed + \returns pointer to the first packet of the last good frame (might be incomplete if npackets lower than the number of packets), or NULL if no frame is found + + */ + + virtual char *findNextFrame(char *data, int &ndata, int dsize) { + char *retval=NULL, *p=data; + int dd=0; + int fn, fnum=-1, np=0, pnum=-1; + while (dd<=(dsize-packetSize)) { + pnum=getPacketNumber(p); + fn=getFrameNumber(p); + //cout <<"fnum:"<nPackets) { + //cout << "Bad packet number " << pnum << " frame "<< fn << endl; + retval=NULL; + np=0; + } else if (pnum==1) { + retval=p; + if (np>0) + /*cout << "*Incomplete frame number " << fnum << endl;*/ + np=0; + fnum=fn; + } else if (fn!=fnum) { + if (fnum!=-1) { + /* cout << " **Incomplete frame number " << fnum << " pnum " << pnum << " " << getFrameNumber(p) << endl;*/ + retval=NULL; + } + np=0; + } + p+=packetSize; + dd+=packetSize; + np++; + //cout <<"fnum:"<0){ + //cprintf(BG_RED, "Too few packets for this frame! fnum:%d, pnum:%d np:%d\n",fnum,pnum,np); + cout << "Too few packets for this frame! "<< fnum << " " << pnum << " " << np <nPackets) { + cout << "too many packets!!!!!!!!!!" << endl; + delete [] data; + return NULL; + } else if (retval!=NULL) { + // cout << "+" << endl;; + for (int ip=0; ipnPackets) { + cout << "*******too many packets!!!!!!!!!!" << endl; + delete [] data; + return NULL; + } else { + // cout << "." << endl;; + np++; + } + } + } + delete [] data; + return NULL; + }; + + + /** + + Loops over a file stream until a complete frame is found (i.e. all packets 0 to nPackets, same frame number). Can be overloaded for different kind of detectors! + \param filebin input file stream (binary) + \param fnum frame number of frame returned + \returns pointer to the first packet of the last good frame, NULL if no frame is found or last frame is incomplete + + */ + + virtual char *readNextFrame(ifstream &filebin, int& fnum) { + char *data=new char[packetSize*nPackets]; + char *retval=0; + int np=0, nd; + fnum = -1; + + if (filebin.is_open()) { + while (filebin.read(data+np*packetSize,packetSize)) { + + if (np==(nPackets-1)) { + + fnum=getFrameNumber(data); //cout << "fnum:"<nPackets) { + cout << "too many packets!!!!!!!!!!" << endl; + delete [] data; + return NULL; + } else if (retval!=NULL) { + // cout << "+" << endl;; + for (int ip=0; ipnPackets) { + cout << "*******too many packets!!!!!!!!!!" << endl; + delete [] data; + return NULL; + } else { + // cout << "." << endl;; + np++; + //cout<<"np:"<

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

diff --git a/slsDetectorServers/eigerDetectorServer/communication_funcs_UDP.h b/slsDetectorServers/eigerDetectorServer/communication_funcs_UDP.h
new file mode 120000
index 000000000..0d434a97d
--- /dev/null
+++ b/slsDetectorServers/eigerDetectorServer/communication_funcs_UDP.h
@@ -0,0 +1 @@
+../slsDetectorServer/communication_funcs_UDP.h
\ No newline at end of file
diff --git a/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c
index 2395d6687..1b57928de 100755
--- a/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c
+++ b/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c
@@ -11,6 +11,7 @@
 #include  //to gethostname
 #include 
 #ifdef VIRTUAL
+#include "communication_funcs_UDP.h"
 #include 
 #include 
 #endif
@@ -182,11 +183,8 @@ void basictests() {
 /* Ids */
 
 int64_t getDetectorId(enum idMode arg) {
-#ifdef VIRTUAL
-	return 0;
-#else
-	int64_t retval = -1;
 
+	int64_t retval = -1;
 	switch(arg) {
 	case DETECTOR_SERIAL_NUMBER:
 		retval =  getDetectorNumber();/** to be implemented with mac? */
@@ -203,7 +201,7 @@ int64_t getDetectorId(enum idMode arg) {
 	}
 
 	return retval;
-#endif
+
 }
 
 u_int64_t getFirmwareVersion() {
@@ -1026,6 +1024,7 @@ void setDAC(enum DACINDEX ind, int val, int mV) {
     }
 
 #ifdef VIRTUAL
+    int dacval = 0;
     if (!mV) {
         (detectorModules)->dacs[ind] = val;
     }
@@ -1213,7 +1212,21 @@ enum externalCommunicationMode getTiming() {
 /* configure mac */
 
 int configureMAC(uint32_t destip, uint64_t destmac, uint64_t sourcemac, uint32_t sourceip, uint32_t udpport, uint32_t udpport2) {
-#ifndef VIRTUAL
+#ifdef VIRTUAL
+	char cDestIp[MAX_STR_LENGTH];
+	memset(cDestIp, 0, MAX_STR_LENGTH);
+	sprintf(cDestIp, "%d.%d.%d.%d", (destip>>24)&0xff,(destip>>16)&0xff,(destip>>8)&0xff,(destip)&0xff);
+	FILE_LOG(logINFO, ("1G UDP: Destination (IP: %s, port:%d, port2:%d)\n", cDestIp, udpport, udpport2));
+	if (setUDPDestinationDetails(0, cDestIp, udpport) == FAIL) {
+		FILE_LOG(logERROR, ("could not set udp destination IP and port\n"));
+		return FAIL;
+	}
+	if (setUDPDestinationDetails(1, cDestIp, udpport2) == FAIL) {
+		FILE_LOG(logERROR, ("could not set udp destination IP and port2\n"));
+		return FAIL;
+	}
+    return OK;
+#else
     FILE_LOG(logINFO, ("Configuring MAC\n"));
 	
 	int src_port = DEFAULT_UDP_SOURCE_PORT;
@@ -1606,6 +1619,14 @@ int prepareAcquisition() {
 
 int startStateMachine() {
 #ifdef VIRTUAL
+	// create udp socket
+	if(createUDPSocket(0) != OK) {
+		return FAIL;
+	}
+	if(createUDPSocket(1) != OK) {
+		return FAIL;
+	}
+	FILE_LOG(logINFOBLUE, ("starting state machine\n"));
 	eiger_virtual_status = 1;
 	eiger_virtual_stop = 0;
 	if (pthread_create(&eiger_virtual_tid, NULL, &start_timer, NULL)) {
@@ -1638,23 +1659,109 @@ int startStateMachine() {
 		FILE_LOG(logINFOGREEN, ("Acquisition started\n"));
 	}
 
-	/*while(getRunStatus() == IDLE) {FILE_LOG(logINFO, ("waiting for being not idle anymore\n"));}*/
-
 	return ret;
 #endif
 }
 
 #ifdef VIRTUAL
 void* start_timer(void* arg) {
-	eiger_virtual_status = 1;
-	int wait_in_s = nimages_per_request * eiger_virtual_period;
-	FILE_LOG(logINFO, ("going to wait for %d s\n", wait_in_s));
-	while(!eiger_virtual_stop && (wait_in_s >= 0)) {
-		usleep(1000 * 1000);
-		wait_in_s--;
-	}
-	FILE_LOG(logINFO, ("Virtual Timer Done***\n"));
+	int64_t periodns = eiger_virtual_period;
+	int numFrames = nimages_per_request;
+	int64_t exp_ns = eiger_virtual_exptime;
 
+	int dr = eiger_dynamicrange;
+	double bytesPerPixel  = (double)dr/8.00;
+	int tgEnable = send_to_ten_gig;
+	int datasize = (tgEnable ? 4096 : 1024);
+	int packetsize = datasize + sizeof(sls_detector_header);
+	int numPacketsPerFrame =  (tgEnable ? 4 : 16) * dr;
+	int npixelsx = 256 * 2 * bytesPerPixel; 
+	int databytes = 256 * 256 * 2 * bytesPerPixel;
+	FILE_LOG(logINFO, (" dr:%f\n bytesperpixel:%d\n tgenable:%d\n datasize:%d\n packetsize:%d\n numpackes:5d\n npixelsx:%d\n databytes:%d\n",
+	dr, bytesPerPixel, tgEnable, datasize, packetsize, numPacketsPerFrame, npixelsx, databytes));
+
+
+		//TODO: Generate data
+		char imageData[databytes * 2];
+		memset(imageData, 0, databytes * 2);
+		{
+			int i = 0;
+			for (i = 0; i < databytes * 2; i += sizeof(uint8_t)) {
+				*((uint8_t*)(imageData + i)) = i;
+			}
+		}
+		
+		
+		//TODO: Send data
+		{
+			int frameNr = 1;
+			for(frameNr=1; frameNr <= numFrames; ++frameNr ) {
+				int srcOffset = 0;
+				int srcOffset2 = npixelsx;
+			
+				struct timespec begin, end;
+				clock_gettime(CLOCK_REALTIME, &begin);
+
+				usleep(exp_ns / 1000);
+
+				char packetData[packetsize];
+				memset(packetData, 0, packetsize);
+				char packetData2[packetsize];
+				memset(packetData2, 0, packetsize);
+				
+				// loop packet
+				{
+					int i = 0;
+					for(i = 0; i != numPacketsPerFrame; ++i) {
+						int dstOffset = sizeof(sls_detector_header);
+						int dstOffset2 = sizeof(sls_detector_header);
+						// set header
+						sls_detector_header* header = (sls_detector_header*)(packetData);
+						header->frameNumber = frameNr;
+						header->packetNumber = i;
+						header = (sls_detector_header*)(packetData2);
+						header->frameNumber = frameNr;
+						header->packetNumber = i;
+						// fill data	
+						{		
+							int psize = 0;	
+							for (psize = 0; psize < datasize; psize += npixelsx) {
+								if (dr == 32 && tgEnable == 0) {
+									memcpy(packetData + dstOffset, imageData + srcOffset, npixelsx/2);
+									memcpy(packetData2 + dstOffset2, imageData + srcOffset2, npixelsx/2);
+									srcOffset += npixelsx;
+									srcOffset2 += npixelsx;
+									dstOffset += npixelsx/2;
+									dstOffset2 += npixelsx/2;
+								} else {
+									memcpy(packetData + dstOffset, imageData + srcOffset, npixelsx);
+									memcpy(packetData2 + dstOffset2, imageData + srcOffset2, npixelsx);
+									srcOffset += 2 * npixelsx;
+									srcOffset2 += 2 * npixelsx;
+									dstOffset += npixelsx;
+									dstOffset2 += npixelsx;
+								}
+							}
+						}
+						
+						sendUDPPacket(0, packetData, packetsize);
+						sendUDPPacket(1, packetData2, packetsize);
+					}
+				}
+				FILE_LOG(logINFO, ("Sent frame: %d\n", frameNr));
+				clock_gettime(CLOCK_REALTIME, &end);
+				int64_t time_ns = ((end.tv_sec - begin.tv_sec) * 1E9 +
+						(end.tv_nsec - begin.tv_nsec));
+	  
+				if (periodns > time_ns) {
+					usleep((periodns - time_ns)/ 1000);
+				}
+			}
+		}
+	
+	closeUDPSocket(0);
+	closeUDPSocket(1);
+	
 	eiger_virtual_status = 0;
 	return NULL;
 }
@@ -1662,6 +1769,7 @@ void* start_timer(void* arg) {
 
 
 
+
 int stopStateMachine() {
 	FILE_LOG(logINFORED, ("Going to stop acquisition\n"));
 #ifdef VIRTUAL
@@ -1749,10 +1857,6 @@ enum runStatus getRunStatus() {
 
 void readFrame(int *ret, char *mess) {
 #ifdef VIRTUAL
-	while(eiger_virtual_status) {
-		//FILE_LOG(logERROR ,"Waiting for finished flag\n"));
-		usleep(5000);
-	}
 	FILE_LOG(logINFOGREEN, ("acquisition successfully finished\n"));
 	return;
 #else
@@ -1857,12 +1961,3 @@ int getTotalNumberOfChannels() {return  ((int)getNumberOfChannelsPerChip() * (in
 int getNumberOfChips() {return  NCHIP;}
 int getNumberOfDACs() {return  NDAC;}
 int getNumberOfChannelsPerChip() {return  NCHAN;}
-
-
-
-
-
-
-
-
-
diff --git a/slsDetectorServers/jungfrauDetectorServer/CMakeLists.txt b/slsDetectorServers/jungfrauDetectorServer/CMakeLists.txt
new file mode 100644
index 000000000..50574aa34
--- /dev/null
+++ b/slsDetectorServers/jungfrauDetectorServer/CMakeLists.txt
@@ -0,0 +1,26 @@
+add_executable(jungfrauDetectorServer
+    slsDetectorFunctionList.c
+    slsDetectorServer.c
+    slsDetectorServer_funcs.c
+    communication_funcs.c
+)
+
+target_include_directories(jungfrauDetectorServer
+    PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+target_compile_definitions(jungfrauDetectorServer
+    PUBLIC JUNGFRAUD VIRTUAL STOP_SERVER
+)
+
+target_link_libraries(jungfrauDetectorServer
+    PUBLIC pthread rt
+)
+
+set_target_properties(jungfrauDetectorServer PROPERTIES
+    RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
+)
+
+install(TARGETS jungfrauDetectorServer
+    RUNTIME  DESTINATION ${CMAKE_INSTALL_BINDIR}
+)
diff --git a/slsDetectorServers/jungfrauDetectorServer/Makefile.virtual b/slsDetectorServers/jungfrauDetectorServer/Makefile.virtual
deleted file mode 100755
index e38c85ca0..000000000
--- a/slsDetectorServers/jungfrauDetectorServer/Makefile.virtual
+++ /dev/null
@@ -1,27 +0,0 @@
-CC    		= gcc
-CFLAGS		+=  -Wall -DJUNGFRAUD -DVIRTUAL -DSTOP_SERVER #-DVERBOSEI #-DVERBOSE
-LDLIBS		+= 	-lm  -lstdc++  -pthread
-
-PROGS		= 	jungfrauDetectorServer_virtual 
-DESTDIR		?= 	bin
-INSTMODE	= 	0777
-
-SRC_CLNT	=	communication_funcs.c slsDetectorServer.c slsDetectorServer_funcs.c  slsDetectorFunctionList.c 
-OBJS 		= 	$(SRC_CLNT:.c=.o) 
- 
-all: clean versioning $(PROGS)
-
-boot: $(OBJS) 
-
-versioning: 
-	@echo `tput setaf 6;	./updateGitVersion.sh; tput sgr0;`
-	
-$(PROGS): $(OBJS)
-#	echo $(OBJS) 
-	mkdir -p $(DESTDIR) 
-	$(CC) -o $@ $^ $(CFLAGS) $(LDLIBS) 
-	mv $(PROGS) $(DESTDIR)
-
-clean:
-	rm -rf $(DESTDIR)/$(PROGS)  *.o
-	
diff --git a/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_virtual b/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_virtual
deleted file mode 100755
index 4c211698faaa1a0db04b99fbe0e05d9ea330a864..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 75496
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
GIrtxn#yS`P

diff --git a/slsDetectorServers/jungfrauDetectorServer/communication_funcs_UDP.h b/slsDetectorServers/jungfrauDetectorServer/communication_funcs_UDP.h
new file mode 120000
index 000000000..0d434a97d
--- /dev/null
+++ b/slsDetectorServers/jungfrauDetectorServer/communication_funcs_UDP.h
@@ -0,0 +1 @@
+../slsDetectorServer/communication_funcs_UDP.h
\ No newline at end of file
diff --git a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c
index d667d1349..ffb270ad4 100755
--- a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c
+++ b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c
@@ -1,7 +1,7 @@
 #include "slsDetectorFunctionList.h"
 #include "versionAPI.h"
 #include "logger.h"
-
+#include 
 #include "AD9257.h"		// commonServerFunctions.h, blackfin.h, ansi.h
 #include "LTC2620.h"    // dacs
 #include "MAX1932.h"    // hv
@@ -9,6 +9,7 @@
 #ifndef VIRTUAL
 #include "programfpga.h"
 #else
+#include "communication_funcs_UDP.h"
 #include "blackfin.h"
 #include 
 #include      // usleep
@@ -1097,6 +1098,14 @@ int configureMAC(int numInterfaces, int selInterface,
 		uint32_t destip, uint64_t destmac, uint64_t sourcemac, uint32_t sourceip, uint32_t udpport,
 		uint32_t destip2, uint64_t destmac2, uint64_t sourcemac2, uint32_t sourceip2, uint32_t udpport2) {
 #ifdef VIRTUAL
+	char cDestIp[MAX_STR_LENGTH];
+	memset(cDestIp, 0, MAX_STR_LENGTH);
+	sprintf(cDestIp, "%d.%d.%d.%d", (destip>>24)&0xff,(destip>>16)&0xff,(destip>>8)&0xff,(destip)&0xff);
+	FILE_LOG(logINFO, ("1G UDP: Destination (IP: %s, port:%d)\n", cDestIp, udpport));
+	if (setUDPDestinationDetails(0, cDestIp, udpport) == FAIL) {
+		FILE_LOG(logERROR, ("could not set udp destination IP and port\n"));
+		return FAIL;
+	}
     return OK;
 #endif
 	FILE_LOG(logINFOBLUE, ("Configuring MAC\n"));
@@ -1437,7 +1446,7 @@ void setAdcPhase(int val, int degrees){
 	alignDeserializer();
 }
 
-int getPhase(degrees) {
+int getPhase(int degrees) {
 	if (!degrees)
 		return adcPhase;
 	// convert back to degrees
@@ -1581,11 +1590,16 @@ int setNetworkParameter(enum NETWORKINDEX mode, int value) {
 
 int startStateMachine(){
 #ifdef VIRTUAL
+	// create udp socket
+	if(createUDPSocket(0) != OK) {
+		return FAIL;
+	}
+	FILE_LOG(logINFOBLUE, ("starting state machine\n"));
 	virtual_status = 1;
 	virtual_stop = 0;
 	if(pthread_create(&pthread_virtual_tid, NULL, &start_timer, NULL)) {
-		virtual_status = 0;
 		FILE_LOG(logERROR, ("Could not start Virtual acquisition thread\n"));
+		virtual_status = 0;
 		return FAIL;
 	}
 	FILE_LOG(logINFOGREEN, ("Virtual Acquisition started\n"));
@@ -1606,16 +1620,69 @@ int startStateMachine(){
 
 #ifdef VIRTUAL
 void* start_timer(void* arg) {
-	int wait_in_s = 	(setTimer(FRAME_NUMBER, -1) *
+	int64_t periodns = setTimer(FRAME_PERIOD, -1);
+	int numFrames = (setTimer(FRAME_NUMBER, -1) *
 						setTimer(CYCLES_NUMBER, -1) *
-						(setTimer(STORAGE_CELL_NUMBER, -1) + 1) *
-						(setTimer(FRAME_PERIOD, -1)/(1E9)));
-	FILE_LOG(logDEBUG1, ("going to wait for %d s\n", wait_in_s));
-	while(!virtual_stop && (wait_in_s >= 0)) {
-		usleep(1000 * 1000);
-		wait_in_s--;
-	}
-	FILE_LOG(logINFOGREEN, ("Virtual Timer Done\n"));
+						(setTimer(STORAGE_CELL_NUMBER, -1) + 1));
+	int64_t exp_ns = 	setTimer(ACQUISITION_TIME, -1);
+
+		//TODO: Generate data
+		char imageData[DATA_BYTES];
+		memset(imageData, 0, DATA_BYTES);
+		{
+			int i = 0;
+			for (i = 0; i < DATA_BYTES; i += sizeof(uint16_t)) {
+				*((uint16_t*)(imageData + i)) = i;
+			}
+		}
+		int datasize = 8192;
+		
+		
+		//TODO: Send data
+		{
+			int frameNr = 0;
+			for(frameNr=0; frameNr!= numFrames; ++frameNr ) {
+				int srcOffset = 0;
+			
+				struct timespec begin, end;
+				clock_gettime(CLOCK_REALTIME, &begin);
+
+				usleep(exp_ns / 1000);
+
+				const int size = datasize + 112;
+				char packetData[size];
+				memset(packetData, 0, sizeof(sls_detector_header));
+				
+				// loop packet
+				{
+					int i = 0;
+					for(i=0; i!=128; ++i) {
+						// set header
+						sls_detector_header* header = (sls_detector_header*)(packetData);
+						header->frameNumber = frameNr;
+						header->packetNumber = i;
+						// fill data
+						memcpy(packetData + sizeof(sls_detector_header), imageData + srcOffset, datasize);
+						srcOffset += datasize;
+						
+						sendUDPPacket(0, packetData, size);
+					}
+				}
+				FILE_LOG(logINFO, ("Sent frame: %d\n", frameNr));
+				clock_gettime(CLOCK_REALTIME, &end);
+				int64_t time_ns = ((end.tv_sec - begin.tv_sec) * 1E9 +
+						(end.tv_nsec - begin.tv_nsec));
+	  
+				if (periodns > time_ns) {
+					usleep((periodns - time_ns)/ 1000);
+				}
+			}
+		}
+		
+	// }
+
+	
+	closeUDPSocket(0);
 
 	virtual_status = 0;
 	return NULL;
@@ -1694,10 +1761,7 @@ enum runStatus getRunStatus(){
 
 void readFrame(int *ret, char *mess){
 #ifdef VIRTUAL
-	while(virtual_status) {
-		//FILE_LOG(logERROR, ("Waiting for finished flag\n");
-		usleep(5000);
-	}
+	FILE_LOG(logINFOGREEN, ("acquisition successfully finished\n"));
 	return;
 #endif
 	// wait for status to be done
@@ -1745,5 +1809,3 @@ int getTotalNumberOfChannels(){return  ((int)getNumberOfChannelsPerChip() * (int
 int getNumberOfChips(){return  NCHIP;}
 int getNumberOfDACs(){return  NDAC;}
 int getNumberOfChannelsPerChip(){return  NCHAN;}
-
-
diff --git a/slsDetectorServers/slsDetectorServer/communication_funcs.c b/slsDetectorServers/slsDetectorServer/communication_funcs.c
index 153b4c719..3c4bae02e 100755
--- a/slsDetectorServers/slsDetectorServer/communication_funcs.c
+++ b/slsDetectorServers/slsDetectorServer/communication_funcs.c
@@ -4,8 +4,12 @@
 #include 
 #include 
 #include 
+
+#include 
 #include 
 
+
+
 #define SEND_REC_MAX_SIZE 4096
 #define DEFAULT_PORTNO    1952
 #define DEFAULT_BACKLOG 5
diff --git a/slsDetectorServers/slsDetectorServer/communication_funcs_UDP.h b/slsDetectorServers/slsDetectorServer/communication_funcs_UDP.h
index e42343351..622e92694 100755
--- a/slsDetectorServers/slsDetectorServer/communication_funcs_UDP.h
+++ b/slsDetectorServers/slsDetectorServer/communication_funcs_UDP.h
@@ -15,25 +15,25 @@
 #include 
 #include 
 
-int udpSockfd = -1;
-struct addrinfo* udpServerAddrInfo = 0;
-unsigned short int udpDestinationPort = 0;
-char udpDestinationIp[MAX_STR_LENGTH] = "";
+int udpSockfd[2] = {-1, -1};
+struct addrinfo* udpServerAddrInfo[2] = {0, 0};
+unsigned short int udpDestinationPort[2] = {0, 0};
+char udpDestinationIp[2][MAX_STR_LENGTH] = {"", ""};
 
 //DEFAULT_TX_UDP_PORT;// src port
-int getUdPSocketDescriptor() {
-	return udpSockfd;
+int getUdPSocketDescriptor(int index) {
+	return udpSockfd[index];
 }
 
-int setUDPDestinationDetails(const char* ip, unsigned short int port) {
-	udpDestinationPort = port;
+int setUDPDestinationDetails(int index, const char* ip, unsigned short int port) {
+	udpDestinationPort[index] = port;
 	size_t len = strlen(ip);
-	memset(udpDestinationIp, 0, MAX_STR_LENGTH);
-	strncpy(udpDestinationIp, ip, len > MAX_STR_LENGTH ? MAX_STR_LENGTH : len );
+	memset(udpDestinationIp[index], 0, MAX_STR_LENGTH);
+	strncpy(udpDestinationIp[index], ip, len > MAX_STR_LENGTH ? MAX_STR_LENGTH : len );
 
-	if (udpServerAddrInfo) {
-		freeaddrinfo(udpServerAddrInfo);
-		udpServerAddrInfo = 0;
+	if (udpServerAddrInfo[index]) {
+		freeaddrinfo(udpServerAddrInfo[index]);
+		udpServerAddrInfo[index] = 0;
 	}
 
 	// convert ip to internet address
@@ -45,73 +45,73 @@ int setUDPDestinationDetails(const char* ip, unsigned short int port) {
 	hints.ai_protocol = 0;
 	char sport[100];
 	memset(sport, 0, 100);
-	sprintf(sport, "%d", udpDestinationPort);
-	int err = getaddrinfo(udpDestinationIp, sport, &hints, &udpServerAddrInfo);
+	sprintf(sport, "%d", udpDestinationPort[index]);
+	int err = getaddrinfo(udpDestinationIp[index], sport, &hints, &udpServerAddrInfo[index]);
 	if (err != 0) {
 		FILE_LOG(logERROR, ("Failed to resolve remote socket address %s at port %d. "
-				"(Error code:%d, %s)\n", udpDestinationIp, udpDestinationPort, err, gai_strerror(err)));
+				"(Error code:%d, %s)\n", udpDestinationIp[index], udpDestinationPort[index], err, gai_strerror(err)));
 		return FAIL;
 	}
-	if (udpServerAddrInfo == NULL) {
+	if (udpServerAddrInfo[index] == NULL) {
 		FILE_LOG(logERROR, ("Failed to resolve remote socket address %s at port %d "
-				"(getaddrinfo returned NULL)\n", udpDestinationIp, udpDestinationPort));
-		udpServerAddrInfo = 0;
+				"(getaddrinfo returned NULL)\n", udpDestinationIp[index], udpDestinationPort[index]));
+		udpServerAddrInfo[index] = 0;
 		return FAIL;
 	}
 
 	return OK;
 }
 
-int createUDPSocket() {
-	FILE_LOG(logDEBUG2, ("Creating UDP Socket\n"));
-	if (!strlen(udpDestinationIp)) {
+int createUDPSocket(int index) {
+	FILE_LOG(logDEBUG2, ("Creating UDP Socket %d\n", index));
+	if (!strlen(udpDestinationIp[index])) {
 		FILE_LOG(logERROR, ("No destination UDP ip specified.\n"));
 		return FAIL;
 	}
 
-	if (udpSockfd != -1) {
+	if (udpSockfd[index] != -1) {
 		FILE_LOG(logERROR, ("Strange that Udp socket was still open. Closing it to create a new one\n"));
-		close(udpSockfd);
-		udpSockfd = -1;
+		close(udpSockfd[index]);
+		udpSockfd[index] = -1;
 	}
 
 	// Creating socket file descriptor
-	udpSockfd = socket(udpServerAddrInfo->ai_family, udpServerAddrInfo->ai_socktype, udpServerAddrInfo->ai_protocol);
-	if (udpSockfd  == -1 ) {
+	udpSockfd[index] = socket(udpServerAddrInfo[index]->ai_family, udpServerAddrInfo[index]->ai_socktype, udpServerAddrInfo[index]->ai_protocol);
+	if (udpSockfd[index]  == -1 ) {
 		FILE_LOG(logERROR, ("UDP socket at port %d failed. (Error code:%d, %s)\n",
-				udpDestinationPort, errno, gai_strerror(errno)));
+				udpDestinationPort[index], errno, gai_strerror(errno)));
 		return FAIL;
 	}
 	FILE_LOG(logINFO, ("Udp client socket created for server (port %d, ip:%s)\n",
-			udpDestinationPort, udpDestinationIp));
+			udpDestinationPort[index], udpDestinationIp[index]));
 
 	// connecting allows to use "send/write" instead of "sendto", avoiding checking for server address for each packet
 	// using write without a connect will end in segv
-	if (connect(udpSockfd,udpServerAddrInfo->ai_addr, udpServerAddrInfo->ai_addrlen)==-1) {
+	if (connect(udpSockfd[index],udpServerAddrInfo[index]->ai_addr, udpServerAddrInfo[index]->ai_addrlen)==-1) {
 		FILE_LOG(logERROR, ("Could not connect to UDP server at ip:%s, port:%d. (Error code:%d, %s)\n",
-				udpDestinationIp, udpDestinationPort,  errno, gai_strerror(errno)));
+				udpDestinationIp[index], udpDestinationPort[index],  errno, gai_strerror(errno)));
 	}
 	FILE_LOG(logINFO, ("Udp client socket connected\n",
-				udpDestinationPort, udpDestinationIp));
+				udpDestinationPort[index], udpDestinationIp[index]));
 	return OK;
 }
 
-int sendUDPPacket(const char* buf, int length) {
-	int n = write(udpSockfd, buf, length);
+int sendUDPPacket(int index, const char* buf, int length) {
+	int n = write(udpSockfd[index], buf, length);
 	// udp sends atomically, no need to handle partial data
 	if (n == -1) {
-		FILE_LOG(logERROR, ("Could not send udp packet. (Error code:%d, %s)\n",
-				n, errno, gai_strerror(errno)));
+		FILE_LOG(logERROR, ("Could not send udp packet for socket %d. (Error code:%d, %s)\n",
+				index, n, errno, gai_strerror(errno)));
 	} else {
 		FILE_LOG(logDEBUG2, ("%d bytes sent\n", n));
 	}
 	return n;
 }
 
-void closeUDPSocket() {
-	if (udpSockfd != -1) {
+void closeUDPSocket(int index) {
+	if (udpSockfd[index] != -1) {
 		FILE_LOG(logINFO, ("Udp client socket closed\n"));
-		close(udpSockfd);
-		udpSockfd = -1;
+		close(udpSockfd[index]);
+		udpSockfd[index] = -1;
 	}
 }
diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h b/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h
index 85eef8e34..ba3bff0fb 100755
--- a/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h
+++ b/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h
@@ -5,7 +5,7 @@
 #endif
 #include 
 #include 					// FILE
-
+#include 
 
 /****************************************************
 This functions are used by the slsDetectroServer_funcs interface.
diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorServer.c b/slsDetectorServers/slsDetectorServer/slsDetectorServer.c
index 6c8413ed5..669009059 100755
--- a/slsDetectorServers/slsDetectorServer/slsDetectorServer.c
+++ b/slsDetectorServers/slsDetectorServer/slsDetectorServer.c
@@ -30,7 +30,6 @@ void error(char *msg){
 }
 
 int main(int argc, char *argv[]){
-	
 	// print version
 	if (argc > 1 && !strcasecmp(argv[1], "-version")) {
         int version = 0;
@@ -142,4 +141,3 @@ int main(int argc, char *argv[]){
 	FILE_LOG(logINFO,("Goodbye!\n"));
 	return 0;
 }
-
diff --git a/slsReceiverSoftware/CMakeLists.txt b/slsReceiverSoftware/CMakeLists.txt
index 4d483adc7..a27633663 100755
--- a/slsReceiverSoftware/CMakeLists.txt
+++ b/slsReceiverSoftware/CMakeLists.txt
@@ -92,7 +92,7 @@ if (SLS_USE_TESTS)
     add_subdirectory(tests)
 endif(SLS_USE_TESTS)
 
-install(TARGETS slsReceiverShared
+install(TARGETS slsReceiverShared slsReceiver
         EXPORT "${TARGETS_EXPORT_NAME}"
         RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
         LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
diff --git a/slsSupportLib/include/versionAPI.h b/slsSupportLib/include/versionAPI.h
index 08ceab081..c223fb436 100644
--- a/slsSupportLib/include/versionAPI.h
+++ b/slsSupportLib/include/versionAPI.h
@@ -6,6 +6,5 @@
 #define APIRECEIVER 0x190405
 #define APIGUI 0x190405
 #define APIEIGER 0x190516
-
 #define APICTB 0x190528
 #define APIJUNGFRAU 0x190528

From 29141ac1a6e7837a6d0e41b613a8fee54a5a332a Mon Sep 17 00:00:00 2001
From: Dhanya Thattil <33750417+thattil@users.noreply.github.com>
Date: Mon, 3 Jun 2019 11:07:53 +0200
Subject: [PATCH 76/76] =?UTF-8?q?set=20starting=20frame=20number=20of=20ne?=
 =?UTF-8?q?xt=20acquisition=20for=20both=20jungfrau=20and=20e=E2=80=A6=20(?=
 =?UTF-8?q?#27)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* set starting frame number of next acquisition for both jungfrau and eiger. firmware has not implemented a get, so workaround. tests included. frame number 0 not allowed due to Eiger. Eiger max frame is 48 bit, while jungfrau is 64 bit

* made argument of setstartingframenumber const
---
 cmk.sh                                        | 33 +++++---
 .../test-integrationDectector.cpp             | 38 +++++++++
 slsDetectorServers/eigerDetectorServer/Beb.c  | 61 ++++++++++++++
 slsDetectorServers/eigerDetectorServer/Beb.h  |  3 +
 .../eigerDetectorServer/FebRegisterDefs.h     |  5 +-
 .../slsDetectorFunctionList.c                 | 22 ++++-
 .../slsDetectorServer_defs.h                  |  3 +
 .../jungfrauDetectorServer/RegisterDefs.h     |  4 +
 .../slsDetectorFunctionList.c                 | 15 ++++
 .../slsDetectorServer_defs.h                  |  1 +
 .../slsDetectorServer/blackfin.h              | 23 ++++++
 .../slsDetectorFunctionList.h                 |  4 +
 .../slsDetectorServer_funcs.c                 | 80 +++++++++++++++++++
 .../slsDetectorServer_funcs.h                 |  2 +
 .../include/multiSlsDetector.h                | 18 ++++-
 slsDetectorSoftware/include/slsDetector.h     | 14 +++-
 slsDetectorSoftware/src/multiSlsDetector.cpp  | 32 +++++++-
 slsDetectorSoftware/src/slsDetector.cpp       | 24 +++++-
 .../src/slsDetectorCommand.cpp                | 21 ++++-
 .../include/slsReceiverImplementation.h       |  6 +-
 .../src/slsReceiverImplementation.cpp         |  8 +-
 .../src/slsReceiverTCPIPInterface.cpp         |  2 +-
 slsSupportLib/include/sls_detector_funcs.h    |  5 +-
 slsSupportLib/include/versionAPI.h            |  4 +-
 slsSupportLib/src/DataSocket.cpp              |  2 +-
 tests/include/tests/config.h                  |  8 +-
 26 files changed, 398 insertions(+), 40 deletions(-)

diff --git a/cmk.sh b/cmk.sh
index 803c0ed8d..964e55b1a 100755
--- a/cmk.sh
+++ b/cmk.sh
@@ -8,6 +8,7 @@ RECEIVER=0
 GUI=0
 DEBUG=0
 PYTHON=0
+TESTS=0
 SIMULATOR=0
 
 
@@ -17,7 +18,7 @@ CMAKE_PRE=""
 CMAKE_POST=""
 
 usage() { echo -e "
-Usage: $0 [-c] [-b] [-p] [e] [t] [r] [g] [s] [-h] [-d ] [-j] 
+Usage: $0 [-c] [-b] [-p] [e] [t] [r] [g] [s] [i] [-h] [-d ] [-j] 
  -[no option]: only make
  -c: Clean
  -b: Builds/Rebuilds CMake files normal mode
@@ -30,6 +31,7 @@ Usage: $0 [-c] [-b] [-p] [e] [t] [r] [g] [s] [-h] [-d ] [-j] > 32) & (0xffffffff));
+		Beb_close(fd,csp0base);
+	}
+
+	uint64_t retval = -1;
+	if ((Beb_GetStartingFrameNumber(&retval) == OK) && (retval == value)) {
+		FILE_LOG(logINFO, ("Going to reset Frame Number\n"));
+		Beb_ResetFrameNumber();
+	}
+	return OK;
+}
+
+int Beb_GetStartingFrameNumber(uint64_t* retval) {
+	if (!Beb_activated) {
+		*retval = Beb_deactivatedStartFrameNumber;
+		return OK;
+	}
+	FILE_LOG(logDEBUG1, ("Getting start frame number\n"));
+
+	// since it is not implemented in firmware yet
+	*retval = Beb_deactivatedStartFrameNumber;
+/*
+	u_int32_t* csp0base = 0;
+	int fd = Beb_open(&csp0base, XPAR_PLB_GPIO_TEST_BASEADDR);
+	if (fd < 0) {
+		FILE_LOG(logERROR, ("Set Start Frame Number FAIL\n"));
+		return FAIL;
+	} else {
+		*retval = Beb_Read32(csp0base, UDP_HEADER_FRAME_NUMBER_MSB_OFST);
+		uint32_t lretval = Beb_Read32(csp0base, UDP_HEADER_FRAME_NUMBER_MSB_OFST);
+		*retval = (*retval << 32) | lretval;
+		Beb_close(fd,csp0base);
+	}
+*/
+	return OK;
+}
+
 
 uint16_t Beb_swap_uint16( uint16_t val) {
 	return (val << 8) | (val >> 8 );
diff --git a/slsDetectorServers/eigerDetectorServer/Beb.h b/slsDetectorServers/eigerDetectorServer/Beb.h
index 6ab1338e8..dcff66286 100755
--- a/slsDetectorServers/eigerDetectorServer/Beb.h
+++ b/slsDetectorServers/eigerDetectorServer/Beb.h
@@ -39,6 +39,7 @@ void Beb_EndofDataSend(int tengiga);
 int Beb_SetMasterViaSoftware();
 int Beb_SetSlaveViaSoftware();
 int Beb_Activate(int enable);
+int Beb_GetActivate();
 int Beb_Set32bitOverflow(int val);
 int Beb_SetNetworkParameter(enum NETWORKINDEX mode, int val);
 int Beb_ResetToHardwareSettings();
@@ -74,6 +75,8 @@ int Beb_GetBebFPGATemp();
 
 void Beb_SetDetectorNumber(uint32_t detid);
 int Beb_SetDetectorPosition(int pos[]);
+int Beb_SetStartingFrameNumber(uint64_t value);
+int Beb_GetStartingFrameNumber(uint64_t* retval);
 
 uint16_t Beb_swap_uint16( uint16_t val);
 int Beb_open(u_int32_t** csp0base, u_int32_t offset);
diff --git a/slsDetectorServers/eigerDetectorServer/FebRegisterDefs.h b/slsDetectorServers/eigerDetectorServer/FebRegisterDefs.h
index a9b2f2459..9f3ac5454 100755
--- a/slsDetectorServers/eigerDetectorServer/FebRegisterDefs.h
+++ b/slsDetectorServers/eigerDetectorServer/FebRegisterDefs.h
@@ -202,8 +202,9 @@
 #define UDP_HEADER_Y_OFST					(16)
 #define UDP_HEADER_Y_MSK					(0xFFFF << UDP_HEADER_Y_OFST)
 
-
-
+// udp header (frame number)
+#define UDP_HEADER_FRAME_NUMBER_LSB_OFST    (0x0140)
+#define UDP_HEADER_FRAME_NUMBER_MSB_OFST    (0x0160)
 
 
 
diff --git a/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c
index 1b57928de..305b7b7c8 100755
--- a/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c
+++ b/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c
@@ -85,6 +85,7 @@ int eiger_virtual_status=0;
 int eiger_virtual_activate=1;
 pthread_t eiger_virtual_tid;
 int eiger_virtual_stop = 0;
+uint64_t eiger_virtual_startingframenumber = 0;
 #endif
 
 
@@ -444,6 +445,7 @@ void setupDetector() {
 	setSpeed(CLOCK_DIVIDER, DEFAULT_CLK_SPEED);//clk_devider,half speed
 	setIODelay(DEFAULT_IO_DELAY);
 	setTiming(DEFAULT_TIMING_MODE);
+	setStartingFrameNumber(DEFAULT_STARTING_FRAME_NUMBER);
 	//SetPhotonEnergyCalibrationParameters(-5.8381e-5,1.838515,5.09948e-7,-4.32390e-11,1.32527e-15);
 	setRateCorrection(DEFAULT_RATE_CORRECTION);
 	int enable[2] = {DEFAULT_EXT_GATING_ENABLE, DEFAULT_EXT_GATING_POLARITY};
@@ -658,6 +660,24 @@ enum readOutFlags setReadOutFlags(enum readOutFlags val) {
 
 /* parameters - timer */
 
+int setStartingFrameNumber(uint64_t value) {
+#ifdef VIRTUAL
+	eiger_virtual_startingframenumber =  value;
+	return OK;
+#else
+	return Beb_SetStartingFrameNumber(value);
+#endif
+}
+
+int getStartingFrameNumber(uint64_t* retval) {
+#ifdef VIRTUAL
+	*retval = eiger_virtual_startingframenumber;
+	return OK;
+#else
+	return Beb_GetStartingFrameNumber(retval);
+#endif
+}
+
 int64_t setTimer(enum timerIndex ind, int64_t val) {
 #ifndef VIRTUAL
 	int64_t subdeadtime = 0;
@@ -1609,8 +1629,6 @@ int prepareAcquisition() {
 #ifndef VIRTUAL
 	FILE_LOG(logINFO, ("Going to prepare for acquisition with counter_bit:%d\n",Feb_Control_Get_Counter_Bit()));
 	Feb_Control_PrepareForAcquisition();
-	FILE_LOG(logINFO, ("Going to reset Frame Number\n"));
-	Beb_ResetFrameNumber();
 #endif
 	return OK;
 
diff --git a/slsDetectorServers/eigerDetectorServer/slsDetectorServer_defs.h b/slsDetectorServers/eigerDetectorServer/slsDetectorServer_defs.h
index 71bf95ca0..7939cc0b4 100755
--- a/slsDetectorServers/eigerDetectorServer/slsDetectorServer_defs.h
+++ b/slsDetectorServers/eigerDetectorServer/slsDetectorServer_defs.h
@@ -51,6 +51,7 @@ enum										{E_PARALLEL, E_NON_PARALLEL, E_SAFE};
 
 /** Default Parameters */
 #define DEFAULT_NUM_FRAMES					(1)
+#define DEFAULT_STARTING_FRAME_NUMBER 		(1)
 #define DEFAULT_NUM_CYCLES					(1)
 #define DEFAULT_EXPTIME						(1E9)			//ns
 #define DEFAULT_PERIOD						(1E9)			//ns
@@ -74,6 +75,8 @@ enum										{E_PARALLEL, E_NON_PARALLEL, E_SAFE};
 #define DEFAULT_TEST_MODE					(0)
 #define DEFAULT_HIGH_VOLTAGE				(0)
 
+#define UDP_HEADER_MAX_FRAME_VALUE          (0xFFFFFFFFFFFF)
+
 #define DAC_MIN_MV                          (0)
 #define DAC_MAX_MV                          (2048)
 #define LTC2620_MIN_VAL                     (0)     // including LTC defines instead of LTC262.h (includes bit banging and blackfin read and write)
diff --git a/slsDetectorServers/jungfrauDetectorServer/RegisterDefs.h b/slsDetectorServers/jungfrauDetectorServer/RegisterDefs.h
index 948fb9fe0..c025c36d6 100755
--- a/slsDetectorServers/jungfrauDetectorServer/RegisterDefs.h
+++ b/slsDetectorServers/jungfrauDetectorServer/RegisterDefs.h
@@ -388,6 +388,10 @@
 #define SET_EXPTIME_LSB_REG    			(0x68 << MEM_MAP_SHIFT)
 #define SET_EXPTIME_MSB_REG    			(0x69 << MEM_MAP_SHIFT)
 
+/* Frame number 64 bit register */
+#define FRAME_NUMBER_LSB_REG   			(0x6A << MEM_MAP_SHIFT)
+#define FRAME_NUMBER_MSB_REG    		(0x6B << MEM_MAP_SHIFT)
+
 /* Trigger Delay 32 bit register */
 #define SET_TRIGGER_DELAY_LSB_REG       (0x70 << MEM_MAP_SHIFT)
 #define SET_TRIGGER_DELAY_MSB_REG       (0x71 << MEM_MAP_SHIFT)
diff --git a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c
index ffb270ad4..f8b03322d 100755
--- a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c
+++ b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c
@@ -441,6 +441,7 @@ void setupDetector() {
 	selectStoragecellStart(DEFAULT_STRG_CLL_STRT);
 	/*setClockDivider(HALF_SPEED); depends if all the previous stuff works*/
 	setTiming(DEFAULT_TIMING_MODE);
+	setStartingFrameNumber(DEFAULT_STARTING_FRAME_NUMBER);
 
 
 	// temp threshold and reset event
@@ -555,6 +556,20 @@ int selectStoragecellStart(int pos) {
     return ((bus_r(DAQ_REG) & DAQ_STRG_CELL_SLCT_MSK) >> DAQ_STRG_CELL_SLCT_OFST);
 }
 
+int setStartingFrameNumber(uint64_t value) {
+	FILE_LOG(logINFO, ("Setting starting frame number: %llu\n",(long long unsigned int)value));
+	// decrement is for firmware
+	setU64BitReg(value - 1, FRAME_NUMBER_LSB_REG, FRAME_NUMBER_MSB_REG);
+	// need to set it twice for the firmware to catch
+	setU64BitReg(value - 1, FRAME_NUMBER_LSB_REG, FRAME_NUMBER_MSB_REG);
+	return OK;
+}
+
+int getStartingFrameNumber(uint64_t* retval) {
+	// increment is for firmware
+	*retval = (getU64BitReg(FRAME_NUMBER_LSB_REG, FRAME_NUMBER_MSB_REG) + 1);
+	return OK;
+}
 
 
 int64_t setTimer(enum timerIndex ind, int64_t val) {
diff --git a/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_defs.h b/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_defs.h
index 98cdbe596..dc164ff11 100755
--- a/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_defs.h
+++ b/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_defs.h
@@ -63,6 +63,7 @@ enum NETWORKINDEX           { TXN_FRAME, FLOWCTRL_10G };
 
 /** Default Parameters */
 #define DEFAULT_NUM_FRAMES			(100*1000*1000)
+#define DEFAULT_STARTING_FRAME_NUMBER (1)
 #define DEFAULT_NUM_CYCLES			(1)
 #define DEFAULT_EXPTIME				(10*1000)		//ns
 #define DEFAULT_PERIOD				(2*1000*1000)	//ns
diff --git a/slsDetectorServers/slsDetectorServer/blackfin.h b/slsDetectorServers/slsDetectorServer/blackfin.h
index 604797148..c2e0d0eb9 100755
--- a/slsDetectorServers/slsDetectorServer/blackfin.h
+++ b/slsDetectorServers/slsDetectorServer/blackfin.h
@@ -97,6 +97,29 @@ int64_t set64BitReg(int64_t value, int aLSB, int aMSB){
 
 }
 
+/**
+ * Read unsigned 64 bit from a 64 bit register
+ * @param aLSB LSB offset address
+ * @param aMSB MSB offset address
+ * @returns unsigned 64 bit data read
+ */
+uint64_t getU64BitReg(int aLSB, int aMSB){
+	uint64_t retval = bus_r(aMSB);
+	retval = (retval << 32) | bus_r(aLSB);
+	return retval;
+}
+
+/**
+ * Write unsigned 64 bit into a 64 bit register
+ * @param value unsigned 64 bit data
+ * @param aLSB LSB offset address
+ * @param aMSB MSB offset address
+ */
+void setU64BitReg(uint64_t value, int aLSB, int aMSB){
+	bus_w(aLSB, value & (0xffffffff));
+	bus_w(aMSB, (value >> 32) & (0xffffffff));
+}
+
 /**
  * Read from a 32 bit register (literal register value provided by client)
  * @param offset address offset
diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h b/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h
index ba3bff0fb..22ce39e72 100755
--- a/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h
+++ b/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h
@@ -139,6 +139,10 @@ enum 		readOutFlags setReadOutFlags(enum readOutFlags val);
 #ifdef JUNGFRAUD
 int         selectStoragecellStart(int pos);
 #endif
+#if defined(JUNGFRAUD) || defined(EIGERD) 
+int 		setStartingFrameNumber(uint64_t value);
+int			getStartingFrameNumber(uint64_t* value);
+#endif
 int64_t 	setTimer(enum timerIndex ind, int64_t val);
 int64_t 	getTimeLeft(enum timerIndex ind);
 #if defined(JUNGFRAUD) || defined(GOTTHARDD) || defined(CHIPTESTBOARDD) || defined(MOENCHD)
diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c
index a9e2736fd..37c50026c 100755
--- a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c
+++ b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c
@@ -242,6 +242,8 @@ const char* getFunctionName(enum detFuncs func) {
 	case F_GET_ADC_INVERT:					return "F_GET_ADC_INVERT";
 	case F_EXTERNAL_SAMPLING_SOURCE:		return "F_EXTERNAL_SAMPLING_SOURCE";				
 	case F_EXTERNAL_SAMPLING:				return "F_EXTERNAL_SAMPLING";	
+	case F_SET_STARTING_FRAME_NUMBER:		return "F_SET_STARTING_FRAME_NUMBER";
+	case F_GET_STARTING_FRAME_NUMBER:		return "F_GET_STARTING_FRAME_NUMBER";
 	default:								return "Unknown Function";
 	}
 }
@@ -324,6 +326,8 @@ void function_table() {
 	flist[F_GET_ADC_INVERT]						= &get_adc_invert;
 	flist[F_EXTERNAL_SAMPLING_SOURCE]			= &set_external_sampling_source;							
 	flist[F_EXTERNAL_SAMPLING]					= &set_external_sampling;
+	flist[F_SET_STARTING_FRAME_NUMBER] 			= &set_starting_frame_number;
+	flist[F_GET_STARTING_FRAME_NUMBER] 			= &get_starting_frame_number;
 
 	// check
 	if (NUM_DET_FUNCTIONS  >= RECEIVER_ENUM_START) {
@@ -3999,3 +4003,79 @@ int set_external_sampling(int file_des) {
 #endif
     return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval));
 }
+
+
+
+int set_starting_frame_number(int file_des) {
+  	ret = OK;
+	memset(mess, 0, sizeof(mess));
+	uint64_t arg = 0;
+
+	if (receiveData(file_des, &arg, sizeof(arg), INT64) < 0)
+	return printSocketReadError();
+	FILE_LOG(logINFO, ("Setting starting frame number to %llu\n", arg));
+
+#if (!defined(EIGERD)) && (!defined(JUNGFRAUD))
+	functionNotImplemented();
+#else
+	// only set
+	if (Server_VerifyLock() == OK) {
+		if (arg == 0) {
+			ret = FAIL;
+			sprintf(mess, "Could not set starting frame number. Cannot be 0.\n");
+			FILE_LOG(logERROR,(mess));
+		}
+#ifdef EIGERD
+		else if (arg > UDP_HEADER_MAX_FRAME_VALUE) {
+			ret = FAIL;
+			sprintf(mess, "Could not set starting frame number. Must be less then %lld (0x%llx)\n", UDP_HEADER_MAX_FRAME_VALUE, UDP_HEADER_MAX_FRAME_VALUE);
+			FILE_LOG(logERROR,(mess));
+		}
+#endif	
+		 else {
+			ret = setStartingFrameNumber(arg);
+			if (ret == FAIL) {
+				sprintf(mess, "Could not set starting frame number. Failed to map address.\n");
+				FILE_LOG(logERROR,(mess));	
+			} 
+			if (ret == OK)  {
+				uint64_t retval = 0;
+				ret = getStartingFrameNumber(&retval);
+				if (ret == FAIL) {
+					sprintf(mess, "Could not get starting frame number. Failed to map address.\n");
+					FILE_LOG(logERROR,(mess));	
+				} else {
+					if (arg != retval) {
+						ret = FAIL;
+						sprintf(mess, "Could not set starting frame number. Set 0x%llx, but read 0x%llx\n", arg, retval);
+						FILE_LOG(logERROR,(mess));
+					}
+				}
+			}
+		}
+	}
+#endif
+	return Server_SendResult(file_des, INT64, UPDATE, NULL, 0);
+}
+
+int get_starting_frame_number(int file_des) {
+	ret = OK;
+	memset(mess, 0, sizeof(mess));
+	uint64_t retval = -1;
+
+	FILE_LOG(logDEBUG1, ("Getting Starting frame number \n"));
+
+#if (!defined(EIGERD)) && (!defined(JUNGFRAUD))
+	functionNotImplemented();
+#else	
+	// get
+	ret = getStartingFrameNumber(&retval);
+	if (ret == FAIL) {
+		sprintf(mess, "Could not get starting frame number. Failed to map address.\n");
+		FILE_LOG(logERROR,(mess));	
+	} else {
+		FILE_LOG(logDEBUG1, ("Start frame number retval: %u\n", retval));
+	}
+#endif
+	return Server_SendResult(file_des, INT64, UPDATE, &retval, sizeof(retval));
+}
\ No newline at end of file
diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.h b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.h
index 6b824b99d..618697dc6 100755
--- a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.h
+++ b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.h
@@ -103,3 +103,5 @@ int set_adc_invert(int);
 int get_adc_invert(int);
 int set_external_sampling_source(int);
 int set_external_sampling(int);
+int set_starting_frame_number(int);
+int get_starting_frame_number(int);
\ No newline at end of file
diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h
index 1ebec7292..28a56a08b 100755
--- a/slsDetectorSoftware/include/multiSlsDetector.h
+++ b/slsDetectorSoftware/include/multiSlsDetector.h
@@ -622,6 +622,20 @@ class multiSlsDetector : public virtual slsDetectorDefs {
      * @returns OK or FAIL
      */
     int configureMAC(int detPos = -1);
+    
+     /**
+     * Set starting frame number for the next acquisition
+     * @param val starting frame number
+     * @param detPos -1 for all detectors in  list or specific detector position
+     */
+    void setStartingFrameNumber(const uint64_t value, int detPos = -1);
+
+     /**
+     * Get starting frame number for the next acquisition
+     * @param detPos -1 for all detectors in  list or specific detector position
+     * @returns starting frame number
+     */
+    uint64_t getStartingFrameNumber(int detPos = -1);
 
     /**
      * Set/get timer value (not all implemented for all detectors)
@@ -1785,9 +1799,9 @@ class multiSlsDetector : public virtual slsDetectorDefs {
     /**
      * Gets the current frame index of receiver
      * @param detPos -1 for all detectors in  list or specific detector position
-     * @returns current frame index of receiver
+     * @returns average of all current frame index of receiver
      */
-    int getReceiverCurrentFrameIndex(int detPos = -1);
+    uint64_t getReceiverCurrentFrameIndex(int detPos = -1);
 
     /**
      * Resets framescaught in receiver
diff --git a/slsDetectorSoftware/include/slsDetector.h b/slsDetectorSoftware/include/slsDetector.h
index 419fe5b5d..99da58602 100755
--- a/slsDetectorSoftware/include/slsDetector.h
+++ b/slsDetectorSoftware/include/slsDetector.h
@@ -730,6 +730,18 @@ class slsDetector : public virtual slsDetectorDefs{
 	 */
     int configureMAC();
 
+	/**
+     * Set starting frame number for the next acquisition
+     * @param val starting frame number
+     */
+    void setStartingFrameNumber(const uint64_t value);
+
+     /**
+     * Get starting frame number for the next acquisition
+     * @returns starting frame number
+     */
+    uint64_t getStartingFrameNumber();
+
     /**
 	 * Set/get timer value (not all implemented for all detectors)
 	 * @param index timer index
@@ -1695,7 +1707,7 @@ class slsDetector : public virtual slsDetectorDefs{
 	 * Gets the current frame index of receiver
 	 * @returns current frame index of receiver
 	 */
-    int getReceiverCurrentFrameIndex();
+    uint64_t getReceiverCurrentFrameIndex();
 
     /**
 	 * Resets framescaught in receiver
diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp
index 14cf70b35..ddbb0ab26 100755
--- a/slsDetectorSoftware/src/multiSlsDetector.cpp
+++ b/slsDetectorSoftware/src/multiSlsDetector.cpp
@@ -1057,6 +1057,34 @@ int multiSlsDetector::configureMAC(int detPos) {
     return sls::allEqualTo(r, static_cast(OK)) ? OK : FAIL;
 }
 
+void multiSlsDetector::setStartingFrameNumber(const uint64_t value, int detPos) {
+    // single
+    if (detPos >= 0) {
+        return detectors[detPos]->setStartingFrameNumber(value);
+    }
+
+    // multi
+    parallelCall(&slsDetector::setStartingFrameNumber, value);
+}
+
+uint64_t multiSlsDetector::getStartingFrameNumber(int detPos) {
+    // single
+    if (detPos >= 0) {
+        return detectors[detPos]->getStartingFrameNumber();
+    }
+
+    // multi
+    auto r = parallelCall(&slsDetector::getStartingFrameNumber);
+    if (sls::allEqual(r)) {
+        return r.front();
+    }
+
+    // can't have different values for next acquisition
+    std::ostringstream ss;
+    ss << "Error: Different Values for starting frame number";
+    throw RuntimeError(ss.str());
+}
+
 int64_t multiSlsDetector::setTimer(timerIndex index, int64_t t, int detPos) {
     // single
     if (detPos >= 0) {
@@ -3121,7 +3149,7 @@ int multiSlsDetector::getFramesCaughtByReceiver(int detPos) {
     return ((sls::sum(r)) / (int)detectors.size());
 }
 
-int multiSlsDetector::getReceiverCurrentFrameIndex(int detPos) {
+uint64_t multiSlsDetector::getReceiverCurrentFrameIndex(int detPos) {
     // single
     if (detPos >= 0) {
         return detectors[detPos]->getReceiverCurrentFrameIndex();
@@ -3131,7 +3159,7 @@ int multiSlsDetector::getReceiverCurrentFrameIndex(int detPos) {
     auto r = parallelCall(&slsDetector::getReceiverCurrentFrameIndex);
 
     // prevent divide by all or do not take avg when -1 for "did not connect"
-    if ((detectors.empty()) || (sls::anyEqualTo(r, -1))) {
+    if ((detectors.empty()) || (sls::anyEqualTo(r, static_cast(-1)))) {
         return -1;
     }
 
diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp
index 4c162475e..5e5757c03 100755
--- a/slsDetectorSoftware/src/slsDetector.cpp
+++ b/slsDetectorSoftware/src/slsDetector.cpp
@@ -1497,6 +1497,23 @@ int slsDetector::configureMAC() {
     return ret;
 }
 
+void slsDetector::setStartingFrameNumber(const uint64_t value) {
+    FILE_LOG(logDEBUG1) << "Setting starting frame number to " << value;
+    if (shm()->onlineFlag == ONLINE_FLAG) {
+        sendToDetector(F_SET_STARTING_FRAME_NUMBER, value, nullptr);
+    }
+}
+
+uint64_t slsDetector::getStartingFrameNumber() {
+    uint64_t retval = -1;
+    FILE_LOG(logDEBUG1) << "Getting starting frame number";
+    if (shm()->onlineFlag == ONLINE_FLAG) {
+        sendToDetector(F_GET_STARTING_FRAME_NUMBER, nullptr, retval);
+        FILE_LOG(logDEBUG1) << "Starting frame number :" << retval;
+    }
+    return retval;
+}
+
 int64_t slsDetector::setTimer(timerIndex index, int64_t t) {
     int ret = FAIL;
     int64_t args[]{static_cast(index), t};
@@ -1554,6 +1571,7 @@ int64_t slsDetector::setTimer(timerIndex index, int64_t t) {
                         DIGITAL_SAMPLES,
                         STORAGE_CELL_NUMBER};
 
+        // if in list (lambda)
         if (std::any_of(std::begin(rt), std::end(rt),
                         [index](timerIndex t) { return t == index; })) {
             args[1] = shm()->timerValue[index];
@@ -1943,7 +1961,7 @@ std::string slsDetector::setReceiverHostname(const std::string &receiverIP) {
                 enableTenGigabitEthernet(shm()->tenGigaEnable);
                 setReadOutFlags(GET_READOUT_FLAGS);
                 break;
-
+            
             case CHIPTESTBOARD:
                 setTimer(ANALOG_SAMPLES, shm()->timerValue[ANALOG_SAMPLES]);
                 setTimer(DIGITAL_SAMPLES, shm()->timerValue[DIGITAL_SAMPLES]);
@@ -3592,8 +3610,8 @@ int slsDetector::getFramesCaughtByReceiver() {
     return retval;
 }
 
-int slsDetector::getReceiverCurrentFrameIndex() {
-    int retval = -1;
+uint64_t slsDetector::getReceiverCurrentFrameIndex() {
+    uint64_t retval = -1;
     FILE_LOG(logDEBUG1) << "Getting Current Frame Index of Receiver";
     if (shm()->rxOnlineFlag == ONLINE_FLAG) {
         sendToReceiver(F_GET_RECEIVER_FRAME_INDEX, nullptr, retval);
diff --git a/slsDetectorSoftware/src/slsDetectorCommand.cpp b/slsDetectorSoftware/src/slsDetectorCommand.cpp
index a9e9c9b99..5ba75e345 100755
--- a/slsDetectorSoftware/src/slsDetectorCommand.cpp
+++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp
@@ -596,6 +596,13 @@ slsDetectorCommand::slsDetectorCommand(multiSlsDetector *det) {
     descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdTimer;
     ++i;
 
+    /*! \page timing
+   - startingfnum [i] sets/gets starting frame number for the next acquisition. Only for Jungfrau and Eiger. \c Returns \c (long long int)
+	 */
+    descrToFuncMap[i].m_pFuncName = "startingfnum";
+    descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdTimer;
+    ++i;
+
     /*! \page timing
    - cycles [i] sets/gets number of triggers. Timing mode should be set appropriately. \c Returns \c (long long int)
 	 */
@@ -4477,6 +4484,16 @@ std::string slsDetectorCommand::cmdTimer(int narg, const char * const args[], in
         }
         sprintf(answer, "%d", myDet->setStoragecellStart(-1, detPos));
         return std::string(answer);
+    } else if (cmd == "startingfnum") {
+        myDet->setOnline(ONLINE_FLAG, detPos);
+        if (action == PUT_ACTION) {
+            uint64_t ival = -1;
+            if (!sscanf(args[1], "%lu", &ival))
+                return std::string("cannot scan starting frame number value ") + std::string(args[1]);
+            myDet->setStartingFrameNumber(ival, detPos);
+            return std::string(args[1]);
+        }
+        return std::to_string(myDet->getStartingFrameNumber(detPos));
     } else
         return std::string("could not decode timer ") + cmd;
 
@@ -4528,6 +4545,7 @@ std::string slsDetectorCommand::helpTimer(int action) {
         os << "period t \t sets the frame period in s" << std::endl;
         os << "delay t \t sets the delay after trigger in s" << std::endl;
         os << "frames t \t sets the number of frames per cycle (e.g. after each trigger)" << std::endl;
+        os << "startingfnum t \t sets starting frame number for the next acquisition. Only for Jungfrau and Eiger." << std::endl;
         os << "cycles t \t sets the number of cycles (e.g. number of triggers)" << std::endl;
         os << "samples t \t sets the number of samples (both analog and digital) expected from the ctb" << std::endl;
         os << "asamples t \t sets the number of analog samples expected from the ctb" << std::endl;
@@ -4545,6 +4563,7 @@ std::string slsDetectorCommand::helpTimer(int action) {
         os << "period  \t gets the frame period in s" << std::endl;
         os << "delay  \t gets the delay after trigger in s" << std::endl;
         os << "frames  \t gets the number of frames per cycle (e.g. after each trigger)" << std::endl;
+        os << "startingfnum \t gets starting frame number for the next acquisition. Only for Jungfrau and Eiger." << std::endl;
         os << "cycles  \t gets the number of cycles (e.g. number of triggers)" << std::endl;
         os << "samples \t gets the number of samples (both analog and digital) expected from the ctb" << std::endl;
         os << "asamples \t gets the number of analog samples expected from the ctb" << std::endl;
@@ -5078,7 +5097,7 @@ std::string slsDetectorCommand::cmdReceiver(int narg, const char * const args[],
         if (action == PUT_ACTION)
             return std::string("cannot put");
         else {
-            sprintf(answer, "%d", myDet->getReceiverCurrentFrameIndex(detPos));
+            sprintf(answer, "%lu", myDet->getReceiverCurrentFrameIndex(detPos));
             return std::string(answer);
         }
     } else if (cmd == "r_readfreq") {
diff --git a/slsReceiverSoftware/include/slsReceiverImplementation.h b/slsReceiverSoftware/include/slsReceiverImplementation.h
index d3abff1b5..576d692a7 100755
--- a/slsReceiverSoftware/include/slsReceiverImplementation.h
+++ b/slsReceiverSoftware/include/slsReceiverImplementation.h
@@ -156,9 +156,9 @@ class slsReceiverImplementation: private virtual slsDetectorDefs {
 
 	/**
 	 * Get Current Frame Index for an entire  acquisition (including all scans)
-	 * @return -1 if no frames have been caught, else current frame index (represents all scans too)
+	 * @return 0 if no frames have been caught, else average of all current frame index 
 	 */
-	int64_t getAcquisitionIndex() const;
+	uint64_t getAcquisitionIndex() const;
 
 
 	//***connection parameters***
@@ -586,7 +586,7 @@ class slsReceiverImplementation: private virtual slsDetectorDefs {
 	 * The data receiver status will change from running to idle when it gets this number of frames
 	 * @param i number of frames expected
 	 */
-	int setNumberOfFrames(const uint64_t i);
+	void setNumberOfFrames(const uint64_t i);
 
 	/**
 	 * Set Number of Analog Samples expected by receiver from detector
diff --git a/slsReceiverSoftware/src/slsReceiverImplementation.cpp b/slsReceiverSoftware/src/slsReceiverImplementation.cpp
index ca1a91da0..65c7a7106 100755
--- a/slsReceiverSoftware/src/slsReceiverImplementation.cpp
+++ b/slsReceiverSoftware/src/slsReceiverImplementation.cpp
@@ -249,7 +249,7 @@ uint64_t slsReceiverImplementation::getFramesCaught() const {
 	return (sum/dataProcessor.size());
 }
 
-int64_t slsReceiverImplementation::getAcquisitionIndex() const {
+uint64_t slsReceiverImplementation::getAcquisitionIndex() const {
 	uint64_t sum = 0;
 	uint32_t flagsum = 0;
 
@@ -259,7 +259,7 @@ int64_t slsReceiverImplementation::getAcquisitionIndex() const {
 	}
 	//no data processed
 	if (flagsum != dataProcessor.size()) 
-		return -1;
+		return 0;
 
 	return (sum/dataProcessor.size());
 }
@@ -963,13 +963,11 @@ void slsReceiverImplementation::setSubPeriod(const uint64_t i) {
 	FILE_LOG(logINFO) << "Sub Exposure Period: " <<  (double)subPeriod/(1E9) << "s";
 }
 
-int slsReceiverImplementation::setNumberOfFrames(const uint64_t i) {
+void slsReceiverImplementation::setNumberOfFrames(const uint64_t i) {
 	FILE_LOG(logDEBUG3) << __SHORT_AT__ << " called";
 
 	numberOfFrames = i;
 	FILE_LOG(logINFO) << "Number of Frames: " << numberOfFrames;
-
-	return OK;
 }
 
 
diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp
index 5cb082b2f..3692720d8 100755
--- a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp
+++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp
@@ -1205,7 +1205,7 @@ int slsReceiverTCPIPInterface::set_file_index(sls::ServerInterface2 &socket) {
 int	slsReceiverTCPIPInterface::get_frame_index(sls::ServerInterface2 &socket){
 	ret = OK;
 	memset(mess, 0, sizeof(mess));
-	int retval = -1;
+	uint64_t retval = -1;
 
 	if(receiver == nullptr){
 		NullObjectError(ret, mess);
diff --git a/slsSupportLib/include/sls_detector_funcs.h b/slsSupportLib/include/sls_detector_funcs.h
index 4b8ecb509..36f90d629 100755
--- a/slsSupportLib/include/sls_detector_funcs.h
+++ b/slsSupportLib/include/sls_detector_funcs.h
@@ -87,6 +87,8 @@ enum detFuncs{
 	F_GET_ADC_INVERT,	/** < get adc invert reg */
 	F_EXTERNAL_SAMPLING_SOURCE,	/** < set/get external sampling source for ctb */
 	F_EXTERNAL_SAMPLING,	/**< enable/disable external sampling for ctb */
+	F_SET_STARTING_FRAME_NUMBER,
+	F_GET_STARTING_FRAME_NUMBER,
 	NUM_DET_FUNCTIONS,
 
 	RECEIVER_ENUM_START = 128, /**< detector function should not exceed this (detector server should not compile anyway) */
@@ -227,7 +229,8 @@ static const char* getFunctionNameFromEnum(enum detFuncs func) {
 	case F_GET_ADC_INVERT:					return "F_GET_ADC_INVERT";
 	case F_EXTERNAL_SAMPLING_SOURCE:		return "F_EXTERNAL_SAMPLING_SOURCE";				
 	case F_EXTERNAL_SAMPLING:				return "F_EXTERNAL_SAMPLING";	
-
+	case F_SET_STARTING_FRAME_NUMBER:		return "F_SET_STARTING_FRAME_NUMBER";
+	case F_GET_STARTING_FRAME_NUMBER:		return "F_GET_STARTING_FRAME_NUMBER";
     case NUM_DET_FUNCTIONS:              	return "NUM_DET_FUNCTIONS";
     case RECEIVER_ENUM_START:				return "RECEIVER_ENUM_START";
 
diff --git a/slsSupportLib/include/versionAPI.h b/slsSupportLib/include/versionAPI.h
index c223fb436..e179ad818 100644
--- a/slsSupportLib/include/versionAPI.h
+++ b/slsSupportLib/include/versionAPI.h
@@ -5,6 +5,6 @@
 #define APILIB 0x190405
 #define APIRECEIVER 0x190405
 #define APIGUI 0x190405
-#define APIEIGER 0x190516
 #define APICTB 0x190528
-#define APIJUNGFRAU 0x190528
+#define APIEIGER 0x190531
+#define APIJUNGFRAU 0x190531
diff --git a/slsSupportLib/src/DataSocket.cpp b/slsSupportLib/src/DataSocket.cpp
index a38d821d4..4a4dc0c11 100755
--- a/slsSupportLib/src/DataSocket.cpp
+++ b/slsSupportLib/src/DataSocket.cpp
@@ -65,7 +65,7 @@ int DataSocket::setReceiveTimeout(int us) {
 
 int DataSocket::sendData(const void *buffer, size_t size) {
     int dataSent = 0;
-    while (dataSent < size) {
+    while (dataSent < (int)size) {
         dataSent +=
             write(getSocketId(), reinterpret_cast(buffer) + dataSent,
                   size - dataSent);
diff --git a/tests/include/tests/config.h b/tests/include/tests/config.h
index c62ddd3f9..5182f0430 100644
--- a/tests/include/tests/config.h
+++ b/tests/include/tests/config.h
@@ -4,9 +4,9 @@
 
 
 struct SingleDetectorConfig {
-    slsDetectorDefs::detectorType type_enum =
-        slsDetectorDefs::detectorType::CHIPTESTBOARD;
-    const std::string hostname = "bchip173";
-    const std::string type_string = "Chiptestboard";
+    slsDetectorDefs::detectorType type_enum = slsDetectorDefs::detectorType::EIGER;
+    const std::string hostname = "beb031+beb032+";
+    const std::string type_string = "Eiger";
     const std::string my_ip = "129.129.205.171";
+
 };

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 AD9257_GetMaxValidVref()) { - ret = FAIL; - sprintf(mess,"Could not set dac. Adc Vpp value should be between 0 and %d\n", AD9257_GetMaxValidVref()); - FILE_LOG(logERROR,(mess)); - } else { - AD9257_SetVrefVoltage(val); - retval = val; // cannot read - } + // set + if (val >= 0) { + ret = AD9257_SetVrefVoltage(val, mV); + if (ret == FAIL) { + sprintf(mess,"Could not set Adc Vpp. Please set a proper value\n"); + FILE_LOG(logERROR,(mess)); + } + } + retval = AD9257_GetVrefVoltage(mV); + FILE_LOG(logDEBUG1, ("Adc Vpp retval: %d %s\n", retval, (mV ? "mV" : "mode"))); + // cannot validate (its just a variable and mv gives different value) break; #endif diff --git a/slsSupportLib/include/versionAPI.h b/slsSupportLib/include/versionAPI.h index dc7f48b13..b31d1f42a 100644 --- a/slsSupportLib/include/versionAPI.h +++ b/slsSupportLib/include/versionAPI.h @@ -6,5 +6,5 @@ #define APILIB 0x190405 #define APIRECEIVER 0x190405 #define APIGUI 0x190405 -#define APICTB 0x190514 #define APIEIGER 0x190514 +#define APICTB 0x190514 From 97dd329a7bccfde29928ee2896249ae8e3e916ca Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Tue, 14 May 2019 18:57:39 +0200 Subject: [PATCH 20/76] client: zmqip bug fix (typo with strlen) --- slsDetectorSoftware/src/slsDetector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index 4b667ef6d..c3eb439a2 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -2177,7 +2177,7 @@ void slsDetector::setReceiverStreamingIP(std::string sourceIP) { memset(shm()->rxZmqip, 0, MAX_STR_LENGTH); sls::strcpy_safe(shm()->rxZmqip, args); // if zmqip is empty, update it - if (strlen(shm()->zmqip) != 0u) { + if (shm()->zmqip != 0u) { sls::strcpy_safe(shm()->zmqip, args); } FILE_LOG(logDEBUG1) << "Sending receiver streaming IP to receiver: " From bf0847e967109d23c945ba160560695226ce8512 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Wed, 15 May 2019 08:38:49 +0200 Subject: [PATCH 21/76] removed ClientInterface --- slsDetectorSoftware/include/slsDetector.h | 2 +- slsDetectorSoftware/src/slsDetector.cpp | 1 - slsSupportLib/CMakeLists.txt | 2 - slsSupportLib/include/ClientInterface.h | 70 -------------------- slsSupportLib/src/ClientInterface.cpp | 43 ------------ slsSupportLib/tests/CMakeLists.txt | 1 - slsSupportLib/tests/test-ClientInterface.cpp | 11 --- 7 files changed, 1 insertion(+), 129 deletions(-) delete mode 100755 slsSupportLib/include/ClientInterface.h delete mode 100755 slsSupportLib/src/ClientInterface.cpp delete mode 100755 slsSupportLib/tests/test-ClientInterface.cpp diff --git a/slsDetectorSoftware/include/slsDetector.h b/slsDetectorSoftware/include/slsDetector.h index 7dcc0cd87..99de817d6 100755 --- a/slsDetectorSoftware/include/slsDetector.h +++ b/slsDetectorSoftware/include/slsDetector.h @@ -6,7 +6,7 @@ #include "sls_detector_defs.h" #include "network_utils.h" #include "FixedCapacityContainer.h" -class ClientInterface; + #include #include diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index c3eb439a2..1e4f62fb0 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -1,5 +1,4 @@ #include "slsDetector.h" -#include "ClientInterface.h" #include "ClientSocket.h" #include "ServerInterface.h" #include "SharedMemory.h" diff --git a/slsSupportLib/CMakeLists.txt b/slsSupportLib/CMakeLists.txt index 7616de574..f9a0134ac 100755 --- a/slsSupportLib/CMakeLists.txt +++ b/slsSupportLib/CMakeLists.txt @@ -1,5 +1,4 @@ set(SOURCES - src/ClientInterface.cpp src/CmdLineParser.cpp src/string_utils.cpp src/file_utils.cpp @@ -22,7 +21,6 @@ set(PUBLICHEADERS include/file_utils.h include/container_utils.h include/string_utils.h - include/ClientInterface.h include/MySocketTCP.h include/genericSocket.h include/logger.h diff --git a/slsSupportLib/include/ClientInterface.h b/slsSupportLib/include/ClientInterface.h deleted file mode 100755 index 19f3cd5e3..000000000 --- a/slsSupportLib/include/ClientInterface.h +++ /dev/null @@ -1,70 +0,0 @@ -#pragma once - - -#include "sls_detector_defs.h" -#include "ClientSocket.h" - - -/** - * @short the ClientInterface class is the interface between the client and the server - */ -// Do not overload to make it easier for manual comparison between client and server functions - -class ClientInterface: public virtual slsDetectorDefs{ - -public: - - /** - * (default) constructor - * @param socket tcp socket between client and receiver - * @param n for debugging purposes (useful only for client side) - * @param t string to identify type (Detector, Receiver) for printouts (useful only for client side) - */ - ClientInterface(sls::ClientSocket* socket, int n); - - /** - * destructor - */ - virtual ~ClientInterface() = default; - - void SetSocket(sls::ClientSocket *socket){ - socket_ = socket; - } - - /** - * Receive ret, mess or retval from Server - * @param ret result of operation - * @param mess pointer to message - * @param retval pointer to retval - * @param sizeOfRetval size of retval - */ - void Client_Receive(int& ret, char* mess, void* retval, int sizeOfRetval); - - /** - * Send Arguments to server and receives result back - * @param fnum function enum to determine what parameter - * @param args pointer to arguments - * @param sizeOfArgs argument size - * @param retval pointer to return value - * @param sizeOfRetval return value size - * @param mess pointer to message if message required externally - * @returns success of operation - */ - int Client_Send(int fnum, - void* args, int sizeOfArgs, - void* retval, int sizeOfRetval, - char* mess = 0); - - - - -private: - - /** - * socket for data acquisition - */ - sls::ClientSocket* socket_; - -}; - - diff --git a/slsSupportLib/src/ClientInterface.cpp b/slsSupportLib/src/ClientInterface.cpp deleted file mode 100755 index 2d5a3c2fb..000000000 --- a/slsSupportLib/src/ClientInterface.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "ClientInterface.h" -#include "ClientSocket.h" -#include - -ClientInterface::ClientInterface(sls::ClientSocket *socket, int n) : socket_(socket){} - -void ClientInterface::Client_Receive(int &ret, char *mess, void *retval, int sizeOfRetval) { - // get result of operation - socket_->receiveData(reinterpret_cast(&ret), sizeof(ret)); - - bool unrecognizedFunction = false; - if (ret == FAIL) { - bool created = false; - // allocate mess if null - if (!mess) { - created = true; - mess = new char[MAX_STR_LENGTH]; - memset(mess, 0, MAX_STR_LENGTH); - } - // get error message - socket_->receiveData(mess, MAX_STR_LENGTH); - // cprintf(RED, "%s %d returned error: %s", type.c_str(), index, mess); - - // unrecognized function, do not ask for retval - if (strstr(mess, "Unrecognized Function") != nullptr) - unrecognizedFunction = true; - // delete allocated mess - if (created) - delete[] mess; - } - // get retval - if (!unrecognizedFunction) - socket_->receiveData(reinterpret_cast(retval), sizeOfRetval); -} - -int ClientInterface::Client_Send(int fnum, void *args, int sizeOfArgs, void *retval, - int sizeOfRetval, char *mess) { - int ret = FAIL; - socket_->sendData(reinterpret_cast(&fnum), sizeof(fnum)); - socket_->sendData(reinterpret_cast(args), sizeOfArgs); - Client_Receive(ret, mess, retval, sizeOfRetval); - return ret; -} \ No newline at end of file diff --git a/slsSupportLib/tests/CMakeLists.txt b/slsSupportLib/tests/CMakeLists.txt index e1a7e7d77..c40c80581 100755 --- a/slsSupportLib/tests/CMakeLists.txt +++ b/slsSupportLib/tests/CMakeLists.txt @@ -1,5 +1,4 @@ target_sources(tests PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/test-ClientInterface.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-CmdLineParser.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-container_utils.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-network_utils.cpp diff --git a/slsSupportLib/tests/test-ClientInterface.cpp b/slsSupportLib/tests/test-ClientInterface.cpp deleted file mode 100755 index 831ca51e8..000000000 --- a/slsSupportLib/tests/test-ClientInterface.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "ClientInterface.h" -#include "catch.hpp" - -//tests to add -//help for all docs -//command for all depreciated commands - -TEST_CASE("hopp") { - REQUIRE(true); - -} \ No newline at end of file From 9d5848d0d69af14d6c86f308f3a5d0f6416b2d0a Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Wed, 15 May 2019 09:12:14 +0200 Subject: [PATCH 22/76] inprogress --- .../include/slsReceiverTCPIPInterface.h | 4 +-- .../src/slsReceiverTCPIPInterface.cpp | 31 +++++++++---------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h b/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h index 00431f8f8..b83b73cfe 100755 --- a/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h +++ b/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h @@ -11,7 +11,7 @@ class MySocketTCP; class ServerInterface; class slsReceiverImplementation; - +#include "ServerSocket.h" /** @@ -113,7 +113,7 @@ class slsReceiverTCPIPInterface : private virtual slsDetectorDefs { int function_table(); /** Decodes Function */ - int decode_function(); + int decode_function(sls::DataSocket &socket); /** function not implemented for specific detector */ void functionNotImplemented(); diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp index 28a2f820f..fc8c0a444 100755 --- a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp +++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp @@ -5,6 +5,7 @@ #include "slsReceiverTCPIPInterface.h" #include "MySocketTCP.h" +#include "ServerSocket.h" #include "ServerInterface.h" #include "slsReceiver.h" #include "slsReceiverImplementation.h" @@ -12,11 +13,10 @@ #include "versionAPI.h" #include -#include //EXIT #include #include #include -#include //unique_ptr +#include #include #include #include @@ -24,14 +24,10 @@ slsReceiverTCPIPInterface::~slsReceiverTCPIPInterface() { stop(); - if(mySock) { - delete mySock; - mySock=nullptr; - } - - delete interface; - - delete receiver; + delete mySock; + mySock=nullptr; + delete interface; + delete receiver; } slsReceiverTCPIPInterface::slsReceiverTCPIPInterface(int pn): @@ -79,9 +75,7 @@ int slsReceiverTCPIPInterface::start(){ return FAIL; } tcpThreadCreated = true; - //#ifdef VERYVERBOSE FILE_LOG(logDEBUG) << "TCP Server thread created successfully."; - //#endif return OK; } @@ -142,10 +136,13 @@ void slsReceiverTCPIPInterface::startTCPServer(){ int ret = OK; while(true) { - if(mySock->Connect() >= 0){ - ret = decode_function(); - mySock->Disconnect(); - } + auto server = sls::ServerSocket(portNumber); + auto socket = server.accept(); + ret = decode_function(socket); + // if(mySock->Connect() >= 0){ + // ret = decode_function(); + // mySock->Disconnect(); + // } //if tcp command was to exit server if(ret == GOODBYE){ @@ -242,7 +239,7 @@ int slsReceiverTCPIPInterface::function_table(){ -int slsReceiverTCPIPInterface::decode_function(){ +int slsReceiverTCPIPInterface::decode_function(sls::DataSocket &socket){ ret = FAIL; int n = mySock->ReceiveDataOnly(&fnum,sizeof(fnum)); if (n <= 0) { From 877bdb8979bfe3322cea48774e58c6c01c046deb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Fr=C3=B6jdh?= Date: Wed, 15 May 2019 09:16:18 +0200 Subject: [PATCH 23/76] Using FixedCapacityContainer for rxDbitList (#22) * fixed capacity container * changed shm date --- slsDetectorSoftware/include/slsDetector.h | 10 +-- slsDetectorSoftware/src/slsDetector.cpp | 62 +++------------ .../src/slsReceiverTCPIPInterface.cpp | 79 +++++++------------ .../include/FixedCapacityContainer.h | 2 + slsSupportLib/include/sls_detector_defs.h | 1 + .../tests/test-FixedCapacityContainer.cpp | 13 +++ 6 files changed, 60 insertions(+), 107 deletions(-) diff --git a/slsDetectorSoftware/include/slsDetector.h b/slsDetectorSoftware/include/slsDetector.h index 99de817d6..419fe5b5d 100755 --- a/slsDetectorSoftware/include/slsDetector.h +++ b/slsDetectorSoftware/include/slsDetector.h @@ -16,8 +16,8 @@ class multiSlsDetector; class ServerInterface; -#define SLS_SHMVERSION 0x190503 -#define MAX_RX_DBIT 64 +#define SLS_SHMVERSION 0x190515 + /** @@ -241,11 +241,7 @@ struct sharedSlsDetector { /** overwrite enable */ bool rxFileOverWrite; - /** receiver dbit size */ - int rxDbitListSize; - - /** receiver dbit list */ - int rxDbitList[MAX_RX_DBIT]; + sls::FixedCapacityContainer rxDbitList; /** reciever dbit offset */ int rxDbitOffset; diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index 1e4f62fb0..d505b3eba 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -387,8 +387,6 @@ void slsDetector::initializeDetectorStructure(detectorType type) { shm()->rxFileWrite = true; shm()->rxMasterFileWrite = true; shm()->rxFileOverWrite = true; - shm()->rxDbitListSize = 0; - memset(shm()->rxDbitList, 0, MAX_RX_DBIT * sizeof(int)); shm()->rxDbitOffset = 0; // get the detector parameters based on type @@ -1905,7 +1903,7 @@ std::string slsDetector::setReceiverHostname(const std::string &receiverIP) { << "\nrx streaming source ip:" << shm()->rxZmqip << "\nrx additional json header:" << shm()->rxAdditionalJsonHeader << "\nrx_datastream:" << enableDataStreamingFromReceiver(-1) - << "\nrx_dbitlistsize:" << shm()->rxDbitListSize + << "\nrx_dbitlistsize:" << shm()->rxDbitList.size() << "\nrx_DbitOffset:" << shm()->rxDbitOffset << std::endl; @@ -1972,8 +1970,7 @@ std::string slsDetector::setReceiverHostname(const std::string &receiverIP) { } if (shm()->myDetectorType == CHIPTESTBOARD) { - std::vector list(shm()->rxDbitList, shm()->rxDbitList + shm()->rxDbitListSize); - setReceiverDbitList(list); + setReceiverDbitList(shm()->rxDbitList); } setReceiverSilentMode(static_cast(shm()->rxSilentMode)); @@ -2729,51 +2726,20 @@ void slsDetector::setReceiverDbitList(std::vector list) { throw sls::RuntimeError("Dbit list value must be between 0 and 63\n"); } } - - // copy size and vector to shm - shm()->rxDbitListSize = list.size(); - std::copy(list.begin(), list.end(), shm()->rxDbitList); - + shm()->rxDbitList = list; if (shm()->rxOnlineFlag == ONLINE_FLAG) { - int args[list.size() + 1]; - args[0] = list.size(); - std::copy(std::begin(list), std::end(list), args + 1); - sendToReceiver(F_SET_RECEIVER_DBIT_LIST, args, sizeof(args), nullptr, 0); + sendToReceiver(F_SET_RECEIVER_DBIT_LIST, shm()->rxDbitList, nullptr); } } std::vector slsDetector::getReceiverDbitList() { - int fnum = F_GET_RECEIVER_DBIT_LIST; - int ret = FAIL; - std::vector retval; - int retsize = 0; + sls::FixedCapacityContainer retval; FILE_LOG(logDEBUG1) << "Getting Receiver Dbit List"; if (shm()->rxOnlineFlag == ONLINE_FLAG) { - auto receiver = - sls::ClientSocket("Receiver", shm()->rxHostname, shm()->rxTCPPort); - receiver.sendData(&fnum, sizeof(fnum)); - receiver.receiveData(&ret, sizeof(ret)); - if (ret == FAIL) { - char mess[MAX_STR_LENGTH]{}; - receiver.receiveData(mess, MAX_STR_LENGTH); - throw ReceiverError("Receiver " + std::to_string(detId) + - " returned error: " + std::string(mess)); - } - receiver.receiveData(&retsize, sizeof(retsize)); - int list[retsize]; - receiver.receiveData(list, sizeof(list)); - - // copy after no errors - shm()->rxDbitListSize = retsize; - std::copy(list, list + retsize, shm()->rxDbitList); + sendToReceiver(F_GET_RECEIVER_DBIT_LIST, nullptr, retval); + shm()->rxDbitList = retval; } - - if (shm()->rxDbitListSize) { - retval.resize(shm()->rxDbitListSize); - std::copy(shm()->rxDbitList, shm()->rxDbitList + shm()->rxDbitListSize, std::begin(retval)); - } - - return retval; + return shm()->rxDbitList; } int slsDetector::setReceiverDbitOffset(int value) { @@ -3420,15 +3386,11 @@ int slsDetector::updateCachedReceiverVariables() const { n += receiver.receiveData(&i32, sizeof(i32)); shm()->rxSilentMode = static_cast(i32); - // dbit list size + // dbit list { - int listsize = 0; - n += receiver.receiveData(&listsize, sizeof(listsize)); - int list[listsize]; - n += receiver.receiveData(list, sizeof(list)); - // copy after no errors - shm()->rxDbitListSize = listsize; - std::copy(list, list + listsize, shm()->rxDbitList); + sls::FixedCapacityContainer temp; + n += receiver.receiveData(&temp, sizeof(temp)); + shm()->rxDbitList = temp; } // dbit offset diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp index 28a2f820f..24e5b31af 100755 --- a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp +++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp @@ -3,11 +3,13 @@ * @short interface between receiver and client ***********************************************/ -#include "slsReceiverTCPIPInterface.h" + +#include "FixedCapacityContainer.h" #include "MySocketTCP.h" #include "ServerInterface.h" #include "slsReceiver.h" #include "slsReceiverImplementation.h" +#include "slsReceiverTCPIPInterface.h" #include "slsReceiverUsers.h" #include "versionAPI.h" @@ -2134,52 +2136,36 @@ int slsReceiverTCPIPInterface::set_adc_mask() { return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); } - - int slsReceiverTCPIPInterface::set_dbit_list() { - ret = OK; - memset(mess, 0, sizeof(mess)); + ret = OK; + memset(mess, 0, sizeof(mess)); + sls::FixedCapacityContainer args; + if (interface->Server_ReceiveArg(ret, mess, &args, sizeof(args), true, receiver) == FAIL) { + return FAIL; + } else if (ret == OK) { + FILE_LOG(logDEBUG1) << "Setting DBIT list"; + for (auto &it : args) { + FILE_LOG(logDEBUG1) << it << " "; + } + FILE_LOG(logDEBUG1) << "\n"; + if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (args.size() > 64) { + ret = FAIL; + sprintf(mess, "Could not set dbit list as size is > 64\n"); + FILE_LOG(logERROR) << mess; + } else + receiver->setDbitList(args); + } - // receive arguments - int narg = -1; - if (mySock->ReceiveDataOnly(&narg,sizeof(narg)) < 0 ) - return interface->Server_SocketCrash(); - int narglist[narg]; - if (mySock->ReceiveDataOnly(narglist, narg * sizeof(int)) < 0 ) - return interface->Server_SocketCrash(); - std::vector arg(narglist, narglist + narg); - - FILE_LOG(logDEBUG1) << "Setting DBIT list"; - for (auto &it : arg) { - FILE_LOG(logDEBUG1) << it << " "; - } - FILE_LOG(logDEBUG1) << "\n"; - - // base object not null - if (receiver == nullptr) - interface->Server_NullObjectError(ret, mess); - else { - // only set - // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { - if (arg.size() > 64) { - ret = FAIL; - sprintf(mess, "Could not set dbit list as size is > 64\n"); - FILE_LOG(logERROR) << mess; - } else - receiver->setDbitList(arg); - } - } - - return interface->Server_SendResult(true, ret, nullptr, 0, mess); + + } + return interface->Server_SendResult(true, ret, nullptr, 0, mess); } - - int slsReceiverTCPIPInterface::get_dbit_list() { ret = OK; memset(mess, 0, sizeof(mess)); - std::vector list; + sls::FixedCapacityContainer retval; // no arg, check receiver is null interface->Server_ReceiveArg(ret, mess, nullptr, 0, true, receiver); @@ -2187,17 +2173,10 @@ int slsReceiverTCPIPInterface::get_dbit_list() { // base object not null if (ret == OK) { // get - list = receiver->getDbitList(); - FILE_LOG(logDEBUG1) << "Dbit list size retval:" << list.size(); + retval = receiver->getDbitList(); + FILE_LOG(logDEBUG1) << "Dbit list size retval:" << retval.size(); } - - interface->Server_SendResult(false, ret, nullptr, 0, mess); - int retvalsize = list.size(); - int retval[retvalsize]; - std::copy(std::begin(list), std::end(list), retval); - mySock->SendDataOnly(&retvalsize, sizeof(retvalsize)); - mySock->SendDataOnly(retval, sizeof(retval)); - return ret; + return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); } diff --git a/slsSupportLib/include/FixedCapacityContainer.h b/slsSupportLib/include/FixedCapacityContainer.h index 4b39d52db..d53136baa 100644 --- a/slsSupportLib/include/FixedCapacityContainer.h +++ b/slsSupportLib/include/FixedCapacityContainer.h @@ -20,6 +20,8 @@ template class FixedCapacityContainer { bool operator==(const std::vector &other) const noexcept; bool operator!=(const std::vector &other) const noexcept; + operator std::vector(){return std::vector(begin(), end());} + template bool operator==(const FixedCapacityContainer &other) const noexcept; diff --git a/slsSupportLib/include/sls_detector_defs.h b/slsSupportLib/include/sls_detector_defs.h index c903d24a9..bf14a3545 100755 --- a/slsSupportLib/include/sls_detector_defs.h +++ b/slsSupportLib/include/sls_detector_defs.h @@ -24,6 +24,7 @@ #include "ansi.h" #define BIT32_MASK 0xFFFFFFFF +#define MAX_RX_DBIT 64 /** default ports */ #define DEFAULT_PORTNO 1952 diff --git a/slsSupportLib/tests/test-FixedCapacityContainer.cpp b/slsSupportLib/tests/test-FixedCapacityContainer.cpp index 9277df258..d4853cab7 100644 --- a/slsSupportLib/tests/test-FixedCapacityContainer.cpp +++ b/slsSupportLib/tests/test-FixedCapacityContainer.cpp @@ -215,3 +215,16 @@ SCENARIO("Assigning containers to each other", "[support]") { } } +SCENARIO("Converting to vector", "[support]"){ + GIVEN("a FixedCapacityContainer"){ + FixedCapacityContainer a{1,2,3}; + WHEN("Converted into a vector"){ + std::vector b(a); + THEN("Data and size matches"){ + REQUIRE(a == b); + REQUIRE(a.size() == b.size()); + } + } + } +} + From 8f8d565e4eeaa52d4cb642475913ebd97e6ba122 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Wed, 15 May 2019 10:09:54 +0200 Subject: [PATCH 24/76] work --- slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp index 36c2ea220..021cb1f36 100755 --- a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp +++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp @@ -243,7 +243,8 @@ int slsReceiverTCPIPInterface::function_table(){ int slsReceiverTCPIPInterface::decode_function(sls::DataSocket &socket){ ret = FAIL; - int n = mySock->ReceiveDataOnly(&fnum,sizeof(fnum)); + // int n = mySock->ReceiveDataOnly(&fnum,sizeof(fnum)); + int n = socket.receiveData(&fnum, sizeof(fnum)); if (n <= 0) { FILE_LOG(logDEBUG3) << "Could not read socket. " "Received " << n << " bytes," << From f1a1391866c34d346c7ccfe1ead73011fc0ef67c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Fr=C3=B6jdh?= Date: Wed, 15 May 2019 10:22:38 +0200 Subject: [PATCH 25/76] Factored out time conversion (#23) * time conversion * with comment * lround in slsDetectorCommand --- .../include/multiSlsDetector.h | 24 ++++--- slsDetectorSoftware/src/multiSlsDetector.cpp | 71 +++++-------------- .../src/slsDetectorCommand.cpp | 6 +- 3 files changed, 35 insertions(+), 66 deletions(-) diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 2a945e38a..1ebec7292 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -2146,14 +2146,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { - /** - * add gap pixels to the image (only for Eiger in 4 bit mode) - * @param image pointer to image without gap pixels - * @param gpImage poiner to image with gap pixels, if NULL, allocated - * inside function - * @returns number of data bytes of image with gap pixels - */ - int processImageWithGapPixels(char *image, char *&gpImage); + /** + * add gap pixels to the image (only for Eiger in 4 bit mode) + * @param image pointer to image without gap pixels + * @param gpImage poiner to image with gap pixels, if NULL, allocated + * inside function + * @returns number of data bytes of image with gap pixels + */ + int processImageWithGapPixels(char *image, char *&gpImage); /** * Set total progress (total number of frames/images in an acquisition) @@ -2209,6 +2209,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ std::vector readPofFile(const std::string &fname); + /** + * Convert a double holding time in seconds to an int64_t with nano seconds + * Used for conversion when sending time to detector + * @param t time in seconds + * @returns time in nano seconds + */ + int64_t secondsToNanoSeconds(double t); + /** Multi detector Id */ const int multiId{0}; diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index 6da911c14..76a1b212f 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -1099,89 +1099,50 @@ int64_t multiSlsDetector::setTimer(timerIndex index, int64_t t, int detPos) { return ret; } +int64_t multiSlsDetector::secondsToNanoSeconds(double t){ + int64_t ns = lround(t * 1E9); + return (ns < 0) ? -1: ns; +} + double multiSlsDetector::setExposureTime(double t, bool inseconds, int detPos) { if (!inseconds) { return setTimer(ACQUISITION_TIME, (int64_t)t, detPos); } - - // + 0.5 to round for precision lost from converting double to int64_t - int64_t tms = (int64_t)(t * (1E+9) + 0.5); - if (t < 0) { - tms = -1; - } - tms = setTimer(ACQUISITION_TIME, tms, detPos); - if (tms < 0) { - return -1; - } - return ((1E-9) * (double)tms); + auto t_ns = setTimer(ACQUISITION_TIME, secondsToNanoSeconds(t), detPos); + return (t_ns < 0) ? -1 : 1E-9 * t_ns; } double multiSlsDetector::setExposurePeriod(double t, bool inseconds, int detPos) { if (!inseconds) { return setTimer(FRAME_PERIOD, (int64_t)t, detPos); } - - // + 0.5 to round for precision lost from converting double to int64_t - int64_t tms = (int64_t)(t * (1E+9) + 0.5); - if (t < 0) { - tms = -1; - } - tms = setTimer(FRAME_PERIOD, tms, detPos); - if (tms < 0) { - return -1; - } - return ((1E-9) * (double)tms); + auto t_ns = setTimer(FRAME_PERIOD, secondsToNanoSeconds(t), detPos); + return (t_ns < 0) ? -1 : 1E-9 * t_ns; } double multiSlsDetector::setDelayAfterTrigger(double t, bool inseconds, int detPos) { if (!inseconds) { return setTimer(DELAY_AFTER_TRIGGER, (int64_t)t, detPos); } - - // + 0.5 to round for precision lost from converting double to int64_t - int64_t tms = (int64_t)(t * (1E+9) + 0.5); - if (t < 0) { - tms = -1; - } - tms = setTimer(DELAY_AFTER_TRIGGER, tms, detPos); - if (tms < 0) { - return -1; - } - return ((1E-9) * (double)tms); + auto t_ns = setTimer(DELAY_AFTER_TRIGGER, secondsToNanoSeconds(t), detPos); + return (t_ns < 0) ? -1 : 1E-9 * t_ns; } double multiSlsDetector::setSubFrameExposureTime(double t, bool inseconds, int detPos) { if (!inseconds) { return setTimer(SUBFRAME_ACQUISITION_TIME, (int64_t)t, detPos); - } else { - // + 0.5 to round for precision lost from converting double to int64_t - int64_t tms = (int64_t)(t * (1E+9) + 0.5); - if (t < 0) { - tms = -1; - } - tms = setTimer(SUBFRAME_ACQUISITION_TIME, tms, detPos); - if (tms < 0) { - return -1; - } - return ((1E-9) * (double)tms); } + auto t_ns = setTimer(SUBFRAME_ACQUISITION_TIME, secondsToNanoSeconds(t), detPos); + return (t_ns < 0) ? -1 : 1E-9 * t_ns; } double multiSlsDetector::setSubFrameExposureDeadTime(double t, bool inseconds, int detPos) { if (!inseconds) { return setTimer(SUBFRAME_DEADTIME, (int64_t)t, detPos); - } else { - // + 0.5 to round for precision lost from converting double to int64_t - int64_t tms = (int64_t)(t * (1E+9) + 0.5); - if (t < 0) { - tms = -1; - } - tms = setTimer(SUBFRAME_DEADTIME, tms, detPos); - if (tms < 0) { - return -1; - } - return ((1E-9) * (double)tms); } + auto t_ns = setTimer(SUBFRAME_DEADTIME, secondsToNanoSeconds(t), detPos); + return (t_ns < 0) ? -1 : 1E-9 * t_ns; + } int64_t multiSlsDetector::setNumberOfFrames(int64_t t, int detPos) { diff --git a/slsDetectorSoftware/src/slsDetectorCommand.cpp b/slsDetectorSoftware/src/slsDetectorCommand.cpp index 4306b6d61..4208c0c25 100755 --- a/slsDetectorSoftware/src/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp @@ -3,6 +3,7 @@ #include "string_utils.h" #include +#include #include #include #include @@ -4496,10 +4497,9 @@ std::string slsDetectorCommand::cmdTimer(int narg, char *args[], int action, int if (index == ACQUISITION_TIME || index == SUBFRAME_ACQUISITION_TIME || index == FRAME_PERIOD || index == DELAY_AFTER_TRIGGER || index == SUBFRAME_DEADTIME || index == STORAGE_CELL_DELAY) { - // +0.5 for precision of eg.0.0000325 - t = (val * 1E9 + 0.5); + t = lround(val * 1E9); } else - t = (int64_t)val; + t = static_cast(val); } myDet->setOnline(ONLINE_FLAG, detPos); From 40c2d9f760d415136be4ef9e3bfe552d16631e8c Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Wed, 15 May 2019 12:17:32 +0200 Subject: [PATCH 26/76] try for accept --- .../include/slsReceiverTCPIPInterface.h | 4 +- .../src/slsReceiverTCPIPInterface.cpp | 104 ++++++++++-------- slsSupportLib/include/DataSocket.h | 2 + slsSupportLib/include/logger.h | 4 +- slsSupportLib/src/DataSocket.cpp | 16 ++- slsSupportLib/src/ServerSocket.cpp | 4 +- 6 files changed, 83 insertions(+), 51 deletions(-) diff --git a/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h b/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h index b83b73cfe..d3f6851cb 100755 --- a/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h +++ b/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h @@ -126,7 +126,7 @@ class slsReceiverTCPIPInterface : private virtual slsDetectorDefs { void validate(T arg, T retval, std::string modename, numberMode hex); /** Unrecognized Function */ - int M_nofunc(); + int M_nofunc(sls::DataSocket & socket); @@ -386,6 +386,8 @@ protected: /** Socket */ MySocketTCP* mySock; + std::unique_ptr server{nullptr}; + /** client interface */ ServerInterface* interface; }; diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp index 021cb1f36..7446dd801 100755 --- a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp +++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp @@ -55,13 +55,13 @@ slsReceiverTCPIPInterface::slsReceiverTCPIPInterface(int pn): // create socket portNumber = (pn > 0 ? pn : DEFAULT_PORTNO + 2); - MySocketTCP* m = new MySocketTCP(portNumber); - mySock = m; - interface = new ServerInterface(mySock, -1, "Receiver"); + // MySocketTCP* m = new MySocketTCP(portNumber); + // mySock = m; + // interface = new ServerInterface(mySock, -1, "Receiver"); //initialize variables - strcpy(mySock->lastClientIP,"none"); - strcpy(mySock->thisClientIP,"none1"); + // strcpy(mySock->lastClientIP,"none"); + // strcpy(mySock->thisClientIP,"none1"); memset(mess,0,sizeof(mess)); strcpy(mess,"dummy message"); @@ -86,7 +86,9 @@ void slsReceiverTCPIPInterface::stop(){ if (tcpThreadCreated) { FILE_LOG(logINFO) << "Shutting down TCP Socket on port " << portNumber; killTCPServerThread = 1; - if(mySock) mySock->ShutDownSocket(); + // if(mySock) mySock->ShutDownSocket(); + if(server) + server->shutDownSocket(); FILE_LOG(logDEBUG) << "TCP Socket closed on port " << portNumber; pthread_join(TCPServer_thread, nullptr); tcpThreadCreated = false; @@ -131,49 +133,56 @@ void* slsReceiverTCPIPInterface::startTCPServerThread(void *this_pointer){ return this_pointer; } +void slsReceiverTCPIPInterface::startTCPServer() { + FILE_LOG(logINFOBLUE) << "Created [ TCP server Tid: " << syscall(SYS_gettid) + << "]"; + ; + FILE_LOG(logINFO) << "SLS Receiver starting TCP Server on port " + << portNumber << std::endl; + int ret = OK; -void slsReceiverTCPIPInterface::startTCPServer(){ - FILE_LOG(logINFOBLUE) << "Created [ TCP server Tid: " << syscall(SYS_gettid) << "]";; - FILE_LOG(logINFO) << "SLS Receiver starting TCP Server on port " << portNumber << std::endl; - int ret = OK; + server = sls::make_unique(portNumber); + while (true) { - while(true) { - auto server = sls::ServerSocket(portNumber); - auto socket = server.accept(); - ret = decode_function(socket); - // if(mySock->Connect() >= 0){ - // ret = decode_function(); - // mySock->Disconnect(); - // } + try { + auto socket = server->accept(); + ret = decode_function(socket); + // if(mySock->Connect() >= 0){ + // ret = decode_function(); + // mySock->Disconnect(); + // } - //if tcp command was to exit server - if(ret == GOODBYE){ - FILE_LOG(logINFO) << "Shutting down UDP Socket"; - if(receiver){ - receiver->shutDownUDPSockets(); - } + // if tcp command was to exit server + if (ret == GOODBYE) { + FILE_LOG(logINFO) << "Shutting down UDP Socket"; + if (receiver) { + receiver->shutDownUDPSockets(); + } - mySock->exitServer(); - FILE_LOG(logINFOBLUE) << "Exiting [ TCP server Tid: " << syscall(SYS_gettid) <<"]"; - pthread_exit(nullptr); + mySock->exitServer(); + FILE_LOG(logINFOBLUE) + << "Exiting [ TCP server Tid: " << syscall(SYS_gettid) + << "]"; + pthread_exit(nullptr); + } + }catch(const sls::SocketError& e){ + std::cout << "Accept failed\n"; } - //if user entered exit - if(killTCPServerThread) { - if (ret != GOODBYE) { - if(receiver){ - receiver->shutDownUDPSockets(); - } - } - FILE_LOG(logINFOBLUE) << "Exiting [ TCP server Tid: " << syscall(SYS_gettid) <<"]"; - pthread_exit(nullptr); - } - } + // if user entered exit + if (killTCPServerThread) { + if (ret != GOODBYE) { + if (receiver) { + receiver->shutDownUDPSockets(); + } + } + FILE_LOG(logINFOBLUE) + << "Exiting [ TCP server Tid: " << syscall(SYS_gettid) << "]"; + pthread_exit(nullptr); + } + } } - - - int slsReceiverTCPIPInterface::function_table(){ flist[F_EXEC_RECEIVER_COMMAND] = &slsReceiverTCPIPInterface::exec_command; flist[F_EXIT_RECEIVER] = &slsReceiverTCPIPInterface::exit_server; @@ -257,7 +266,7 @@ int slsReceiverTCPIPInterface::decode_function(sls::DataSocket &socket){ if (fnum <= NUM_DET_FUNCTIONS || fnum >= NUM_REC_FUNCTIONS) { FILE_LOG(logERROR) << "Unknown function enum " << fnum; - ret = (this->M_nofunc)(); + ret = (this->M_nofunc)(socket); } else{ FILE_LOG(logDEBUG1) << "calling function fnum: "<< fnum << " " "(" << getFunctionNameFromEnum((enum detFuncs)fnum) << ") " @@ -301,18 +310,23 @@ void slsReceiverTCPIPInterface::validate(T arg, T retval, std::string modename, } } -int slsReceiverTCPIPInterface::M_nofunc(){ +int slsReceiverTCPIPInterface::M_nofunc(sls::DataSocket &socket){ ret = FAIL; memset(mess, 0, sizeof(mess)); // to receive any arguments + + socket.setReceiveTimeout(500); int n = 1; while (n > 0) - n = mySock->ReceiveDataOnly(mess, MAX_STR_LENGTH); + n = socket.read(mess, MAX_STR_LENGTH); sprintf(mess,"Unrecognized Function enum %d. Please do not proceed.\n", fnum); FILE_LOG(logERROR) << mess; - return interface->Server_SendResult(false, ret, nullptr, 0, mess); + socket.sendData(&ret, sizeof(ret)); + socket.sendData(mess, sizeof(mess)); + return 0; + // return interface->Server_SendResult(false, ret, nullptr, 0, mess); } diff --git a/slsSupportLib/include/DataSocket.h b/slsSupportLib/include/DataSocket.h index a4ad27fe1..a9e7dcc6e 100755 --- a/slsSupportLib/include/DataSocket.h +++ b/slsSupportLib/include/DataSocket.h @@ -20,7 +20,9 @@ class DataSocket { } size_t sendData(const void *buffer, size_t size); size_t receiveData(void *buffer, size_t size); + size_t read(void *buffer, size_t size); int setTimeOut(int t_seconds); + int setReceiveTimeout(int us); void close(); void shutDownSocket(); diff --git a/slsSupportLib/include/logger.h b/slsSupportLib/include/logger.h index 8de0c2f49..541da95b0 100755 --- a/slsSupportLib/include/logger.h +++ b/slsSupportLib/include/logger.h @@ -17,8 +17,8 @@ #endif #ifndef FILELOG_MAX_LEVEL -#define FILELOG_MAX_LEVEL logINFO -// #define FILELOG_MAX_LEVEL logDEBUG5 +// #define FILELOG_MAX_LEVEL logINFO +#define FILELOG_MAX_LEVEL logDEBUG5 #endif diff --git a/slsSupportLib/src/DataSocket.cpp b/slsSupportLib/src/DataSocket.cpp index 1af3db89f..3da9cbf75 100755 --- a/slsSupportLib/src/DataSocket.cpp +++ b/slsSupportLib/src/DataSocket.cpp @@ -9,6 +9,7 @@ #include #include #include +#include namespace sls { @@ -43,12 +44,25 @@ size_t DataSocket::receiveData(void *buffer, size_t size) { size_t dataRead = 0; while (dataRead < size) { dataRead += - read(getSocketId(), reinterpret_cast(buffer) + dataRead, + ::read(getSocketId(), reinterpret_cast(buffer) + dataRead, size - dataRead); } return dataRead; } +size_t DataSocket::read(void *buffer, size_t size){ + return ::read(getSocketId(), reinterpret_cast(buffer), size); +} + +int DataSocket::setReceiveTimeout(int us) { + timeval t{}; + t.tv_sec = 0; + t.tv_usec = us; + return ::setsockopt(getSocketId(), SOL_SOCKET, SO_RCVTIMEO, &t, + sizeof(struct timeval)); +} + + size_t DataSocket::sendData(const void *buffer, size_t size) { size_t dataSent = 0; while (dataSent < size) { diff --git a/slsSupportLib/src/ServerSocket.cpp b/slsSupportLib/src/ServerSocket.cpp index 0876c212c..7f07b49fc 100755 --- a/slsSupportLib/src/ServerSocket.cpp +++ b/slsSupportLib/src/ServerSocket.cpp @@ -27,7 +27,7 @@ ServerSocket::ServerSocket(int port) if (bind(getSocketId(), (struct sockaddr *)&serverAddr, sizeof(serverAddr)) != 0) { close(); - throw std::runtime_error("Server ERROR: cannot bind socket"); + throw sls::SocketError("Server ERROR: cannot bind socket"); } if (listen(getSocketId(), DEFAULT_BACKLOG) != 0) { close(); @@ -41,7 +41,7 @@ DataSocket ServerSocket::accept() { int newSocket = ::accept(getSocketId(), (struct sockaddr *)&clientAddr, &addr_size); if (newSocket == -1) { - throw std::runtime_error("Server ERROR: socket accept failed\n"); + throw sls::SocketError("Server ERROR: socket accept failed\n"); } inet_ntop(AF_INET, &(clientAddr.sin_addr), &thisClient_.front(), INET_ADDRSTRLEN); From e252b8e0e9ebcb336ff2c3175399f35553063ce5 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Wed, 15 May 2019 17:51:48 +0200 Subject: [PATCH 27/76] receiver socket --- .../include/slsReceiverTCPIPInterface.h | 122 ++-- .../src/slsReceiverTCPIPInterface.cpp | 563 +++++++++--------- slsSupportLib/CMakeLists.txt | 1 + slsSupportLib/include/ServerInterface2.h | 28 + slsSupportLib/include/ServerSocket.h | 17 +- slsSupportLib/include/network_utils.h | 1 + slsSupportLib/src/ServerInterface2.cpp | 32 + slsSupportLib/src/ServerSocket.cpp | 17 +- slsSupportLib/src/network_utils.cpp | 1 + 9 files changed, 440 insertions(+), 342 deletions(-) create mode 100644 slsSupportLib/include/ServerInterface2.h create mode 100644 slsSupportLib/src/ServerInterface2.cpp diff --git a/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h b/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h index d3f6851cb..292b74bbd 100755 --- a/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h +++ b/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h @@ -113,7 +113,7 @@ class slsReceiverTCPIPInterface : private virtual slsDetectorDefs { int function_table(); /** Decodes Function */ - int decode_function(sls::DataSocket &socket); + int decode_function(sls::ServerInterface2 &socket); /** function not implemented for specific detector */ void functionNotImplemented(); @@ -126,177 +126,177 @@ class slsReceiverTCPIPInterface : private virtual slsDetectorDefs { void validate(T arg, T retval, std::string modename, numberMode hex); /** Unrecognized Function */ - int M_nofunc(sls::DataSocket & socket); + int M_nofunc(sls::ServerInterface2 & socket); /** Execute command */ - int exec_command(); + int exec_command(sls::ServerInterface2 &socket); /** Exit Receiver Server */ - int exit_server(); + int exit_server(sls::ServerInterface2 &socket); /** Locks Receiver */ - int lock_receiver(); + int lock_receiver(sls::ServerInterface2 &socket); /** Get Last Client IP*/ - int get_last_client_ip(); + int get_last_client_ip(sls::ServerInterface2 &socket); /** Set port */ - int set_port(); + int set_port(sls::ServerInterface2 &socket); /** Updates Client if different clients connect */ - int update_client(); + int update_client(sls::ServerInterface2 &socket); /** Sends the updated parameters to client */ - int send_update(); + int send_update(sls::ServerInterface2 &socket); /** get version, calls get_version */ - int get_id(); + int get_id(sls::ServerInterface2 &socket); /** Set detector type */ - int set_detector_type(); + int set_detector_type(sls::ServerInterface2 &socket); /** set detector hostname */ - int set_detector_hostname(); + int set_detector_hostname(sls::ServerInterface2 &socket); /** set roi */ - int set_roi(); + int set_roi(sls::ServerInterface2 &socket); /** Set up UDP Details */ - int setup_udp(); + int setup_udp(sls::ServerInterface2 &socket); /** set acquisition period, frame number etc */ - int set_timer(); + int set_timer(sls::ServerInterface2 &socket); /** set dynamic range */ - int set_dynamic_range(); + int set_dynamic_range(sls::ServerInterface2 &socket); /** Sets the receiver streaming frequency */ - int set_streaming_frequency(); + int set_streaming_frequency(sls::ServerInterface2 &socket); /** Gets receiver status */ - int get_status(); + int get_status(sls::ServerInterface2 &socket); /** Start Receiver - starts listening to udp packets from detector */ - int start_receiver(); + int start_receiver(sls::ServerInterface2 &socket); /** Stop Receiver - stops listening to udp packets from detector*/ - int stop_receiver(); + int stop_receiver(sls::ServerInterface2 &socket); /** Set File path */ - int set_file_dir(); + int set_file_dir(sls::ServerInterface2 &socket); /** Set File name without frame index, file index and extension */ - int set_file_name(); + int set_file_name(sls::ServerInterface2 &socket); /** Set File index */ - int set_file_index(); + int set_file_index(sls::ServerInterface2 &socket); /** Gets frame index for each acquisition */ - int get_frame_index(); + int get_frame_index(sls::ServerInterface2 &socket); /** Gets Total Frames Caught */ - int get_frames_caught(); + int get_frames_caught(sls::ServerInterface2 &socket); /** Resets Total Frames Caught */ - int reset_frames_caught(); + int reset_frames_caught(sls::ServerInterface2 &socket); /** Enable File Write*/ - int enable_file_write(); + int enable_file_write(sls::ServerInterface2 &socket); /** Enable Master File Write */ - int enable_master_file_write(); + int enable_master_file_write(sls::ServerInterface2 &socket); /** enable compression */ - int enable_compression(); + int enable_compression(sls::ServerInterface2 &socket); /** enable overwrite */ - int enable_overwrite(); + int enable_overwrite(sls::ServerInterface2 &socket); /** enable 10Gbe */ - int enable_tengiga(); + int enable_tengiga(sls::ServerInterface2 &socket); /** set fifo depth */ - int set_fifo_depth(); + int set_fifo_depth(sls::ServerInterface2 &socket); /** activate/ deactivate */ - int set_activate(); + int set_activate(sls::ServerInterface2 &socket); /* Set the data stream enable */ - int set_data_stream_enable(); + int set_data_stream_enable(sls::ServerInterface2 &socket); /** Sets the steadming timer when frequency is set to 0 */ - int set_streaming_timer(); + int set_streaming_timer(sls::ServerInterface2 &socket); /** enable flipped data */ - int set_flipped_data(); + int set_flipped_data(sls::ServerInterface2 &socket); /** set file format */ - int set_file_format(); + int set_file_format(sls::ServerInterface2 &socket); /** set position id */ - int set_detector_posid(); + int set_detector_posid(sls::ServerInterface2 &socket); /** set multi detector size */ - int set_multi_detector_size(); + int set_multi_detector_size(sls::ServerInterface2 &socket); /** set streaming port */ - int set_streaming_port(); + int set_streaming_port(sls::ServerInterface2 &socket); /** set streaming source ip */ - int set_streaming_source_ip(); + int set_streaming_source_ip(sls::ServerInterface2 &socket); /** set silent mode */ - int set_silent_mode(); + int set_silent_mode(sls::ServerInterface2 &socket); /** enable gap pixels */ - int enable_gap_pixels(); + int enable_gap_pixels(sls::ServerInterface2 &socket); /** restream stop packet */ - int restream_stop(); + int restream_stop(sls::ServerInterface2 &socket); /** set additional json header */ - int set_additional_json_header(); + int set_additional_json_header(sls::ServerInterface2 &socket); /** get additional json header */ - int get_additional_json_header(); + int get_additional_json_header(sls::ServerInterface2 &socket); /** set udp socket buffer size */ - int set_udp_socket_buffer_size(); + int set_udp_socket_buffer_size(sls::ServerInterface2 &socket); /** get real udp socket buffer size */ - int get_real_udp_socket_buffer_size(); + int get_real_udp_socket_buffer_size(sls::ServerInterface2 &socket); /** set frames per file */ - int set_frames_per_file(); + int set_frames_per_file(sls::ServerInterface2 &socket); /** check version compatibility */ - int check_version_compatibility(); + int check_version_compatibility(sls::ServerInterface2 &socket); /** set frame discard policy */ - int set_discard_policy(); + int set_discard_policy(sls::ServerInterface2 &socket); /** set partial frame padding enable*/ - int set_padding_enable(); + int set_padding_enable(sls::ServerInterface2 &socket); /** set deactivated receiver padding enable */ - int set_deactivated_padding_enable(); + int set_deactivated_padding_enable(sls::ServerInterface2 &socket); /** set readout flags */ - int set_readout_flags(); + int set_readout_flags(sls::ServerInterface2 &socket); /** set adc mask */ - int set_adc_mask(); + int set_adc_mask(sls::ServerInterface2 &socket); /** set receiver dbit list */ - int set_dbit_list(); + int set_dbit_list(sls::ServerInterface2 &socket); /** get receiver dbit list */ - int get_dbit_list(); + int get_dbit_list(sls::ServerInterface2 &socket); /** set dbit offset */ - int set_dbit_offset(); + int set_dbit_offset(sls::ServerInterface2 &socket); /** detector type */ @@ -306,7 +306,7 @@ class slsReceiverTCPIPInterface : private virtual slsDetectorDefs { slsReceiverImplementation *receiver; /** Function List */ - int (slsReceiverTCPIPInterface::*flist[NUM_REC_FUNCTIONS])(); + int (slsReceiverTCPIPInterface::*flist[NUM_REC_FUNCTIONS])(sls::ServerInterface2& socket); /** Message */ char mess[MAX_STR_LENGTH]; @@ -390,4 +390,8 @@ protected: /** client interface */ ServerInterface* interface; + + private: + int VerifyLock(int &ret, char *mess); + int VerifyLockAndIdle(int &ret, char *mess, int fnum); }; diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp index 7446dd801..b620fb094 100755 --- a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp +++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp @@ -145,8 +145,15 @@ void slsReceiverTCPIPInterface::startTCPServer() { while (true) { try { + std::cout << "<--------- hej\n"; auto socket = server->accept(); + std::cout << "<--------- hej2\n"; + socket.setTimeOut(1); + socket.setReceiveTimeout(1000); + std::cout << "<--------- hej3\n"; ret = decode_function(socket); + std::cout << "<--------- hej4\n"; + socket.close(); // if(mySock->Connect() >= 0){ // ret = decode_function(); // mySock->Disconnect(); @@ -250,10 +257,11 @@ int slsReceiverTCPIPInterface::function_table(){ -int slsReceiverTCPIPInterface::decode_function(sls::DataSocket &socket){ +int slsReceiverTCPIPInterface::decode_function(sls::ServerInterface2 &socket){ ret = FAIL; - // int n = mySock->ReceiveDataOnly(&fnum,sizeof(fnum)); - int n = socket.receiveData(&fnum, sizeof(fnum)); + std::cout << "<------ decode 1\n"; + int n = socket.read(&fnum, sizeof(fnum)); + std::cout << "<------ decode 2\n"; if (n <= 0) { FILE_LOG(logDEBUG3) << "Could not read socket. " "Received " << n << " bytes," << @@ -271,7 +279,7 @@ int slsReceiverTCPIPInterface::decode_function(sls::DataSocket &socket){ FILE_LOG(logDEBUG1) << "calling function fnum: "<< fnum << " " "(" << getFunctionNameFromEnum((enum detFuncs)fnum) << ") " "located at " << flist[fnum]; - ret = (this->*flist[fnum])(); + ret = (this->*flist[fnum])(socket); if (ret == FAIL) { FILE_LOG(logDEBUG1) << "Failed to execute function = " << fnum << " (" @@ -310,7 +318,7 @@ void slsReceiverTCPIPInterface::validate(T arg, T retval, std::string modename, } } -int slsReceiverTCPIPInterface::M_nofunc(sls::DataSocket &socket){ +int slsReceiverTCPIPInterface::M_nofunc(sls::ServerInterface2 &socket){ ret = FAIL; memset(mess, 0, sizeof(mess)); @@ -323,29 +331,43 @@ int slsReceiverTCPIPInterface::M_nofunc(sls::DataSocket &socket){ sprintf(mess,"Unrecognized Function enum %d. Please do not proceed.\n", fnum); FILE_LOG(logERROR) << mess; - socket.sendData(&ret, sizeof(ret)); - socket.sendData(mess, sizeof(mess)); - return 0; - // return interface->Server_SendResult(false, ret, nullptr, 0, mess); + return socket.sendResult(false, ret, nullptr, 0, mess); } +int slsReceiverTCPIPInterface::VerifyLock(int &ret, char *mess) { + if (server->getThisClient() != server->getLockedBy() && lockStatus) { + ret = FAIL; + sprintf(mess, "Receiver locked\n"); + FILE_LOG(logERROR) << mess; + } + return ret; +} +int slsReceiverTCPIPInterface::VerifyLockAndIdle(int &ret, char *mess, int fnum) { + VerifyLock(ret, mess); + if (ret == FAIL) + return ret; + if (receiver->getStatus() != IDLE) { + sprintf(mess, "Can not execute %s when receiver is not idle\n", + getFunctionNameFromEnum((enum detFuncs)fnum)); + } + ret = OK; + return ret; +} - -int slsReceiverTCPIPInterface::exec_command() { +int slsReceiverTCPIPInterface::exec_command(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); - char cmd[MAX_STR_LENGTH] = {0}; - char retval[MAX_STR_LENGTH] = {0}; + char cmd[MAX_STR_LENGTH]{}; + char retval[MAX_STR_LENGTH]{}; // get args, return if socket crashed - if (interface->Server_ReceiveArg(ret, mess, cmd, MAX_STR_LENGTH) == FAIL) + if (socket.receiveArg(ret, mess, cmd, MAX_STR_LENGTH) == FAIL) return FAIL; FILE_LOG(logINFO) << "Executing command (" << cmd << ")"; // verify if receiver is unlocked - if (interface->Server_VerifyLock(ret, mess, lockStatus) == OK) { - + if (VerifyLock(ret, mess) == OK) { const size_t tempsize = 256; std::array temp; std::string sresult; @@ -364,56 +386,55 @@ int slsReceiverTCPIPInterface::exec_command() { FILE_LOG(logINFO) << "Result of cmd (" << cmd << "):\n" << retval; } } - return interface->Server_SendResult(false, ret, retval, MAX_STR_LENGTH, mess); + return socket.sendResult(false, ret, retval, MAX_STR_LENGTH, mess); } -int slsReceiverTCPIPInterface::exit_server() { +int slsReceiverTCPIPInterface::exit_server(sls::ServerInterface2 &socket) { FILE_LOG(logINFO) << "Closing server"; ret = OK; memset(mess, 0, sizeof(mess)); - interface->Server_SendResult(false, ret, nullptr, 0); + socket.sendResult(false, ret, nullptr, 0, nullptr); return GOODBYE; } +int slsReceiverTCPIPInterface::lock_receiver(sls::ServerInterface2 &socket) { + ret = OK; + memset(mess, 0, sizeof(mess)); + int lock = 0; + // get args, return if socket crashed + if (socket.receiveArg(ret, mess, &lock, sizeof(lock)) == FAIL) + return FAIL; + FILE_LOG(logDEBUG1) << "Locking Server to " << lock; -int slsReceiverTCPIPInterface::lock_receiver() { + // execute action + if (lock >= 0) { + if (!lockStatus || (server->getLockedBy() == server->getThisClient())) { + lockStatus = lock; + lock ? server->setLockedBy(server->getThisClient()) + : server->setLockedBy(sls::IpAddr{}); + } else{ + sprintf(mess, "Receiver locked\n"); + FILE_LOG(logERROR) << mess; + } + + } + return socket.sendResult(true, ret, &lockStatus, + sizeof(lockStatus), mess); +} + +int slsReceiverTCPIPInterface::get_last_client_ip(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); - int lock = 0; - - // get args, return if socket crashed - if (interface->Server_ReceiveArg(ret, mess, &lock, sizeof(lock)) == FAIL) - return FAIL; - FILE_LOG(logDEBUG1) << "Locking Server to " << lock; - - // execute action - if (lock >= 0) { - if (!lockStatus || // if it was unlocked, anyone can lock - (!strcmp(mySock->lastClientIP,mySock->thisClientIP)) || // if it was locked, need same ip - (!strcmp(mySock->lastClientIP,"none"))) // if it was locked, must be by "none" - { - lockStatus = lock; - strcpy(mySock->lastClientIP,mySock->thisClientIP); - } else - interface->Server_LockedError(ret, mess); - } - return interface->Server_SendResult(true, ret, &lockStatus,sizeof(lockStatus), mess); + auto ip = server->getLastClient().str(); + return socket.sendResult(true, ret, &ip.front(), ip.length()+1, nullptr); } -int slsReceiverTCPIPInterface::get_last_client_ip() { - ret = OK; - memset(mess, 0, sizeof(mess)); - return interface->Server_SendResult(true, ret,mySock->lastClientIP, sizeof(mySock->lastClientIP)); -} - - - -int slsReceiverTCPIPInterface::set_port() { +int slsReceiverTCPIPInterface::set_port(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); int p_number = -1; @@ -421,11 +442,11 @@ int slsReceiverTCPIPInterface::set_port() { char oldLastClientIP[INET_ADDRSTRLEN] = {0}; // get args, return if socket crashed - if (interface->Server_ReceiveArg(ret, mess, &p_number, sizeof(p_number)) == FAIL) + if (socket.receiveArg(ret, mess, &p_number, sizeof(p_number)) == FAIL) return FAIL; // verify if receiver is unlocked - if (interface->Server_VerifyLock(ret, mess, lockStatus) == OK) { + if (VerifyLock(ret, mess) == OK) { // port number too low if (p_number < 1024) { ret = FAIL; @@ -451,7 +472,7 @@ int slsReceiverTCPIPInterface::set_port() { } } - interface->Server_SendResult(true, ret, &p_number,sizeof(p_number), mess); + socket.sendResult(true, ret, &p_number,sizeof(p_number), mess); // delete old socket if(ret != FAIL){ mySock->Disconnect(); @@ -464,107 +485,106 @@ int slsReceiverTCPIPInterface::set_port() { -int slsReceiverTCPIPInterface::update_client() { +int slsReceiverTCPIPInterface::update_client(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); // no arg, check receiver is null - interface->Server_ReceiveArg(ret, mess, nullptr, 0, true, receiver); - - interface->Server_SendResult(false, ret, nullptr, 0, mess); + socket.receiveArg(ret, mess, nullptr, 0); + socket.sendResult(false, ret, nullptr, 0, mess); if (ret == FAIL) return ret; // update - return send_update(); + return send_update(socket); } -int slsReceiverTCPIPInterface::send_update() { +int slsReceiverTCPIPInterface::send_update(sls::ServerInterface2 &socket) { int n = 0; int i32 = -1; char cstring[MAX_STR_LENGTH] = {0}; - n += mySock->SendDataOnly(mySock->lastClientIP,sizeof(mySock->lastClientIP)); + n += socket.sendData(mySock->lastClientIP,sizeof(mySock->lastClientIP)); // filepath strcpy(cstring, receiver->getFilePath().c_str()); - n += mySock->SendDataOnly(cstring, sizeof(cstring)); + n += socket.sendData(cstring, sizeof(cstring)); // filename strcpy(cstring, receiver->getFileName().c_str()); - n += mySock->SendDataOnly(cstring, sizeof(cstring)); + n += socket.sendData(cstring, sizeof(cstring)); // index i32=receiver->getFileIndex(); - n += mySock->SendDataOnly(&i32, sizeof(i32)); + n += socket.sendData(&i32, sizeof(i32)); //file format i32=(int)receiver->getFileFormat(); - n += mySock->SendDataOnly(&i32, sizeof(i32)); + n += socket.sendData(&i32, sizeof(i32)); //frames per file i32=(int)receiver->getFramesPerFile(); - n += mySock->SendDataOnly(&i32, sizeof(i32)); + n += socket.sendData(&i32, sizeof(i32)); //frame discard policy i32=(int)receiver->getFrameDiscardPolicy(); - n += mySock->SendDataOnly(&i32, sizeof(i32)); + n += socket.sendData(&i32, sizeof(i32)); //frame padding i32=(int)receiver->getFramePaddingEnable(); - n += mySock->SendDataOnly(&i32, sizeof(i32)); + n += socket.sendData(&i32, sizeof(i32)); // file write enable i32=(int)receiver->getFileWriteEnable(); - n += mySock->SendDataOnly(&i32, sizeof(i32)); + n += socket.sendData(&i32, sizeof(i32)); // master file write enable i32=(int)receiver->getMasterFileWriteEnable(); - n += mySock->SendDataOnly(&i32, sizeof(i32)); + n += socket.sendData(&i32, sizeof(i32)); // file overwrite enable i32=(int)receiver->getOverwriteEnable(); - n += mySock->SendDataOnly(&i32, sizeof(i32)); + n += socket.sendData(&i32, sizeof(i32)); // gap pixels i32=(int)receiver->getGapPixelsEnable(); - n += mySock->SendDataOnly(&i32, sizeof(i32)); + n += socket.sendData(&i32, sizeof(i32)); // streaming frequency i32=(int)receiver->getStreamingFrequency(); - n += mySock->SendDataOnly(&i32, sizeof(i32)); + n += socket.sendData(&i32, sizeof(i32)); // streaming port i32=(int)receiver->getStreamingPort(); - n += mySock->SendDataOnly(&i32, sizeof(i32)); + n += socket.sendData(&i32, sizeof(i32)); // streaming source ip strcpy(cstring, receiver->getStreamingSourceIP().c_str()); - n += mySock->SendDataOnly(cstring, sizeof(cstring)); + n += socket.sendData(cstring, sizeof(cstring)); // additional json header strcpy(cstring, receiver->getAdditionalJsonHeader().c_str()); - n += mySock->SendDataOnly(cstring, sizeof(cstring)); + n += socket.sendData(cstring, sizeof(cstring)); // data streaming enable i32=(int)receiver->getDataStreamEnable(); - n += mySock->SendDataOnly(&i32, sizeof(i32)); + n += socket.sendData(&i32, sizeof(i32)); // activate i32=(int)receiver->getActivate(); - n += mySock->SendDataOnly(&i32, sizeof(i32)); + n += socket.sendData(&i32, sizeof(i32)); // deactivated padding enable i32=(int)receiver->getDeactivatedPadding(); - n += mySock->SendDataOnly(&i32, sizeof(i32)); + n += socket.sendData(&i32, sizeof(i32)); // silent mode i32=(int)receiver->getSilentMode(); - n += mySock->SendDataOnly(&i32, sizeof(i32)); + n += socket.sendData(&i32, sizeof(i32)); // dbit list { @@ -572,48 +592,51 @@ int slsReceiverTCPIPInterface::send_update() { int retvalsize = list.size(); int retval[retvalsize]; std::copy(std::begin(list), std::end(list), retval); - mySock->SendDataOnly(&retvalsize, sizeof(retvalsize)); - mySock->SendDataOnly(retval, sizeof(retval)); + socket.sendData(&retvalsize, sizeof(retvalsize)); + socket.sendData(retval, sizeof(retval)); } // dbit offset i32=receiver->getDbitOffset(); - n += mySock->SendDataOnly(&i32, sizeof(i32)); + n += socket.sendData(&i32, sizeof(i32)); - if (!lockStatus) - strcpy(mySock->lastClientIP, mySock->thisClientIP); + // if (!lockStatus) + // strcpy(mySock->lastClientIP, mySock->thisClientIP); return OK; } -int slsReceiverTCPIPInterface::get_id(){ +int slsReceiverTCPIPInterface::get_id(sls::ServerInterface2 &socket){ ret = OK; memset(mess, 0, sizeof(mess)); int64_t retval = getReceiverVersion(); - return interface->Server_SendResult(true, ret, &retval, sizeof(retval)); + return socket.sendResult(true, ret, &retval, sizeof(retval)); } -int slsReceiverTCPIPInterface::set_detector_type(){ +int slsReceiverTCPIPInterface::set_detector_type(sls::ServerInterface2 &socket){ ret = OK; memset(mess, 0, sizeof(mess)); detectorType arg = GENERIC; detectorType retval = GENERIC; // get args, return if socket crashed - if (interface->Server_ReceiveArg(ret, mess, &arg, sizeof(arg)) == FAIL) + if (socket.receiveArg(ret, mess, &arg, sizeof(arg)) == FAIL) return FAIL; // set if (arg >= 0) { // if object exists, verify unlocked and idle, else only verify lock (connecting first time) - if (receiver == nullptr) - interface->Server_VerifyLock(ret, mess, lockStatus); - else - interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum); + if (receiver == nullptr){ + VerifyLock(ret, mess); + } + else{ + VerifyLockAndIdle(ret, mess, fnum); + } + if (ret == OK) { switch(arg) { case GOTTHARD: @@ -646,9 +669,9 @@ int slsReceiverTCPIPInterface::set_detector_type(){ if(rawDataModifyReadyCallBack) receiver->registerCallBackRawDataModifyReady(rawDataModifyReadyCallBack,pRawDataReady); - // client has started updating receiver, update ip - if (!lockStatus) - strcpy(mySock->lastClientIP, mySock->thisClientIP); + // // client has started updating receiver, update ip + // if (!lockStatus) + // strcpy(mySock->lastClientIP, mySock->thisClientIP); } } @@ -656,19 +679,19 @@ int slsReceiverTCPIPInterface::set_detector_type(){ //get retval = myDetectorType; validate((int)arg, (int)retval, std::string("set detector type"), DEC); - return interface->Server_SendResult(false, ret, &retval, sizeof(retval), mess); + return socket.sendResult(false, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::set_detector_hostname() { +int slsReceiverTCPIPInterface::set_detector_hostname(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); char hostname[MAX_STR_LENGTH] = {0}; char retval[MAX_STR_LENGTH] = {0}; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, hostname,MAX_STR_LENGTH, true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, hostname,MAX_STR_LENGTH) == FAIL) return FAIL; // base object not null @@ -676,7 +699,7 @@ int slsReceiverTCPIPInterface::set_detector_hostname() { // set if (strlen(hostname)) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) + if (VerifyLockAndIdle(ret, mess, fnum) == OK) receiver->setDetectorHostname(hostname); } // get @@ -689,12 +712,12 @@ int slsReceiverTCPIPInterface::set_detector_hostname() { } } - return interface->Server_SendResult(true, ret, retval, MAX_STR_LENGTH, mess); + return socket.sendResult(true, ret, retval, MAX_STR_LENGTH, mess); } -int slsReceiverTCPIPInterface::set_roi() { +int slsReceiverTCPIPInterface::set_roi(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); int narg = -1; @@ -731,30 +754,30 @@ int slsReceiverTCPIPInterface::set_roi() { else { // only set // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) + if (VerifyLockAndIdle(ret, mess, fnum) == OK) ret = receiver->setROI(arg); } arg.clear(); - return interface->Server_SendResult(true, ret, nullptr, 0, mess); + return socket.sendResult(true, ret, nullptr, 0, mess); } -int slsReceiverTCPIPInterface::setup_udp(){ +int slsReceiverTCPIPInterface::setup_udp(sls::ServerInterface2 &socket){ ret = OK; memset(mess, 0, sizeof(mess)); char args[6][MAX_STR_LENGTH] = {{""}, {""}, {""}, {""}, {""}, {""}}; char retvals[2][MAX_STR_LENGTH] = {{""}, {""}}; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, args, sizeof(args), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, args, sizeof(args)) == FAIL) return FAIL; // base object not null if (ret == OK) { // only set // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { //setup interfaces count int numInterfaces = atoi(args[0]) > 1 ? 2 : 1; @@ -865,19 +888,19 @@ int slsReceiverTCPIPInterface::setup_udp(){ } } } - return interface->Server_SendResult(true, ret, retvals, sizeof(retvals), mess); + return socket.sendResult(true, ret, retvals, sizeof(retvals), mess); } -int slsReceiverTCPIPInterface::set_timer() { +int slsReceiverTCPIPInterface::set_timer(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); int64_t index[2] = {-1, -1}; int64_t retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, &index, sizeof(index), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, &index, sizeof(index)) == FAIL) return FAIL; // base object not null @@ -887,7 +910,7 @@ int slsReceiverTCPIPInterface::set_timer() { // set if (index[1] >= 0) { // verify if receiver is unlocked - if (interface->Server_VerifyLock(ret, mess, lockStatus) == OK) { + if (VerifyLock(ret, mess) == OK) { switch (index[0]) { case ACQUISITION_TIME: ret = receiver->setAcquisitionTime(index[1]); @@ -970,19 +993,19 @@ int slsReceiverTCPIPInterface::set_timer() { validate((int)index[1], (int)retval, std::string("set timer"), DEC); FILE_LOG(logDEBUG1) << slsDetectorDefs::getTimerType((timerIndex)(index[0])) << ":" << retval; } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::set_dynamic_range() { +int slsReceiverTCPIPInterface::set_dynamic_range(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); int dr = -1; int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, &dr, sizeof(dr), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, &dr, sizeof(dr)) == FAIL) return FAIL; // base object not null @@ -990,7 +1013,7 @@ int slsReceiverTCPIPInterface::set_dynamic_range() { // set if (dr >= 0) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting dynamic range: " << dr; bool exists = false; switch (dr) { @@ -1025,19 +1048,19 @@ int slsReceiverTCPIPInterface::set_dynamic_range() { validate(dr, retval, std::string("set dynamic range"), DEC); FILE_LOG(logDEBUG1) << "dynamic range: " << retval; } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::set_streaming_frequency() { +int slsReceiverTCPIPInterface::set_streaming_frequency(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); int index = -1; int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, &index, sizeof(index), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, &index, sizeof(index)) == FAIL) return FAIL; // base object not null @@ -1045,7 +1068,7 @@ int slsReceiverTCPIPInterface::set_streaming_frequency() { // set if (index >= 0) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting streaming frequency: " << index; ret = receiver->setStreamingFrequency(index); if(ret == FAIL) { @@ -1058,41 +1081,43 @@ int slsReceiverTCPIPInterface::set_streaming_frequency() { retval = receiver->getStreamingFrequency(); validate(index, retval, std::string("set streaming frequency"), DEC); } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::get_status(){ +int slsReceiverTCPIPInterface::get_status(sls::ServerInterface2 &socket){ ret = OK; memset(mess, 0, sizeof(mess)); enum runStatus retval = ERROR; // no arg, check receiver is null - interface->Server_ReceiveArg(ret, mess, nullptr, 0, true, receiver); + socket.receiveArg(ret, mess, nullptr, 0); if (ret == OK) { FILE_LOG(logDEBUG1) << "Getting Status"; + std::cout << "kalas\n"; retval = receiver->getStatus(); + std::cout << "puff\n"; FILE_LOG(logDEBUG1) << "Status:" << runStatusType(retval); } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::start_receiver(){ +int slsReceiverTCPIPInterface::start_receiver(sls::ServerInterface2 &socket){ ret = OK; memset(mess, 0, sizeof(mess)); // no arg, and check receiver is null - interface->Server_ReceiveArg(ret, mess, nullptr, 0, true, receiver); + socket.receiveArg(ret, mess, nullptr, 0); // receiver is not null if (ret == OK) { // only set // verify if receiver is unlocked - if (interface->Server_VerifyLock(ret, mess, lockStatus) == OK) { + if (VerifyLock(ret, mess) == OK) { // should not be idle enum runStatus s = receiver->getStatus(); if (s != IDLE) { @@ -1108,23 +1133,23 @@ int slsReceiverTCPIPInterface::start_receiver(){ } } } - return interface->Server_SendResult(true, ret, nullptr, 0, mess); + return socket.sendResult(true, ret, nullptr, 0, mess); } -int slsReceiverTCPIPInterface::stop_receiver(){ +int slsReceiverTCPIPInterface::stop_receiver(sls::ServerInterface2 &socket){ ret = OK; memset(mess, 0, sizeof(mess)); // no arg, and check receiver is null - interface->Server_ReceiveArg(ret, mess, nullptr, 0, true, receiver); + socket.receiveArg(ret, mess, nullptr, 0); // receiver is not null if (ret == OK) { // only set // verify if receiver is unlocked - if (interface->Server_VerifyLock(ret, mess, lockStatus) == OK) { + if (VerifyLock(ret, mess) == OK) { if(receiver->getStatus() != IDLE) { FILE_LOG(logDEBUG1) << "Stopping Receiver"; receiver->stopReceiver(); @@ -1139,19 +1164,19 @@ int slsReceiverTCPIPInterface::stop_receiver(){ } } } - return interface->Server_SendResult(true, ret, nullptr, 0, mess); + return socket.sendResult(true, ret, nullptr, 0, mess); } -int slsReceiverTCPIPInterface::set_file_dir() { +int slsReceiverTCPIPInterface::set_file_dir(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); char fPath[MAX_STR_LENGTH] = {0}; char retval[MAX_STR_LENGTH] = {0}; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, fPath, sizeof(fPath), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, fPath, sizeof(fPath)) == FAIL) return FAIL; // base object not null @@ -1171,19 +1196,19 @@ int slsReceiverTCPIPInterface::set_file_dir() { } else FILE_LOG(logDEBUG1) << "file path:" << retval; } - return interface->Server_SendResult(true, ret, retval, MAX_STR_LENGTH, mess); + return socket.sendResult(true, ret, retval, MAX_STR_LENGTH, mess); } -int slsReceiverTCPIPInterface::set_file_name() { +int slsReceiverTCPIPInterface::set_file_name(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); char fName[MAX_STR_LENGTH] = {0}; char retval[MAX_STR_LENGTH] = {0}; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, fName, sizeof(fName), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, fName, sizeof(fName)) == FAIL) return FAIL; // base object not null @@ -1203,19 +1228,19 @@ int slsReceiverTCPIPInterface::set_file_name() { } else FILE_LOG(logDEBUG1) << "file name:" << retval; } - return interface->Server_SendResult(true, ret, retval, MAX_STR_LENGTH, mess); + return socket.sendResult(true, ret, retval, MAX_STR_LENGTH, mess); } -int slsReceiverTCPIPInterface::set_file_index() { +int slsReceiverTCPIPInterface::set_file_index(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); int index = -1; int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, &index, sizeof(index), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, &index, sizeof(index)) == FAIL) return FAIL; // base object not null @@ -1223,7 +1248,7 @@ int slsReceiverTCPIPInterface::set_file_index() { // set if (index >= 0) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting file index: " << index; receiver->setFileIndex(index); } @@ -1233,76 +1258,76 @@ int slsReceiverTCPIPInterface::set_file_index() { validate(index, retval, std::string("set file index"), DEC); FILE_LOG(logDEBUG1) << "file index:" << retval; } - return interface->Server_SendResult(true, ret, &retval,sizeof(retval), mess); + return socket.sendResult(true, ret, &retval,sizeof(retval), mess); } -int slsReceiverTCPIPInterface::get_frame_index(){ +int slsReceiverTCPIPInterface::get_frame_index(sls::ServerInterface2 &socket){ ret = OK; memset(mess, 0, sizeof(mess)); int retval = -1; // no arg, check receiver is null - interface->Server_ReceiveArg(ret, mess, nullptr, 0, true, receiver); + socket.receiveArg(ret, mess, nullptr, 0); if (ret == OK) { FILE_LOG(logDEBUG1) << "Getting frame index"; retval = receiver->getAcquisitionIndex(); FILE_LOG(logDEBUG1) << "frame index:" << retval; } - return interface->Server_SendResult(true, ret, &retval,sizeof(retval), mess); + return socket.sendResult(true, ret, &retval,sizeof(retval), mess); } -int slsReceiverTCPIPInterface::get_frames_caught(){ +int slsReceiverTCPIPInterface::get_frames_caught(sls::ServerInterface2 &socket){ ret = OK; memset(mess, 0, sizeof(mess)); int retval = -1; // no arg, check receiver is null - interface->Server_ReceiveArg(ret, mess, nullptr, 0, true, receiver); + socket.receiveArg(ret, mess, nullptr, 0); if (ret == OK) { FILE_LOG(logDEBUG1) << "Getting frames caught"; retval = receiver->getTotalFramesCaught(); FILE_LOG(logDEBUG1) << "frames caught:" << retval; } - return interface->Server_SendResult(true, ret, &retval,sizeof(retval), mess); + return socket.sendResult(true, ret, &retval,sizeof(retval), mess); } -int slsReceiverTCPIPInterface::reset_frames_caught(){ +int slsReceiverTCPIPInterface::reset_frames_caught(sls::ServerInterface2 &socket){ ret = OK; memset(mess, 0, sizeof(mess)); // no arg, and check receiver is null - interface->Server_ReceiveArg(ret, mess, nullptr, 0, true, receiver); + socket.receiveArg(ret, mess, nullptr, 0); // receiver is not null if (ret == OK) { // only set // verify if receiver is unlocked - if (interface->Server_VerifyLock(ret, mess, lockStatus) == OK) { + if (VerifyLock(ret, mess) == OK) { FILE_LOG(logDEBUG1) << "Reset frames caught"; receiver->resetAcquisitionCount(); } } - return interface->Server_SendResult(true, ret, nullptr, 0, mess); + return socket.sendResult(true, ret, nullptr, 0, mess); } -int slsReceiverTCPIPInterface::enable_file_write(){ +int slsReceiverTCPIPInterface::enable_file_write(sls::ServerInterface2 &socket){ ret = OK; memset(mess, 0, sizeof(mess)); int enable = -1; int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, &enable, sizeof(enable), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, &enable, sizeof(enable)) == FAIL) return FAIL; // base object not null @@ -1310,7 +1335,7 @@ int slsReceiverTCPIPInterface::enable_file_write(){ // set if (enable >= 0) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting File write enable:" << enable; receiver->setFileWriteEnable(enable); } @@ -1320,19 +1345,19 @@ int slsReceiverTCPIPInterface::enable_file_write(){ validate(enable, retval, std::string("set file write enable"), DEC); FILE_LOG(logDEBUG1) << "file write enable:" << retval; } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::enable_master_file_write(){ +int slsReceiverTCPIPInterface::enable_master_file_write(sls::ServerInterface2 &socket){ ret = OK; memset(mess, 0, sizeof(mess)); int enable = -1; int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, &enable, sizeof(enable), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, &enable, sizeof(enable)) == FAIL) return FAIL; // base object not null @@ -1340,7 +1365,7 @@ int slsReceiverTCPIPInterface::enable_master_file_write(){ // set if (enable >= 0) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting Master File write enable:" << enable; receiver->setMasterFileWriteEnable(enable); } @@ -1350,18 +1375,18 @@ int slsReceiverTCPIPInterface::enable_master_file_write(){ validate(enable, retval, std::string("set master file write enable"), DEC); FILE_LOG(logDEBUG1) << "master file write enable:" << retval; } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::enable_overwrite() { +int slsReceiverTCPIPInterface::enable_overwrite(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); int index = -1; int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, &index, sizeof(index), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, &index, sizeof(index)) == FAIL) return FAIL; // base object not null @@ -1369,7 +1394,7 @@ int slsReceiverTCPIPInterface::enable_overwrite() { // set if (index >= 0) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting File overwrite enable:" << index; receiver->setOverwriteEnable(index); } @@ -1379,19 +1404,19 @@ int slsReceiverTCPIPInterface::enable_overwrite() { validate(index, retval, std::string("set file overwrite enable"), DEC); FILE_LOG(logDEBUG1) << "file overwrite enable:" << retval; } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::enable_tengiga() { +int slsReceiverTCPIPInterface::enable_tengiga(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); int val = -1; int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, &val, sizeof(val), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, &val, sizeof(val)) == FAIL) return FAIL; if (myDetectorType != EIGER && myDetectorType != CHIPTESTBOARD && myDetectorType != MOENCH) @@ -1402,7 +1427,7 @@ int slsReceiverTCPIPInterface::enable_tengiga() { // set if (val >= 0) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting 10GbE:" << val; ret = receiver->setTenGigaEnable(val); } @@ -1412,19 +1437,19 @@ int slsReceiverTCPIPInterface::enable_tengiga() { validate(val, retval, std::string("set 10GbE"), DEC); FILE_LOG(logDEBUG1) << "10Gbe:" << retval; } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::set_fifo_depth() { +int slsReceiverTCPIPInterface::set_fifo_depth(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); int value = -1; int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, &value, sizeof(value), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, &value, sizeof(value)) == FAIL) return FAIL; // base object not null @@ -1432,7 +1457,7 @@ int slsReceiverTCPIPInterface::set_fifo_depth() { // set if (value >= 0) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting fifo depth:" << value; ret = receiver->setFifoDepth(value); if (ret == FAIL) { @@ -1446,19 +1471,19 @@ int slsReceiverTCPIPInterface::set_fifo_depth() { validate(value, retval, std::string("set fifo depth"), DEC); FILE_LOG(logDEBUG1) << "fifo depth:" << retval; } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::set_activate() { +int slsReceiverTCPIPInterface::set_activate(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); int enable = -1; int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, &enable, sizeof(enable), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, &enable, sizeof(enable)) == FAIL) return FAIL; if (myDetectorType != EIGER) @@ -1469,7 +1494,7 @@ int slsReceiverTCPIPInterface::set_activate() { // set if (enable >= 0) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting activate:" << enable; receiver->setActivate(enable > 0 ? true : false); } @@ -1479,19 +1504,19 @@ int slsReceiverTCPIPInterface::set_activate() { validate(enable, retval, std::string("set activate"), DEC); FILE_LOG(logDEBUG1) << "Activate: " << retval; } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::set_data_stream_enable(){ +int slsReceiverTCPIPInterface::set_data_stream_enable(sls::ServerInterface2 &socket){ ret = OK; memset(mess, 0, sizeof(mess)); int index = -1; int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, &index, sizeof(index), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, &index, sizeof(index)) == FAIL) return FAIL; // base object not null @@ -1499,7 +1524,7 @@ int slsReceiverTCPIPInterface::set_data_stream_enable(){ // set if (index >= 0) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting data stream enable:" << index; ret = receiver->setDataStreamEnable(index); } @@ -1509,19 +1534,19 @@ int slsReceiverTCPIPInterface::set_data_stream_enable(){ validate(index, retval, std::string("set data stream enable"), DEC); FILE_LOG(logDEBUG1) << "data streaming enable:" << retval; } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::set_streaming_timer(){ +int slsReceiverTCPIPInterface::set_streaming_timer(sls::ServerInterface2 &socket){ ret = OK; memset(mess, 0, sizeof(mess)); int index = -1; int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, &index, sizeof(index), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, &index, sizeof(index)) == FAIL) return FAIL; // base object not null @@ -1529,7 +1554,7 @@ int slsReceiverTCPIPInterface::set_streaming_timer(){ // set if (index >= 0) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting streaming timer:" << index; receiver->setStreamingTimer(index); } @@ -1539,19 +1564,19 @@ int slsReceiverTCPIPInterface::set_streaming_timer(){ validate(index, retval, std::string("set data stream timer"), DEC); FILE_LOG(logDEBUG1) << "Streaming timer:" << retval; } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::set_flipped_data(){ +int slsReceiverTCPIPInterface::set_flipped_data(sls::ServerInterface2 &socket){ ret = OK; memset(mess, 0, sizeof(mess)); int args[2] = {0,-1}; int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, args, sizeof(args), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, args, sizeof(args)) == FAIL) return FAIL; if (myDetectorType != EIGER) @@ -1562,7 +1587,7 @@ int slsReceiverTCPIPInterface::set_flipped_data(){ // set if (args[1] >= 0) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting flipped data:" << args[1]; receiver->setFlippedData(args[0],args[1]); } @@ -1572,19 +1597,19 @@ int slsReceiverTCPIPInterface::set_flipped_data(){ validate(args[1], retval, std::string("set flipped data"), DEC); FILE_LOG(logDEBUG1) << "Flipped Data:" << retval; } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::set_file_format() { +int slsReceiverTCPIPInterface::set_file_format(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); fileFormat retval = GET_FILE_FORMAT; fileFormat f = GET_FILE_FORMAT; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, &f, sizeof(f), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, &f, sizeof(f)) == FAIL) return FAIL; // base object not null @@ -1592,7 +1617,7 @@ int slsReceiverTCPIPInterface::set_file_format() { // set if (f >= 0) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting file format:" << f; receiver->setFileFormat(f); } @@ -1602,19 +1627,19 @@ int slsReceiverTCPIPInterface::set_file_format() { validate(f, retval, std::string("set file format"), DEC); FILE_LOG(logDEBUG1) << "File Format: " << retval; } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::set_detector_posid() { +int slsReceiverTCPIPInterface::set_detector_posid(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); int arg = -1; int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, &arg, sizeof(arg), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, &arg, sizeof(arg)) == FAIL) return FAIL; // base object not null @@ -1622,7 +1647,7 @@ int slsReceiverTCPIPInterface::set_detector_posid() { // set if (arg >= 0) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting detector position id:" << arg; receiver->setDetectorPositionId(arg); } @@ -1632,19 +1657,19 @@ int slsReceiverTCPIPInterface::set_detector_posid() { validate(arg, retval, std::string("set detector position id"), DEC); FILE_LOG(logDEBUG1) << "Position Id:" << retval; } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::set_multi_detector_size() { +int slsReceiverTCPIPInterface::set_multi_detector_size(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); - int arg[2] = {-1, -1}; + int arg[]{-1, -1}; int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, arg, sizeof(arg), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, arg, sizeof(arg)) == FAIL) return FAIL; // base object not null @@ -1652,7 +1677,7 @@ int slsReceiverTCPIPInterface::set_multi_detector_size() { // set if((arg[0] > 0) && (arg[1] > 0)) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting multi detector size:" << arg[0] << "," << arg[1]; receiver->setMultiDetectorSize(arg); } @@ -1667,19 +1692,19 @@ int slsReceiverTCPIPInterface::set_multi_detector_size() { } FILE_LOG(logDEBUG1) << "Multi Detector Size:" << retval; } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::set_streaming_port() { +int slsReceiverTCPIPInterface::set_streaming_port(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); int port = -1; int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, &port, sizeof(port), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, &port, sizeof(port)) == FAIL) return FAIL; // base object not null @@ -1687,7 +1712,7 @@ int slsReceiverTCPIPInterface::set_streaming_port() { // set if (port >= 0) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting streaming port:" << port; receiver->setStreamingPort(port); } @@ -1697,26 +1722,26 @@ int slsReceiverTCPIPInterface::set_streaming_port() { validate(port, retval, std::string("set streaming port"), DEC); FILE_LOG(logDEBUG1) << "streaming port:" << retval; } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::set_streaming_source_ip() { +int slsReceiverTCPIPInterface::set_streaming_source_ip(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); char arg[MAX_STR_LENGTH] = {0}; char retval[MAX_STR_LENGTH] = {0}; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, arg, MAX_STR_LENGTH, true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, arg, MAX_STR_LENGTH) == FAIL) return FAIL; // base object not null if (ret == OK) { // only set // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting streaming source ip:" << arg; receiver->setStreamingSourceIP(arg); } @@ -1724,19 +1749,19 @@ int slsReceiverTCPIPInterface::set_streaming_source_ip() { strcpy(retval, receiver->getStreamingSourceIP().c_str()); FILE_LOG(logDEBUG1) << "streaming source ip:" << retval; } - return interface->Server_SendResult(true, ret, retval, MAX_STR_LENGTH, mess); + return socket.sendResult(true, ret, retval, MAX_STR_LENGTH, mess); } -int slsReceiverTCPIPInterface::set_silent_mode() { +int slsReceiverTCPIPInterface::set_silent_mode(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); int value = -1; int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, &value, sizeof(value), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, &value, sizeof(value)) == FAIL) return FAIL; // base object not null @@ -1744,7 +1769,7 @@ int slsReceiverTCPIPInterface::set_silent_mode() { // set if (value >= 0) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting silent mode:" << value; receiver->setSilentMode(value); } @@ -1754,19 +1779,19 @@ int slsReceiverTCPIPInterface::set_silent_mode() { validate(value, retval, std::string("set silent mode"), DEC); FILE_LOG(logDEBUG1) << "silent mode:" << retval; } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::enable_gap_pixels() { +int slsReceiverTCPIPInterface::enable_gap_pixels(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); int enable = -1; int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, &enable, sizeof(enable), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, &enable, sizeof(enable)) == FAIL) return FAIL; if (myDetectorType != EIGER) @@ -1777,7 +1802,7 @@ int slsReceiverTCPIPInterface::enable_gap_pixels() { // set if (enable >= 0) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting gap pixels enable:" << enable; receiver->setGapPixelsEnable(enable); } @@ -1787,23 +1812,23 @@ int slsReceiverTCPIPInterface::enable_gap_pixels() { validate(enable, retval, std::string("set gap pixels enable"), DEC); FILE_LOG(logDEBUG1) << "Gap Pixels Enable: " << retval; } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::restream_stop(){ +int slsReceiverTCPIPInterface::restream_stop(sls::ServerInterface2 &socket){ ret = OK; memset(mess, 0, sizeof(mess)); // no arg, and check receiver is null - interface->Server_ReceiveArg(ret, mess, nullptr, 0, true, receiver); + socket.receiveArg(ret, mess, nullptr, 0); // receiver is not null if (ret == OK) { // only set // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { if (receiver->getDataStreamEnable() == false) { ret = FAIL; sprintf(mess,"Could not restream stop packet as data Streaming is disabled.\n"); @@ -1818,26 +1843,26 @@ int slsReceiverTCPIPInterface::restream_stop(){ } } } - return interface->Server_SendResult(true, ret, nullptr, 0, mess); + return socket.sendResult(true, ret, nullptr, 0, mess); } -int slsReceiverTCPIPInterface::set_additional_json_header() { +int slsReceiverTCPIPInterface::set_additional_json_header(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); char arg[MAX_STR_LENGTH] = {0}; char retval[MAX_STR_LENGTH] = {0}; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, arg, sizeof(arg), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, arg, sizeof(arg)) == FAIL) return FAIL; // base object not null if (ret == OK) { // only set // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting additional json header: " << arg; receiver->setAdditionalJsonHeader(arg); } @@ -1845,18 +1870,18 @@ int slsReceiverTCPIPInterface::set_additional_json_header() { strcpy(retval, receiver->getAdditionalJsonHeader().c_str()); FILE_LOG(logDEBUG1) << "additional json header:" << retval; } - return interface->Server_SendResult(true, ret, retval, MAX_STR_LENGTH, mess); + return socket.sendResult(true, ret, retval, MAX_STR_LENGTH, mess); } -int slsReceiverTCPIPInterface::get_additional_json_header() { +int slsReceiverTCPIPInterface::get_additional_json_header(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); char retval[MAX_STR_LENGTH] = {0}; // no arg, check receiver is null - interface->Server_ReceiveArg(ret, mess, nullptr, 0, true, receiver); + socket.receiveArg(ret, mess, nullptr, 0); // base object not null if (ret == OK) { @@ -1864,19 +1889,19 @@ int slsReceiverTCPIPInterface::get_additional_json_header() { strcpy(retval, receiver->getAdditionalJsonHeader().c_str()); FILE_LOG(logDEBUG1) << "additional json header:" << retval; } - return interface->Server_SendResult(true, ret, retval, MAX_STR_LENGTH, mess); + return socket.sendResult(true, ret, retval, MAX_STR_LENGTH, mess); } -int slsReceiverTCPIPInterface::set_udp_socket_buffer_size() { +int slsReceiverTCPIPInterface::set_udp_socket_buffer_size(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); int64_t index = -1; int64_t retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, &index, sizeof(index), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, &index, sizeof(index)) == FAIL) return FAIL; // base object not null @@ -1884,7 +1909,7 @@ int slsReceiverTCPIPInterface::set_udp_socket_buffer_size() { // set if (index >= 0) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting UDP Socket Buffer size: " << index; if (receiver->setUDPSocketBufferSize(index) == FAIL) { ret = FAIL; @@ -1899,36 +1924,36 @@ int slsReceiverTCPIPInterface::set_udp_socket_buffer_size() { validate(index, retval, std::string("set udp socket buffer size (No CAP_NET_ADMIN privileges?)"), DEC); FILE_LOG(logDEBUG1) << "UDP Socket Buffer Size:" << retval; } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::get_real_udp_socket_buffer_size(){ +int slsReceiverTCPIPInterface::get_real_udp_socket_buffer_size(sls::ServerInterface2 &socket){ ret = OK; memset(mess, 0, sizeof(mess)); int64_t retval = -1; // no arg, check receiver is null - interface->Server_ReceiveArg(ret, mess, nullptr, 0, true, receiver); + socket.receiveArg(ret, mess, nullptr, 0); if (ret == OK) { FILE_LOG(logDEBUG1) << "Getting actual UDP buffer size"; retval = receiver->getActualUDPSocketBufferSize(); } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::set_frames_per_file() { +int slsReceiverTCPIPInterface::set_frames_per_file(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); int index = -1; int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, &index, sizeof(index), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, &index, sizeof(index)) == FAIL) return FAIL; // base object not null @@ -1936,7 +1961,7 @@ int slsReceiverTCPIPInterface::set_frames_per_file() { // set if (index >= 0) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting frames per file: " << index; receiver->setFramesPerFile(index); } @@ -1946,18 +1971,18 @@ int slsReceiverTCPIPInterface::set_frames_per_file() { validate(index, retval, std::string("set frames per file"), DEC); FILE_LOG(logDEBUG1) << "frames per file:" << retval; } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::check_version_compatibility() { +int slsReceiverTCPIPInterface::check_version_compatibility(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); int64_t arg = -1; - + std::cout << "<----------------- HEY\n"; // get args, return if socket crashed - if (interface->Server_ReceiveArg(ret, mess, &arg, sizeof(arg)) == FAIL) + if (socket.receiveArg(ret, mess, &arg, sizeof(arg)) == FAIL) return FAIL; FILE_LOG(logDEBUG1) << "Checking versioning compatibility with value " << arg; int64_t client_requiredVersion = arg; @@ -1986,19 +2011,19 @@ int slsReceiverTCPIPInterface::check_version_compatibility() { FILE_LOG(logERROR) << mess; } else FILE_LOG(logINFO) << "Compatibility with Client: Successful"; - return interface->Server_SendResult(true, ret, nullptr, 0, mess); + return socket.sendResult(true, ret, nullptr, 0, mess); } -int slsReceiverTCPIPInterface::set_discard_policy() { +int slsReceiverTCPIPInterface::set_discard_policy(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); int index = -1; int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, &index, sizeof(index), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, &index, sizeof(index)) == FAIL) return FAIL; // base object not null @@ -2006,7 +2031,7 @@ int slsReceiverTCPIPInterface::set_discard_policy() { // set if (index >= 0) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting frames discard policy: " << index; receiver->setFrameDiscardPolicy((frameDiscardPolicy)index); } @@ -2016,19 +2041,19 @@ int slsReceiverTCPIPInterface::set_discard_policy() { validate(index, retval, std::string("set discard policy"), DEC); FILE_LOG(logDEBUG1) << "frame discard policy:" << retval; } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::set_padding_enable() { +int slsReceiverTCPIPInterface::set_padding_enable(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); int index = -1; int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, &index, sizeof(index), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, &index, sizeof(index)) == FAIL) return FAIL; // base object not null @@ -2036,7 +2061,7 @@ int slsReceiverTCPIPInterface::set_padding_enable() { // set if (index >= 0) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { index = (index == 0) ? 0 : 1; FILE_LOG(logDEBUG1) << "Setting frames padding enable: " << index; receiver->setFramePaddingEnable(index); @@ -2047,19 +2072,19 @@ int slsReceiverTCPIPInterface::set_padding_enable() { validate(index, retval, std::string("set frame padding enable"), DEC); FILE_LOG(logDEBUG1) << "Frame Padding Enable:" << retval; } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::set_deactivated_padding_enable() { +int slsReceiverTCPIPInterface::set_deactivated_padding_enable(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); int enable = -1; int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, &enable, sizeof(enable), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, &enable, sizeof(enable)) == FAIL) return FAIL; if (myDetectorType != EIGER) @@ -2070,7 +2095,7 @@ int slsReceiverTCPIPInterface::set_deactivated_padding_enable() { // set if (enable >= 0) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting deactivated padding enable: " << enable; receiver->setDeactivatedPadding(enable > 0 ? true : false); } @@ -2080,18 +2105,18 @@ int slsReceiverTCPIPInterface::set_deactivated_padding_enable() { validate(enable, retval, std::string("set deactivated padding enable"), DEC); FILE_LOG(logDEBUG1) << "Deactivated Padding Enable: " << retval; } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::set_readout_flags() { +int slsReceiverTCPIPInterface::set_readout_flags(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); readOutFlags arg = GET_READOUT_FLAGS; readOutFlags retval = GET_READOUT_FLAGS; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, &arg, sizeof(arg), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, &arg, sizeof(arg)) == FAIL) return FAIL; if (myDetectorType == JUNGFRAU || myDetectorType == GOTTHARD || myDetectorType == MOENCH) @@ -2102,7 +2127,7 @@ int slsReceiverTCPIPInterface::set_readout_flags() { // set if (arg >= 0) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting readout flag: " << arg; ret = receiver->setReadOutFlags(arg); } @@ -2112,26 +2137,26 @@ int slsReceiverTCPIPInterface::set_readout_flags() { validate((int)arg, (int)(retval & arg), std::string("set readout flags"), HEX); FILE_LOG(logDEBUG1) << "Readout flags: " << retval; } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::set_adc_mask() { +int slsReceiverTCPIPInterface::set_adc_mask(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); uint32_t arg = -1; uint32_t retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, &arg, sizeof(arg), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, &arg, sizeof(arg)) == FAIL) return FAIL; // base object not null else if (ret == OK) { // set // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting ADC enable mask: " << arg; receiver->setADCEnableMask(arg); } @@ -2145,14 +2170,14 @@ int slsReceiverTCPIPInterface::set_adc_mask() { } FILE_LOG(logDEBUG1) << "ADC enable mask retval: " << retval; } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::set_dbit_list() { +int slsReceiverTCPIPInterface::set_dbit_list(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); sls::FixedCapacityContainer args; - if (interface->Server_ReceiveArg(ret, mess, &args, sizeof(args), true, receiver) == FAIL) { + if (socket.receiveArg(ret, mess, &args, sizeof(args)) == FAIL) { return FAIL; } else if (ret == OK) { FILE_LOG(logDEBUG1) << "Setting DBIT list"; @@ -2171,16 +2196,16 @@ int slsReceiverTCPIPInterface::set_dbit_list() { } - return interface->Server_SendResult(true, ret, nullptr, 0, mess); + return socket.sendResult(true, ret, nullptr, 0, mess); } -int slsReceiverTCPIPInterface::get_dbit_list() { +int slsReceiverTCPIPInterface::get_dbit_list(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); sls::FixedCapacityContainer retval; // no arg, check receiver is null - interface->Server_ReceiveArg(ret, mess, nullptr, 0, true, receiver); + socket.receiveArg(ret, mess, nullptr, 0); // base object not null if (ret == OK) { @@ -2188,18 +2213,18 @@ int slsReceiverTCPIPInterface::get_dbit_list() { retval = receiver->getDbitList(); FILE_LOG(logDEBUG1) << "Dbit list size retval:" << retval.size(); } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } -int slsReceiverTCPIPInterface::set_dbit_offset() { +int slsReceiverTCPIPInterface::set_dbit_offset(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); int arg = -1; int retval = -1; // get args, return if socket crashed, ret is fail if receiver is not null - if (interface->Server_ReceiveArg(ret, mess, &arg, sizeof(arg), true, receiver) == FAIL) + if (socket.receiveArg(ret, mess, &arg, sizeof(arg)) == FAIL) return FAIL; // base object not null @@ -2207,7 +2232,7 @@ int slsReceiverTCPIPInterface::set_dbit_offset() { // set if (arg >= 0) { // verify if receiver is unlocked and idle - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting Dbit offset: " << arg; receiver->setDbitOffset(arg); } @@ -2217,5 +2242,5 @@ int slsReceiverTCPIPInterface::set_dbit_offset() { validate(arg, retval, std::string("set dbit offset"), DEC); FILE_LOG(logDEBUG1) << "Dbit offset retval: " << retval; } - return interface->Server_SendResult(true, ret, &retval, sizeof(retval), mess); + return socket.sendResult(true, ret, &retval, sizeof(retval), mess); } \ No newline at end of file diff --git a/slsSupportLib/CMakeLists.txt b/slsSupportLib/CMakeLists.txt index f9a0134ac..1a675972f 100755 --- a/slsSupportLib/CMakeLists.txt +++ b/slsSupportLib/CMakeLists.txt @@ -6,6 +6,7 @@ set(SOURCES src/DataSocket.cpp src/ServerSocket.cpp src/ServerInterface.cpp + src/ServerInterface2.cpp src/network_utils.cpp ) diff --git a/slsSupportLib/include/ServerInterface2.h b/slsSupportLib/include/ServerInterface2.h new file mode 100644 index 000000000..997ee3e13 --- /dev/null +++ b/slsSupportLib/include/ServerInterface2.h @@ -0,0 +1,28 @@ +#pragma once + +#include "DataSocket.h" +namespace sls { +class ServerInterface2; +} + +#include "ServerSocket.h" +#include "sls_detector_defs.h" +namespace sls { + +class ServerInterface2 : public DataSocket { + using defs = slsDetectorDefs; + + public: + ServerInterface2(int socketId) : DataSocket(socketId){} + + int sendResult(bool update, int ret, void *retval, int retvalSize, + char *mess = nullptr); + int receiveArg(int &ret, char *mess, void *arg, int sizeofArg); + + + +private: + +}; + +} // namespace sls \ No newline at end of file diff --git a/slsSupportLib/include/ServerSocket.h b/slsSupportLib/include/ServerSocket.h index 4e15a820a..45abf942b 100755 --- a/slsSupportLib/include/ServerSocket.h +++ b/slsSupportLib/include/ServerSocket.h @@ -1,7 +1,8 @@ #pragma once #include "DataSocket.h" - +#include "ServerInterface2.h" +#include "network_utils.h" #include #include #include @@ -13,14 +14,18 @@ namespace sls { class ServerSocket : public DataSocket { public: ServerSocket(int port); - DataSocket accept(); - const std::string &getLastClient(); + ServerInterface2 accept(); + constexpr IpAddr getLastClient() noexcept { return lastClient; } + constexpr IpAddr getThisClient() noexcept { return thisClient; } + constexpr IpAddr getLockedBy() noexcept { return lockedBy; } + void setLockedBy(IpAddr addr){ lockedBy = addr; } int getPort() const; - void SendResult(int &ret, void *retval, int retvalSize, char* mess); + void SendResult(int &ret, void *retval, int retvalSize, char *mess); private: - std::string lastClient_ = std::string(INET_ADDRSTRLEN, '\0'); - std::string thisClient_ = std::string(INET_ADDRSTRLEN, '\0'); + IpAddr thisClient; + IpAddr lastClient; + IpAddr lockedBy; int serverPort; // char lastClient_[INET_ADDRSTRLEN]{}; }; diff --git a/slsSupportLib/include/network_utils.h b/slsSupportLib/include/network_utils.h index 59a7432a1..9a8410531 100755 --- a/slsSupportLib/include/network_utils.h +++ b/slsSupportLib/include/network_utils.h @@ -11,6 +11,7 @@ class IpAddr { uint32_t addr_{0}; public: + constexpr IpAddr() noexcept{} constexpr IpAddr(uint32_t address) noexcept : addr_{address} {} IpAddr(const std::string &address); IpAddr(const char *address); diff --git a/slsSupportLib/src/ServerInterface2.cpp b/slsSupportLib/src/ServerInterface2.cpp new file mode 100644 index 000000000..2eab250f5 --- /dev/null +++ b/slsSupportLib/src/ServerInterface2.cpp @@ -0,0 +1,32 @@ +#include "ServerInterface2.h" + +namespace sls { + +int ServerInterface2::sendResult(bool update, int ret, void *retval, + int retvalSize, char *mess) { + + // if (update && ret == defs::OK && server_->DifferentClients()) { + // ret = defs::FORCE_UPDATE; + // } + sendData(&ret, sizeof(ret)); + if (ret == defs::FAIL) { + // send error message + if (mess) + sendData(mess, MAX_STR_LENGTH); + // debugging feature. should not happen. + else + FILE_LOG(logERROR) << "No error message provided for this " + "failure. Will mess up TCP\n"; + } + sendData(retval, retvalSize); + return ret; +} + +int ServerInterface2::receiveArg(int &ret, char *mess, void *arg, + int sizeofArg) { + if (sizeofArg && receiveData(arg, sizeofArg) < 0) + return defs::FAIL; + return defs::OK; +} + +} // namespace sls diff --git a/slsSupportLib/src/ServerSocket.cpp b/slsSupportLib/src/ServerSocket.cpp index 7f07b49fc..a0d1f64e7 100755 --- a/slsSupportLib/src/ServerSocket.cpp +++ b/slsSupportLib/src/ServerSocket.cpp @@ -1,4 +1,6 @@ +#include "ServerInterface2.h" #include "ServerSocket.h" + #include "DataSocket.h" #include "logger.h" #include "sls_detector_defs.h" @@ -35,7 +37,8 @@ ServerSocket::ServerSocket(int port) } } -DataSocket ServerSocket::accept() { +ServerInterface2 ServerSocket::accept() { + lastClient = thisClient; //update from previous connection struct sockaddr_in clientAddr; socklen_t addr_size = sizeof clientAddr; int newSocket = @@ -43,17 +46,15 @@ DataSocket ServerSocket::accept() { if (newSocket == -1) { throw sls::SocketError("Server ERROR: socket accept failed\n"); } - inet_ntop(AF_INET, &(clientAddr.sin_addr), &thisClient_.front(), - INET_ADDRSTRLEN); - std::cout << "lastClient: " << lastClient_ << " thisClient: " << thisClient_ + char tc[INET_ADDRSTRLEN]{}; + inet_ntop(AF_INET, &(clientAddr.sin_addr), tc, INET_ADDRSTRLEN); + thisClient = tc; + std::cout << "lastClient: " << lastClient << " thisClient: " << thisClient << '\n'; - // Here goes any check for locks etc - lastClient_ = thisClient_; - return DataSocket(newSocket); + return ServerInterface2(newSocket); } -const std::string &ServerSocket::getLastClient() { return lastClient_; } int ServerSocket::getPort() const { return serverPort; } diff --git a/slsSupportLib/src/network_utils.cpp b/slsSupportLib/src/network_utils.cpp index a3dba74a8..3b71af9f4 100755 --- a/slsSupportLib/src/network_utils.cpp +++ b/slsSupportLib/src/network_utils.cpp @@ -16,6 +16,7 @@ namespace sls { + IpAddr::IpAddr(const std::string &address) { inet_pton(AF_INET, address.c_str(), &addr_); } From c6651df1b2724d0509443b4d74f36cbcb2dbde3d Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Thu, 16 May 2019 11:14:03 +0200 Subject: [PATCH 28/76] remove mySock --- slsDetectorSoftware/src/slsDetector.cpp | 8 +- .../include/slsReceiverTCPIPInterface.h | 34 ++- .../src/slsReceiverTCPIPInterface.cpp | 219 ++++++------------ slsSupportLib/include/DataSocket.h | 2 +- slsSupportLib/include/ServerSocket.h | 2 +- slsSupportLib/include/logger.h | 4 +- slsSupportLib/src/DataSocket.cpp | 2 +- 7 files changed, 91 insertions(+), 180 deletions(-) diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index d505b3eba..b904dc26a 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -3220,10 +3220,10 @@ int slsDetector::setReceiverOnline(int value) { } else { shm()->rxOnlineFlag = OFFLINE_FLAG; if (value == ONLINE_FLAG) { - // connect and set offline flag - auto receiver = - ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort); - receiver.close(); + // Connect and ask for receiver id to verify that + // it's online and working + int64_t retval{0}; + sendToReceiver(F_GET_RECEIVER_ID, nullptr, retval); shm()->rxOnlineFlag = ONLINE_FLAG; if (shm()->receiverAPIVersion == 0) { checkReceiverVersionCompatibility(); diff --git a/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h b/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h index 292b74bbd..37fdc7c75 100755 --- a/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h +++ b/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h @@ -299,6 +299,9 @@ class slsReceiverTCPIPInterface : private virtual slsDetectorDefs { int set_dbit_offset(sls::ServerInterface2 &socket); + int LogSocketCrash(); + void NullObjectError(int& ret, char* mess); + /** detector type */ detectorType myDetectorType; @@ -309,25 +312,25 @@ class slsReceiverTCPIPInterface : private virtual slsDetectorDefs { int (slsReceiverTCPIPInterface::*flist[NUM_REC_FUNCTIONS])(sls::ServerInterface2& socket); /** Message */ - char mess[MAX_STR_LENGTH]; + char mess[MAX_STR_LENGTH]{"dummy message"}; /** success/failure */ - int ret; + int ret{OK}; /** function index */ - int fnum; + int fnum{-1}; /** Lock Status if server locked to a client */ - int lockStatus; + int lockStatus{0}; /** kill tcp server thread */ - int killTCPServerThread; + int killTCPServerThread{0}; /** thread for TCP server */ pthread_t TCPServer_thread; /** tcp thread created flag*/ - bool tcpThreadCreated; + bool tcpThreadCreated{false}; /** port number */ int portNumber; @@ -345,16 +348,16 @@ class slsReceiverTCPIPInterface : private virtual slsDetectorDefs { * we write depending on file write enable * users get data to write depending on call backs registered */ - int (*startAcquisitionCallBack)(char*, char*, uint64_t, uint32_t, void*); - void *pStartAcquisition; + int (*startAcquisitionCallBack)(char*, char*, uint64_t, uint32_t, void*) = nullptr; + void *pStartAcquisition{nullptr}; /** * Call back for acquisition finished * callback argument is * total frames caught */ - void (*acquisitionFinishedCallBack)(uint64_t, void*); - void *pAcquisitionFinished; + void (*acquisitionFinishedCallBack)(uint64_t, void*) = nullptr; + void *pAcquisitionFinished{nullptr}; /** @@ -365,7 +368,7 @@ class slsReceiverTCPIPInterface : private virtual slsDetectorDefs { * dataSize in bytes is the size of the data in bytes. */ void (*rawDataReadyCallBack)(char* , - char*, uint32_t, void*); + char*, uint32_t, void*) = nullptr; /** * Call back for raw data (modified) @@ -375,22 +378,17 @@ class slsReceiverTCPIPInterface : private virtual slsDetectorDefs { * revDatasize is the reference of data size in bytes. Can be modified to the new size to be written/streamed. (only smaller value). */ void (*rawDataModifyReadyCallBack)(char* , - char*, uint32_t &, void*); + char*, uint32_t &, void*) = nullptr; - void *pRawDataReady; + void *pRawDataReady{nullptr}; protected: - /** Socket */ - MySocketTCP* mySock; std::unique_ptr server{nullptr}; - /** client interface */ - ServerInterface* interface; - private: int VerifyLock(int &ret, char *mess); int VerifyLockAndIdle(int &ret, char *mess, int fnum); diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp index b620fb094..bc55f67b3 100755 --- a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp +++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp @@ -5,7 +5,6 @@ #include "FixedCapacityContainer.h" -#include "MySocketTCP.h" #include "ServerSocket.h" #include "ServerInterface.h" #include "slsReceiver.h" @@ -13,6 +12,7 @@ #include "slsReceiverTCPIPInterface.h" #include "slsReceiverUsers.h" #include "versionAPI.h" +#include "string_utils.h" #include #include @@ -26,45 +26,12 @@ slsReceiverTCPIPInterface::~slsReceiverTCPIPInterface() { stop(); - delete mySock; - mySock=nullptr; - delete interface; - delete receiver; } slsReceiverTCPIPInterface::slsReceiverTCPIPInterface(int pn): myDetectorType(GOTTHARD), - receiver(nullptr), - ret(OK), - fnum(-1), - lockStatus(0), - killTCPServerThread(0), - tcpThreadCreated(false), - portNumber(DEFAULT_PORTNO+2), - mySock(nullptr), - interface(nullptr) + portNumber(pn > 0 ? pn : DEFAULT_PORTNO + 2) { - //***callback parameters*** - startAcquisitionCallBack = nullptr; - pStartAcquisition = nullptr; - acquisitionFinishedCallBack = nullptr; - pAcquisitionFinished = nullptr; - rawDataReadyCallBack = nullptr; - rawDataModifyReadyCallBack = nullptr; - pRawDataReady = nullptr; - - // create socket - portNumber = (pn > 0 ? pn : DEFAULT_PORTNO + 2); - // MySocketTCP* m = new MySocketTCP(portNumber); - // mySock = m; - // interface = new ServerInterface(mySock, -1, "Receiver"); - - //initialize variables - // strcpy(mySock->lastClientIP,"none"); - // strcpy(mySock->thisClientIP,"none1"); - memset(mess,0,sizeof(mess)); - strcpy(mess,"dummy message"); - function_table(); } @@ -86,7 +53,6 @@ void slsReceiverTCPIPInterface::stop(){ if (tcpThreadCreated) { FILE_LOG(logINFO) << "Shutting down TCP Socket on port " << portNumber; killTCPServerThread = 1; - // if(mySock) mySock->ShutDownSocket(); if(server) server->shutDownSocket(); FILE_LOG(logDEBUG) << "TCP Socket closed on port " << portNumber; @@ -134,30 +100,17 @@ void* slsReceiverTCPIPInterface::startTCPServerThread(void *this_pointer){ } void slsReceiverTCPIPInterface::startTCPServer() { - FILE_LOG(logINFOBLUE) << "Created [ TCP server Tid: " << syscall(SYS_gettid) - << "]"; - ; + FILE_LOG(logINFOBLUE) << "Created [ TCP server Tid: " + << syscall(SYS_gettid) << "]"; FILE_LOG(logINFO) << "SLS Receiver starting TCP Server on port " << portNumber << std::endl; int ret = OK; - server = sls::make_unique(portNumber); while (true) { - try { - std::cout << "<--------- hej\n"; auto socket = server->accept(); - std::cout << "<--------- hej2\n"; - socket.setTimeOut(1); - socket.setReceiveTimeout(1000); - std::cout << "<--------- hej3\n"; + socket.setReceiveTimeout(10000); ret = decode_function(socket); - std::cout << "<--------- hej4\n"; - socket.close(); - // if(mySock->Connect() >= 0){ - // ret = decode_function(); - // mySock->Disconnect(); - // } // if tcp command was to exit server if (ret == GOODBYE) { @@ -165,8 +118,6 @@ void slsReceiverTCPIPInterface::startTCPServer() { if (receiver) { receiver->shutDownUDPSockets(); } - - mySock->exitServer(); FILE_LOG(logINFOBLUE) << "Exiting [ TCP server Tid: " << syscall(SYS_gettid) << "]"; @@ -254,43 +205,38 @@ int slsReceiverTCPIPInterface::function_table(){ return OK; } - - - -int slsReceiverTCPIPInterface::decode_function(sls::ServerInterface2 &socket){ - ret = FAIL; - std::cout << "<------ decode 1\n"; - int n = socket.read(&fnum, sizeof(fnum)); - std::cout << "<------ decode 2\n"; - if (n <= 0) { - FILE_LOG(logDEBUG3) << "Could not read socket. " - "Received " << n << " bytes," << - "fnum:" << fnum << " " - "(" << getFunctionNameFromEnum((enum detFuncs)fnum) << ")"; - return FAIL; - } - else - FILE_LOG(logDEBUG3) << "Received " << n << " bytes"; - - if (fnum <= NUM_DET_FUNCTIONS || fnum >= NUM_REC_FUNCTIONS) { - FILE_LOG(logERROR) << "Unknown function enum " << fnum; - ret = (this->M_nofunc)(socket); - } else{ - FILE_LOG(logDEBUG1) << "calling function fnum: "<< fnum << " " - "(" << getFunctionNameFromEnum((enum detFuncs)fnum) << ") " - "located at " << flist[fnum]; - ret = (this->*flist[fnum])(socket); - - if (ret == FAIL) { - FILE_LOG(logDEBUG1) << "Failed to execute function = " << fnum << " (" - << getFunctionNameFromEnum((enum detFuncs)fnum) << ")"; - } else FILE_LOG(logDEBUG1) << "Function " << - getFunctionNameFromEnum((enum detFuncs)fnum) << " executed OK"; - } - return ret; +int slsReceiverTCPIPInterface::decode_function(sls::ServerInterface2 &socket) { + ret = FAIL; + int n = socket.read(&fnum, sizeof(fnum)); + if (n <= 0) { + FILE_LOG(logDEBUG3) + << "Could not read socket. Received " << n + << " bytes, fnum:" << fnum << " (" + << getFunctionNameFromEnum((enum detFuncs)fnum) << ")"; + return FAIL; + } else { + FILE_LOG(logDEBUG3) << "Received " << n << " bytes"; + } + if (fnum <= NUM_DET_FUNCTIONS || fnum >= NUM_REC_FUNCTIONS) { + FILE_LOG(logERROR) << "Unknown function enum " << fnum; + ret = (this->M_nofunc)(socket); + } else { + FILE_LOG(logDEBUG1) << "calling function fnum: " << fnum << " (" + << getFunctionNameFromEnum((enum detFuncs)fnum) + << ") located at " << flist[fnum]; + ret = (this->*flist[fnum])(socket); + if (ret == FAIL) { + FILE_LOG(logDEBUG1) + << "Failed to execute function = " << fnum << " (" + << getFunctionNameFromEnum((enum detFuncs)fnum) << ")"; + } else + FILE_LOG(logDEBUG1) + << "Function " << getFunctionNameFromEnum((enum detFuncs)fnum) + << " executed OK"; + } + return ret; } - void slsReceiverTCPIPInterface::functionNotImplemented() { ret = FAIL; sprintf(mess, "Function (%s) is not implemented for this detector\n", @@ -322,9 +268,6 @@ int slsReceiverTCPIPInterface::M_nofunc(sls::ServerInterface2 &socket){ ret = FAIL; memset(mess, 0, sizeof(mess)); - // to receive any arguments - - socket.setReceiveTimeout(500); int n = 1; while (n > 0) n = socket.read(mess, MAX_STR_LENGTH); @@ -428,8 +371,9 @@ int slsReceiverTCPIPInterface::lock_receiver(sls::ServerInterface2 &socket) { int slsReceiverTCPIPInterface::get_last_client_ip(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); - auto ip = server->getLastClient().str(); - return socket.sendResult(true, ret, &ip.front(), ip.length()+1, nullptr); + char ip[INET_ADDRSTRLEN]{}; + sls::strcpy_safe(ip, server->getLastClient().str().c_str()); + return socket.sendResult(true, ret, &ip, sizeof(ip)); } @@ -438,30 +382,23 @@ int slsReceiverTCPIPInterface::set_port(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); int p_number = -1; - MySocketTCP* mySocket = nullptr; - char oldLastClientIP[INET_ADDRSTRLEN] = {0}; - - // get args, return if socket crashed if (socket.receiveArg(ret, mess, &p_number, sizeof(p_number)) == FAIL) return FAIL; - // verify if receiver is unlocked if (VerifyLock(ret, mess) == OK) { - // port number too low if (p_number < 1024) { ret = FAIL; sprintf(mess,"Port Number (%d) too low\n", p_number); FILE_LOG(logERROR) << mess; } else { FILE_LOG(logINFO) << "set port to " << p_number <lastClientIP); - // create new socket try { - mySocket = new MySocketTCP(p_number); - strcpy(mySock->lastClientIP,oldLastClientIP); + auto new_server = sls::make_unique(p_number); + new_server->setLockedBy(server->getLockedBy()); + new_server->setLastClient(server->getLastClient()); + server = std::move(new_server); } catch(SocketError &e) { ret = FAIL; - // same socket, could not bind port sprintf(mess, "%s", e.what()); FILE_LOG(logERROR) << mess; } catch (...) { @@ -473,13 +410,6 @@ int slsReceiverTCPIPInterface::set_port(sls::ServerInterface2 &socket) { } socket.sendResult(true, ret, &p_number,sizeof(p_number), mess); - // delete old socket - if(ret != FAIL){ - mySock->Disconnect(); - delete mySock; - mySock = mySocket; - interface->SetSocket(mySock); - } return ret; } @@ -505,10 +435,11 @@ int slsReceiverTCPIPInterface::update_client(sls::ServerInterface2 &socket) { int slsReceiverTCPIPInterface::send_update(sls::ServerInterface2 &socket) { int n = 0; int i32 = -1; - char cstring[MAX_STR_LENGTH] = {0}; + char cstring[MAX_STR_LENGTH]{}; - - n += socket.sendData(mySock->lastClientIP,sizeof(mySock->lastClientIP)); + char ip[INET_ADDRSTRLEN]{}; + sls::strcpy_safe(ip, server->getLastClient().str().c_str()); + n += socket.sendData(ip,sizeof(ip)); // filepath strcpy(cstring, receiver->getFilePath().c_str()); @@ -600,9 +531,6 @@ int slsReceiverTCPIPInterface::send_update(sls::ServerInterface2 &socket) { i32=receiver->getDbitOffset(); n += socket.sendData(&i32, sizeof(i32)); - // if (!lockStatus) - // strcpy(mySock->lastClientIP, mySock->thisClientIP); - return OK; } @@ -668,10 +596,6 @@ int slsReceiverTCPIPInterface::set_detector_type(sls::ServerInterface2 &socket){ receiver->registerCallBackRawDataReady(rawDataReadyCallBack,pRawDataReady); if(rawDataModifyReadyCallBack) receiver->registerCallBackRawDataModifyReady(rawDataModifyReadyCallBack,pRawDataReady); - - // // client has started updating receiver, update ip - // if (!lockStatus) - // strcpy(mySock->lastClientIP, mySock->thisClientIP); } } @@ -715,27 +639,30 @@ int slsReceiverTCPIPInterface::set_detector_hostname(sls::ServerInterface2 &sock return socket.sendResult(true, ret, retval, MAX_STR_LENGTH, mess); } +int slsReceiverTCPIPInterface::LogSocketCrash(){ + FILE_LOG(logERROR) << "Reading from socket failed. Possible socket crash"; + return FAIL; +} + +void slsReceiverTCPIPInterface::NullObjectError(int& ret, char* mess){ + ret=FAIL; + strcpy(mess,"Receiver not set up. Please use rx_hostname first.\n"); + FILE_LOG(logERROR) << mess; +} + int slsReceiverTCPIPInterface::set_roi(sls::ServerInterface2 &socket) { ret = OK; memset(mess, 0, sizeof(mess)); + static_assert(sizeof(ROI) == 4*sizeof(int), "ROI not packed"); int narg = -1; - std::vector arg; + socket.read(&narg,sizeof(narg)); - // receive arguments - if (mySock->ReceiveDataOnly(&narg,sizeof(narg)) < 0 ) - return interface->Server_SocketCrash(); + std::vector arg; for (int iloop = 0; iloop < narg; ++iloop) { - ROI temp; - if ( mySock->ReceiveDataOnly(&temp.xmin, sizeof(int)) < 0 ) - return interface->Server_SocketCrash(); - if ( mySock->ReceiveDataOnly(&temp.xmax, sizeof(int)) < 0 ) - return interface->Server_SocketCrash(); - if ( mySock->ReceiveDataOnly(&temp.ymin, sizeof(int)) < 0 ) - return interface->Server_SocketCrash(); - if ( mySock->ReceiveDataOnly(&temp.ymax, sizeof(int)) < 0 ) - return interface->Server_SocketCrash(); + ROI temp{}; + socket.read(&temp, sizeof(temp)); arg.push_back(temp); } FILE_LOG(logDEBUG1) << "Set ROI narg: " << narg; @@ -750,14 +677,11 @@ int slsReceiverTCPIPInterface::set_roi(sls::ServerInterface2 &socket) { // base object not null else if (receiver == nullptr) - interface->Server_NullObjectError(ret, mess); + NullObjectError(ret, mess); else { - // only set - // verify if receiver is unlocked and idle if (VerifyLockAndIdle(ret, mess, fnum) == OK) ret = receiver->setROI(arg); } - arg.clear(); return socket.sendResult(true, ret, nullptr, 0, mess); } @@ -766,8 +690,8 @@ int slsReceiverTCPIPInterface::set_roi(sls::ServerInterface2 &socket) { int slsReceiverTCPIPInterface::setup_udp(sls::ServerInterface2 &socket){ ret = OK; memset(mess, 0, sizeof(mess)); - char args[6][MAX_STR_LENGTH] = {{""}, {""}, {""}, {""}, {""}, {""}}; - char retvals[2][MAX_STR_LENGTH] = {{""}, {""}}; + char args[6][MAX_STR_LENGTH]{}; + char retvals[2][MAX_STR_LENGTH]{}; // get args, return if socket crashed, ret is fail if receiver is not null if (socket.receiveArg(ret, mess, args, sizeof(args)) == FAIL) @@ -2094,7 +2018,6 @@ int slsReceiverTCPIPInterface::set_deactivated_padding_enable(sls::ServerInterfa else if (ret == OK) { // set if (enable >= 0) { - // verify if receiver is unlocked and idle if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting deactivated padding enable: " << enable; receiver->setDeactivatedPadding(enable > 0 ? true : false); @@ -2154,14 +2077,10 @@ int slsReceiverTCPIPInterface::set_adc_mask(sls::ServerInterface2 &socket) { // base object not null else if (ret == OK) { - // set - // verify if receiver is unlocked and idle if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting ADC enable mask: " << arg; receiver->setADCEnableMask(arg); } - - // get retval = receiver->getADCEnableMask(); if (ret == OK && retval != arg) { ret = FAIL; @@ -2185,7 +2104,7 @@ int slsReceiverTCPIPInterface::set_dbit_list(sls::ServerInterface2 &socket) { FILE_LOG(logDEBUG1) << it << " "; } FILE_LOG(logDEBUG1) << "\n"; - if (interface->Server_VerifyLockAndIdle(ret, mess, lockStatus, receiver->getStatus(), fnum) == OK) { + if (VerifyLockAndIdle(ret, mess, fnum) == OK) { if (args.size() > 64) { ret = FAIL; sprintf(mess, "Could not set dbit list as size is > 64\n"); @@ -2193,8 +2112,6 @@ int slsReceiverTCPIPInterface::set_dbit_list(sls::ServerInterface2 &socket) { } else receiver->setDbitList(args); } - - } return socket.sendResult(true, ret, nullptr, 0, mess); } @@ -2209,7 +2126,6 @@ int slsReceiverTCPIPInterface::get_dbit_list(sls::ServerInterface2 &socket) { // base object not null if (ret == OK) { - // get retval = receiver->getDbitList(); FILE_LOG(logDEBUG1) << "Dbit list size retval:" << retval.size(); } @@ -2229,15 +2145,12 @@ int slsReceiverTCPIPInterface::set_dbit_offset(sls::ServerInterface2 &socket) { // base object not null else if (ret == OK) { - // set if (arg >= 0) { - // verify if receiver is unlocked and idle if (VerifyLockAndIdle(ret, mess, fnum) == OK) { FILE_LOG(logDEBUG1) << "Setting Dbit offset: " << arg; receiver->setDbitOffset(arg); } } - // get retval = receiver->getDbitOffset(); validate(arg, retval, std::string("set dbit offset"), DEC); FILE_LOG(logDEBUG1) << "Dbit offset retval: " << retval; diff --git a/slsSupportLib/include/DataSocket.h b/slsSupportLib/include/DataSocket.h index a9e7dcc6e..87de7d39d 100755 --- a/slsSupportLib/include/DataSocket.h +++ b/slsSupportLib/include/DataSocket.h @@ -20,7 +20,7 @@ class DataSocket { } size_t sendData(const void *buffer, size_t size); size_t receiveData(void *buffer, size_t size); - size_t read(void *buffer, size_t size); + ssize_t read(void *buffer, size_t size); int setTimeOut(int t_seconds); int setReceiveTimeout(int us); void close(); diff --git a/slsSupportLib/include/ServerSocket.h b/slsSupportLib/include/ServerSocket.h index 45abf942b..505eb3568 100755 --- a/slsSupportLib/include/ServerSocket.h +++ b/slsSupportLib/include/ServerSocket.h @@ -19,6 +19,7 @@ class ServerSocket : public DataSocket { constexpr IpAddr getThisClient() noexcept { return thisClient; } constexpr IpAddr getLockedBy() noexcept { return lockedBy; } void setLockedBy(IpAddr addr){ lockedBy = addr; } + void setLastClient(IpAddr addr){ lastClient = addr; } int getPort() const; void SendResult(int &ret, void *retval, int retvalSize, char *mess); @@ -27,7 +28,6 @@ class ServerSocket : public DataSocket { IpAddr lastClient; IpAddr lockedBy; int serverPort; - // char lastClient_[INET_ADDRSTRLEN]{}; }; }; // namespace sls \ No newline at end of file diff --git a/slsSupportLib/include/logger.h b/slsSupportLib/include/logger.h index 541da95b0..8de0c2f49 100755 --- a/slsSupportLib/include/logger.h +++ b/slsSupportLib/include/logger.h @@ -17,8 +17,8 @@ #endif #ifndef FILELOG_MAX_LEVEL -// #define FILELOG_MAX_LEVEL logINFO -#define FILELOG_MAX_LEVEL logDEBUG5 +#define FILELOG_MAX_LEVEL logINFO +// #define FILELOG_MAX_LEVEL logDEBUG5 #endif diff --git a/slsSupportLib/src/DataSocket.cpp b/slsSupportLib/src/DataSocket.cpp index 3da9cbf75..9a70c5c19 100755 --- a/slsSupportLib/src/DataSocket.cpp +++ b/slsSupportLib/src/DataSocket.cpp @@ -50,7 +50,7 @@ size_t DataSocket::receiveData(void *buffer, size_t size) { return dataRead; } -size_t DataSocket::read(void *buffer, size_t size){ +ssize_t DataSocket::read(void *buffer, size_t size){ return ::read(getSocketId(), reinterpret_cast(buffer), size); } From 9a8773d9a59abdc621a9f6d7a083b94f0d2a725a Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Thu, 16 May 2019 11:25:18 +0200 Subject: [PATCH 29/76] ip test --- slsSupportLib/tests/test-network_utils.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/slsSupportLib/tests/test-network_utils.cpp b/slsSupportLib/tests/test-network_utils.cpp index c9457da4f..54683807c 100755 --- a/slsSupportLib/tests/test-network_utils.cpp +++ b/slsSupportLib/tests/test-network_utils.cpp @@ -42,9 +42,9 @@ TEST_CASE("Hex representation of MAC", "[support]") { } TEST_CASE("Convert IP using classes ", "[support]") { - std::vector vec_addr{4073554305, 2747957633, 2697625985}; + std::vector vec_addr{4073554305, 2747957633, 2697625985, 16779786}; std::vector vec_ans{"129.129.205.242", "129.129.202.163", - "129.129.202.160"}; + "129.129.202.160", "10.10.0.1"}; for (size_t i = 0; i != vec_addr.size(); ++i) { auto ip0 = IpAddr(vec_addr[i]); From 54983c5fd0ea626e1a80c9f6bccdbc74795aecd6 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Thu, 16 May 2019 11:36:25 +0200 Subject: [PATCH 30/76] removing constexpr --- slsSupportLib/include/ServerSocket.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/slsSupportLib/include/ServerSocket.h b/slsSupportLib/include/ServerSocket.h index 505eb3568..74831a46d 100755 --- a/slsSupportLib/include/ServerSocket.h +++ b/slsSupportLib/include/ServerSocket.h @@ -15,11 +15,11 @@ class ServerSocket : public DataSocket { public: ServerSocket(int port); ServerInterface2 accept(); - constexpr IpAddr getLastClient() noexcept { return lastClient; } - constexpr IpAddr getThisClient() noexcept { return thisClient; } - constexpr IpAddr getLockedBy() noexcept { return lockedBy; } - void setLockedBy(IpAddr addr){ lockedBy = addr; } - void setLastClient(IpAddr addr){ lastClient = addr; } + IpAddr getLastClient() noexcept { return lastClient; } + IpAddr getThisClient() noexcept { return thisClient; } + IpAddr getLockedBy() noexcept { return lockedBy; } + void setLockedBy(IpAddr addr) { lockedBy = addr; } + void setLastClient(IpAddr addr) { lastClient = addr; } int getPort() const; void SendResult(int &ret, void *retval, int retvalSize, char *mess); From 0d98bd0048fbe14a45358c0819f7af0b4dc3c5f9 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Thu, 16 May 2019 11:43:12 +0200 Subject: [PATCH 31/76] init --- slsReceiverSoftware/include/slsReceiverTCPIPInterface.h | 2 +- slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h b/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h index 37fdc7c75..d54e92cc5 100755 --- a/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h +++ b/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h @@ -312,7 +312,7 @@ class slsReceiverTCPIPInterface : private virtual slsDetectorDefs { int (slsReceiverTCPIPInterface::*flist[NUM_REC_FUNCTIONS])(sls::ServerInterface2& socket); /** Message */ - char mess[MAX_STR_LENGTH]{"dummy message"}; + char mess[MAX_STR_LENGTH] = "dummy message"; /** success/failure */ int ret{OK}; diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp index bc55f67b3..1414f31a9 100755 --- a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp +++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp @@ -29,9 +29,10 @@ slsReceiverTCPIPInterface::~slsReceiverTCPIPInterface() { } slsReceiverTCPIPInterface::slsReceiverTCPIPInterface(int pn): - myDetectorType(GOTTHARD), - portNumber(pn > 0 ? pn : DEFAULT_PORTNO + 2) + myDetectorType(GOTTHARD) + { + portNumber = pn > 0 ? pn : DEFAULT_PORTNO + 2; function_table(); } From 1db1b0307c909bbe0b43b2779d13a1e11463d3bd Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Thu, 16 May 2019 11:50:35 +0200 Subject: [PATCH 32/76] init --- slsReceiverSoftware/include/slsReceiverTCPIPInterface.h | 2 +- slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h b/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h index d54e92cc5..4676ac532 100755 --- a/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h +++ b/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h @@ -312,7 +312,7 @@ class slsReceiverTCPIPInterface : private virtual slsDetectorDefs { int (slsReceiverTCPIPInterface::*flist[NUM_REC_FUNCTIONS])(sls::ServerInterface2& socket); /** Message */ - char mess[MAX_STR_LENGTH] = "dummy message"; + char mess[MAX_STR_LENGTH]{}; /** success/failure */ int ret{OK}; diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp index 1414f31a9..bc55f67b3 100755 --- a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp +++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp @@ -29,10 +29,9 @@ slsReceiverTCPIPInterface::~slsReceiverTCPIPInterface() { } slsReceiverTCPIPInterface::slsReceiverTCPIPInterface(int pn): - myDetectorType(GOTTHARD) - + myDetectorType(GOTTHARD), + portNumber(pn > 0 ? pn : DEFAULT_PORTNO + 2) { - portNumber = pn > 0 ? pn : DEFAULT_PORTNO + 2; function_table(); } From 9315768159406661548a76d93cbc2dd6668d2638 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Thu, 16 May 2019 14:07:58 +0200 Subject: [PATCH 33/76] client bug fix: smaller ips convert to hex --- slsSupportLib/src/network_utils.cpp | 4 ++-- slsSupportLib/tests/test-network_utils.cpp | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/slsSupportLib/src/network_utils.cpp b/slsSupportLib/src/network_utils.cpp index a3dba74a8..6147cfb19 100755 --- a/slsSupportLib/src/network_utils.cpp +++ b/slsSupportLib/src/network_utils.cpp @@ -31,9 +31,9 @@ std::string IpAddr::str() const { } std::string IpAddr::hex() const { std::ostringstream ss; - ss << std::hex << std::setfill('0') << std::setw(2); for (int i = 0; i != 4; ++i) { - ss << ((addr_ >> i * 8) & 0xFF); + ss << std::hex << std::setfill('0') << std::setw(2) + << ((addr_ >> i * 8) & 0xFF); } return ss.str(); } diff --git a/slsSupportLib/tests/test-network_utils.cpp b/slsSupportLib/tests/test-network_utils.cpp index c9457da4f..a9d68ae19 100755 --- a/slsSupportLib/tests/test-network_utils.cpp +++ b/slsSupportLib/tests/test-network_utils.cpp @@ -42,9 +42,12 @@ TEST_CASE("Hex representation of MAC", "[support]") { } TEST_CASE("Convert IP using classes ", "[support]") { - std::vector vec_addr{4073554305, 2747957633, 2697625985}; + std::vector vec_addr{4073554305, 2747957633, 2697625985, 2566979594, 0}; std::vector vec_ans{"129.129.205.242", "129.129.202.163", - "129.129.202.160"}; + "129.129.202.160", "10.0.1.153", "0.0.0.0"}; + std::vector vec_hex{"8181cdf2", "8181caa3", + "8181caa0", "0a000199","00000000"}; + for (size_t i = 0; i != vec_addr.size(); ++i) { auto ip0 = IpAddr(vec_addr[i]); @@ -57,6 +60,8 @@ TEST_CASE("Convert IP using classes ", "[support]") { CHECK(ip1 == vec_ans[i]); CHECK(ip0.str() == vec_ans[i]); CHECK(ip1.str() == vec_ans[i]); + CHECK(ip0.hex() == vec_hex[i]); + CHECK(ip1.hex() == vec_hex[i]); } } From 615d1b1f338b4aac805fbc6b747b0352dfbf01fb Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Thu, 16 May 2019 14:27:16 +0200 Subject: [PATCH 34/76] refactor --- .../src/slsReceiverTCPIPInterface.cpp | 12 ++-- slsSupportLib/include/network_utils.h | 6 +- slsSupportLib/src/network_utils.cpp | 61 ++++++++++++++++++- 3 files changed, 71 insertions(+), 8 deletions(-) diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp index bc55f67b3..87cfaaf53 100755 --- a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp +++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp @@ -6,13 +6,13 @@ #include "FixedCapacityContainer.h" #include "ServerSocket.h" -#include "ServerInterface.h" #include "slsReceiver.h" #include "slsReceiverImplementation.h" #include "slsReceiverTCPIPInterface.h" #include "slsReceiverUsers.h" #include "versionAPI.h" #include "string_utils.h" +#include "sls_detector_exceptions.h" #include #include @@ -24,6 +24,8 @@ #include #include +using sls::SocketError; + slsReceiverTCPIPInterface::~slsReceiverTCPIPInterface() { stop(); } @@ -725,7 +727,7 @@ int slsReceiverTCPIPInterface::setup_udp(sls::ServerInterface2 &socket){ } FILE_LOG(logINFO) << "Receiver UDP IP: " << ip1; // get eth - std::string temp = genericSocket::ipToName(ip1); + std::string temp = sls::IpToInterfaceName(ip1); if (temp == "none"){ ret = FAIL; strcpy(mess, "Failed to get ethernet interface or IP \n"); @@ -747,7 +749,7 @@ int slsReceiverTCPIPInterface::setup_udp(sls::ServerInterface2 &socket){ } //get mac address if (ret != FAIL) { - temp = genericSocket::nameToMac(eth); + temp = sls::InterfaceNameToMac(eth).str(); if (temp=="00:00:00:00:00:00") { ret = FAIL; strcpy(mess,"failed to get mac adddress to listen to\n"); @@ -771,7 +773,7 @@ int slsReceiverTCPIPInterface::setup_udp(sls::ServerInterface2 &socket){ receiver->setUDPPortNumber2(port2); FILE_LOG(logINFO) << "Receiver UDP IP 2: " << ip2; // get eth - temp = genericSocket::ipToName(ip2); + temp = sls::IpToInterfaceName(ip2); if (temp == "none"){ ret = FAIL; strcpy(mess, "Failed to get 2nd ethernet interface or IP \n"); @@ -791,7 +793,7 @@ int slsReceiverTCPIPInterface::setup_udp(sls::ServerInterface2 &socket){ //get mac address if (ret != FAIL) { - temp = genericSocket::nameToMac(eth); + temp = sls::InterfaceNameToMac(eth).str(); if (temp=="00:00:00:00:00:00") { ret = FAIL; strcpy(mess,"failed to get 2nd mac adddress to listen to\n"); diff --git a/slsSupportLib/include/network_utils.h b/slsSupportLib/include/network_utils.h index 9a8410531..e4a963033 100755 --- a/slsSupportLib/include/network_utils.h +++ b/slsSupportLib/include/network_utils.h @@ -4,8 +4,6 @@ namespace sls { -uint32_t HostnameToIp(const char *hostname); - class IpAddr { private: uint32_t addr_{0}; @@ -58,6 +56,10 @@ class MacAddr { constexpr uint64_t uint64() const noexcept { return addr_; } }; +uint32_t HostnameToIp(const char *hostname); +std::string IpToInterfaceName(const std::string& ip); +MacAddr InterfaceNameToMac(std::string inf); + std::ostream &operator<<(std::ostream &out, const IpAddr &addr); std::ostream &operator<<(std::ostream &out, const MacAddr &addr); diff --git a/slsSupportLib/src/network_utils.cpp b/slsSupportLib/src/network_utils.cpp index 3b71af9f4..5153cf234 100755 --- a/slsSupportLib/src/network_utils.cpp +++ b/slsSupportLib/src/network_utils.cpp @@ -6,11 +6,14 @@ #include #include #include - +#include #include #include #include #include +#include +#include +#include #include "network_utils.h" @@ -93,4 +96,60 @@ uint32_t HostnameToIp(const char *hostname) { return ip; } +std::string IpToInterfaceName(const std::string &ip) { + //TODO! Copied from genericSocket needs to be refactored! + struct ifaddrs *addrs, *iap; + struct sockaddr_in *sa; + + char buf[32]; + const int buf_len = sizeof(buf); + memset(buf, 0, buf_len); + strcpy(buf, "none"); + + getifaddrs(&addrs); + for (iap = addrs; iap != NULL; iap = iap->ifa_next) { + if (iap->ifa_addr && (iap->ifa_flags & IFF_UP) && + iap->ifa_addr->sa_family == AF_INET) { + sa = (struct sockaddr_in *)(iap->ifa_addr); + inet_ntop(iap->ifa_addr->sa_family, (void *)&(sa->sin_addr), buf, + buf_len); + if (ip == std::string(buf)) { + strcpy(buf, iap->ifa_name); + break; + } + } + } + freeifaddrs(addrs); + return std::string(buf); +} + +MacAddr InterfaceNameToMac(std::string inf) { + //TODO! Copied from genericSocket needs to be refactored! + struct ifreq ifr; + char mac[32]; + const int mac_len = sizeof(mac); + memset(mac,0,mac_len); + + int sock=socket(PF_INET, SOCK_STREAM, 0); + strncpy(ifr.ifr_name,inf.c_str(),sizeof(ifr.ifr_name)-1); + ifr.ifr_name[sizeof(ifr.ifr_name)-1]='\0'; + + + if (-1==ioctl(sock, SIOCGIFHWADDR, &ifr)) { + perror("ioctl(SIOCGIFHWADDR) "); + return std::string("00:00:00:00:00:00"); + } + for (int j=0, k=0; j<6; j++) { + k+=snprintf(mac+k, mac_len-k-1, j ? ":%02X" : "%02X", + (int)(unsigned int)(unsigned char)ifr.ifr_hwaddr.sa_data[j]); + } + mac[mac_len-1]='\0'; + + if(sock!=1){ + close(sock); + } + return MacAddr(mac); + + } + } // namespace sls From c30c6bb88377e2aa3e6aacad5ea7e63cc6fa4615 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Thu, 16 May 2019 15:00:15 +0200 Subject: [PATCH 35/76] fixed uninitialized pointer --- slsReceiverSoftware/include/slsReceiverTCPIPInterface.h | 2 +- slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h b/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h index 4676ac532..77ea28485 100755 --- a/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h +++ b/slsReceiverSoftware/include/slsReceiverTCPIPInterface.h @@ -306,7 +306,7 @@ class slsReceiverTCPIPInterface : private virtual slsDetectorDefs { detectorType myDetectorType; /** slsReceiverBase object */ - slsReceiverImplementation *receiver; + slsReceiverImplementation *receiver{nullptr}; /** Function List */ int (slsReceiverTCPIPInterface::*flist[NUM_REC_FUNCTIONS])(sls::ServerInterface2& socket); diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp index 87cfaaf53..2e3344d2b 100755 --- a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp +++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp @@ -1906,7 +1906,6 @@ int slsReceiverTCPIPInterface::check_version_compatibility(sls::ServerInterface2 ret = OK; memset(mess, 0, sizeof(mess)); int64_t arg = -1; - std::cout << "<----------------- HEY\n"; // get args, return if socket crashed if (socket.receiveArg(ret, mess, &arg, sizeof(arg)) == FAIL) return FAIL; From e6ad80e187c56806a9f8555b527f587ff24d4828 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Thu, 16 May 2019 15:10:24 +0200 Subject: [PATCH 36/76] removed cout --- slsSupportLib/src/ServerSocket.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/slsSupportLib/src/ServerSocket.cpp b/slsSupportLib/src/ServerSocket.cpp index a0d1f64e7..35048268b 100755 --- a/slsSupportLib/src/ServerSocket.cpp +++ b/slsSupportLib/src/ServerSocket.cpp @@ -49,9 +49,6 @@ ServerInterface2 ServerSocket::accept() { char tc[INET_ADDRSTRLEN]{}; inet_ntop(AF_INET, &(clientAddr.sin_addr), tc, INET_ADDRSTRLEN); thisClient = tc; - std::cout << "lastClient: " << lastClient << " thisClient: " << thisClient - << '\n'; - return ServerInterface2(newSocket); } From 1943e77b243e1495e172d93c996fd7ae55a25151 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Thu, 16 May 2019 15:12:42 +0200 Subject: [PATCH 37/76] server interface: ip made to use inet_ntop, mac address and ip to string made common --- .../bin/eigerDetectorServer_developer | Bin 289172 -> 289212 bytes .../slsDetectorFunctionList.c | 26 ++---- .../slsDetectorServer_defs.h | 1 + .../slsDetectorServer/communication_funcs.c | 16 ++++ .../slsDetectorServer/communication_funcs.h | 15 ++++ .../slsDetectorServer_funcs.c | 83 +++++++----------- slsSupportLib/include/versionAPI.h | 2 +- 7 files changed, 75 insertions(+), 68 deletions(-) diff --git a/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer b/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer index e8fc3dea528c8820f84b37f8838ef8fd606983d4..5381a6f4234bd31a83d3d0d144332d4cdc5c457f 100755 GIT binary patch delta 51869 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