From cff4d162c1ca6c2201c9b52196c4c4b263eb9054 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Wed, 7 Aug 2019 11:52:03 +0200 Subject: [PATCH 001/108] commenting headers already done, adding positions for filename and filepath, pos instead of Positions{} --- slsDetectorSoftware/include/Detector.h | 12 +++-- .../include/multiSlsDetector.h | 50 +++++++++---------- slsDetectorSoftware/src/Detector.cpp | 27 +++++----- 3 files changed, 48 insertions(+), 41 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 3dd3b40ad..9ac13bbec 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -101,15 +101,15 @@ class Detector { * @param pos detector positions * @returns file name prefix */ - Result getFileName() const; + Result getFileName(Positions pos = {}) const; /** * Sets the receiver file name prefix * @param fname file name prefix */ - void setFileName(const std::string &fname); - Result getFilePath() const; - void setFilePath(const std::string &fname); + void setFileName(const std::string &fname, Positions pos = {}); + Result getFilePath(Positions pos = {}) const; + void setFilePath(const std::string &fname, Positions pos = {}); Result getFileWrite(Positions pos = {}) const; void setFileWrite(bool value, Positions pos = {}); Result getFileOverWrite(Positions pos = {}) const; @@ -122,6 +122,10 @@ class Detector { void setSubExptime(ns t, Positions pos = {}); Result getPeriod(Positions pos = {}) const; void setPeriod(ns t, Positions pos = {}); + + // dhanya + + }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index ef9908af7..a420d3b60 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -266,13 +266,13 @@ class multiSlsDetector : public virtual slsDetectorDefs { * Set acquiring flag in shared memory * @param b acquiring flag */ - void setAcquiringFlag(bool flag); + void setAcquiringFlag(bool flag);// /** * Get acquiring flag from shared memory * @returns acquiring flag */ - bool getAcquiringFlag() const; + bool getAcquiringFlag() const;// /** * Check if acquiring flag is set, set error if set @@ -329,7 +329,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param multiId multi detector Id * @param detPos -1 for all detectors in list or specific detector position */ - static void freeSharedMemory(int multiId, int detPos = -1); + static void freeSharedMemory(int multiId, int detPos = -1);// /** * Free shared memory and delete shared memory structure @@ -361,7 +361,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns concatenated hostnames of all detectors or hostname of specific * one */ - std::string getHostname(int detPos = -1) const; + std::string getHostname(int detPos = -1) const;// /** * Appends detectors to the end of the list in shared memory @@ -578,7 +578,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * Load configuration from a configuration File * @param fname configuration file name */ - void readConfigurationFile(const std::string &fname); + void readConfigurationFile(const std::string &fname);// /** * Write current configuration to a file @@ -715,14 +715,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @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); + 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); + uint64_t getStartingFrameNumber(int detPos = -1);// /** * Set/get timer value (not all implemented for all detectors) @@ -742,7 +742,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns exposure time in ns, or s if specified */ double setExposureTime(double t = -1, bool inseconds = false, - int detPos = -1); + int detPos = -1);// /** * Set/get exposure period @@ -752,7 +752,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns exposure period in ns, or s if specified */ double setExposurePeriod(double t = -1, bool inseconds = false, - int detPos = -1); + int detPos = -1);// /** * Set/get delay after trigger (Gotthard, Jungfrau(not for this release)) @@ -773,7 +773,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns sub frame exposure time in ns, or s if specified */ double setSubFrameExposureTime(double t = -1, bool inseconds = false, - int detPos = -1); + int detPos = -1);// /** * (Advanced users) @@ -959,7 +959,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns value read from register */ - uint32_t readRegister(uint32_t addr, int detPos = -1); + uint32_t readRegister(uint32_t addr, int detPos = -1);// /** * Set bit in a register. For Advanced users @@ -968,7 +968,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns value read from register */ - uint32_t setBit(uint32_t addr, int n, int detPos = -1); + uint32_t setBit(uint32_t addr, int n, int detPos = -1);// /** * Clear bit in a register. For Advanced users @@ -977,7 +977,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns value read from register */ - uint32_t clearBit(uint32_t addr, int n, int detPos = -1); + uint32_t clearBit(uint32_t addr, int n, int detPos = -1);// /** * Validates the format of the detector MAC address and sets it @@ -1787,7 +1787,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns output file directory */ - std::string getFilePath(int detPos = -1); + std::string getFilePath(int detPos = -1);// /** * Sets up the file directory @@ -1795,14 +1795,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param s file directory * @returns file dir */ - std::string setFilePath(const std::string &path, int detPos = -1); + std::string setFilePath(const std::string &path, int detPos = -1);// /** * Returns file name prefix * @param detPos -1 for all detectors in list or specific detector position * @returns file name prefix */ - std::string getFileName(int detPos = -1); + std::string getFileName(int detPos = -1);// /** * Sets up the file name prefix @@ -1810,7 +1810,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param s file name prefix * @returns file name prefix */ - std::string setFileName(const std::string &fname, int detPos = -1); + std::string setFileName(const std::string &fname, int detPos = -1);// /** * Sets the max frames per file in receiver @@ -1887,20 +1887,20 @@ class multiSlsDetector : public virtual slsDetectorDefs { * Receiver starts listening to packets * @param detPos -1 for all detectors in list or specific detector position */ - void startReceiver(int detPos = -1); + void startReceiver(int detPos = -1);// /** * Stops the listening mode of receiver * @param detPos -1 for all detectors in list or specific detector position */ - void stopReceiver(int detPos = -1); + void stopReceiver(int detPos = -1);// /** * Gets the status of the listening mode of receiver * @param detPos -1 for all detectors in list or specific detector position * @returns status */ - runStatus getReceiverStatus(int detPos = -1); + runStatus getReceiverStatus(int detPos = -1);// /** * Gets the number of frames caught by receiver @@ -1942,13 +1942,13 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns file write enable */ - int setFileWrite(bool value, int detPos = -1); + int setFileWrite(bool value, int detPos = -1);// /** * Gets file write enable * @returns file write enable */ - int getFileWrite(int detPos = -1) const; + int getFileWrite(int detPos = -1) const;// /** * Sets/Gets receiver master file write enable @@ -1971,14 +1971,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns file overwrite enable */ - int setFileOverWrite(bool enable, int detPos = -1); + int setFileOverWrite(bool enable, int detPos = -1);// /** * Gets file over write enable * @param detPos -1 for all detectors in list or specific detector position * @returns file over write enable */ - int getFileOverWrite(int detPos = -1) const; + int getFileOverWrite(int detPos = -1) const;// /** * (previously setReadReceiverFrequency) @@ -2212,7 +2212,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * index, loops for measurements, calls required call backs. * @returns OK or FAIL depending on if it already started */ - int acquire(); + int acquire();// /** * Combines data from all readouts and gives it to the gui diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index fe7f12b81..a501e0ebe 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -96,34 +96,37 @@ void Detector::setPeriod(ns t, Positions pos) { } // File -void Detector::setFileName(const std::string &fname) { - pimpl->Parallel(&slsDetector::setFileName, Positions{}, fname); +void Detector::setFileName(const std::string &fname, Positions pos) { + pimpl->Parallel(&slsDetector::setFileName, pos, fname); } -Result Detector::getFileName() const { - return pimpl->Parallel(&slsDetector::setFileName, Positions{}, ""); +Result Detector::getFileName(Positions pos) const { + return pimpl->Parallel(&slsDetector::setFileName, pos, ""); } -void Detector::setFilePath(const std::string &fpath) { - pimpl->Parallel(&slsDetector::setFilePath, Positions{}, fpath); +void Detector::setFilePath(const std::string &fpath, Positions pos) { + pimpl->Parallel(&slsDetector::setFilePath, pos, fpath); } -Result Detector::getFilePath() const { - return pimpl->Parallel(&slsDetector::getFilePath, Positions{}); +Result Detector::getFilePath(Positions pos) const { + return pimpl->Parallel(&slsDetector::getFilePath, pos); } void Detector::setFileWrite(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setFileWrite, Positions{}, value); + pimpl->Parallel(&slsDetector::setFileWrite, pos, value); } Result Detector::getFileWrite(Positions pos) const { - return pimpl->Parallel(&slsDetector::getFileWrite, Positions{}); + return pimpl->Parallel(&slsDetector::getFileWrite, pos); } void Detector::setFileOverWrite(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setFileOverWrite, Positions{}, value); + pimpl->Parallel(&slsDetector::setFileOverWrite, pos, value); } Result Detector::getFileOverWrite(Positions pos) const { - return pimpl->Parallel(&slsDetector::getFileOverWrite, Positions{}); + return pimpl->Parallel(&slsDetector::getFileOverWrite, pos); } +// dhanya + + } // namespace sls \ No newline at end of file From dd6a95d0412a2d35a4e8a80cc062faaf88ee0661 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Wed, 7 Aug 2019 12:02:59 +0200 Subject: [PATCH 002/108] first one --- slsDetectorSoftware/include/Detector.h | 8 +++++++- slsDetectorSoftware/include/multiSlsDetector.h | 8 ++++---- slsDetectorSoftware/src/Detector.cpp | 5 +++++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 9ac13bbec..6640a474b 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -124,7 +124,13 @@ class Detector { void setPeriod(ns t, Positions pos = {}); // dhanya - + /** + * Check version compatibility with detector software + * (if hostname/rx_hostname has been set/ sockets created) + * @param p port type control port or receiver port + * @param detPos -1 for all detectors in list or specific detector position + */ + void checkDetectorVersionCompatibility(Positions pos = {}); }; diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index a420d3b60..d05465887 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -210,7 +210,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * one * @param update true to update last user pid, date etc */ - void setupMultiDetector(bool verify = true, bool update = true); + void setupMultiDetector(bool verify = true, bool update = true); // private /** * Loop through the detectors serially and return the result as a vector @@ -260,7 +260,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param channelY channel number from detector offset in x direction * @returns detector id or -1 if channel number out of range */ - int decodeNChannel(int offsetX, int offsetY, int &channelX, int &channelY); + int decodeNChannel(int offsetX, int offsetY, int &channelX, int &channelY);// private /** * Set acquiring flag in shared memory @@ -278,7 +278,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * Check if acquiring flag is set, set error if set * @returns FAIL if not ready, OK if ready */ - bool isAcquireReady(); + bool isAcquireReady(); // private /** * Check version compatibility with detector software @@ -286,7 +286,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param p port type control port or receiver port * @param detPos -1 for all detectors in list or specific detector position */ - void checkDetectorVersionCompatibility(int detPos = -1); + void checkDetectorVersionCompatibility(int detPos = -1);// /** * Check version compatibility with receiver software diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index a501e0ebe..eaf1d7ce9 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -126,7 +126,12 @@ Result Detector::getFileOverWrite(Positions pos) const { return pimpl->Parallel(&slsDetector::getFileOverWrite, pos); } + // dhanya +Result Detector::checkDetectorVersionCompatibility(Positions pos) const { + return pimpl->Parallel(&slsDetector::checkDetectorVersionCompatibility, pos); +} + } // namespace sls \ No newline at end of file From 615835f03dbe6f8893702106f8e92461219377b9 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Wed, 7 Aug 2019 12:32:59 +0200 Subject: [PATCH 003/108] WIP --- slsDetectorSoftware/include/Detector.h | 56 ++++++++++++++++--- .../include/multiSlsDetector.h | 12 ++-- slsDetectorSoftware/src/Detector.cpp | 37 ++++++++---- 3 files changed, 79 insertions(+), 26 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 6640a474b..60a19cc1c 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -36,13 +36,13 @@ class Detector { /** * Get the acquiring flag. When true the detector blocks - * any attempt to start a new acquisition. + * any attempt to start a new acquisition. */ bool getAcquiringFlag() const; /** - * Set the acquiring flag. This might have to done manually - * after an acquisition was aborted. + * Set the acquiring flag. This might have to done manually + * after an acquisition was aborted. */ void setAcquiringFlag(bool value); @@ -66,7 +66,7 @@ class Detector { // Bits and registers /** - * Clears (sets to 0) bit number bitnr in register at addr. + * Clears (sets to 0) bit number bitnr in register at addr. * @param addr address of the register * @param bitnr bit number to clear * @param pos detector position @@ -124,14 +124,52 @@ class Detector { void setPeriod(ns t, Positions pos = {}); // dhanya + /** * Check version compatibility with detector software - * (if hostname/rx_hostname has been set/ sockets created) - * @param p port type control port or receiver port - * @param detPos -1 for all detectors in list or specific detector position + * @param pos detector position */ - void checkDetectorVersionCompatibility(Positions pos = {}); - + void checkDetectorVersionCompatibility(Positions pos = {}) const; + + /** + * Check version compatibility with receiver software + * @param pos detector position + */ + void checkReceiverVersionCompatibility(Positions pos = {}) const; + + /** + * Get detector firmware version + * @param pos detector position + * @returns detector firmware version + */ + int64_t getDetectorFirmwareVersion(Positions pos = {}) const; + + /** + * Get detector server version + * @param pos detector position + * @returns detector server version + */ + int64_t getDetectorServerVersion(Positions pos = {}) const; + + /** + * Get detector serial number + * @param pos detector position + * @returns detector serial number + */ + int64_t getDetectorSerialNumber(Positions pos = {}) const; + + /** + * Get Client Software version + * @returns client software version + */ + int64_t getClientSoftwareVersion() const; + + /** + * Get Receiver software version + * @param pos detector position + * @return receiver software version + */ + int64_t getReceiverSoftwareVersion(Positions pos = {}) const; }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index d05465887..433612f9d 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -294,7 +294,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param p port type control port or receiver port * @param detPos -1 for all detectors in list or specific detector position */ - void checkReceiverVersionCompatibility(int detPos = -1); + void checkReceiverVersionCompatibility(int detPos = -1);// /** * Get ID or version numbers @@ -302,27 +302,27 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns Id or version number of that type */ - int64_t getId(idMode mode, int detPos = -1); + int64_t getId(idMode mode, int detPos = -1);//not needed anymore (later remove this_software_version from enum) - int getMultiId()const{return multiId;} + int getMultiId()const{return multiId;} //public but part of multi /** * Get Client Software version * @returns client software version */ - int64_t getClientSoftwareVersion() const; + int64_t getClientSoftwareVersion() const;// /** * Get Receiver software version * @return receiver software version */ - int64_t getReceiverSoftwareVersion(int detPos = -1); + int64_t getReceiverSoftwareVersion(int detPos = -1);// /** * Get Detector Number * @returns vector of detector number */ - std::vector getDetectorNumber(); + std::vector getDetectorNumber(); // renamed to getDetectorSerialNumber /** * Free shared memory from the command line * avoiding creating the constructor classes and mapping diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index eaf1d7ce9..5206f2368 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -11,7 +11,6 @@ Detector::Detector(int multi_id) : pimpl(sls::make_unique(multi_id)) {} Detector::~Detector() = default; - // Acquisition void Detector::acquire() { pimpl->acquire(); } @@ -26,13 +25,9 @@ Result Detector::getReceiverStatus(Positions pos) { return pimpl->Parallel(&slsDetector::getReceiverStatus, pos); } -bool Detector::getAcquiringFlag() const{ - return pimpl->getAcquiringFlag(); -} +bool Detector::getAcquiringFlag() const { return pimpl->getAcquiringFlag(); } -void Detector::setAcquiringFlag(bool value){ - pimpl->setAcquiringFlag(value); -} +void Detector::setAcquiringFlag(bool value) { pimpl->setAcquiringFlag(value); } // Configuration Result Detector::getHostname(Positions pos) const { @@ -41,7 +36,6 @@ Result Detector::getHostname(Positions pos) const { void Detector::freeSharedMemory() { pimpl->freeSharedMemory(); } - void Detector::setConfig(const std::string &fname) { pimpl->readConfigurationFile(fname); } @@ -126,12 +120,33 @@ Result Detector::getFileOverWrite(Positions pos) const { return pimpl->Parallel(&slsDetector::getFileOverWrite, pos); } - // dhanya -Result Detector::checkDetectorVersionCompatibility(Positions pos) const { - return pimpl->Parallel(&slsDetector::checkDetectorVersionCompatibility, pos); +Result Detector::checkDetectorVersionCompatibility(Positions pos) const { + pimpl->Parallel(&slsDetector::checkDetectorVersionCompatibility, pos); } +Result Detector::checkReceiverVersionCompatibility(Positions pos) const { + pimpl->Parallel(&slsDetector::checkReceiverVersionCompatibility, pos); +} +Result Detector::getDetectorFirmwareVersion(Positions pos) const { + return pimpl->Parallel(&slsDetector::getId, DETECTOR_FIRMWARE_VERSION, pos); +} + +Result Detector::getDetectorServerVersion(Positions pos) const { + return pimpl->Parallel(&slsDetector::getId, DETECTOR_SOFTWARE_VERSION, pos); +} + +Result Detector::getDetectorSerialNumber(Positions pos) const { + return pimpl->Parallel(&slsDetector::getId, DETECTOR_SERIAL_NUMBER, pos); +} + +Result Detector::getClientSoftwareVersion() const { + return APILIB; +} + +Result Detector::getReceiverSoftwareVersion(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverSoftwareVersion, pos); +} } // namespace sls \ No newline at end of file From 6a71e61c129cc70bb092085c8d13c74877706e0c Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Wed, 7 Aug 2019 15:23:58 +0200 Subject: [PATCH 004/108] WIP --- slsDetectorSoftware/include/Detector.h | 48 +++++++++++++++++-- .../include/multiSlsDetector.h | 29 ++++++++--- slsDetectorSoftware/src/Detector.cpp | 33 +++++++++++-- slsDetectorSoftware/src/multiSlsDetector.cpp | 33 ++++++++++++- 4 files changed, 125 insertions(+), 18 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 60a19cc1c..a363aea7e 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -124,6 +124,11 @@ class Detector { void setPeriod(ns t, Positions pos = {}); // dhanya + /** + * Get multidetector Id + * @returns multidetector Id + */ + int getMultiId() const; /** * Check version compatibility with detector software @@ -142,34 +147,67 @@ class Detector { * @param pos detector position * @returns detector firmware version */ - int64_t getDetectorFirmwareVersion(Positions pos = {}) const; + Result getDetectorFirmwareVersion(Positions pos = {}) const; /** * Get detector server version * @param pos detector position * @returns detector server version */ - int64_t getDetectorServerVersion(Positions pos = {}) const; + Result getDetectorServerVersion(Positions pos = {}) const; /** * Get detector serial number * @param pos detector position * @returns detector serial number */ - int64_t getDetectorSerialNumber(Positions pos = {}) const; + Result getDetectorSerialNumber(Positions pos = {}) const; /** * Get Client Software version * @returns client software version */ - int64_t getClientSoftwareVersion() const; + Result getClientSoftwareVersion() const; /** * Get Receiver software version * @param pos detector position * @return receiver software version */ - int64_t getReceiverSoftwareVersion(Positions pos = {}) const; + Result getReceiverSoftwareVersion(Positions pos = {}) const; + + /** + * Get user details of shared memory + * @returns string with user details + */ + std::string getUserDetails() const; + + /** + * Frees shared memory and adds detectors to the list + * Also updates local detector cache + * @param name hostnames for the positions given + */ + void setHostname(const std::vector &name); + + /** + * Get Detector type as an enum + * @returns detector type + */ + detectorType Detector::getDetectorTypeAsEnum() const; + + /** + * Get Detector type as an enum + * @param pos detector position + * @returns detector type + */ + Result getDetectorTypeAsEnum(Positions pos = {}) const; + + /** + * Returns detector type as a string + * @param pos detector position + * @returns detector type as string + */ + Result getDetectorTypeAsString(Positions pos = {}); }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 433612f9d..43cd153de 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -304,7 +304,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ int64_t getId(idMode mode, int detPos = -1);//not needed anymore (later remove this_software_version from enum) - int getMultiId()const{return multiId;} //public but part of multi + int getMultiId()const{return multiId;} //part of multi also /** * Get Client Software version @@ -329,7 +329,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param multiId multi detector Id * @param detPos -1 for all detectors in list or specific detector position */ - static void freeSharedMemory(int multiId, int detPos = -1);// + static void freeSharedMemory(int multiId, int detPos = -1);// private or not needed /** * Free shared memory and delete shared memory structure @@ -338,21 +338,27 @@ class multiSlsDetector : public virtual slsDetectorDefs { * object back to state before object creation amap * @param detPos -1 for all detectors in list or specific detector position */ - void freeSharedMemory(int detPos = -1); + void freeSharedMemory(int detPos = -1);// /** * Get user details of shared memory * @returns string with user details */ - std::string getUserDetails(); + std::string getUserDetails();// part of multi + /** + * Sets the hostname of all sls detectors in shared memory and updates local cache + * @param name hostname of all the sls detectors + */ + void setHostname(const std::vector &name);//cannot set individually + /** * Sets the hostname of all sls detectors in shared memory * Connects to them * @param name concatenated hostname of all the sls detectors * @param detPos -1 for all detectors in list or specific detector position */ - void setHostname(const char *name, int detPos = -1); + void setHostname(const char *name, int detPos = -1);// not needed /** * Gets the hostname of detector at particular position @@ -369,7 +375,13 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param name concatenated hostname of the sls detectors to be appended to * the list */ - void addMultipleDetectors(const char *name); + void addMultipleDetectors(const char *name);// ???? + + /** + * Get Detector type as an enum + * @returns detector type + */ + detectorType getDetectorTypeAsEnum() const; /** * Get Detector type for a particular sls detector or get the first one @@ -377,7 +389,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns detector type of sls detector in position pos, if -1, returns * the first det type */ - detectorType getDetectorTypeAsEnum(int detPos = -1); + detectorType getDetectorTypeAsEnum(int detPos);//?? /** * Concatenates string types of all sls detectors or @@ -2335,6 +2347,9 @@ class multiSlsDetector : public virtual slsDetectorDefs { /** Multi detector Id */ const int multiId{0}; + /** multi detector type */ + detectorType multiDetType; + /** Shared Memory object */ sls::SharedMemory multi_shm{0, -1}; diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 5206f2368..b4407d646 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -121,11 +121,15 @@ Result Detector::getFileOverWrite(Positions pos) const { } // dhanya -Result Detector::checkDetectorVersionCompatibility(Positions pos) const { +int Detector::getMultiId() const { + pimpl->getMultiId()); +} + +void Detector::checkDetectorVersionCompatibility(Positions pos) const { pimpl->Parallel(&slsDetector::checkDetectorVersionCompatibility, pos); } -Result Detector::checkReceiverVersionCompatibility(Positions pos) const { +void Detector::checkReceiverVersionCompatibility(Positions pos) const { pimpl->Parallel(&slsDetector::checkReceiverVersionCompatibility, pos); } @@ -141,12 +145,31 @@ Result Detector::getDetectorSerialNumber(Positions pos) const { return pimpl->Parallel(&slsDetector::getId, DETECTOR_SERIAL_NUMBER, pos); } -Result Detector::getClientSoftwareVersion() const { - return APILIB; -} +Result Detector::getClientSoftwareVersion() const { return APILIB; } Result Detector::getReceiverSoftwareVersion(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverSoftwareVersion, pos); } +std::string Detector::getUserDetails() const { + return pimpl->getUserDetails(); +} + +void Detector::setHostname(const std::vector &name, + Positions pos) { + pimpl->setHostname(name); +} + +detectorType Detector::getDetectorTypeAsEnum() const { + return pimpl->getDetectorTypeAsEnum(); +} + +Result Detector::getDetectorTypeAsEnum(Positions pos) const { + return pimpl->Parallel(&slsDetector::getDetectorTypeAsEnum, pos); +} + +Result Detector::getDetectorTypeAsString(Positions pos) const { + return pimpl->Parallel(&slsDetector::getDetectorTypeAsString, pos); +} + } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index 0c7b14feb..9f94d3b76 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -30,7 +30,7 @@ using namespace sls; multiSlsDetector::multiSlsDetector(int multi_id, bool verify, bool update) - : multiId(multi_id), multi_shm(multi_id, -1) { + : multiId(multi_id), multiDetType(GENERIC), multi_shm(multi_id, -1) { setupMultiDetector(verify, update); } @@ -332,6 +332,11 @@ void multiSlsDetector::initializeDetectorStructure() { void multiSlsDetector::initializeMembers(bool verify) { // multiSlsDetector + if (multi_shm()->numberOfDetectors == 0) { + multiDetType = GENERIC; + } else { + multiDetType = getDetectorTypeAsEnum(); + } zmqSocket.clear(); // get objects from single det shared memory (open) @@ -385,6 +390,22 @@ std::string multiSlsDetector::exec(const char *cmd) { return result; } +void multiSlsDetector::setHostname(const std::vector &name) { + // this check is there only to allow the previous detsizechan command + if (multi_shm()->numberOfDetectors != 0) { + FILE_LOG(logWARNING) + << "There are already detector(s) in shared memory." + "Freeing Shared memory now."; + freeSharedMemory(); + setupMultiDetector(); + } + for (const auto &hostname : name) { + addSlsDetector(hostname); + } + + updateOffsets(); +} + void multiSlsDetector::setHostname(const char *name, int detPos) { // single if (detPos >= 0) { @@ -461,6 +482,10 @@ void multiSlsDetector::addSlsDetector(std::unique_ptr det) { detectors.back()->getTotalNumberOfChannels(); } +slsDetectorDefs::detectorType multiSlsDetector::getDetectorTypeAsEnum() const { + return multiDetType; +} + slsDetectorDefs::detectorType multiSlsDetector::getDetectorTypeAsEnum(int detPos) { // single @@ -842,6 +867,12 @@ void multiSlsDetector::readConfigurationFile(const std::string &fname) { } } input_file.close(); + + if (multi_shm()->numberOfDetectors == 0) { + multiDetType = GENERIC; + } else { + multiDetType = getDetectorTypeAsEnum(); + } } int multiSlsDetector::writeConfigurationFile(const std::string &fname) { From dc1e01b4443bf2749f301b1f9691f7a19c4e8c30 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Wed, 7 Aug 2019 15:33:55 +0200 Subject: [PATCH 005/108] multidettype in one place --- slsDetectorSoftware/src/multiSlsDetector.cpp | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index 9f94d3b76..8a196ae43 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -332,11 +332,6 @@ void multiSlsDetector::initializeDetectorStructure() { void multiSlsDetector::initializeMembers(bool verify) { // multiSlsDetector - if (multi_shm()->numberOfDetectors == 0) { - multiDetType = GENERIC; - } else { - multiDetType = getDetectorTypeAsEnum(); - } zmqSocket.clear(); // get objects from single det shared memory (open) @@ -470,6 +465,7 @@ void multiSlsDetector::addSlsDetector(const std::string &hostname) { multi_shm()->numberOfChannels += detectors[pos]->getTotalNumberOfChannels(); detectors[pos]->setHostname(hostname); + multiDetType = getDetectorTypeAsEnum(); } void multiSlsDetector::addSlsDetector(std::unique_ptr det) { @@ -867,12 +863,6 @@ void multiSlsDetector::readConfigurationFile(const std::string &fname) { } } input_file.close(); - - if (multi_shm()->numberOfDetectors == 0) { - multiDetType = GENERIC; - } else { - multiDetType = getDetectorTypeAsEnum(); - } } int multiSlsDetector::writeConfigurationFile(const std::string &fname) { From 0a2a5933dac4d7e9b717daf5e6d44678023be3aa Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Wed, 7 Aug 2019 15:51:25 +0200 Subject: [PATCH 006/108] WIP --- .../include/multiSlsDetector.h | 52 +++++------ slsDetectorSoftware/src/multiSlsDetector.cpp | 86 +++++++++---------- 2 files changed, 69 insertions(+), 69 deletions(-) diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 43cd153de..f89f4921d 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -203,15 +203,6 @@ class multiSlsDetector : public virtual slsDetectorDefs { } } - /** - * Creates/open shared memory, initializes detector structure and members - * Called by constructor/ set hostname / read config file - * @param verify true to verify if shared memory version matches existing - * one - * @param update true to update last user pid, date etc - */ - void setupMultiDetector(bool verify = true, bool update = true); // private - /** * Loop through the detectors serially and return the result as a vector */ @@ -251,17 +242,6 @@ class multiSlsDetector : public virtual slsDetectorDefs { void parallelCall(void (slsDetector::*somefunc)(CT...) const, typename NonDeduced::type... Args) const; - /** - * Decodes which detector and the corresponding channel numbers for it - * Mainly useful in a multi detector setROI (Gotthard) - * @param offsetX channel number or total channel offset in x direction - * @param offsetY channel number or total channel offset in y direction - * @param channelX channel number from detector offset in x direction - * @param channelY channel number from detector offset in x direction - * @returns detector id or -1 if channel number out of range - */ - int decodeNChannel(int offsetX, int offsetY, int &channelX, int &channelY);// private - /** * Set acquiring flag in shared memory * @param b acquiring flag @@ -274,12 +254,6 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ bool getAcquiringFlag() const;// - /** - * Check if acquiring flag is set, set error if set - * @returns FAIL if not ready, OK if ready - */ - bool isAcquireReady(); // private - /** * Check version compatibility with detector software * (if hostname/rx_hostname has been set/ sockets created) @@ -2235,6 +2209,15 @@ class multiSlsDetector : public virtual slsDetectorDefs { void addSlsDetector(std::unique_ptr det); private: + /** + * Creates/open shared memory, initializes detector structure and members + * Called by constructor/ set hostname / read config file + * @param verify true to verify if shared memory version matches existing + * one + * @param update true to update last user pid, date etc + */ + void setupMultiDetector(bool verify = true, bool update = true); + /** * Initialize (open/create) shared memory for the sharedMultiDetector * structure @@ -2260,6 +2243,23 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ void updateUserdetails(); + /** + * Check if acquiring flag is set, set error if set + * @returns FAIL if not ready, OK if ready + */ + bool isAcquireReady(); + + /** + * Decodes which detector and the corresponding channel numbers for it + * Mainly useful in a multi detector setROI (Gotthard) + * @param offsetX channel number or total channel offset in x direction + * @param offsetY channel number or total channel offset in y direction + * @param channelX channel number from detector offset in x direction + * @param channelY channel number from detector offset in x direction + * @returns detector id or -1 if channel number out of range + */ + int decodeNChannel(int offsetX, int offsetY, int &channelX, int &channelY); + /** * Execute in command line and return result * @param cmd command diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index 8a196ae43..48564d7e9 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -131,37 +131,6 @@ void multiSlsDetector::parallelCall( return; } -int multiSlsDetector::decodeNChannel(int offsetX, int offsetY, int &channelX, - int &channelY) { - channelX = -1; - channelY = -1; - // loop over - for (size_t i = 0; i < detectors.size(); ++i) { - int x = detectors[i]->getDetectorOffset(X); - int y = detectors[i]->getDetectorOffset(Y); - // check x offset range - if ((offsetX >= x) && - (offsetX < - (x + detectors[i]->getTotalNumberOfChannelsInclGapPixels(X)))) { - if (offsetY == -1) { - channelX = offsetX - x; - return i; - } else { - // check y offset range - if ((offsetY >= y) && - (offsetY < - (y + detectors[i]->getTotalNumberOfChannelsInclGapPixels( - Y)))) { - channelX = offsetX - x; - channelY = offsetY - y; - return i; - } - } - } - } - return -1; -} - void multiSlsDetector::setAcquiringFlag(bool flag) { multi_shm()->acquiringFlag = flag; } @@ -170,18 +139,6 @@ bool multiSlsDetector::getAcquiringFlag() const { return multi_shm()->acquiringFlag; } -bool multiSlsDetector::isAcquireReady() { - if (multi_shm()->acquiringFlag) { - FILE_LOG(logWARNING) - << "Acquire has already started. " - "If previous acquisition terminated unexpectedly, " - "reset busy flag to restart.(sls_detector_put busy 0)"; - return FAIL != 0u; - } - multi_shm()->acquiringFlag = true; - return OK != 0u; -} - void multiSlsDetector::checkDetectorVersionCompatibility(int detPos) { if (detPos >= 0) { detectors[detPos]->checkDetectorVersionCompatibility(); @@ -362,6 +319,49 @@ void multiSlsDetector::updateUserdetails() { } } +bool multiSlsDetector::isAcquireReady() { + if (multi_shm()->acquiringFlag) { + FILE_LOG(logWARNING) + << "Acquire has already started. " + "If previous acquisition terminated unexpectedly, " + "reset busy flag to restart.(sls_detector_put busy 0)"; + return FAIL != 0u; + } + multi_shm()->acquiringFlag = true; + return OK != 0u; +} + +int multiSlsDetector::decodeNChannel(int offsetX, int offsetY, int &channelX, + int &channelY) { + channelX = -1; + channelY = -1; + // loop over + for (size_t i = 0; i < detectors.size(); ++i) { + int x = detectors[i]->getDetectorOffset(X); + int y = detectors[i]->getDetectorOffset(Y); + // check x offset range + if ((offsetX >= x) && + (offsetX < + (x + detectors[i]->getTotalNumberOfChannelsInclGapPixels(X)))) { + if (offsetY == -1) { + channelX = offsetX - x; + return i; + } else { + // check y offset range + if ((offsetY >= y) && + (offsetY < + (y + detectors[i]->getTotalNumberOfChannelsInclGapPixels( + Y)))) { + channelX = offsetX - x; + channelY = offsetY - y; + return i; + } + } + } + } + return -1; +} + std::string multiSlsDetector::exec(const char *cmd) { int bufsize = 128; char buffer[bufsize]; From eec7b22582bbaf7d8605039ecb70d3e7a5c4260b Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Wed, 7 Aug 2019 16:11:42 +0200 Subject: [PATCH 007/108] compiles --- slsDetectorSoftware/include/Detector.h | 6 +++--- slsDetectorSoftware/src/Detector.cpp | 19 ++++++++++--------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index a363aea7e..55461e656 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -193,21 +193,21 @@ class Detector { * Get Detector type as an enum * @returns detector type */ - detectorType Detector::getDetectorTypeAsEnum() const; + defs::detectorType getDetectorTypeAsEnum() const; /** * Get Detector type as an enum * @param pos detector position * @returns detector type */ - Result getDetectorTypeAsEnum(Positions pos = {}) const; + Result getDetectorTypeAsEnum(Positions pos = {}) const; /** * Returns detector type as a string * @param pos detector position * @returns detector type as string */ - Result getDetectorTypeAsString(Positions pos = {}); + Result getDetectorTypeAsString(Positions pos = {}) const; }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index d2922325a..2d7b2210f 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -118,7 +118,7 @@ Result Detector::getFileOverWrite(Positions pos) const { // dhanya int Detector::getMultiId() const { - pimpl->getMultiId()); + return pimpl->getMultiId(); } void Detector::checkDetectorVersionCompatibility(Positions pos) const { @@ -130,18 +130,20 @@ void Detector::checkReceiverVersionCompatibility(Positions pos) const { } Result Detector::getDetectorFirmwareVersion(Positions pos) const { - return pimpl->Parallel(&slsDetector::getId, DETECTOR_FIRMWARE_VERSION, pos); + return pimpl->Parallel(&slsDetector::getId, pos, defs::DETECTOR_FIRMWARE_VERSION); } Result Detector::getDetectorServerVersion(Positions pos) const { - return pimpl->Parallel(&slsDetector::getId, DETECTOR_SOFTWARE_VERSION, pos); + return pimpl->Parallel(&slsDetector::getId, pos, defs::DETECTOR_SOFTWARE_VERSION); } Result Detector::getDetectorSerialNumber(Positions pos) const { - return pimpl->Parallel(&slsDetector::getId, DETECTOR_SERIAL_NUMBER, pos); + return pimpl->Parallel(&slsDetector::getId, pos, defs::DETECTOR_SERIAL_NUMBER); } -Result Detector::getClientSoftwareVersion() const { return APILIB; } +Result Detector::getClientSoftwareVersion() const { + return pimpl->getClientSoftwareVersion(); +} Result Detector::getReceiverSoftwareVersion(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverSoftwareVersion, pos); @@ -151,16 +153,15 @@ std::string Detector::getUserDetails() const { return pimpl->getUserDetails(); } -void Detector::setHostname(const std::vector &name, - Positions pos) { +void Detector::setHostname(const std::vector &name) { pimpl->setHostname(name); } -detectorType Detector::getDetectorTypeAsEnum() const { +defs::detectorType Detector::getDetectorTypeAsEnum() const { return pimpl->getDetectorTypeAsEnum(); } -Result Detector::getDetectorTypeAsEnum(Positions pos) const { +Result Detector::getDetectorTypeAsEnum(Positions pos) const { return pimpl->Parallel(&slsDetector::getDetectorTypeAsEnum, pos); } From 21046bcae05c1dc7392454fc6de077d59d956362 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Wed, 7 Aug 2019 16:32:12 +0200 Subject: [PATCH 008/108] multidet to multi shm --- .../include/multiSlsDetector.h | 11 ++++++----- slsDetectorSoftware/src/multiSlsDetector.cpp | 19 ++++++++++++++----- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index f89f4921d..b3a893936 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -15,7 +15,8 @@ class detectorData; #include #include -#define MULTI_SHMVERSION 0x190726 +#define MULTI_SHMAPIVERSION 0x190807 +#define MULTI_SHMVERSION 0x190807 #define SHORT_STRING_LENGTH 50 #define DATE_LENGTH 30 @@ -46,9 +47,12 @@ struct sharedMultiSlsDetector { /** number of sls detectors in shared memory */ int numberOfDetectors; + /** multi detector type */ + slsDetectorDefs::detectorType multiDetectorType; + /** END OF FIXED PATTERN * -----------------------------------------------*/ - + /** Number of detectors operated at once */ int numberOfDetector[2]; @@ -2347,9 +2351,6 @@ class multiSlsDetector : public virtual slsDetectorDefs { /** Multi detector Id */ const int multiId{0}; - /** multi detector type */ - detectorType multiDetType; - /** Shared Memory object */ sls::SharedMemory multi_shm{0, -1}; diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index 48564d7e9..c6fc94707 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -30,7 +30,7 @@ using namespace sls; multiSlsDetector::multiSlsDetector(int multi_id, bool verify, bool update) - : multiId(multi_id), multiDetType(GENERIC), multi_shm(multi_id, -1) { + : multiId(multi_id), multi_shm(multi_id, -1) { setupMultiDetector(verify, update); } @@ -236,8 +236,15 @@ std::string multiSlsDetector::getUserDetails() { sstream << (d->isFixedPatternSharedMemoryCompatible() ? d->getHostname() : "Unknown") << "+"; } sstream << "\nType: "; - for (auto &d : detectors) { - sstream << (d->isFixedPatternSharedMemoryCompatible() ? d->getDetectorTypeAsString() : "Unknown") << "+"; + // get type from multi shm + if (multi_shm()->shmversion >= MULTI_SHMAPIVERSION) { + sstream << slsDetectorDefs::detectorTypeToString(getDetectorTypeAsEnum()); + } + // get type from slsdet shm + else { + for (auto &d : detectors) { + sstream << (d->isFixedPatternSharedMemoryCompatible() ? d->getDetectorTypeAsString() : "Unknown") << "+"; + } } sstream << "\nPID: " << multi_shm()->lastPID @@ -268,6 +275,7 @@ void multiSlsDetector::initSharedMemory(bool verify) { void multiSlsDetector::initializeDetectorStructure() { multi_shm()->shmversion = MULTI_SHMVERSION; multi_shm()->numberOfDetectors = 0; + multi_shm()->multiDetectorType = GENERIC; multi_shm()->numberOfDetector[X] = 0; multi_shm()->numberOfDetector[Y] = 0; multi_shm()->dataBytes = 0; @@ -465,7 +473,7 @@ void multiSlsDetector::addSlsDetector(const std::string &hostname) { multi_shm()->numberOfChannels += detectors[pos]->getTotalNumberOfChannels(); detectors[pos]->setHostname(hostname); - multiDetType = getDetectorTypeAsEnum(); + multi_shm()->multiDetectorType = getDetectorTypeAsEnum(-1);// -1 needed here } void multiSlsDetector::addSlsDetector(std::unique_ptr det) { @@ -476,10 +484,11 @@ void multiSlsDetector::addSlsDetector(std::unique_ptr det) { detectors.back()->getDataBytesInclGapPixels(); multi_shm()->numberOfChannels += detectors.back()->getTotalNumberOfChannels(); + multi_shm()->multiDetectorType = getDetectorTypeAsEnum(-1);// -1 needed here } slsDetectorDefs::detectorType multiSlsDetector::getDetectorTypeAsEnum() const { - return multiDetType; + return multi_shm()->multiDetectorType; } slsDetectorDefs::detectorType From bba6e1667b982b836fb7ff5050dc0ed5e70e6d43 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Wed, 7 Aug 2019 18:00:25 +0200 Subject: [PATCH 009/108] some ctb funcs --- python/src/experimental.cpp | 4 +-- slsDetectorSoftware/include/Detector.h | 24 ++++++++++++++ slsDetectorSoftware/include/Result.h | 17 +++++----- slsDetectorSoftware/src/Detector.cpp | 46 +++++++++++++++++--------- 4 files changed, 65 insertions(+), 26 deletions(-) diff --git a/python/src/experimental.cpp b/python/src/experimental.cpp index b8d31a9b2..b8ae33d4f 100644 --- a/python/src/experimental.cpp +++ b/python/src/experimental.cpp @@ -45,9 +45,9 @@ void init_experimental(py::module &m) { // File .def("getFileName", &Detector::getFileName) - .def("setFileName", &Detector::setFileName, py::arg()) + .def("setFileName", &Detector::setFileName, py::arg(),py::arg() = Positions{}) .def("getFilePath", &Detector::getFilePath) - .def("setFilePath", &Detector::setFilePath, py::arg()) + .def("setFilePath", &Detector::setFilePath, py::arg(),py::arg() = Positions{}) .def("setFileWrite", &Detector::setFileWrite, py::arg(), py::arg() = Positions{}) .def("getFileWrite", &Detector::getFileWrite, py::arg() = Positions{}) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 55461e656..994761cb1 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -208,6 +208,30 @@ class Detector { * @returns detector type as string */ Result getDetectorTypeAsString(Positions pos = {}) const; + + + // Erik + + /** + * Set LED Enable for CTB + * @param enable true to switch on, false to switch off + */ + void setLEDEnable(bool enable, Positions pos = {}); + + + /** + * Get LED enable for CTB + */ + Result getLEDEnable(Positions pos = {}) const; + + + /** + * Set Digital IO Delay CTB + * @param digital IO mask to select the pins + * @param delay delay in ps(1 bit=25ps, max of 775 ps) + */ + void setDigitalIODelay(uint64_t pinMask, int delay, Positions pos = {}); + }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/include/Result.h b/slsDetectorSoftware/include/Result.h index ea9b810d8..33ce0c04a 100644 --- a/slsDetectorSoftware/include/Result.h +++ b/slsDetectorSoftware/include/Result.h @@ -31,32 +31,33 @@ template > class Result { Result() = default; Result(std::initializer_list list) : vec(list){}; - - /** Custom constructor from integer type to Result */ + /** Custom constructor from integer type to Result or Result */ template ::value && - std::is_same::value>::type> + (std::is_same::value || + std::is_same::value)>::type> Result(const std::vector &from) { - vec.reserve(from.size()); for (const auto &item : from) vec.push_back(T(item)); } - /** Custom constructor from integer type to Result */ + /** Custom constructor from integer type to Result or Result */ template ::value && - std::is_same::value>::type> + (std::is_same::value || + std::is_same::value)>::type> Result(std::vector &from) { vec.reserve(from.size()); for (const auto &item : from) vec.push_back(T(item)); } - /** Custom constructor from integer type to Result */ + /** Custom constructor from integer type to Result or Result */ template ::value && - std::is_same::value>::type> + (std::is_same::value || + std::is_same::value)>::type> Result(std::vector &&from) { vec.reserve(from.size()); for (const auto &item : from) diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 2d7b2210f..a014375e5 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -117,9 +117,7 @@ Result Detector::getFileOverWrite(Positions pos) const { } // dhanya -int Detector::getMultiId() const { - return pimpl->getMultiId(); -} +int Detector::getMultiId() const { return pimpl->getMultiId(); } void Detector::checkDetectorVersionCompatibility(Positions pos) const { pimpl->Parallel(&slsDetector::checkDetectorVersionCompatibility, pos); @@ -130,43 +128,59 @@ void Detector::checkReceiverVersionCompatibility(Positions pos) const { } Result Detector::getDetectorFirmwareVersion(Positions pos) const { - return pimpl->Parallel(&slsDetector::getId, pos, defs::DETECTOR_FIRMWARE_VERSION); + return pimpl->Parallel(&slsDetector::getId, pos, + defs::DETECTOR_FIRMWARE_VERSION); } Result Detector::getDetectorServerVersion(Positions pos) const { - return pimpl->Parallel(&slsDetector::getId, pos, defs::DETECTOR_SOFTWARE_VERSION); + return pimpl->Parallel(&slsDetector::getId, pos, + defs::DETECTOR_SOFTWARE_VERSION); } Result Detector::getDetectorSerialNumber(Positions pos) const { - return pimpl->Parallel(&slsDetector::getId, pos, defs::DETECTOR_SERIAL_NUMBER); + return pimpl->Parallel(&slsDetector::getId, pos, + defs::DETECTOR_SERIAL_NUMBER); } -Result Detector::getClientSoftwareVersion() const { - return pimpl->getClientSoftwareVersion(); +Result Detector::getClientSoftwareVersion() const { + return pimpl->getClientSoftwareVersion(); } Result Detector::getReceiverSoftwareVersion(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverSoftwareVersion, pos); } -std::string Detector::getUserDetails() const { - return pimpl->getUserDetails(); -} +std::string Detector::getUserDetails() const { return pimpl->getUserDetails(); } -void Detector::setHostname(const std::vector &name) { +void Detector::setHostname(const std::vector &name) { pimpl->setHostname(name); } defs::detectorType Detector::getDetectorTypeAsEnum() const { - return pimpl->getDetectorTypeAsEnum(); + return pimpl->getDetectorTypeAsEnum(); } -Result Detector::getDetectorTypeAsEnum(Positions pos) const { - return pimpl->Parallel(&slsDetector::getDetectorTypeAsEnum, pos); +Result +Detector::getDetectorTypeAsEnum(Positions pos) const { + return pimpl->Parallel(&slsDetector::getDetectorTypeAsEnum, pos); } Result Detector::getDetectorTypeAsString(Positions pos) const { - return pimpl->Parallel(&slsDetector::getDetectorTypeAsString, pos); + return pimpl->Parallel(&slsDetector::getDetectorTypeAsString, pos); +} + +// Erik + +void Detector::setLEDEnable(bool enable, Positions pos) { + pimpl->Parallel(&slsDetector::setLEDEnable, pos, static_cast(enable)); +} + +Result Detector::getLEDEnable(Positions pos) const { + return pimpl->Parallel(&slsDetector::setLEDEnable, pos, -1); +} + +void Detector::setDigitalIODelay(uint64_t pinMask, int delay, Positions pos){ + pimpl->Parallel(&slsDetector::setDigitalIODelay, pos, pinMask, delay); } } // namespace sls \ No newline at end of file From 095a7eac059480e045d5d9b6f919464982ac894a Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Thu, 8 Aug 2019 10:18:21 +0200 Subject: [PATCH 010/108] more ctb --- slsDetectorSoftware/include/Detector.h | 29 ++++- .../include/multiSlsDetector.h | 15 +-- slsDetectorSoftware/src/Detector.cpp | 13 ++ slsDetectorSoftware/src/multiSlsDetector.cpp | 11 -- .../tests/test-multiSlsDetector.cpp | 122 +++++++++--------- 5 files changed, 103 insertions(+), 87 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 994761cb1..212c2f03b 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -209,29 +209,44 @@ class Detector { */ Result getDetectorTypeAsString(Positions pos = {}) const; - // Erik + /** CTB only.Sets the mask applied to every pattern. */ + void setPatternMask(uint64_t mask, Positions pos = {}); + + /** CTB only. Gets the mask applied to every pattern. */ + Result getPatternMask(Positions pos = {}); + /** - * Set LED Enable for CTB + * CTB only. Sets the bitmask that the mask will be applied to for every + * pattern. + * @param mask mask to select bits + */ + void setPatternBitMask(uint64_t mask, Positions pos = {}); + + /** + * CTB only. Gets the bits that the mask will be applied to for every + * pattern + */ + Result getPatternBitMask(Positions pos = {}) const; + + /** + * CTB only. Enable or disable the LED * @param enable true to switch on, false to switch off */ void setLEDEnable(bool enable, Positions pos = {}); - /** - * Get LED enable for CTB + * CTB only. Get LED enable. */ Result getLEDEnable(Positions pos = {}) const; - /** - * Set Digital IO Delay CTB + * CTB only. Set Digital IO Delay * @param digital IO mask to select the pins * @param delay delay in ps(1 bit=25ps, max of 775 ps) */ void setDigitalIODelay(uint64_t pinMask, int delay, Positions pos = {}); - }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index b3a893936..36e45fa29 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -2106,14 +2106,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param mask mask to be applied * @param detPos -1 for all detectors in list or specific detector position */ - void setPatternMask(uint64_t mask, int detPos = -1); + void setPatternMask(uint64_t mask, int detPos = -1); // /** * Gets the mask applied to every pattern (CTB/ Moench) * @param detPos -1 for all detectors in list or specific detector position * @returns mask set */ - uint64_t getPatternMask(int detPos = -1); + uint64_t getPatternMask(int detPos = -1); // /** * Selects the bits that the mask will be applied to for every pattern (CTB/ @@ -2121,7 +2121,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param mask mask to select bits * @param detPos -1 for all detectors in list or specific detector position */ - void setPatternBitMask(uint64_t mask, int detPos = -1); + void setPatternBitMask(uint64_t mask, int detPos = -1);// /** * Gets the bits that the mask will be applied to for every pattern (CTB/ @@ -2129,7 +2129,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns mask of bits selected */ - uint64_t getPatternBitMask(int detPos = -1); + uint64_t getPatternBitMask(int detPos = -1);// /** * Set LED Enable (Moench, CTB only) @@ -2137,7 +2137,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns LED enable */ - int setLEDEnable(int enable = -1, int detPos = -1); + int setLEDEnable(int enable = -1, int detPos = -1); // /** * Set Digital IO Delay (Moench, CTB only) @@ -2145,7 +2145,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param delay delay in ps(1 bit=25ps, max of 775 ps) * @param detPos -1 for all detectors in list or specific detector position */ - void setDigitalIODelay(uint64_t pinMask, int delay, int detPos = -1); + void setDigitalIODelay(uint64_t pinMask, int delay, int detPos = -1); // /** * Loads the detector setup from file @@ -2209,8 +2209,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * or just gives progress of acquisition by polling receivers */ void processData(); - - void addSlsDetector(std::unique_ptr det); + private: /** diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index a014375e5..f8a5c8a4d 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -171,6 +171,19 @@ Result Detector::getDetectorTypeAsString(Positions pos) const { // Erik + +Result Detector::getPatternMask(Positions pos){ + return pimpl->Parallel(&slsDetector::getPatternMask, pos); +} + +void Detector::setPatternBitMask(uint64_t mask, Positions pos){ + pimpl->Parallel(&slsDetector::setPatternBitMask, pos, mask); +} + +Result Detector::getPatternBitMask(Positions pos) const{ + return pimpl->Parallel(&slsDetector::getPatternBitMask, pos); +} + void Detector::setLEDEnable(bool enable, Positions pos) { pimpl->Parallel(&slsDetector::setLEDEnable, pos, static_cast(enable)); } diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index c6fc94707..7a175406e 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -476,17 +476,6 @@ void multiSlsDetector::addSlsDetector(const std::string &hostname) { multi_shm()->multiDetectorType = getDetectorTypeAsEnum(-1);// -1 needed here } -void multiSlsDetector::addSlsDetector(std::unique_ptr det) { - detectors.push_back(std::move(det)); - multi_shm()->numberOfDetectors = detectors.size(); - multi_shm()->dataBytes += detectors.back()->getDataBytes(); - multi_shm()->dataBytesInclGapPixels += - detectors.back()->getDataBytesInclGapPixels(); - multi_shm()->numberOfChannels += - detectors.back()->getTotalNumberOfChannels(); - multi_shm()->multiDetectorType = getDetectorTypeAsEnum(-1);// -1 needed here -} - slsDetectorDefs::detectorType multiSlsDetector::getDetectorTypeAsEnum() const { return multi_shm()->multiDetectorType; } diff --git a/slsDetectorSoftware/tests/test-multiSlsDetector.cpp b/slsDetectorSoftware/tests/test-multiSlsDetector.cpp index 37342ece6..5f09b1a03 100755 --- a/slsDetectorSoftware/tests/test-multiSlsDetector.cpp +++ b/slsDetectorSoftware/tests/test-multiSlsDetector.cpp @@ -9,75 +9,75 @@ using namespace sls; -SCENARIO("Multi detector operation", "[detector]") { +// SCENARIO("Multi detector operation", "[detector]") { - multiSlsDetector::freeSharedMemory(20, -1); +// multiSlsDetector::freeSharedMemory(20, -1); - GIVEN("An empty multi detector") { - multiSlsDetector m(20); - THEN("the size is zero") { - CHECK(m.getNumberOfDetectors() == 0); - CHECK(m.getDataBytes() == 0); - CHECK(m.getTotalNumberOfChannels() == 0); - } +// GIVEN("An empty multi detector") { +// multiSlsDetector m(20); +// THEN("the size is zero") { +// CHECK(m.getNumberOfDetectors() == 0); +// CHECK(m.getDataBytes() == 0); +// CHECK(m.getTotalNumberOfChannels() == 0); +// } - WHEN("we add a detector") { - m.addSlsDetector(sls::make_unique( - slsDetectorDefs::detectorType::EIGER, 20, 0)); - THEN("the size and number of detector changes") { - CHECK(m.getNumberOfDetectors() == 1); - CHECK(m.getTotalNumberOfChannels() == 256 * 1024); - } +// WHEN("we add a detector") { +// m.addSlsDetector(sls::make_unique( +// slsDetectorDefs::detectorType::EIGER, 20, 0)); +// THEN("the size and number of detector changes") { +// CHECK(m.getNumberOfDetectors() == 1); +// CHECK(m.getTotalNumberOfChannels() == 256 * 1024); +// } - WHEN("we add another detector") { - m.addSlsDetector(sls::make_unique( - slsDetectorDefs::detectorType::EIGER, 20, 1)); - THEN("the size and number of detector changes") { - CHECK(m.getNumberOfDetectors() == 2); - CHECK(m.getTotalNumberOfChannels() == 2 * 256 * 1024); - } +// WHEN("we add another detector") { +// m.addSlsDetector(sls::make_unique( +// slsDetectorDefs::detectorType::EIGER, 20, 1)); +// THEN("the size and number of detector changes") { +// CHECK(m.getNumberOfDetectors() == 2); +// CHECK(m.getTotalNumberOfChannels() == 2 * 256 * 1024); +// } - WHEN("We set the trimen") { - std::vector energies{5000, 6000, 7000, 8000, 9000}; - m.setTrimEn(energies); - THEN("we read back the same values") { - CHECK(m.getTrimEn() == energies); - } - } - WHEN("We set the trimen to different values") { - std::vector en0{5000, 6000, 7000, 8000, 9000}; - std::vector en1{6000, 7000, 8000, 9000}; - m.setTrimEn(en0, 0); - m.setTrimEn(en1, 1); - THEN("we read back the same values") { - CHECK(m.getTrimEn(0) == en0); - CHECK(m.getTrimEn(1) == en1); - CHECK(m.getTrimEn() == std::vector{-1}); - } - } - } - } - m.freeSharedMemory(); - } -} +// WHEN("We set the trimen") { +// std::vector energies{5000, 6000, 7000, 8000, 9000}; +// m.setTrimEn(energies); +// THEN("we read back the same values") { +// CHECK(m.getTrimEn() == energies); +// } +// } +// WHEN("We set the trimen to different values") { +// std::vector en0{5000, 6000, 7000, 8000, 9000}; +// std::vector en1{6000, 7000, 8000, 9000}; +// m.setTrimEn(en0, 0); +// m.setTrimEn(en1, 1); +// THEN("we read back the same values") { +// CHECK(m.getTrimEn(0) == en0); +// CHECK(m.getTrimEn(1) == en1); +// CHECK(m.getTrimEn() == std::vector{-1}); +// } +// } +// } +// } +// m.freeSharedMemory(); +// } +// } -TEST_CASE("Set and get partialFramesPadding", "[detector][somenewtag]"){ +// TEST_CASE("Set and get partialFramesPadding", "[detector][somenewtag]"){ - multiSlsDetector::freeSharedMemory(20, -1); - multiSlsDetector m(20); - m.addSlsDetector(sls::make_unique( - slsDetectorDefs::detectorType::EIGER, 20, 0)); - m.addSlsDetector(sls::make_unique( - slsDetectorDefs::detectorType::EIGER, 20, 1)); +// multiSlsDetector::freeSharedMemory(20, -1); +// multiSlsDetector m(20); +// m.addSlsDetector(sls::make_unique( +// slsDetectorDefs::detectorType::EIGER, 20, 0)); +// m.addSlsDetector(sls::make_unique( +// slsDetectorDefs::detectorType::EIGER, 20, 1)); - m.setPartialFramesPadding(false); - CHECK(m.getPartialFramesPadding() == 0); +// m.setPartialFramesPadding(false); +// CHECK(m.getPartialFramesPadding() == 0); - m.setPartialFramesPadding(true); - CHECK(m.getPartialFramesPadding() == 1); +// m.setPartialFramesPadding(true); +// CHECK(m.getPartialFramesPadding() == 1); - m.setPartialFramesPadding(false, 0); - CHECK(m.getPartialFramesPadding() == -1); +// m.setPartialFramesPadding(false, 0); +// CHECK(m.getPartialFramesPadding() == -1); - m.freeSharedMemory(); -} +// m.freeSharedMemory(); +// } From e7e4bf13c31a14d8ee894b07b13076a1cb8d950e Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Thu, 8 Aug 2019 11:07:41 +0200 Subject: [PATCH 011/108] WIP --- slsDetectorSoftware/include/Detector.h | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 212c2f03b..9c13d936b 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -211,6 +211,15 @@ class Detector { // Erik + /** + * CTB only. Sets the wait time + * @param level 0,1,2, wait level + * @param t wait time, -1 gets + * @param detPos -1 for all detectors in list or specific detector position + * @returns actual value + */ + uint64_t setPatternWaitTime(int level, uint64_t t = -1, int detPos = -1); + /** CTB only.Sets the mask applied to every pattern. */ void setPatternMask(uint64_t mask, Positions pos = {}); @@ -230,15 +239,10 @@ class Detector { */ Result getPatternBitMask(Positions pos = {}) const; - /** - * CTB only. Enable or disable the LED - * @param enable true to switch on, false to switch off - */ + /** CTB only. Enable or disable the LED */ void setLEDEnable(bool enable, Positions pos = {}); - /** - * CTB only. Get LED enable. - */ + /** CTB only. Get LED enable. */ Result getLEDEnable(Positions pos = {}) const; /** From 553b7d8568ca69ff4bc2b366b3080a5ddf724002 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Thu, 8 Aug 2019 11:11:08 +0200 Subject: [PATCH 012/108] WIP --- slsDetectorSoftware/include/Detector.h | 20 +++++++++++++ .../include/multiSlsDetector.h | 28 +++++++++---------- slsDetectorSoftware/src/Detector.cpp | 21 ++++++++++---- .../src/slsDetectorCommand.cpp | 20 ++----------- 4 files changed, 53 insertions(+), 36 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 212c2f03b..33a43e90b 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -209,6 +209,26 @@ class Detector { */ Result getDetectorTypeAsString(Positions pos = {}) const; + /** + * Returns the number of detectors in the multidetector structure + * @returns number of detectors + */ + int getNumberOfDetectors() const; + + /** + * Returns number of detectors in dimension d + * @param d dimension d + * @returns number of detectors in dimension d + */ + int getNumberOfDetectors(defs::dimension d) const; + + /** + * Returns the number of detectors in each direction + @param nx number of detectors in x direction + @param ny number of detectors in y direction + */ + void getNumberOfDetectors(int &nx, int &ny) const; + // Erik /** CTB only.Sets the mask applied to every pattern. */ diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 36e45fa29..6b8198404 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -347,19 +347,11 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ std::string getHostname(int detPos = -1) const;// - /** - * Appends detectors to the end of the list in shared memory - * Connects to them - * @param name concatenated hostname of the sls detectors to be appended to - * the list - */ - void addMultipleDetectors(const char *name);// ???? - /** * Get Detector type as an enum * @returns detector type */ - detectorType getDetectorTypeAsEnum() const; + detectorType getDetectorTypeAsEnum() const; // /** * Get Detector type for a particular sls detector or get the first one @@ -367,7 +359,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns detector type of sls detector in position pos, if -1, returns * the first det type */ - detectorType getDetectorTypeAsEnum(int detPos);//?? + detectorType getDetectorTypeAsEnum(int detPos);// /** * Concatenates string types of all sls detectors or @@ -376,27 +368,27 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns detector type of sls detector in position pos, if -1, * concatenates */ - std::string getDetectorTypeAsString(int detPos = -1); + std::string getDetectorTypeAsString(int detPos = -1);// /** * Returns the number of detectors in the multidetector structure * @returns number of detectors */ - int getNumberOfDetectors() const; + int getNumberOfDetectors() const;// /** * Returns number of detectors in dimension d * @param d dimension d * @returns number of detectors in dimension d */ - int getNumberOfDetectors(dimension d) const; + int getNumberOfDetectors(dimension d) const;// /** * Returns the number of detectors in each direction @param nx number of detectors in x direction @param ny number of detectors in y direction */ - void getNumberOfDetectors(int &nx, int &ny) const; + void getNumberOfDetectors(int &nx, int &ny) const;// /** * Returns the total number of channels of all sls detectors from shared @@ -2241,6 +2233,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ void initializeMembers(bool verify = true); + /** + * Appends detectors to the end of the list in shared memory + * Connects to them + * @param name concatenated hostname of the sls detectors to be appended to + * the list + */ + void addMultipleDetectors(const char *name);// + /** * Update user details in detector structure */ diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index f8a5c8a4d..9d38a5fb1 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -169,18 +169,29 @@ Result Detector::getDetectorTypeAsString(Positions pos) const { return pimpl->Parallel(&slsDetector::getDetectorTypeAsString, pos); } +int Detector::getNumberOfDetectors() const { + return pimpl->getNumberOfDetectors(); +} + +int Detector::getNumberOfDetectors(defs::dimension d) const { + return pimpl->getNumberOfDetectors(d); +} + +void Detector::getNumberOfDetectors(int &nx, int &ny) const { + pimpl->getNumberOfDetectors(nx, ny); +} + // Erik - -Result Detector::getPatternMask(Positions pos){ +Result Detector::getPatternMask(Positions pos) { return pimpl->Parallel(&slsDetector::getPatternMask, pos); } -void Detector::setPatternBitMask(uint64_t mask, Positions pos){ +void Detector::setPatternBitMask(uint64_t mask, Positions pos) { pimpl->Parallel(&slsDetector::setPatternBitMask, pos, mask); } -Result Detector::getPatternBitMask(Positions pos) const{ +Result Detector::getPatternBitMask(Positions pos) const { return pimpl->Parallel(&slsDetector::getPatternBitMask, pos); } @@ -192,7 +203,7 @@ Result Detector::getLEDEnable(Positions pos) const { return pimpl->Parallel(&slsDetector::setLEDEnable, pos, -1); } -void Detector::setDigitalIODelay(uint64_t pinMask, int delay, Positions pos){ +void Detector::setDigitalIODelay(uint64_t pinMask, int delay, Positions pos) { pimpl->Parallel(&slsDetector::setDigitalIODelay, pos, pinMask, delay); } diff --git a/slsDetectorSoftware/src/slsDetectorCommand.cpp b/slsDetectorSoftware/src/slsDetectorCommand.cpp index e5f3ee928..af2d12e85 100755 --- a/slsDetectorSoftware/src/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp @@ -275,13 +275,6 @@ slsDetectorCommand::slsDetectorCommand(multiSlsDetector *det) { descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdHostname; ++i; - /*! \page config - - \b add appends a hostname (or IP address) at the end of the multi-detector structure. Only allowed at multi detector level. Cannot get. \c Returns the current list of detector hostnames. \c (string) - */ - descrToFuncMap[i].m_pFuncName = "add"; - descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdHostname; - ++i; - /*! \page config - replace \c Sets the hostname (or IP adress) for a single detector. Only allowed at single detector level. Cannot get. \c Returns the hostnames for that detector \c (string) */ @@ -2379,12 +2372,12 @@ std::string slsDetectorCommand::cmdHostname(int narg, const char * const args[], return helpHostname(HELP_ACTION); } if (action == GET_ACTION) { - if ((cmd == "add") || (cmd == "replace")) + if (cmd == "replace") return std::string("cannot get"); } if (action == PUT_ACTION) { - if (((cmd == "add") || (cmd == "hostname")) && + if ((cmd == "hostname") && (detPos >= 0)) { return std::string("Wrong usage - setting hostname/add only from " "multiDetector level"); @@ -2403,10 +2396,7 @@ std::string slsDetectorCommand::cmdHostname(int narg, const char * const args[], strcat(hostname, "+"); } - if (cmd == "add") - myDet->addMultipleDetectors(hostname); - else - myDet->setHostname(hostname, detPos); + myDet->setHostname(hostname, detPos); } return myDet->getHostname(detPos); @@ -2416,15 +2406,11 @@ std::string slsDetectorCommand::helpHostname(int action) { std::ostringstream os; if (action == GET_ACTION || action == HELP_ACTION) { os << std::string("hostname \t returns the hostname(s) of the multi detector structure.\n"); - os << std::string("add \t cannot get\n"); os << std::string("replace \t cannot get\n"); } if (action == PUT_ACTION || action == HELP_ACTION) { os << std::string("hostname name [name name]\t frees shared memory and " "sets the hostname (or IP adress). Only allowed at multi detector level.\n"); - os << std::string("add det [det det]\t appends a hostname (or IP address) at " - "the end of the multi-detector structure. Only allowed at multi detector level." - "Returns hostnames in the multi detector structure\n"); os << std::string("replace det \t Sets the hostname (or IP adress) for a " "single detector. Only allowed at single detector level. " "Returns the hostnames for that detector\n"); From 1bdff2b681993b2da8bbdbedaa142d65db25e2eb Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Thu, 8 Aug 2019 12:02:36 +0200 Subject: [PATCH 013/108] WIP --- slsDetectorSoftware/include/Detector.h | 77 ++++++++++++++++--- .../include/multiSlsDetector.h | 12 +-- slsDetectorSoftware/src/Detector.cpp | 49 +++++++++++- 3 files changed, 116 insertions(+), 22 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 9c13d936b..9fc251fb4 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -211,42 +211,95 @@ class Detector { // Erik + /** [CTB] */ + void setPatternClockControl(uint64_t word, Positions pos = {}); + + /** [CTB] */ + Result getPatternClockControl(Positions pos = {}) const; + /** - * CTB only. Sets the wait time - * @param level 0,1,2, wait level - * @param t wait time, -1 gets - * @param detPos -1 for all detectors in list or specific detector position + * [CTB] Writes a pattern word + * @param addr address of the word + * @param word word to be written, -1 reads the addr (same as + * executing the pattern) + * @param pos detector position * @returns actual value */ - uint64_t setPatternWaitTime(int level, uint64_t t = -1, int detPos = -1); + void setPatternWord(int addr, uint64_t word, Positions pos = {}); - /** CTB only.Sets the mask applied to every pattern. */ + // TODO! Does this have side effects? + // uint64_t getPatternWord()... + + /** + * [CTB] Sets the pattern or loop limits. + * @param level -1 complete pattern, 0,1,2, loop level + * @param start start address for level 0-2 + * @param stop stop address for level 0-2 + * @param n number of loops for level 0-2 + * @param detPos -1 for all detectors in list or specific detector position + */ + void setPatternLoops(int level, int start, int stop, int n, + Positions pos = {}); + + /** + * [CTB] Gets the pattern loop limits + * @param level -1 complete pattern, 0,1,2, loop level + * @param pos detector positions + * @returns array of start address, stop address and number of loops + */ + Result> getPatternLoops(int level, + Positions pos = {}) const; + + /** + * [CTB] Sets the wait address + * @param level 0,1,2, wait level + * @param addr wait address + * @param pos detector position + * @returns actual value + */ + void setPatternWaitAddr(int level, int addr, Positions pos = {}); + + /* [CTB] */ + Result getPatternWaitAddr(int level, Positions pos = {}) const; + + /** + * [CTB] Sets the wait time + * @param level 0,1,2, wait level + * @param t wait time + * @param pos detector position + */ + void setPatternWaitTime(int level, uint64_t t, Positions pos = {}); + + /** [CTB] */ + Result getPatternWaitTime(int level, Positions pos = {}) const; + + /** [CTB] Sets the mask applied to every pattern. */ void setPatternMask(uint64_t mask, Positions pos = {}); - /** CTB only. Gets the mask applied to every pattern. */ + /** [CTB] Gets the mask applied to every pattern. */ Result getPatternMask(Positions pos = {}); /** - * CTB only. Sets the bitmask that the mask will be applied to for every + * [CTB] Sets the bitmask that the mask will be applied to for every * pattern. * @param mask mask to select bits */ void setPatternBitMask(uint64_t mask, Positions pos = {}); /** - * CTB only. Gets the bits that the mask will be applied to for every + * [CTB] Gets the bits that the mask will be applied to for every * pattern */ Result getPatternBitMask(Positions pos = {}) const; - /** CTB only. Enable or disable the LED */ + /** [CTB] Enable or disable the LED */ void setLEDEnable(bool enable, Positions pos = {}); - /** CTB only. Get LED enable. */ + /** [CTB] Get LED enable. */ Result getLEDEnable(Positions pos = {}) const; /** - * CTB only. Set Digital IO Delay + * [CTB] Set Digital IO Delay * @param digital IO mask to select the pins * @param delay delay in ps(1 bit=25ps, max of 775 ps) */ diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 36e45fa29..e421915e9 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -2052,7 +2052,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns actual value */ - uint64_t setPatternClockControl(uint64_t word = -1, int detPos = -1); + uint64_t setPatternClockControl(uint64_t word = -1, int detPos = -1); // /** * Writes a pattern word (CTB/ Moench) @@ -2062,7 +2062,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns actual value */ - uint64_t setPatternWord(int addr, uint64_t word, int detPos = -1); + uint64_t setPatternWord(int addr, uint64_t word, int detPos = -1); // /** * Sets the pattern or loop limits (CTB/ Moench) @@ -2073,7 +2073,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position */ void setPatternLoops(int level, int start = -1, int stop = -1, int n = -1, - int detPos = -1); + int detPos = -1); // /** * Gets the pattern loop limits (CTB/ Moench) @@ -2081,7 +2081,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns array of start address, stop address and number of loops */ - std::array getPatternLoops(int level, int detPos = -1); + std::array getPatternLoops(int level, int detPos = -1); // /** * Sets the wait address (CTB/ Moench) @@ -2090,7 +2090,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns actual value */ - int setPatternWaitAddr(int level, int addr = -1, int detPos = -1); + int setPatternWaitAddr(int level, int addr = -1, int detPos = -1); // /** * Sets the wait time (CTB/ Moench) @@ -2099,7 +2099,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns actual value */ - uint64_t setPatternWaitTime(int level, uint64_t t = -1, int detPos = -1); + uint64_t setPatternWaitTime(int level, uint64_t t = -1, int detPos = -1); // /** * Sets the mask applied to every pattern (CTB/ Moench) diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index f8a5c8a4d..6903e572c 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -172,15 +172,56 @@ Result Detector::getDetectorTypeAsString(Positions pos) const { // Erik -Result Detector::getPatternMask(Positions pos){ +void Detector::setPatternClockControl(uint64_t word, Positions pos){ + pimpl->Parallel(&slsDetector::setPatternClockControl, pos, word); +} + +Result Detector::getPatternClockControl(Positions pos) const{ + return pimpl->Parallel(&slsDetector::setPatternClockControl, pos, -1); +} + +void Detector::setPatternWord(int addr, uint64_t word, Positions pos){ + pimpl->Parallel(&slsDetector::setPatternWord, pos, addr, word); +} + + + +void Detector::setPatternLoops(int level, int start, int stop, int n, Positions pos){ + pimpl->Parallel(&slsDetector::setPatternLoops, pos, level, start, stop, n); + +} + +Result> Detector::getPatternLoops(int level, + Positions pos) const { + return pimpl->Parallel(&slsDetector::setPatternLoops, pos, level, -1, -1, + -1); +} + +void Detector::setPatternWaitAddr(int level, int addr, Positions pos) { + pimpl->Parallel(&slsDetector::setPatternWaitAddr, pos, level, addr); +} + +Result Detector::getPatternWaitAddr(int level, Positions pos) const { + return pimpl->Parallel(&slsDetector::setPatternWaitAddr, pos, level, -1); +} + +void Detector::setPatternWaitTime(int level, uint64_t t, Positions pos) { + pimpl->Parallel(&slsDetector::setPatternWaitTime, pos, level, t); +} + +Result Detector::getPatternWaitTime(int level, Positions pos) const { + return pimpl->Parallel(&slsDetector::setPatternWaitTime, pos, level, -1); +} + +Result Detector::getPatternMask(Positions pos) { return pimpl->Parallel(&slsDetector::getPatternMask, pos); } -void Detector::setPatternBitMask(uint64_t mask, Positions pos){ +void Detector::setPatternBitMask(uint64_t mask, Positions pos) { pimpl->Parallel(&slsDetector::setPatternBitMask, pos, mask); } -Result Detector::getPatternBitMask(Positions pos) const{ +Result Detector::getPatternBitMask(Positions pos) const { return pimpl->Parallel(&slsDetector::getPatternBitMask, pos); } @@ -192,7 +233,7 @@ Result Detector::getLEDEnable(Positions pos) const { return pimpl->Parallel(&slsDetector::setLEDEnable, pos, -1); } -void Detector::setDigitalIODelay(uint64_t pinMask, int delay, Positions pos){ +void Detector::setDigitalIODelay(uint64_t pinMask, int delay, Positions pos) { pimpl->Parallel(&slsDetector::setDigitalIODelay, pos, pinMask, delay); } From f0e106f94f14cdcb9c17fc32ea46490cc82fb746 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Thu, 8 Aug 2019 13:49:28 +0200 Subject: [PATCH 014/108] WIP --- slsDetectorSoftware/include/Detector.h | 12 +++++++ .../include/multiSlsDetector.h | 6 ++-- slsDetectorSoftware/src/Detector.cpp | 32 +++++++++++++++---- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 9fc251fb4..80f46a536 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -210,6 +210,18 @@ class Detector { Result getDetectorTypeAsString(Positions pos = {}) const; // Erik + Result getReceiverSilentMode(Positions pos = {}) const; + + void setReceiverSilentMode(bool value, Positions pos = {}); + + /** [CTB] */ + void setPattern(const std::string &fname, Positions pos = {}); + + /** [CTB] */ + void setPatternIOControl(uint64_t word, Positions pos = {}); + + /** [CTB] */ + Result getPatternIOControl(Positions pos = {}) const; /** [CTB] */ void setPatternClockControl(uint64_t word, Positions pos = {}); diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index e421915e9..b103a4b99 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -2028,7 +2028,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the receiver silent mode enable */ - int setReceiverSilentMode(int i = -1, int detPos = -1); + int setReceiverSilentMode(int i = -1, int detPos = -1); // /** * Opens pattern file and sends pattern (CTB/ Moench) @@ -2036,7 +2036,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns OK/FAIL */ - int setPattern(const std::string &fname, int detPos = -1); + int setPattern(const std::string &fname, int detPos = -1); // /** * Sets pattern IO control (CTB/ Moench) @@ -2044,7 +2044,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns actual value */ - uint64_t setPatternIOControl(uint64_t word = -1, int detPos = -1); + uint64_t setPatternIOControl(uint64_t word = -1, int detPos = -1);// /** * Sets pattern clock control (CTB/ Moench) diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 6903e572c..b691bacdc 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -171,24 +171,42 @@ Result Detector::getDetectorTypeAsString(Positions pos) const { // Erik +Result Detector::getReceiverSilentMode(Positions pos){ + return pimpl->Parallel(&slsDetector::setReceiverSilentMode, pos, -1); +} -void Detector::setPatternClockControl(uint64_t word, Positions pos){ +void Detector::setReceiverSilentMode(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverSilentMode, pos, + static_cast(value)); +} + +void Detector::setPattern(const std::string &fname, Positions pos) { + pimpl->Parallel(&slsDetector::setPattern, pos, fname); +} + +void Detector::setPatternIOControl(uint64_t word, Positions pos) { + pimpl->Parallel(&slsDetector::setPatternIOControl, pos, word); +} + +Result Detector::getPatternIOControl(Positions pos) const { + return pimpl->Parallel(&slsDetector::setPatternIOControl, pos, -1); +} + +void Detector::setPatternClockControl(uint64_t word, Positions pos) { pimpl->Parallel(&slsDetector::setPatternClockControl, pos, word); } -Result Detector::getPatternClockControl(Positions pos) const{ +Result Detector::getPatternClockControl(Positions pos) const { return pimpl->Parallel(&slsDetector::setPatternClockControl, pos, -1); } -void Detector::setPatternWord(int addr, uint64_t word, Positions pos){ +void Detector::setPatternWord(int addr, uint64_t word, Positions pos) { pimpl->Parallel(&slsDetector::setPatternWord, pos, addr, word); } - - -void Detector::setPatternLoops(int level, int start, int stop, int n, Positions pos){ +void Detector::setPatternLoops(int level, int start, int stop, int n, + Positions pos) { pimpl->Parallel(&slsDetector::setPatternLoops, pos, level, start, stop, n); - } Result> Detector::getPatternLoops(int level, From 79d6ea614a43c4b2b32ed7aa33542c4b81b0f7ff Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Thu, 8 Aug 2019 14:30:02 +0200 Subject: [PATCH 015/108] WIP --- slsDetectorSoftware/include/Detector.h | 46 +++- .../include/multiSlsDetector.h | 215 +++++++++--------- slsDetectorSoftware/src/Detector.cpp | 47 +++- 3 files changed, 204 insertions(+), 104 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 80f46a536..11aa2ffe7 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -210,10 +210,54 @@ class Detector { Result getDetectorTypeAsString(Positions pos = {}) const; // Erik - Result getReceiverSilentMode(Positions pos = {}) const; + + Result getFramesCaughtByReceiver(Positions pos = {}) const; + + Result getReceiverCurrentFrameIndex(Positions pos = {}) const; + + void resetFramesCaught(Positions pos = {}); + + //TODO! + // int createReceivingDataSockets(const bool destroy = false); + // void readFrameFromReceiver(); + + void setMasterFileWrite(bool value, Positions pos = {}); + + Result getMasterFileWrite(Positions pos = {}) const; + + void setReceiverStreamingFrequency(int freq = -1, int detPos = -1); + /** + * [All] If receiver streaming frequency is 0, then this timer between each + * data stream is set. Default is 500 ms. + */ + void setReceiverStreamingTimer(int time_in_ms = 500, Positions pos = {}); + + /** [All] */ + Result getReceiverStreamingTimer(Positions pos = {}) const; + + // TODO! + // int enableDataStreamingToClient(int enable = -1); + // int enableDataStreamingFromReceiver(int enable = -1, int detPos = -1) + + /** [TODO! All?] */ + void setTenGigaEnabled(bool value, Positions pos = {}); + + /** [TODO! All?] */ + Result getTenGigaEnabled(Positions pos = {}) const; + + /** [All] */ + void setReceiverFifoDepth(int nframes, Positions pos = {}); + + /** [All] */ + Result getReceiverFifoDepth(Positions pos = {}) const; + + /** [All] */ void setReceiverSilentMode(bool value, Positions pos = {}); + /** [All] */ + Result getReceiverSilentMode(Positions pos = {}) const; + /** [CTB] */ void setPattern(const std::string &fname, Positions pos = {}); diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index b103a4b99..93b9163e0 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -20,7 +20,6 @@ class detectorData; #define SHORT_STRING_LENGTH 50 #define DATE_LENGTH 30 - #include #include /** @@ -49,10 +48,10 @@ struct sharedMultiSlsDetector { /** multi detector type */ slsDetectorDefs::detectorType multiDetectorType; - + /** END OF FIXED PATTERN * -----------------------------------------------*/ - + /** Number of detectors operated at once */ int numberOfDetector[2]; @@ -118,7 +117,8 @@ class multiSlsDetector : public virtual slsDetectorDefs { std::vector positions, typename NonDeduced::type... Args) { - if (positions.empty() || (positions.size() == 1 && positions[0] == -1 )) { + if (positions.empty() || + (positions.size() == 1 && positions[0] == -1)) { positions.resize(detectors.size()); std::iota(begin(positions), end(positions), 0); } @@ -141,9 +141,10 @@ class multiSlsDetector : public virtual slsDetectorDefs { template std::vector Parallel(RT (slsDetector::*somefunc)(CT...) const, std::vector positions, - typename NonDeduced::type... Args) const{ + typename NonDeduced::type... Args) const { - if (positions.empty() || (positions.size() == 1 && positions[0] == -1 )) { + if (positions.empty() || + (positions.size() == 1 && positions[0] == -1)) { positions.resize(detectors.size()); std::iota(begin(positions), end(positions), 0); } @@ -165,10 +166,11 @@ class multiSlsDetector : public virtual slsDetectorDefs { template void Parallel(void (slsDetector::*somefunc)(CT...), - std::vector positions, - typename NonDeduced::type... Args) { + std::vector positions, + typename NonDeduced::type... Args) { - if (positions.empty() || (positions.size() == 1 && positions[0] == -1 )) { + if (positions.empty() || + (positions.size() == 1 && positions[0] == -1)) { positions.resize(detectors.size()); std::iota(begin(positions), end(positions), 0); } @@ -187,10 +189,11 @@ class multiSlsDetector : public virtual slsDetectorDefs { template void Parallel(void (slsDetector::*somefunc)(CT...) const, - std::vector positions, - typename NonDeduced::type... Args) const{ + std::vector positions, + typename NonDeduced::type... Args) const { - if (positions.empty() || (positions.size() == 1 && positions[0] == -1 )) { + if (positions.empty() || + (positions.size() == 1 && positions[0] == -1)) { positions.resize(detectors.size()); std::iota(begin(positions), end(positions), 0); } @@ -210,7 +213,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { /** * Loop through the detectors serially and return the result as a vector */ - + template std::vector serialCall(RT (slsDetector::*somefunc)(CT...), typename NonDeduced::type... Args); @@ -250,13 +253,13 @@ class multiSlsDetector : public virtual slsDetectorDefs { * Set acquiring flag in shared memory * @param b acquiring flag */ - void setAcquiringFlag(bool flag);// + void setAcquiringFlag(bool flag); // /** * Get acquiring flag from shared memory * @returns acquiring flag */ - bool getAcquiringFlag() const;// + bool getAcquiringFlag() const; // /** * Check version compatibility with detector software @@ -264,7 +267,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param p port type control port or receiver port * @param detPos -1 for all detectors in list or specific detector position */ - void checkDetectorVersionCompatibility(int detPos = -1);// + void checkDetectorVersionCompatibility(int detPos = -1); // /** * Check version compatibility with receiver software @@ -272,7 +275,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param p port type control port or receiver port * @param detPos -1 for all detectors in list or specific detector position */ - void checkReceiverVersionCompatibility(int detPos = -1);// + void checkReceiverVersionCompatibility(int detPos = -1); // /** * Get ID or version numbers @@ -280,34 +283,38 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns Id or version number of that type */ - int64_t getId(idMode mode, int detPos = -1);//not needed anymore (later remove this_software_version from enum) + int64_t getId(idMode mode, + int detPos = -1); // not needed anymore (later remove + // this_software_version from enum) - int getMultiId()const{return multiId;} //part of multi also + int getMultiId() const { return multiId; } // part of multi also /** * Get Client Software version * @returns client software version */ - int64_t getClientSoftwareVersion() const;// + int64_t getClientSoftwareVersion() const; // /** * Get Receiver software version * @return receiver software version */ - int64_t getReceiverSoftwareVersion(int detPos = -1);// + int64_t getReceiverSoftwareVersion(int detPos = -1); // /** * Get Detector Number * @returns vector of detector number */ - std::vector getDetectorNumber(); // renamed to getDetectorSerialNumber + std::vector + getDetectorNumber(); // renamed to getDetectorSerialNumber /** * Free shared memory from the command line * avoiding creating the constructor classes and mapping * @param multiId multi detector Id * @param detPos -1 for all detectors in list or specific detector position */ - static void freeSharedMemory(int multiId, int detPos = -1);// private or not needed + static void freeSharedMemory(int multiId, + int detPos = -1); // private or not needed /** * Free shared memory and delete shared memory structure @@ -316,27 +323,29 @@ class multiSlsDetector : public virtual slsDetectorDefs { * object back to state before object creation amap * @param detPos -1 for all detectors in list or specific detector position */ - void freeSharedMemory(int detPos = -1);// + void freeSharedMemory(int detPos = -1); // /** * Get user details of shared memory * @returns string with user details */ - std::string getUserDetails();// part of multi + std::string getUserDetails(); // part of multi /** - * Sets the hostname of all sls detectors in shared memory and updates local cache + * Sets the hostname of all sls detectors in shared memory and updates local + * cache * @param name hostname of all the sls detectors */ - void setHostname(const std::vector &name);//cannot set individually - + void setHostname( + const std::vector &name); // cannot set individually + /** * Sets the hostname of all sls detectors in shared memory * Connects to them * @param name concatenated hostname of all the sls detectors * @param detPos -1 for all detectors in list or specific detector position */ - void setHostname(const char *name, int detPos = -1);// not needed + void setHostname(const char *name, int detPos = -1); // not needed /** * Gets the hostname of detector at particular position @@ -345,15 +354,15 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns concatenated hostnames of all detectors or hostname of specific * one */ - std::string getHostname(int detPos = -1) const;// + std::string getHostname(int detPos = -1) const; // /** * Appends detectors to the end of the list in shared memory - * Connects to them + * Connects to them * @param name concatenated hostname of the sls detectors to be appended to * the list */ - void addMultipleDetectors(const char *name);// ???? + void addMultipleDetectors(const char *name); // ???? /** * Get Detector type as an enum @@ -367,7 +376,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns detector type of sls detector in position pos, if -1, returns * the first det type */ - detectorType getDetectorTypeAsEnum(int detPos);//?? + detectorType getDetectorTypeAsEnum(int detPos); //?? /** * Concatenates string types of all sls detectors or @@ -453,12 +462,12 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ int getQuad(int detPos = -1); - /** - * Set Quad Type (Only for Eiger Quad detector hardware) - * @param enable true if quad type set, else false - * @param detPos -1 for all detectors in list or specific detector position - */ - void setQuad(const bool enable, int detPos = -1); + /** + * Set Quad Type (Only for Eiger Quad detector hardware) + * @param enable true if quad type set, else false + * @param detPos -1 for all detectors in list or specific detector position + */ + void setQuad(const bool enable, int detPos = -1); /** * Set number of rows to read out (Only for Eiger) @@ -529,11 +538,11 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ int setReceiverPort(int port_number = -1, int detPos = -1); - /** - * Get Receiver port - * @param detPos -1 for all detectors in list or specific detector position - * @returns vector of receiver port - */ + /** + * Get Receiver port + * @param detPos -1 for all detectors in list or specific detector position + * @returns vector of receiver port + */ int getReceiverPort(int detPos = -1) const; /** @@ -568,7 +577,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * Load configuration from a configuration File * @param fname configuration file name */ - void readConfigurationFile(const std::string &fname);// + void readConfigurationFile(const std::string &fname); // /** * Write current configuration to a file @@ -699,20 +708,20 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position */ void 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);// + 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);// + uint64_t getStartingFrameNumber(int detPos = -1); // /** * Set/get timer value (not all implemented for all detectors) @@ -732,7 +741,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns exposure time in ns, or s if specified */ double setExposureTime(double t = -1, bool inseconds = false, - int detPos = -1);// + int detPos = -1); // /** * Set/get exposure period @@ -742,7 +751,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns exposure period in ns, or s if specified */ double setExposurePeriod(double t = -1, bool inseconds = false, - int detPos = -1);// + int detPos = -1); // /** * Set/get delay after trigger (Gotthard, Jungfrau(not for this release)) @@ -763,7 +772,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns sub frame exposure time in ns, or s if specified */ double setSubFrameExposureTime(double t = -1, bool inseconds = false, - int detPos = -1);// + int detPos = -1); // /** * (Advanced users) @@ -843,7 +852,8 @@ class multiSlsDetector : public virtual slsDetectorDefs { * adcphase for Gotthard, others for CTB & Moench) * @param value (clkdivider 0,1,2 for full, half and quarter speed). Other * values check manual - * @param mode 0 for shift, 1 for degrees. relevant only for speed type adcphase and dbit phase + * @param mode 0 for shift, 1 for degrees. relevant only for speed type + * adcphase and dbit phase * @param detPos -1 for all detectors in list or specific detector position * @returns value of speed set */ @@ -949,7 +959,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns value read from register */ - uint32_t readRegister(uint32_t addr, int detPos = -1);// + uint32_t readRegister(uint32_t addr, int detPos = -1); // /** * Set bit in a register. For Advanced users @@ -958,7 +968,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns value read from register */ - uint32_t setBit(uint32_t addr, int n, int detPos = -1);// + uint32_t setBit(uint32_t addr, int n, int detPos = -1); // /** * Clear bit in a register. For Advanced users @@ -967,7 +977,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns value read from register */ - uint32_t clearBit(uint32_t addr, int n, int detPos = -1);// + uint32_t clearBit(uint32_t addr, int n, int detPos = -1); // /** * Validates the format of the detector MAC address and sets it @@ -1380,7 +1390,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position */ void loadImageToDetector(imageType index, const std::string &fname, - int detPos = -1); + int detPos = -1); /** * Writes the counter memory block from the detector (Gotthard) @@ -1389,7 +1399,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position */ void writeCounterBlockFile(const std::string &fname, int startACQ = 0, - int detPos = -1); + int detPos = -1); /** * Resets counter in detector (Gotthard) @@ -1671,7 +1681,8 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param hostname name of pc to tftp from * @param detPos -1 for all detectors in list or specific detector position */ - void copyDetectorServer(const std::string &fname, const std::string &hostname, int detPos = -1); + void copyDetectorServer(const std::string &fname, + const std::string &hostname, int detPos = -1); /** * Reboot detector controller (Not Eiger) @@ -1687,7 +1698,8 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param fname programming file name * @param detPos -1 for all detectors in list or specific detector position */ - void update(const std::string &sname, const std::string &hostname, const std::string &fname, int detPos = -1); + void update(const std::string &sname, const std::string &hostname, + const std::string &fname, int detPos = -1); /** * Power on/off Chip (Jungfrau) @@ -1706,12 +1718,12 @@ class multiSlsDetector : public virtual slsDetectorDefs { int setAutoComparatorDisableMode(int ival = -1, int detPos = -1); /** - * Set Rate correction ( Eiger) - * @param t dead time in ns - if 0 disable correction, - * if >0 set dead time to t, if < 0 set deadtime to default dead time - * for current settings - * @param detPos -1 for all detectors in list or specific detector position - */ + * Set Rate correction ( Eiger) + * @param t dead time in ns - if 0 disable correction, + * if >0 set dead time to t, if < 0 set deadtime to default dead time + * for current settings + * @param detPos -1 for all detectors in list or specific detector position + */ void setRateCorrection(int64_t t = 0, int detPos = -1); /** @@ -1777,7 +1789,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns output file directory */ - std::string getFilePath(int detPos = -1);// + std::string getFilePath(int detPos = -1); // /** * Sets up the file directory @@ -1785,14 +1797,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param s file directory * @returns file dir */ - std::string setFilePath(const std::string &path, int detPos = -1);// + std::string setFilePath(const std::string &path, int detPos = -1); // /** * Returns file name prefix * @param detPos -1 for all detectors in list or specific detector position * @returns file name prefix */ - std::string getFileName(int detPos = -1);// + std::string getFileName(int detPos = -1); // /** * Sets up the file name prefix @@ -1800,7 +1812,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param s file name prefix * @returns file name prefix */ - std::string setFileName(const std::string &fname, int detPos = -1);// + std::string setFileName(const std::string &fname, int detPos = -1); // /** * Sets the max frames per file in receiver @@ -1861,57 +1873,51 @@ class multiSlsDetector : public virtual slsDetectorDefs { /** * Get File index - * @param detPos -1 for all detectors in list or specific detector position + * @param detPos -1 for all detectors in list or specific detector + * position * @returns file index */ int getFileIndex(int detPos = -1) const; - /** - * increments file index - * @param detPos -1 for all detectors in list or specific detector position - * @returns the file index - */ - int incrementFileIndex(int detPos = -1); - /** * Receiver starts listening to packets * @param detPos -1 for all detectors in list or specific detector position */ - void startReceiver(int detPos = -1);// + void startReceiver(int detPos = -1); // /** * Stops the listening mode of receiver * @param detPos -1 for all detectors in list or specific detector position */ - void stopReceiver(int detPos = -1);// + void stopReceiver(int detPos = -1); // /** * Gets the status of the listening mode of receiver * @param detPos -1 for all detectors in list or specific detector position * @returns status */ - runStatus getReceiverStatus(int detPos = -1);// + runStatus getReceiverStatus(int detPos = -1); // /** * Gets the number of frames caught by receiver * @param detPos -1 for all detectors in list or specific detector position * @returns number of frames caught by receiver */ - int getFramesCaughtByReceiver(int detPos = -1); + int getFramesCaughtByReceiver(int detPos = -1); // /** * Gets the current frame index of receiver * @param detPos -1 for all detectors in list or specific detector position * @returns average of all current frame index of receiver */ - uint64_t getReceiverCurrentFrameIndex(int detPos = -1); + uint64_t getReceiverCurrentFrameIndex(int detPos = -1); // /** * Resets framescaught in receiver * Use this when using startAcquisition instead of acquire * @param detPos -1 for all detectors in list or specific detector position */ - void resetFramesCaught(int detPos = -1); + void resetFramesCaught(int detPos = -1); // /** * Create Receiving Data Sockets @@ -1932,13 +1938,13 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns file write enable */ - int setFileWrite(bool value, int detPos = -1);// + int setFileWrite(bool value, int detPos = -1); // /** * Gets file write enable * @returns file write enable */ - int getFileWrite(int detPos = -1) const;// + int getFileWrite(int detPos = -1) const; // /** * Sets/Gets receiver master file write enable @@ -1946,14 +1952,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns master file write enable */ - int setMasterFileWrite(bool value, int detPos = -1); + int setMasterFileWrite(bool value, int detPos = -1); // /** * Gets master file write enable * @param detPos -1 for all detectors in list or specific detector position * @returns master file write enable */ - int getMasterFileWrite(int detPos = -1) const; + int getMasterFileWrite(int detPos = -1) const; // /** * Sets/Gets file overwrite enable @@ -1961,14 +1967,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns file overwrite enable */ - int setFileOverWrite(bool enable, int detPos = -1);// + int setFileOverWrite(bool enable, int detPos = -1); // /** * Gets file over write enable * @param detPos -1 for all detectors in list or specific detector position * @returns file over write enable */ - int getFileOverWrite(int detPos = -1) const;// + int getFileOverWrite(int detPos = -1) const; // /** * (previously setReadReceiverFrequency) @@ -1989,7 +1995,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns receiver streaming timer in ms */ - int setReceiverStreamingTimer(int time_in_ms = 500, int detPos = -1); + int setReceiverStreamingTimer(int time_in_ms = 500, int detPos = -1); // /** * Enable data streaming to client @@ -2012,7 +2018,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns if 10Gbe is enabled */ - int enableTenGigabitEthernet(int i = -1, int detPos = -1); + int enableTenGigabitEthernet(int i = -1, int detPos = -1); // /** * Set/get receiver fifo depth @@ -2020,7 +2026,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the receiver fifo depth */ - int setReceiverFifoDepth(int i = -1, int detPos = -1); + int setReceiverFifoDepth(int i = -1, int detPos = -1); // /** * Set/get receiver silent mode @@ -2044,7 +2050,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns actual value */ - uint64_t setPatternIOControl(uint64_t word = -1, int detPos = -1);// + uint64_t setPatternIOControl(uint64_t word = -1, int detPos = -1); // /** * Sets pattern clock control (CTB/ Moench) @@ -2121,7 +2127,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param mask mask to select bits * @param detPos -1 for all detectors in list or specific detector position */ - void setPatternBitMask(uint64_t mask, int detPos = -1);// + void setPatternBitMask(uint64_t mask, int detPos = -1); // /** * Gets the bits that the mask will be applied to for every pattern (CTB/ @@ -2129,7 +2135,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns mask of bits selected */ - uint64_t getPatternBitMask(int detPos = -1);// + uint64_t getPatternBitMask(int detPos = -1); // /** * Set LED Enable (Moench, CTB only) @@ -2191,8 +2197,8 @@ class multiSlsDetector : public virtual slsDetectorDefs { * s is for subframe number for eiger for 32 bit mode * @param pArg argument */ - void registerDataCallback(void (*userCallback)(detectorData *, uint64_t, uint32_t, - void *), + void registerDataCallback(void (*userCallback)(detectorData *, uint64_t, + uint32_t, void *), void *pArg); /** @@ -2202,16 +2208,21 @@ class multiSlsDetector : public virtual slsDetectorDefs { * index, loops for measurements, calls required call backs. * @returns OK or FAIL depending on if it already started */ - int acquire();// + int acquire(); // /** * Combines data from all readouts and gives it to the gui * or just gives progress of acquisition by polling receivers */ void processData(); - private: + /** + * increments file index + * @param detPos -1 for all detectors in list or specific detector position + * @returns the file index + */ + int incrementFileIndex(int detPos = -1); /** * Creates/open shared memory, initializes detector structure and members * Called by constructor/ set hostname / read config file @@ -2219,8 +2230,8 @@ class multiSlsDetector : public virtual slsDetectorDefs { * one * @param update true to update last user pid, date etc */ - void setupMultiDetector(bool verify = true, bool update = true); - + void setupMultiDetector(bool verify = true, bool update = true); + /** * Initialize (open/create) shared memory for the sharedMultiDetector * structure diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index b691bacdc..45638a960 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -171,7 +171,52 @@ Result Detector::getDetectorTypeAsString(Positions pos) const { // Erik -Result Detector::getReceiverSilentMode(Positions pos){ +Result Detector::getFramesCaughtByReceiver(Positions pos) const{ + return pimpl->Parallel(&slsDetector::getFramesCaughtByReceiver, pos); +} + +Result Detector::getReceiverCurrentFrameIndex(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverCurrentFrameIndex, pos); +} + +void Detector::resetFramesCaught(Positions pos) { + pimpl->Parallel(&slsDetector::resetFramesCaught, pos); +} + +void Detector::setMasterFileWrite(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setMasterFileWrite, pos, value); +} + +Result Detector::getMasterFileWrite(Positions pos) const { + return pimpl->Parallel(&slsDetector::getMasterFileWrite, pos); +} + +void Detector::setReceiverStreamingTimer(int time_in_ms, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverStreamingTimer, pos, time_in_ms); +} + +Result Detector::getReceiverStreamingTimer(Positions pos) const { + return pimpl->Parallel(&slsDetector::setReceiverStreamingTimer, pos, -1); +} + +void Detector::setTenGigaEnabled(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::enableTenGigabitEthernet, pos, + static_cast(value)); +} + +Result Detector::getTenGigaEnabled(Positions pos) const { + return pimpl->Parallel(&slsDetector::enableTenGigabitEthernet, pos, -1); +} + +Result Detector::getReceiverFifoDepth(Positions pos) const { + return pimpl->Parallel(&slsDetector::setReceiverFifoDepth, pos, -1); +} + +void Detector::setReceiverFifoDepth(int nframes, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverFifoDepth, pos, nframes); +} + +Result Detector::getReceiverSilentMode(Positions pos) const { return pimpl->Parallel(&slsDetector::setReceiverSilentMode, pos, -1); } From 8740e4f6833de54d874435b7cf3ef6de8b0afc72 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Thu, 8 Aug 2019 14:49:13 +0200 Subject: [PATCH 016/108] WIP --- slsDetectorSoftware/include/Detector.h | 47 ++++++++++++++----- .../include/multiSlsDetector.h | 38 +++++++++++++-- slsDetectorSoftware/include/slsDetector.h | 12 +++++ slsDetectorSoftware/src/Detector.cpp | 37 +++++++++++---- slsDetectorSoftware/src/multiSlsDetector.cpp | 26 ++++++++++ slsDetectorSoftware/src/slsDetector.cpp | 15 ++++++ slsSupportLib/include/sls_detector_defs.h | 6 +++ 7 files changed, 156 insertions(+), 25 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 33a43e90b..1a47dd611 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -167,7 +167,7 @@ class Detector { * Get Client Software version * @returns client software version */ - Result getClientSoftwareVersion() const; + int64_t getClientSoftwareVersion() const; /** * Get Receiver software version @@ -187,7 +187,7 @@ class Detector { * Also updates local detector cache * @param name hostnames for the positions given */ - void setHostname(const std::vector &name); + void setHostname(const std::vector &value); /** * Get Detector type as an enum @@ -209,25 +209,48 @@ class Detector { */ Result getDetectorTypeAsString(Positions pos = {}) const; + /** + * Returns the total number of detectors in the multidetector structure + * @returns total number of detectors in the multidetector structure + */ + int getTotalNumberOfDetectors() const; + /** * Returns the number of detectors in the multidetector structure - * @returns number of detectors + * @returns number of detectors in the multidetector structure */ - int getNumberOfDetectors() const; + defs::coordinates getNumberOfDetectors() const; /** - * Returns number of detectors in dimension d - * @param d dimension d - * @returns number of detectors in dimension d + * Returns the number of channels + * @param pos detector position + * @returns the number of channels */ - int getNumberOfDetectors(defs::dimension d) const; + Result getNumberOfChannels(Positions pos = {}) const; /** - * Returns the number of detectors in each direction - @param nx number of detectors in x direction - @param ny number of detectors in y direction + * Returns the number of channels including gap pixels + * @param pos detector position + * @returns the number of channels including gap pixels */ - void getNumberOfDetectors(int &nx, int &ny) const; + Result + getNumberOfChannelsInclGapPixels(Positions pos = {}) const; + + /** + * Returns the maximum number of channels of complete detector in both + * dimensions. -1 means no limit in this dimension. This value is used to + * calculate row and column offsets for each module. + * @returns the maximum number of channels of complete detector + */ + defs::coordinates getMaxNumberOfChannels() const; + + /** + * Sets the maximum number of channels of complete detector in both + * dimensions. -1 means no limit in this dimension. This value is used to + * calculate row and column offsets for each module. + * @param value the maximum number of channels of complete detector + */ + void setMaxNumberOfChannels(const defs::coordinates value); // Erik diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 6b8198404..7c1d065aa 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -396,7 +396,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the total number of channels of all sls detectors */ - int getTotalNumberOfChannels(int detPos = -1); + int getTotalNumberOfChannels(int detPos = -1);// /** * Returns the total number of channels of all sls detectors in dimension d @@ -405,7 +405,13 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the total number of channels of all sls detectors in dimension d */ - int getTotalNumberOfChannels(dimension d, int detPos = -1); + int getTotalNumberOfChannels(dimension d, int detPos = -1);// + + /** + * Returns the total number of channels from shared memory in each dimension + * @returns the total number of channels in each dimension + */ + slsDetectorDefs::coordinates getNumberOfChannels() const; // /** * Returns the total number of channels of all sls detectors in dimension d @@ -415,7 +421,13 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns the total number of channels of all sls detectors in dimension d * including gap pixels */ - int getTotalNumberOfChannelsInclGapPixels(dimension d, int detPos = -1); + int getTotalNumberOfChannelsInclGapPixels(dimension d, int detPos = -1);// + + /** + * Returns the total number of channels including gap pixels + * @returns the total number of channels including gap pixels + */ + slsDetectorDefs::coordinates getTotalNumberOfChannelsInclGapPixels() const; // /** * Returns the maximum number of channels of all sls detectors in each @@ -425,7 +437,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns the maximum number of channels of all sls detectors in dimension * d */ - int getMaxNumberOfChannelsPerDetector(dimension d); + int getMaxNumberOfChannelsPerDetector(dimension d);// /** * Sets the maximum number of channels of all sls detectors in each @@ -436,7 +448,23 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns the maximum number of channels of all sls detectors in dimension * d */ - int setMaxNumberOfChannelsPerDetector(dimension d, int i); + int setMaxNumberOfChannelsPerDetector(dimension d, int i);// + + /** + * Returns maximum number of channels of all sls detectors in each + * dimension d from shared memory, multi detector shared memory variable to + * calculate offsets for each sls detector + * @returns maximum number of channels of all sls detectors + */ + slsDetectorDefs::coordinates getMaxNumberOfChannels() const; // + + /** + * Sets maximum number of channels of all sls detectors in each + * dimension d from shared memory, multi detector shared memory variable to + * calculate offsets for each sls detector + * @param c maximum number of channels of all sls detectors + */ + void setMaxNumberOfChannels(const slsDetectorDefs::coordinates c); // /** * Get Quad Type (Only for Eiger Quad detector hardware) diff --git a/slsDetectorSoftware/include/slsDetector.h b/slsDetectorSoftware/include/slsDetector.h index 582b3283f..3150d1aed 100755 --- a/slsDetectorSoftware/include/slsDetector.h +++ b/slsDetectorSoftware/include/slsDetector.h @@ -350,6 +350,12 @@ class slsDetector : public virtual slsDetectorDefs { */ int getTotalNumberOfChannels(dimension d) const; + /** + * Returns the total number of channels from shared memory in each dimension + * @returns the total number of channels in each dimension + */ + slsDetectorDefs::coordinates getNumberOfChannels() const; + /** * Returns the total number of channels of in dimension d including gap * pixels from shared memory @@ -359,6 +365,12 @@ class slsDetector : public virtual slsDetectorDefs { */ int getTotalNumberOfChannelsInclGapPixels(dimension d) const; + /** + * Returns the total number of channels including gap pixels + * @returns the total number of channels including gap pixels + */ + slsDetectorDefs::coordinates getNumberOfChannelsInclGapPixels() const; + /** * returns the number of channels per chip from shared memory (Mythen) * @returns number of channels per chip diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 9d38a5fb1..8cba007d9 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -142,7 +142,7 @@ Result Detector::getDetectorSerialNumber(Positions pos) const { defs::DETECTOR_SERIAL_NUMBER); } -Result Detector::getClientSoftwareVersion() const { +int64_t Detector::getClientSoftwareVersion() const { return pimpl->getClientSoftwareVersion(); } @@ -152,8 +152,8 @@ Result Detector::getReceiverSoftwareVersion(Positions pos) const { std::string Detector::getUserDetails() const { return pimpl->getUserDetails(); } -void Detector::setHostname(const std::vector &name) { - pimpl->setHostname(name); +void Detector::setHostname(const std::vector &value) { + pimpl->setHostname(value); } defs::detectorType Detector::getDetectorTypeAsEnum() const { @@ -169,18 +169,39 @@ Result Detector::getDetectorTypeAsString(Positions pos) const { return pimpl->Parallel(&slsDetector::getDetectorTypeAsString, pos); } -int Detector::getNumberOfDetectors() const { +int Detector::getTotalNumberOfDetectors() const { return pimpl->getNumberOfDetectors(); } -int Detector::getNumberOfDetectors(defs::dimension d) const { - return pimpl->getNumberOfDetectors(d); +defs::coordinates Detector::getNumberOfDetectors() const { + defs::coordinates coord; + coord.x = pimpl->getNumberOfDetectors(defs::X); + coord.y = pimpl->getNumberOfDetectors(defs::Y); + return coord; } -void Detector::getNumberOfDetectors(int &nx, int &ny) const { - pimpl->getNumberOfDetectors(nx, ny); +Result Detector::getNumberOfChannels(Positions pos) const { + if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) { + return {pimpl->getNumberOfChannels()}; + } + return pimpl->Parallel(&slsDetector::getNumberOfChannels, pos); } +Result +Detector::getNumberOfChannelsInclGapPixels(Positions pos) const { + if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) { + return {pimpl->getTotalNumberOfChannelsInclGapPixels()}; + } + return pimpl->Parallel(&slsDetector::getNumberOfChannelsInclGapPixels, pos); +} + +defs::coordinates Detector::getMaxNumberOfChannels() const { + return pimpl->getMaxNumberOfChannels(); +} + +void Detector::setMaxNumberOfChannels(const defs::coordinates value) { + pimpl->setMaxNumberOfChannels(value); +} // Erik Result Detector::getPatternMask(Positions pos) { diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index 7a175406e..b00cccd72 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -534,6 +534,13 @@ int multiSlsDetector::getTotalNumberOfChannels(dimension d, int detPos) { return multi_shm()->numberOfChannel[d]; } +slsDetectorDefs::coordinates multiSlsDetector::getNumberOfChannels() const { + slsDetectorDefs::coordinates coord; + coord.x = multi_shm()->numberOfChannel[X]; + coord.y = multi_shm()->numberOfChannel[Y]; + return coord; +} + int multiSlsDetector::getTotalNumberOfChannelsInclGapPixels(dimension d, int detPos) { // single @@ -545,6 +552,13 @@ int multiSlsDetector::getTotalNumberOfChannelsInclGapPixels(dimension d, return multi_shm()->numberOfChannelInclGapPixels[d]; } +slsDetectorDefs::coordinates multiSlsDetector::getTotalNumberOfChannelsInclGapPixels() const { + slsDetectorDefs::coordinates coord; + coord.x = multi_shm()->numberOfChannelInclGapPixels[X]; + coord.y = multi_shm()->numberOfChannelInclGapPixels[Y]; + return coord; +} + int multiSlsDetector::getMaxNumberOfChannelsPerDetector(dimension d) { return multi_shm()->maxNumberOfChannelsPerDetector[d]; } @@ -554,6 +568,18 @@ int multiSlsDetector::setMaxNumberOfChannelsPerDetector(dimension d, int i) { return multi_shm()->maxNumberOfChannelsPerDetector[d]; } +slsDetectorDefs::coordinates multiSlsDetector::getMaxNumberOfChannels() const { + slsDetectorDefs::coordinates coord; + coord.x = multi_shm()->maxNumberOfChannelsPerDetector[X]; + coord.y = multi_shm()->maxNumberOfChannelsPerDetector[Y]; + return coord; +} + +void multiSlsDetector::setMaxNumberOfChannels(const slsDetectorDefs::coordinates c) { + multi_shm()->maxNumberOfChannelsPerDetector[X] = c.x; + multi_shm()->maxNumberOfChannelsPerDetector[Y] = c.y; +} + int multiSlsDetector::getQuad(int detPos) { int retval = detectors[0]->getQuad(); if (retval && getNumberOfDetectors() > 1) { diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index 6a6386a6e..0a8e38a62 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -626,11 +626,26 @@ int slsDetector::getTotalNumberOfChannels(dimension d) const { return shm()->nChan[d] * shm()->nChip[d]; } +slsDetectorDefs::coordinates slsDetector::getNumberOfChannels() const { + slsDetectorDefs::coordinates coord; + coord.x = shm()->nChan[X] * shm()->nChip[X]; + coord.y = shm()->nChan[Y] * shm()->nChip[Y]; + return coord; +} + int slsDetector::getTotalNumberOfChannelsInclGapPixels(dimension d) const { return (shm()->nChan[d] * shm()->nChip[d] + shm()->gappixels * shm()->nGappixels[d]); } +slsDetectorDefs::coordinates slsDetector::getNumberOfChannelsInclGapPixels() const { + slsDetectorDefs::coordinates coord; + coord.x = (shm()->nChan[X] * shm()->nChip[X] + shm()->gappixels * shm()->nGappixels[X]); + coord.y = (shm()->nChan[Y] * shm()->nChip[Y] + shm()->gappixels * shm()->nGappixels[Y]); + return coord; +} + + int slsDetector::getNChans() const { return shm()->nChans; } int slsDetector::getNChans(dimension d) const { return shm()->nChan[d]; } diff --git a/slsSupportLib/include/sls_detector_defs.h b/slsSupportLib/include/sls_detector_defs.h index 63f474901..ec3d5022f 100755 --- a/slsSupportLib/include/sls_detector_defs.h +++ b/slsSupportLib/include/sls_detector_defs.h @@ -284,6 +284,12 @@ format Y = 1 /**< Y dimension */ }; +#ifdef __cplusplus + struct coordinates { + int x{0}; + int y{0}; + }; +#endif /** enable/disable flags */ From 6a780de22f4571a602e20b10900b6ebd6fe48572 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Thu, 8 Aug 2019 15:06:08 +0200 Subject: [PATCH 017/108] WIP --- .../include/multiSlsDetector.h | 8 ------- slsDetectorSoftware/src/Detector.cpp | 4 ++++ .../src/slsDetectorCommand.cpp | 22 +------------------ 3 files changed, 5 insertions(+), 29 deletions(-) diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index f35a258b2..bc47db92b 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -356,14 +356,6 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ std::string getHostname(int detPos = -1) const; // - /** - * Appends detectors to the end of the list in shared memory - * Connects to them - * @param name concatenated hostname of the sls detectors to be appended to - * the list - */ - void addMultipleDetectors(const char *name); // ???? - /** * Get Detector type as an enum * @returns detector type diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 4a0b30428..f4bf604ad 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -202,6 +202,10 @@ defs::coordinates Detector::getMaxNumberOfChannels() const { void Detector::setMaxNumberOfChannels(const defs::coordinates value) { pimpl->setMaxNumberOfChannels(value); } + +// +// +// // Erik Result Detector::getFramesCaughtByReceiver(Positions pos) const{ return pimpl->Parallel(&slsDetector::getFramesCaughtByReceiver, pos); diff --git a/slsDetectorSoftware/src/slsDetectorCommand.cpp b/slsDetectorSoftware/src/slsDetectorCommand.cpp index af2d12e85..7ac82ced0 100755 --- a/slsDetectorSoftware/src/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp @@ -275,13 +275,6 @@ slsDetectorCommand::slsDetectorCommand(multiSlsDetector *det) { descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdHostname; ++i; - /*! \page config - - replace \c Sets the hostname (or IP adress) for a single detector. Only allowed at single detector level. Cannot get. \c Returns the hostnames for that detector \c (string) - */ - descrToFuncMap[i].m_pFuncName = "replace"; - descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdHostname; - ++i; - /*! \page config - user \c Returns user details from shared memory. Only allowed at multi detector level. Cannot put. \c (string) */ @@ -2371,21 +2364,12 @@ std::string slsDetectorCommand::cmdHostname(int narg, const char * const args[], if (action == HELP_ACTION) { return helpHostname(HELP_ACTION); } - if (action == GET_ACTION) { - if (cmd == "replace") - return std::string("cannot get"); - } if (action == PUT_ACTION) { - if ((cmd == "hostname") && - (detPos >= 0)) { + if (detPos >= 0) { return std::string("Wrong usage - setting hostname/add only from " "multiDetector level"); } - if ((cmd == "replace") && (detPos < 0)) { - return std::string("Wrong usage - replace only from " - "single detector level"); - } char hostname[1000]; strcpy(hostname, ""); @@ -2406,14 +2390,10 @@ std::string slsDetectorCommand::helpHostname(int action) { std::ostringstream os; if (action == GET_ACTION || action == HELP_ACTION) { os << std::string("hostname \t returns the hostname(s) of the multi detector structure.\n"); - os << std::string("replace \t cannot get\n"); } if (action == PUT_ACTION || action == HELP_ACTION) { os << std::string("hostname name [name name]\t frees shared memory and " "sets the hostname (or IP adress). Only allowed at multi detector level.\n"); - os << std::string("replace det \t Sets the hostname (or IP adress) for a " - "single detector. Only allowed at single detector level. " - "Returns the hostnames for that detector\n"); } return os.str(); } From 0b006b5080ff3129a487ba5eeb846e27bb92efa0 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Thu, 8 Aug 2019 15:36:03 +0200 Subject: [PATCH 018/108] WIP --- slsDetectorSoftware/include/Detector.h | 30 +++++++++++- .../include/multiSlsDetector.h | 20 ++++---- slsDetectorSoftware/src/Detector.cpp | 49 ++++++++++++++++++- 3 files changed, 86 insertions(+), 13 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 66ef0564f..306c7de47 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -254,14 +254,13 @@ class Detector { // Erik - Result getFramesCaughtByReceiver(Positions pos = {}) const; Result getReceiverCurrentFrameIndex(Positions pos = {}) const; void resetFramesCaught(Positions pos = {}); - //TODO! + // TODO! // int createReceivingDataSockets(const bool destroy = false); // void readFrameFromReceiver(); @@ -403,6 +402,33 @@ class Detector { * @param delay delay in ps(1 bit=25ps, max of 775 ps) */ void setDigitalIODelay(uint64_t pinMask, int delay, Positions pos = {}); + + Result getFileIndex(Positions pos = {}) const; + + void setFileIndex(int i, Positions pos = {}); + + Result getFileFormat(Positions pos = {}) const; + + void setFileFormat(defs::fileFormat f, Positions pos = {}); + + Result getPartialFramesPadding(Positions pos = {}) const; + + void setPartialFramesPadding(bool value, Positions pos = {}); + + void setReceiverFrameDiscardPolicy(defs::frameDiscardPolicy f, + Positions pos = {}); + + Result + getReceiverFrameDiscardPolicy(Positions pos = {}) const; + + void setFramesPerFile(int n, Positions pos = {}); + + Result getFramesPerFile(Positions pos = {}) const; + + // void execReceiverCommand(const std::string &cmd, int detPos = -1); + // void exitReceiver(int detPos = -1); + + Result getReceiverLastClientIP(Positions pos = {}) const; }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index bc47db92b..c6376bffb 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -1788,7 +1788,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns IP of last client connecting to receiver */ - std::string getReceiverLastClientIP(int detPos = -1); + std::string getReceiverLastClientIP(int detPos = -1); // /** * Turns off the receiver server! @@ -1840,14 +1840,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns max frames per file in receiver */ - int setFramesPerFile(int f = -1, int detPos = -1); + int setFramesPerFile(int f = -1, int detPos = -1); // /** * Gets the max frames per file in receiver * @param detPos -1 for all detectors in list or specific detector position * @returns max frames per file in receiver */ - int getFramesPerFile(int detPos = -1) const; + int getFramesPerFile(int detPos = -1) const; // /** * Sets the frames discard policy in receiver @@ -1856,7 +1856,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns frames discard policy set in receiver */ frameDiscardPolicy setReceiverFramesDiscardPolicy( - frameDiscardPolicy f = GET_FRAME_DISCARD_POLICY, int detPos = -1); + frameDiscardPolicy f = GET_FRAME_DISCARD_POLICY, int detPos = -1); // /** * Sets the partial frames padding enable in receiver @@ -1864,16 +1864,16 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns partial frames padding enable in receiver */ - int setPartialFramesPadding(bool padding, int detPos = -1); + int setPartialFramesPadding(bool padding, int detPos = -1); // - int getPartialFramesPadding(int detPos = -1) const; + int getPartialFramesPadding(int detPos = -1) const; // /** * Returns file format * @param detPos -1 for all detectors in list or specific detector position * @returns file name */ - fileFormat getFileFormat(int detPos = -1); + fileFormat getFileFormat(int detPos = -1); // /** * Sets up the file format @@ -1881,7 +1881,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns file format */ - fileFormat setFileFormat(fileFormat f, int detPos = -1); + fileFormat setFileFormat(fileFormat f, int detPos = -1); // /** * Sets up the file index @@ -1889,7 +1889,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns file index */ - int setFileIndex(int i, int detPos = -1); + int setFileIndex(int i, int detPos = -1); // /** * Get File index @@ -1897,7 +1897,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * position * @returns file index */ - int getFileIndex(int detPos = -1) const; + int getFileIndex(int detPos = -1) const; // /** * Receiver starts listening to packets diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index f4bf604ad..3904eccaf 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -207,7 +207,7 @@ void Detector::setMaxNumberOfChannels(const defs::coordinates value) { // // // Erik -Result Detector::getFramesCaughtByReceiver(Positions pos) const{ +Result Detector::getFramesCaughtByReceiver(Positions pos) const { return pimpl->Parallel(&slsDetector::getFramesCaughtByReceiver, pos); } @@ -336,4 +336,51 @@ void Detector::setDigitalIODelay(uint64_t pinMask, int delay, Positions pos) { pimpl->Parallel(&slsDetector::setDigitalIODelay, pos, pinMask, delay); } +Result Detector::getFileIndex(Positions pos) const { + return pimpl->Parallel(&slsDetector::getFileIndex, pos); +} + +void Detector::setFileIndex(int i, Positions pos) { + pimpl->Parallel(&slsDetector::setFileIndex, pos, i); +} + +Result Detector::getFileFormat(Positions pos) const { + return pimpl->Parallel(&slsDetector::getFileFormat, pos); +} + +void Detector::setFileFormat(defs::fileFormat f, Positions pos) { + pimpl->Parallel(&slsDetector::setFileFormat, pos, f); +} + +Result Detector::getPartialFramesPadding(Positions pos) const { + return pimpl->Parallel(&slsDetector::getPartialFramesPadding, pos); +} + +void Detector::setPartialFramesPadding(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setPartialFramesPadding, pos, value); +} + +void Detector::setReceiverFrameDiscardPolicy(defs::frameDiscardPolicy f, + Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverFramesDiscardPolicy, pos, f); +} + +Result +Detector::getReceiverFrameDiscardPolicy(Positions pos) const { + return pimpl->Parallel(&slsDetector::setReceiverFramesDiscardPolicy, pos, + defs::GET_FRAME_DISCARD_POLICY); +} + +void Detector::setFramesPerFile(int n, Positions pos) { + pimpl->Parallel(&slsDetector::setFramesPerFile, pos, n); +} + +Result Detector::getFramesPerFile(Positions pos) const { + return pimpl->Parallel(&slsDetector::getFramesPerFile, pos); +} + +Result Detector::getReceiverLastClientIP(Positions pos) const{ + return pimpl->Parallel(&slsDetector::getReceiverLastClientIP, pos); +} + } // namespace sls \ No newline at end of file From d79447ed3acf419bd0854c9607546b0ea668cd99 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Thu, 8 Aug 2019 15:50:56 +0200 Subject: [PATCH 019/108] WIP --- slsDetectorSoftware/include/Detector.h | 47 ++- .../include/multiSlsDetector.h | 66 ++-- slsDetectorSoftware/include/slsDetector.h | 14 +- slsDetectorSoftware/src/Detector.cpp | 29 +- slsDetectorSoftware/src/multiSlsDetector.cpp | 338 +++++++++--------- slsDetectorSoftware/src/slsDetector.cpp | 16 +- 6 files changed, 301 insertions(+), 209 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 66ef0564f..4eab2c339 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -252,6 +252,51 @@ class Detector { */ void setMaxNumberOfChannels(const defs::coordinates value); + /** + * Get Detector offset from shared memory (Gotthard only) + * @param pos detector position + * @returns offset in both dimensions + */ + Result getDetectorOffsets(Positions pos = {}) const; + + /** + * Set Detector offset in shared memory for each module + * @param value offset for detector in both dimensions + * @param pos detector position + */ + void setDetectorOffsets(defs::coordinates value, Positions pos = {}); + + /** + * Get Quad Type (Only for Eiger Quad detector hardware) + * @param pos detector position + * @returns quad type + */ + Result getQuad(Positions pos = {}) const; + + /** + * Set Quad Type (Only for Eiger Quad detector hardware) + * @param enable true if quad type set, else false + * @param pos detector position + */ + void setQuad(const bool enable, Positions pos = {}); + + /** + * Get number of rows to read out (Only for Eiger) + * @param pos detector position + * @returns number of lines + */ + Result getReadNLines(Positions pos = {}) const; + + /** + * Set number of rows to read out (Only for Eiger) + * @param value number of lines + * @param pos detector position + */ + void setReadNLines(const int value, Positions pos = {}); + + + + // Erik @@ -335,7 +380,7 @@ class Detector { * @param start start address for level 0-2 * @param stop stop address for level 0-2 * @param n number of loops for level 0-2 - * @param detPos -1 for all detectors in list or specific detector position + * @param pos detector position */ void setPatternLoops(int level, int start, int stop, int n, Positions pos = {}); diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index bc47db92b..5ee7c340e 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -475,34 +475,6 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ void setMaxNumberOfChannels(const slsDetectorDefs::coordinates c); // - /** - * Get Quad Type (Only for Eiger Quad detector hardware) - * @param detPos -1 for all detectors in list or specific detector position - * @returns quad type - */ - int getQuad(int detPos = -1); - - /** - * Set Quad Type (Only for Eiger Quad detector hardware) - * @param enable true if quad type set, else false - * @param detPos -1 for all detectors in list or specific detector position - */ - void setQuad(const bool enable, int detPos = -1); - - /** - * Set number of rows to read out (Only for Eiger) - * @param value number of lines - * @param detPos -1 for all detectors in list or specific detector position - */ - void setReadNLines(const int value, int detPos = -1); - - /** - * Get number of rows to read out (Only for Eiger) - * @param detPos -1 for all detectors in list or specific detector position - * @returns number of lines - */ - int getReadNLines(int detPos = -1); - /** * Get Detector offset from shared memory in dimension d * @param d dimension d @@ -510,7 +482,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns offset in dimension d, -1 if pos is not an actual position in * list */ - int getDetectorOffset(dimension d, int detPos = -1); + int getDetectorOffset(dimension d, int detPos = -1); // /** * Set Detector offset in shared memory in dimension d @@ -518,13 +490,35 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param off offset for detector * @param detPos -1 for all detectors in list or specific detector position */ - void setDetectorOffset(dimension d, int off, int detPos = -1); + void setDetectorOffset(dimension d, int off, int detPos = -1);// /** - * Updates the channel offsets in X and Y dimension for all the sls - * detectors It is required for decodeNMod and setting ROI + * Get Quad Type (Only for Eiger Quad detector hardware) + * @param detPos -1 for all detectors in list or specific detector position + * @returns quad type */ - void updateOffsets(); + int getQuad(int detPos = -1);// + + /** + * Set Quad Type (Only for Eiger Quad detector hardware) + * @param enable true if quad type set, else false + * @param detPos -1 for all detectors in list or specific detector position + */ + void setQuad(const bool enable, int detPos = -1);// + + /** + * Set number of rows to read out (Only for Eiger) + * @param value number of lines + * @param detPos -1 for all detectors in list or specific detector position + */ + void setReadNLines(const int value, int detPos = -1);// + + /** + * Get number of rows to read out (Only for Eiger) + * @param detPos -1 for all detectors in list or specific detector position + * @returns number of lines + */ + int getReadNLines(int detPos = -1);// /** * Checks if each of the detectors are online/offline @@ -2302,6 +2296,12 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ int decodeNChannel(int offsetX, int offsetY, int &channelX, int &channelY); + /** + * Updates the channel offsets in X and Y dimension for all the sls + * detectors It is required for decodeNMod and setting ROI + */ + void updateOffsets(); + /** * Execute in command line and return result * @param cmd command diff --git a/slsDetectorSoftware/include/slsDetector.h b/slsDetectorSoftware/include/slsDetector.h index 3150d1aed..91c8cf684 100755 --- a/slsDetectorSoftware/include/slsDetector.h +++ b/slsDetectorSoftware/include/slsDetector.h @@ -403,7 +403,7 @@ class slsDetector : public virtual slsDetectorDefs { * Get Quad Type (Only for Eiger Quad detector hardware) * @returns quad type */ - int getQuad(); + bool getQuad(); /** * Set Quad Type (Only for Eiger Quad detector hardware) @@ -430,12 +430,24 @@ class slsDetector : public virtual slsDetectorDefs { */ int getDetectorOffset(dimension d) const; + /** + * Get Detector offset from shared memory in dimension d + * @returns offset + */ + slsDetectorDefs::coordinates getDetectorOffsets() const; + /** * Set Detector offset in shared memory in dimension d * @param d dimension d * @param off offset for detector */ void setDetectorOffset(dimension d, int off); + + /** + * Set Detector offset in shared memory + * @param value offset for detector + */ + void setDetectorOffsets(slsDetectorDefs::coordinates value); /** * Set Detector offset in shared memory in dimension d diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index f4bf604ad..88fe7634d 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -203,9 +203,32 @@ void Detector::setMaxNumberOfChannels(const defs::coordinates value) { pimpl->setMaxNumberOfChannels(value); } -// -// -// +Result Detector::getDetectorOffsets(Positions pos) const { + return pimpl->Parallel(&slsDetector::getDetectorOffsets, pos); +} + +void Detector::setDetectorOffsets(defs::coordinates value, Positions pos) { + return pimpl->Parallel(&slsDetector::setDetectorOffsets, pos, value); +} + +Result Detector::getQuad(Positions pos) const { + return pimpl->Parallel(&slsDetector::getQuad, pos); +} + +void Detector::setQuad(const bool value, Positions pos) { + pimpl->setQuad(value, 0); +} + +Result Detector::getReadNLines(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReadNLines, pos); +} + +void Detector::setReadNLines(const int value, Positions pos) { + pimpl->Parallel(&slsDetector::setReadNLines, pos, value); +} + + + // Erik Result Detector::getFramesCaughtByReceiver(Positions pos) const{ return pimpl->Parallel(&slsDetector::getFramesCaughtByReceiver, pos); diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index b00cccd72..a13c79a6c 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -370,6 +370,167 @@ int multiSlsDetector::decodeNChannel(int offsetX, int offsetY, int &channelX, return -1; } +void multiSlsDetector::updateOffsets() { + FILE_LOG(logDEBUG1) << "Updating Multi-Detector Offsets"; + + int offsetX = 0, offsetY = 0, numX = 0, numY = 0; + int maxChanX = multi_shm()->maxNumberOfChannelsPerDetector[X]; + int maxChanY = multi_shm()->maxNumberOfChannelsPerDetector[Y]; + int prevChanX = 0; + int prevChanY = 0; + bool firstTime = true; + + multi_shm()->numberOfChannel[X] = 0; + multi_shm()->numberOfChannel[Y] = 0; + multi_shm()->numberOfDetector[X] = 0; + multi_shm()->numberOfDetector[Y] = 0; + + // gap pixels + int offsetX_gp = 0, offsetY_gp = 0, numX_gp = 0, numY_gp = 0; + int prevChanX_gp = 0, prevChanY_gp = 0; + multi_shm()->numberOfChannelInclGapPixels[X] = 0; + multi_shm()->numberOfChannelInclGapPixels[Y] = 0; + + for (size_t idet = 0; idet < detectors.size(); ++idet) { + FILE_LOG(logDEBUG1) + << "offsetX:" << offsetX << " prevChanX:" << prevChanX + << " offsetY:" << offsetY << " prevChanY:" << prevChanY + << " offsetX_gp:" << offsetX_gp << " prevChanX_gp:" << prevChanX_gp + << " offsetY_gp:" << offsetY_gp << " prevChanY_gp:" << prevChanY_gp; + + // incrementing in both direction + if (firstTime) { + // incrementing in both directions + firstTime = false; + if ((maxChanX > 0) && + ((offsetX + detectors[idet]->getTotalNumberOfChannels(X)) > + maxChanX)) { + FILE_LOG(logWARNING) + << "\nDetector[" << idet + << "] exceeds maximum channels " + "allowed for complete detector set in X dimension!"; + } + if ((maxChanY > 0) && + ((offsetY + detectors[idet]->getTotalNumberOfChannels(Y)) > + maxChanY)) { + FILE_LOG(logERROR) + << "\nDetector[" << idet + << "] exceeds maximum channels " + "allowed for complete detector set in Y dimension!"; + } + prevChanX = detectors[idet]->getTotalNumberOfChannels(X); + prevChanY = detectors[idet]->getTotalNumberOfChannels(Y); + prevChanX_gp = + detectors[idet]->getTotalNumberOfChannelsInclGapPixels(X); + prevChanY_gp = + detectors[idet]->getTotalNumberOfChannelsInclGapPixels(Y); + numX += detectors[idet]->getTotalNumberOfChannels(X); + numY += detectors[idet]->getTotalNumberOfChannels(Y); + numX_gp += + detectors[idet]->getTotalNumberOfChannelsInclGapPixels(X); + numY_gp += + detectors[idet]->getTotalNumberOfChannelsInclGapPixels(Y); + ++multi_shm()->numberOfDetector[X]; + ++multi_shm()->numberOfDetector[Y]; + FILE_LOG(logDEBUG1) << "incrementing in both direction"; + } + + // incrementing in y direction + else if ((maxChanY == -1) || + ((maxChanY > 0) && ((offsetY + prevChanY + + detectors[idet]->getTotalNumberOfChannels( + Y)) <= maxChanY))) { + offsetY += prevChanY; + offsetY_gp += prevChanY_gp; + prevChanY = detectors[idet]->getTotalNumberOfChannels(Y); + prevChanY_gp = + detectors[idet]->getTotalNumberOfChannelsInclGapPixels(Y); + numY += detectors[idet]->getTotalNumberOfChannels(Y); + numY_gp += + detectors[idet]->getTotalNumberOfChannelsInclGapPixels(Y); + // increment in y again only in the first column (else you double + // increment) + if (multi_shm()->numberOfDetector[X] == 1) + ++multi_shm()->numberOfDetector[Y]; + FILE_LOG(logDEBUG1) << "incrementing in y direction"; + } + + // incrementing in x direction + else { + if ((maxChanX > 0) && + ((offsetX + prevChanX + + detectors[idet]->getTotalNumberOfChannels(X)) > maxChanX)) { + FILE_LOG(logDEBUG1) + << "\nDetector[" << idet + << "] exceeds maximum channels " + "allowed for complete detector set in X dimension!"; + } + offsetY = 0; + offsetY_gp = 0; + prevChanY = detectors[idet]->getTotalNumberOfChannels(Y); + prevChanY_gp = + detectors[idet]->getTotalNumberOfChannelsInclGapPixels(Y); + numY = 0; // assuming symmetry with this statement. + // whats on 1st column should be on 2nd column + numY_gp = 0; + offsetX += prevChanX; + offsetX_gp += prevChanX_gp; + prevChanX = detectors[idet]->getTotalNumberOfChannels(X); + prevChanX_gp = + detectors[idet]->getTotalNumberOfChannelsInclGapPixels(X); + numX += detectors[idet]->getTotalNumberOfChannels(X); + numX_gp += + detectors[idet]->getTotalNumberOfChannelsInclGapPixels(X); + ++multi_shm()->numberOfDetector[X]; + FILE_LOG(logDEBUG1) << "incrementing in x direction"; + } + + double bytesperchannel = + (double)detectors[idet]->getDataBytes() / + (double)(detectors[idet]->getTotalNumberOfChannels(X) * + detectors[idet]->getTotalNumberOfChannels(Y)); + detectors[idet]->setDetectorOffset( + X, (bytesperchannel >= 1.0) ? offsetX_gp : offsetX); + detectors[idet]->setDetectorOffset( + Y, (bytesperchannel >= 1.0) ? offsetY_gp : offsetY); + + FILE_LOG(logDEBUG1) << "Detector[" << idet << "] has offsets (" + << detectors[idet]->getDetectorOffset(X) << ", " + << detectors[idet]->getDetectorOffset(Y) << ")"; + // offsetY has been reset sometimes and offsetX the first time, + // but remember the highest values + if (numX > multi_shm()->numberOfChannel[X]) { + multi_shm()->numberOfChannel[X] = numX; + } + if (numY > multi_shm()->numberOfChannel[Y]) { + multi_shm()->numberOfChannel[Y] = numY; + } + if (numX_gp > multi_shm()->numberOfChannelInclGapPixels[X]) { + multi_shm()->numberOfChannelInclGapPixels[X] = numX_gp; + } + if (numY_gp > multi_shm()->numberOfChannelInclGapPixels[Y]) { + multi_shm()->numberOfChannelInclGapPixels[Y] = numY_gp; + } + } + FILE_LOG(logDEBUG1) + << "\n\tNumber of Channels in X direction:" + << multi_shm()->numberOfChannel[X] + << "\n\tNumber of Channels in Y direction:" + << multi_shm()->numberOfChannel[Y] + << "\n\tNumber of Channels in X direction with Gap Pixels:" + << multi_shm()->numberOfChannelInclGapPixels[X] + << "\n\tNumber of Channels in Y direction with Gap Pixels:" + << multi_shm()->numberOfChannelInclGapPixels[Y]; + + multi_shm()->numberOfChannels = + multi_shm()->numberOfChannel[0] * multi_shm()->numberOfChannel[1]; + + for (auto &d : detectors) { + d->updateMultiSize(multi_shm()->numberOfDetector[0], + multi_shm()->numberOfDetector[1]); + } +} + std::string multiSlsDetector::exec(const char *cmd) { int bufsize = 128; char buffer[bufsize]; @@ -580,6 +741,14 @@ void multiSlsDetector::setMaxNumberOfChannels(const slsDetectorDefs::coordinates multi_shm()->maxNumberOfChannelsPerDetector[Y] = c.y; } +int multiSlsDetector::getDetectorOffset(dimension d, int detPos) { + return detectors[detPos]->getDetectorOffset(d); +} + +void multiSlsDetector::setDetectorOffset(dimension d, int off, int detPos) { + detectors[detPos]->setDetectorOffset(d, off); +} + int multiSlsDetector::getQuad(int detPos) { int retval = detectors[0]->getQuad(); if (retval && getNumberOfDetectors() > 1) { @@ -619,175 +788,6 @@ int multiSlsDetector::getReadNLines(int detPos) { return sls::minusOneIfDifferent(r); } -int multiSlsDetector::getDetectorOffset(dimension d, int detPos) { - return detectors[detPos]->getDetectorOffset(d); -} - -void multiSlsDetector::setDetectorOffset(dimension d, int off, int detPos) { - detectors[detPos]->setDetectorOffset(d, off); -} - -void multiSlsDetector::updateOffsets() { - FILE_LOG(logDEBUG1) << "Updating Multi-Detector Offsets"; - - int offsetX = 0, offsetY = 0, numX = 0, numY = 0; - int maxChanX = multi_shm()->maxNumberOfChannelsPerDetector[X]; - int maxChanY = multi_shm()->maxNumberOfChannelsPerDetector[Y]; - int prevChanX = 0; - int prevChanY = 0; - bool firstTime = true; - - multi_shm()->numberOfChannel[X] = 0; - multi_shm()->numberOfChannel[Y] = 0; - multi_shm()->numberOfDetector[X] = 0; - multi_shm()->numberOfDetector[Y] = 0; - - // gap pixels - int offsetX_gp = 0, offsetY_gp = 0, numX_gp = 0, numY_gp = 0; - int prevChanX_gp = 0, prevChanY_gp = 0; - multi_shm()->numberOfChannelInclGapPixels[X] = 0; - multi_shm()->numberOfChannelInclGapPixels[Y] = 0; - - for (size_t idet = 0; idet < detectors.size(); ++idet) { - FILE_LOG(logDEBUG1) - << "offsetX:" << offsetX << " prevChanX:" << prevChanX - << " offsetY:" << offsetY << " prevChanY:" << prevChanY - << " offsetX_gp:" << offsetX_gp << " prevChanX_gp:" << prevChanX_gp - << " offsetY_gp:" << offsetY_gp << " prevChanY_gp:" << prevChanY_gp; - - // incrementing in both direction - if (firstTime) { - // incrementing in both directions - firstTime = false; - if ((maxChanX > 0) && - ((offsetX + detectors[idet]->getTotalNumberOfChannels(X)) > - maxChanX)) { - FILE_LOG(logWARNING) - << "\nDetector[" << idet - << "] exceeds maximum channels " - "allowed for complete detector set in X dimension!"; - } - if ((maxChanY > 0) && - ((offsetY + detectors[idet]->getTotalNumberOfChannels(Y)) > - maxChanY)) { - FILE_LOG(logERROR) - << "\nDetector[" << idet - << "] exceeds maximum channels " - "allowed for complete detector set in Y dimension!"; - } - prevChanX = detectors[idet]->getTotalNumberOfChannels(X); - prevChanY = detectors[idet]->getTotalNumberOfChannels(Y); - prevChanX_gp = - detectors[idet]->getTotalNumberOfChannelsInclGapPixels(X); - prevChanY_gp = - detectors[idet]->getTotalNumberOfChannelsInclGapPixels(Y); - numX += detectors[idet]->getTotalNumberOfChannels(X); - numY += detectors[idet]->getTotalNumberOfChannels(Y); - numX_gp += - detectors[idet]->getTotalNumberOfChannelsInclGapPixels(X); - numY_gp += - detectors[idet]->getTotalNumberOfChannelsInclGapPixels(Y); - ++multi_shm()->numberOfDetector[X]; - ++multi_shm()->numberOfDetector[Y]; - FILE_LOG(logDEBUG1) << "incrementing in both direction"; - } - - // incrementing in y direction - else if ((maxChanY == -1) || - ((maxChanY > 0) && ((offsetY + prevChanY + - detectors[idet]->getTotalNumberOfChannels( - Y)) <= maxChanY))) { - offsetY += prevChanY; - offsetY_gp += prevChanY_gp; - prevChanY = detectors[idet]->getTotalNumberOfChannels(Y); - prevChanY_gp = - detectors[idet]->getTotalNumberOfChannelsInclGapPixels(Y); - numY += detectors[idet]->getTotalNumberOfChannels(Y); - numY_gp += - detectors[idet]->getTotalNumberOfChannelsInclGapPixels(Y); - // increment in y again only in the first column (else you double - // increment) - if (multi_shm()->numberOfDetector[X] == 1) - ++multi_shm()->numberOfDetector[Y]; - FILE_LOG(logDEBUG1) << "incrementing in y direction"; - } - - // incrementing in x direction - else { - if ((maxChanX > 0) && - ((offsetX + prevChanX + - detectors[idet]->getTotalNumberOfChannels(X)) > maxChanX)) { - FILE_LOG(logDEBUG1) - << "\nDetector[" << idet - << "] exceeds maximum channels " - "allowed for complete detector set in X dimension!"; - } - offsetY = 0; - offsetY_gp = 0; - prevChanY = detectors[idet]->getTotalNumberOfChannels(Y); - prevChanY_gp = - detectors[idet]->getTotalNumberOfChannelsInclGapPixels(Y); - numY = 0; // assuming symmetry with this statement. - // whats on 1st column should be on 2nd column - numY_gp = 0; - offsetX += prevChanX; - offsetX_gp += prevChanX_gp; - prevChanX = detectors[idet]->getTotalNumberOfChannels(X); - prevChanX_gp = - detectors[idet]->getTotalNumberOfChannelsInclGapPixels(X); - numX += detectors[idet]->getTotalNumberOfChannels(X); - numX_gp += - detectors[idet]->getTotalNumberOfChannelsInclGapPixels(X); - ++multi_shm()->numberOfDetector[X]; - FILE_LOG(logDEBUG1) << "incrementing in x direction"; - } - - double bytesperchannel = - (double)detectors[idet]->getDataBytes() / - (double)(detectors[idet]->getTotalNumberOfChannels(X) * - detectors[idet]->getTotalNumberOfChannels(Y)); - detectors[idet]->setDetectorOffset( - X, (bytesperchannel >= 1.0) ? offsetX_gp : offsetX); - detectors[idet]->setDetectorOffset( - Y, (bytesperchannel >= 1.0) ? offsetY_gp : offsetY); - - FILE_LOG(logDEBUG1) << "Detector[" << idet << "] has offsets (" - << detectors[idet]->getDetectorOffset(X) << ", " - << detectors[idet]->getDetectorOffset(Y) << ")"; - // offsetY has been reset sometimes and offsetX the first time, - // but remember the highest values - if (numX > multi_shm()->numberOfChannel[X]) { - multi_shm()->numberOfChannel[X] = numX; - } - if (numY > multi_shm()->numberOfChannel[Y]) { - multi_shm()->numberOfChannel[Y] = numY; - } - if (numX_gp > multi_shm()->numberOfChannelInclGapPixels[X]) { - multi_shm()->numberOfChannelInclGapPixels[X] = numX_gp; - } - if (numY_gp > multi_shm()->numberOfChannelInclGapPixels[Y]) { - multi_shm()->numberOfChannelInclGapPixels[Y] = numY_gp; - } - } - FILE_LOG(logDEBUG1) - << "\n\tNumber of Channels in X direction:" - << multi_shm()->numberOfChannel[X] - << "\n\tNumber of Channels in Y direction:" - << multi_shm()->numberOfChannel[Y] - << "\n\tNumber of Channels in X direction with Gap Pixels:" - << multi_shm()->numberOfChannelInclGapPixels[X] - << "\n\tNumber of Channels in Y direction with Gap Pixels:" - << multi_shm()->numberOfChannelInclGapPixels[Y]; - - multi_shm()->numberOfChannels = - multi_shm()->numberOfChannel[0] * multi_shm()->numberOfChannel[1]; - - for (auto &d : detectors) { - d->updateMultiSize(multi_shm()->numberOfDetector[0], - multi_shm()->numberOfDetector[1]); - } -} - std::string multiSlsDetector::checkOnline(int detPos) { if (detPos >= 0) { return detectors[detPos]->checkOnline(); diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index 0a8e38a62..0c942a57d 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -654,12 +654,12 @@ int slsDetector::getNChips() const { return shm()->nChips; } int slsDetector::getNChips(dimension d) const { return shm()->nChip[d]; } -int slsDetector::getQuad() { +bool slsDetector::getQuad() { int retval = -1; FILE_LOG(logDEBUG1) << "Getting Quad Type"; sendToDetector(F_GET_QUAD, nullptr, retval); FILE_LOG(logDEBUG1) << "Quad Type :" << retval; - return retval; + return (retval == 0 ? false : true); } void slsDetector::setQuad(const bool enable) { @@ -693,12 +693,24 @@ int slsDetector::getDetectorOffset(dimension d) const { return shm()->offset[d]; } +slsDetectorDefs::coordinates slsDetector::getDetectorOffsets() const { + slsDetectorDefs::coordinates coord; + coord.x = shm()->offset[X]; + coord.y = shm()->offset[Y]; + return coord; +} + void slsDetector::setDetectorOffset(dimension d, int off) { if (off >= 0) { shm()->offset[d] = off; } } +void slsDetector::setDetectorOffsets(slsDetectorDefs::coordinates value) { + shm()->offset[X] = value.x; + shm()->offset[Y] = value.y; +} + void slsDetector::updateMultiSize(int detx, int dety) { shm()->multiSize[0] = detx; shm()->multiSize[1] = dety; From e6349d0312f4a5c3be29322590548296eb89b4a4 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Thu, 8 Aug 2019 15:51:21 +0200 Subject: [PATCH 020/108] WIP --- slsDetectorSoftware/include/Detector.h | 21 ++++++++++++++ .../include/multiSlsDetector.h | 8 +++--- slsDetectorSoftware/src/Detector.cpp | 28 ++++++++++++++++++- 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 306c7de47..4b6c3de06 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -429,6 +429,27 @@ class Detector { // void exitReceiver(int detPos = -1); Result getReceiverLastClientIP(Positions pos = {}) const; + + void setReceiverLock(bool value, Positions pos = {}); + + Result getReceiverLock(Positions pos = {}); + + /** true when receiver is used otherwise false */ + Result getUseReceiverFlag(Positions pos = {}) const; + + void printReceiverConfiguration(Positions pos = {}) const; + + + /** [Eiger] + * @returns deadtime in ns, 0 = disabled + */ + Result getRateCorrection(Positions pos = {}) const; + + /** + * [Eiger] Set Rate correction + * 0 disable correction, <0 set to default, >0 deadtime in ns + */ + void setRateCorrection(int64_t dead_time_ns, Positions pos = {}); }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index c6376bffb..e4ffe42fb 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -1758,14 +1758,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param level print level * @param detPos -1 for all detectors in list or specific detector position */ - void printReceiverConfiguration(TLogLevel level = logINFO, int detPos = -1); + void printReceiverConfiguration(TLogLevel level = logINFO, int detPos = -1); // /** * Get receiver online status * @param detPos -1 for all detectors in list or specific detector position * @returns use receiver flag */ - bool getUseReceiverFlag(int detPos = -1); + bool getUseReceiverFlag(int detPos = -1); // /** * Checks if the receiver is really online @@ -1773,7 +1773,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns empty string if all online, else concatenates hostnames of all * detectors that are offline */ - std::string checkReceiverOnline(int detPos = -1); + std::string checkReceiverOnline(int detPos = -1); //not needed /** * Locks/Unlocks the connection to the receiver @@ -1781,7 +1781,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns lock status of the receiver */ - int lockReceiver(int lock = -1, int detPos = -1); + int lockReceiver(int lock = -1, int detPos = -1); // /** * Returns the IP of the last client connecting to the receiver diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 3904eccaf..82d5e0bef 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -1,5 +1,6 @@ #include "Detector.h" #include "container_utils.h" +#include "logger.h" #include "multiSlsDetector.h" #include "slsDetector.h" #include "sls_detector_defs.h" @@ -379,8 +380,33 @@ Result Detector::getFramesPerFile(Positions pos) const { return pimpl->Parallel(&slsDetector::getFramesPerFile, pos); } -Result Detector::getReceiverLastClientIP(Positions pos) const{ +Result Detector::getReceiverLastClientIP(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverLastClientIP, pos); } +void Detector::setReceiverLock(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::lockReceiver, pos, static_cast(value)); +} + +Result Detector::getReceiverLock(Positions pos) { + return pimpl->Parallel(&slsDetector::lockReceiver, pos, -1); +} + +Result Detector::getUseReceiverFlag(Positions pos) const { + return pimpl->Parallel(&slsDetector::getUseReceiverFlag, pos); +} + +void Detector::printReceiverConfiguration(Positions pos) const { + pimpl->Parallel(&slsDetector::printReceiverConfiguration, pos, + TLogLevel::logINFO); +} + +Result Detector::getRateCorrection(Positions pos) const { + return pimpl->Parallel(&slsDetector::getRateCorrection, pos); +} + +void Detector::setRateCorrection(int64_t dead_time_ns, Positions pos) { + pimpl->Parallel(&slsDetector::setRateCorrection, pos, dead_time_ns); +} + } // namespace sls \ No newline at end of file From ddfb66e999816ad848e64120d1d22bd98f04bf5b Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Thu, 8 Aug 2019 15:58:00 +0200 Subject: [PATCH 021/108] not compiling --- slsDetectorSoftware/include/Detector.h | 41 +++++++++++++++++++++++ slsDetectorSoftware/include/slsDetector.h | 2 +- slsDetectorSoftware/src/Detector.cpp | 2 +- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 0794a5dda..ceecabd78 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -294,6 +294,47 @@ class Detector { */ void setReadNLines(const int value, Positions pos = {}); + /** + * Get Receiver TCP port (for client communication with Receiver) + * @param pos detector position + * @returns receiver port + */ + //int getControlort(Positions pos = {}) const; + + /** + * Set TCP Port of the detector (for client communication with Receiver) + * @param value port number + * @param pos detector position + */ + //void setControlPort(int port_number, Positions pos = {}); + + /** + * Get Receiver TCP port (for client communication with Receiver) + * @param pos detector position + * @returns receiver port + */ + //int getStopPort(Positions pos = {}) const; + + /** + * Set TCP Port of the detector (for client communication with Receiver) + * @param value port number + * @param pos detector position + */ + //void setStopPort(int port_number, Positions pos = {}); + + /** + * Get Receiver TCP port (for client communication with Receiver) + * @param pos detector position + * @returns receiver port + */ + //int getReceiverPort(Positions pos = {}) const; + + /** + * Set TCP Port of the detector (for client communication with Receiver) + * @param value port number + * @param pos detector position + */ + //void setReceiverPort(int port_number, Positions pos = {}); diff --git a/slsDetectorSoftware/include/slsDetector.h b/slsDetectorSoftware/include/slsDetector.h index 91c8cf684..2a96ce92f 100755 --- a/slsDetectorSoftware/include/slsDetector.h +++ b/slsDetectorSoftware/include/slsDetector.h @@ -447,7 +447,7 @@ class slsDetector : public virtual slsDetectorDefs { * Set Detector offset in shared memory * @param value offset for detector */ - void setDetectorOffsets(slsDetectorDefs::coordinates value); + void setDetectorOffset(slsDetectorDefs::coordinates value); /** * Set Detector offset in shared memory in dimension d diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 8c5894c9e..d6e190a3a 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -208,7 +208,7 @@ Result Detector::getDetectorOffsets(Positions pos) const { } void Detector::setDetectorOffsets(defs::coordinates value, Positions pos) { - return pimpl->Parallel(&slsDetector::setDetectorOffsets, pos, value); + return pimpl->Parallel(&slsDetector::setDetectorOffset, pos, value); } Result Detector::getQuad(Positions pos) const { From 23ea16f4b86ac21c52d2ec4b8e02d3ae935b38a3 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Thu, 8 Aug 2019 15:59:51 +0200 Subject: [PATCH 022/108] not compiling --- 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 0c942a57d..7133a4a53 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -706,7 +706,7 @@ void slsDetector::setDetectorOffset(dimension d, int off) { } } -void slsDetector::setDetectorOffsets(slsDetectorDefs::coordinates value) { +void slsDetector::setDetectorOffset(slsDetectorDefs::coordinates value) { shm()->offset[X] = value.x; shm()->offset[Y] = value.y; } From 9d5cff3b345e34c7adb7b43b2af754bebdbcd84e Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Thu, 8 Aug 2019 16:09:29 +0200 Subject: [PATCH 023/108] WIP --- slsDetectorSoftware/src/Detector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 577e7415a..d77c13647 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -209,7 +209,7 @@ Result Detector::getDetectorOffsets(Positions pos) const { } void Detector::setDetectorOffsets(defs::coordinates value, Positions pos) { - return pimpl->Parallel(&slsDetector::setDetectorOffset, pos, value); + pimpl->Parallel(&slsDetector::setDetectorOffset, pos, value); } Result Detector::getQuad(Positions pos) const { From a77964e1dd0d63d85bda39f3a5b87db1e287a90a Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Thu, 8 Aug 2019 16:18:04 +0200 Subject: [PATCH 024/108] WIP --- slsDetectorSoftware/include/Detector.h | 46 +++++++++---------- .../include/multiSlsDetector.h | 8 ++-- slsDetectorSoftware/include/slsDetector.h | 2 +- slsDetectorSoftware/src/Detector.cpp | 24 +++++++++- slsDetectorSoftware/src/slsDetector.cpp | 2 +- 5 files changed, 52 insertions(+), 30 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 2270abbe3..341ec91e5 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -295,46 +295,46 @@ class Detector { void setReadNLines(const int value, Positions pos = {}); /** - * Get Receiver TCP port (for client communication with Receiver) + * Get Detector Control TCP port (for client communication with Detector control server) * @param pos detector position - * @returns receiver port + * @returns control TCP port */ - //int getControlort(Positions pos = {}) const; + Result getControlPort(Positions pos = {}) const; /** - * Set TCP Port of the detector (for client communication with Receiver) + * Set Detector Control TCP port (for client communication with Detector control server) * @param value port number * @param pos detector position */ - //void setControlPort(int port_number, Positions pos = {}); + void setControlPort(int value, Positions pos = {}); + + /** + * Get Detector Stop TCP port (for client communication with Detector Stop server) + * @param pos detector position + * @returns Stop TCP port + */ + Result getStopPort(Positions pos = {}) const; + + /** + * Set Detector Stop TCP port (for client communication with Detector Stop server) + * @param value port number + * @param pos detector position + */ + void setStopPort(int value, Positions pos = {}); /** * Get Receiver TCP port (for client communication with Receiver) * @param pos detector position - * @returns receiver port + * @returns Receiver TCP port */ - //int getStopPort(Positions pos = {}) const; + Result getReceiverPort(Positions pos = {}) const; /** - * Set TCP Port of the detector (for client communication with Receiver) + * Set Receiver TCP port (for client communication with Receiver) * @param value port number * @param pos detector position */ - //void setStopPort(int port_number, Positions pos = {}); - - /** - * Get Receiver TCP port (for client communication with Receiver) - * @param pos detector position - * @returns receiver port - */ - //int getReceiverPort(Positions pos = {}) const; - - /** - * Set TCP Port of the detector (for client communication with Receiver) - * @param value port number - * @param pos detector position - */ - //void setReceiverPort(int port_number, Positions pos = {}); + void setReceiverPort(int value, Positions pos = {}); diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 556eb28c0..3e9f3ee43 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -534,7 +534,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns port number */ - int setControlPort(int port_number = -1, int detPos = -1); + int setControlPort(int port_number = -1, int detPos = -1);// /** * Set/Gets TCP STOP Port of the detector @@ -542,7 +542,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns port number */ - int setStopPort(int port_number = -1, int detPos = -1); + int setStopPort(int port_number = -1, int detPos = -1);// /** * Set/Gets TCP Port of the receiver @@ -550,14 +550,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns port number */ - int setReceiverPort(int port_number = -1, int detPos = -1); + int setReceiverPort(int port_number = -1, int detPos = -1);// /** * Get Receiver port * @param detPos -1 for all detectors in list or specific detector position * @returns vector of receiver port */ - int getReceiverPort(int detPos = -1) const; + int getReceiverPort(int detPos = -1) const;// /** * Lock server for this client IP diff --git a/slsDetectorSoftware/include/slsDetector.h b/slsDetectorSoftware/include/slsDetector.h index 2a96ce92f..91c8cf684 100755 --- a/slsDetectorSoftware/include/slsDetector.h +++ b/slsDetectorSoftware/include/slsDetector.h @@ -447,7 +447,7 @@ class slsDetector : public virtual slsDetectorDefs { * Set Detector offset in shared memory * @param value offset for detector */ - void setDetectorOffset(slsDetectorDefs::coordinates value); + void setDetectorOffsets(slsDetectorDefs::coordinates value); /** * Set Detector offset in shared memory in dimension d diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 577e7415a..0d39b6b34 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -209,7 +209,7 @@ Result Detector::getDetectorOffsets(Positions pos) const { } void Detector::setDetectorOffsets(defs::coordinates value, Positions pos) { - return pimpl->Parallel(&slsDetector::setDetectorOffset, pos, value); + return pimpl->Parallel(&slsDetector::setDetectorOffsets, pos, value); } Result Detector::getQuad(Positions pos) const { @@ -228,7 +228,29 @@ void Detector::setReadNLines(const int value, Positions pos) { pimpl->Parallel(&slsDetector::setReadNLines, pos, value); } +Result Detector::getControlPort(Positions pos) const { + return pimpl->Parallel(&slsDetector::getControlPort, pos); +} +void Detector::setControlPort(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setControlPort, pos, value); +} + +Result Detector::getStopPort(Positions pos) const { + return pimpl->Parallel(&slsDetector::getStopPort, pos); +} + +void Detector::setStopPort(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setStopPort, pos, value); +} + +Result Detector::getReceiverPort(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverPort, pos); +} + +void Detector::setReceiverPort(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverPort, pos, value); +} // Erik Result Detector::getFramesCaughtByReceiver(Positions pos) const { diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index 7133a4a53..0c942a57d 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -706,7 +706,7 @@ void slsDetector::setDetectorOffset(dimension d, int off) { } } -void slsDetector::setDetectorOffset(slsDetectorDefs::coordinates value) { +void slsDetector::setDetectorOffsets(slsDetectorDefs::coordinates value) { shm()->offset[X] = value.x; shm()->offset[Y] = value.y; } From eaf0d8668b280244d8104f8df571d667999e4d90 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Thu, 8 Aug 2019 16:39:25 +0200 Subject: [PATCH 025/108] WIP --- slsDetectorSoftware/include/Detector.h | 1 - .../include/multiSlsDetector.h | 16 --------- slsDetectorSoftware/include/slsDetector.h | 12 ------- slsDetectorSoftware/src/Detector.cpp | 1 + slsDetectorSoftware/src/multiSlsDetector.cpp | 20 ----------- slsDetectorSoftware/src/slsDetector.cpp | 20 ----------- .../src/slsDetectorCommand.cpp | 33 ++----------------- 7 files changed, 3 insertions(+), 100 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 341ec91e5..a8150b7b3 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -337,7 +337,6 @@ class Detector { void setReceiverPort(int value, Positions pos = {}); - // Erik Result getFramesCaughtByReceiver(Positions pos = {}) const; diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 3e9f3ee43..d659987b6 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -520,14 +520,6 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ int getReadNLines(int detPos = -1);// - /** - * Checks if each of the detectors are online/offline - * @param detPos -1 for all detectors in list or specific detector position - * @returns empty string if they are all online, - * else returns concatenation of strings of all detectors that are offline - */ - std::string checkOnline(int detPos = -1); - /** * Set/Gets TCP Port of the detector * @param port_number (-1 gets) @@ -1761,14 +1753,6 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ bool getUseReceiverFlag(int detPos = -1); // - /** - * Checks if the receiver is really online - * @param detPos -1 for all detectors in list or specific detector position - * @returns empty string if all online, else concatenates hostnames of all - * detectors that are offline - */ - std::string checkReceiverOnline(int detPos = -1); //not needed - /** * Locks/Unlocks the connection to the receiver * @param lock sets (1), usets (0), gets (-1) the lock diff --git a/slsDetectorSoftware/include/slsDetector.h b/slsDetectorSoftware/include/slsDetector.h index 91c8cf684..300bdec08 100755 --- a/slsDetectorSoftware/include/slsDetector.h +++ b/slsDetectorSoftware/include/slsDetector.h @@ -456,12 +456,6 @@ class slsDetector : public virtual slsDetectorDefs { */ void updateMultiSize(int detx, int dety); - /** - * Checks if each of the detector is online/offline - * @returns empty string if it is online - * else returns hostname if it is offline - */ - std::string checkOnline(); int setControlPort(int port_number); @@ -1474,12 +1468,6 @@ class slsDetector : public virtual slsDetectorDefs { */ bool getUseReceiverFlag() const; - /** - * Checks if the receiver is really online - * @returns empty string if online, else returns receiver hostname - */ - std::string checkReceiverOnline(); - /** * Locks/Unlocks the connection to the receiver * @param lock sets (1), usets (0), gets (-1) the lock diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 216f9aa5c..ea62ba2f7 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -253,6 +253,7 @@ void Detector::setReceiverPort(int value, Positions pos) { pimpl->Parallel(&slsDetector::setReceiverPort, pos, value); } + // Erik Result Detector::getFramesCaughtByReceiver(Positions pos) const { return pimpl->Parallel(&slsDetector::getFramesCaughtByReceiver, pos); diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index a13c79a6c..cf772606f 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -788,15 +788,6 @@ int multiSlsDetector::getReadNLines(int detPos) { return sls::minusOneIfDifferent(r); } -std::string multiSlsDetector::checkOnline(int detPos) { - if (detPos >= 0) { - return detectors[detPos]->checkOnline(); - } - - auto r = parallelCall(&slsDetector::checkOnline); - return sls::concatenateNonEmptyStrings(r); -} - int multiSlsDetector::setControlPort(int port_number, int detPos) { if (detPos >= 0) { return detectors[detPos]->setControlPort(port_number); @@ -2995,17 +2986,6 @@ bool multiSlsDetector::getUseReceiverFlag(int detPos) { } } -std::string multiSlsDetector::checkReceiverOnline(int detPos) { - // single - if (detPos >= 0) { - return detectors[detPos]->checkReceiverOnline(); - } - - // multi - auto r = parallelCall(&slsDetector::checkReceiverOnline); - return sls::concatenateNonEmptyStrings(r); -} - int multiSlsDetector::lockReceiver(int lock, int detPos) { // single if (detPos >= 0) { diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index 0c942a57d..2b608b922 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -716,17 +716,6 @@ void slsDetector::updateMultiSize(int detx, int dety) { shm()->multiSize[1] = dety; } -std::string slsDetector::checkOnline() { - std::string retval; - try { - // Need both control and stop socket to work! - auto client = DetectorSocket(shm()->hostname, shm()->controlPort); - auto stop = DetectorSocket(shm()->hostname, shm()->stopPort); - } catch (...) { - retval = shm()->hostname; - } - return retval; -} int slsDetector::setControlPort(int port_number) { int retval = -1; @@ -2970,15 +2959,6 @@ void slsDetector::printReceiverConfiguration(TLogLevel level) { bool slsDetector::getUseReceiverFlag() const { return shm()->useReceiverFlag; } -std::string slsDetector::checkReceiverOnline() { - try { - getReceiverSoftwareVersion(); - } catch (...) { - return shm()->rxHostname; - } - return std::string(); -} - int slsDetector::lockReceiver(int lock) { FILE_LOG(logDEBUG1) << "Setting receiver server lock to " << lock; int retval = -1; diff --git a/slsDetectorSoftware/src/slsDetectorCommand.cpp b/slsDetectorSoftware/src/slsDetectorCommand.cpp index 7ac82ced0..4f1153667 100755 --- a/slsDetectorSoftware/src/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp @@ -287,12 +287,6 @@ slsDetectorCommand::slsDetectorCommand(multiSlsDetector *det) { commands to configure detector status */ - /*! \page config - - checkonline returns the hostnames of all detectors without connecting to them. \c Returns (string) "All online" or "[list of offline hostnames] : Not online". - */ - descrToFuncMap[i].m_pFuncName = "checkonline"; - descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdOnline; - ++i; /*! \page config - activate [b] [p] Activates/Deactivates the detector. \c b is 1 for activate, 0 for deactivate. Deactivated detector does not send data. \c p is optional and can be padding (default) or nonpadding for receivers for deactivated detectors. Used for EIGER only. \c Returns \c (int) (string) */ @@ -1797,13 +1791,6 @@ slsDetectorCommand::slsDetectorCommand(multiSlsDetector *det) { descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdReceiver; ++i; - /*! \page receiver - - rx_checkonline Checks the receiver if it is online/offline mode. Only get! \c Returns (string) "All online" or "[list of offline hostnames] : Not online". - */ - descrToFuncMap[i].m_pFuncName = "rx_checkonline"; - descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdOnline; - ++i; - /*! \page receiver - framescaught gets the number of frames caught by receiver. Average of all for multi-detector command. Only get! \c Returns \c (int) */ @@ -3207,15 +3194,7 @@ std::string slsDetectorCommand::cmdOnline(int narg, const char * const args[], i int ival; char ans[1000]; - if (cmd == "checkonline") { - if (action == PUT_ACTION) - return std::string("cannot set"); - strcpy(ans, myDet->checkOnline(detPos).c_str()); - if (!strlen(ans)) - strcpy(ans, "All online"); - else - strcat(ans, " :Not online"); - } else if (cmd == "activate") { + if (cmd == "activate") { if (action == PUT_ACTION) { if (!sscanf(args[1], "%d", &ival)) @@ -3235,13 +3214,7 @@ std::string slsDetectorCommand::cmdOnline(int narg, const char * const args[], i int ret = myDet->setDeactivatedRxrPaddingMode(-1, detPos); sprintf(ans, "%d %s", myDet->activate(-1, detPos), ret == 1 ? "padding" : (ret == 0 ? "nopadding" : "unknown")); } else { - if (action == PUT_ACTION) - return std::string("cannot set"); - strcpy(ans, myDet->checkReceiverOnline(detPos).c_str()); - if (!strlen(ans)) - strcpy(ans, "All receiver online"); - else - strcat(ans, " :Not all receiver online"); + return std::string("unknown command"); } return ans; @@ -3254,8 +3227,6 @@ std::string slsDetectorCommand::helpOnline(int action) { os << "activate i [p]\n sets the detector in activated (1) or deactivated (0) mode (does not send data). p is optional and can be padding (default) or nonpadding for receivers for deactivated detectors. Only for Eiger." << std::endl; } if (action == GET_ACTION || action == HELP_ACTION) { - os << "checkonline \n returns the hostnames of all detectors in offline mode" << std::endl; - os << "rx_checkonline \n returns the hostnames of all receiver in offline mode" << std::endl; os << "activate \n gets the detector activated (1) or deactivated (0) mode. And padding or nonpadding for the deactivated receiver. Only for Eiger." << std::endl; } return os.str(); From 40bc498e9a5d779839a3173052699f057099a553 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Thu, 8 Aug 2019 16:44:52 +0200 Subject: [PATCH 026/108] WIP --- slsDetectorSoftware/include/Detector.h | 64 +++++++++++++++---- .../include/multiSlsDetector.h | 34 +++++----- slsDetectorSoftware/src/Detector.cpp | 57 ++++++++++++++++- 3 files changed, 125 insertions(+), 30 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 2270abbe3..5d1e45b9c 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -299,44 +299,42 @@ class Detector { * @param pos detector position * @returns receiver port */ - //int getControlort(Positions pos = {}) const; + // int getControlort(Positions pos = {}) const; /** * Set TCP Port of the detector (for client communication with Receiver) * @param value port number * @param pos detector position */ - //void setControlPort(int port_number, Positions pos = {}); + // void setControlPort(int port_number, Positions pos = {}); /** * Get Receiver TCP port (for client communication with Receiver) * @param pos detector position * @returns receiver port */ - //int getStopPort(Positions pos = {}) const; + // int getStopPort(Positions pos = {}) const; /** * Set TCP Port of the detector (for client communication with Receiver) * @param value port number * @param pos detector position */ - //void setStopPort(int port_number, Positions pos = {}); + // void setStopPort(int port_number, Positions pos = {}); - /** + /** * Get Receiver TCP port (for client communication with Receiver) * @param pos detector position * @returns receiver port */ - //int getReceiverPort(Positions pos = {}) const; + // int getReceiverPort(Positions pos = {}) const; /** * Set TCP Port of the detector (for client communication with Receiver) * @param value port number * @param pos detector position */ - //void setReceiverPort(int port_number, Positions pos = {}); - - + // void setReceiverPort(int port_number, Positions pos = {}); // Erik @@ -525,17 +523,61 @@ class Detector { void printReceiverConfiguration(Positions pos = {}) const; - /** [Eiger] * @returns deadtime in ns, 0 = disabled */ Result getRateCorrection(Positions pos = {}) const; /** - * [Eiger] Set Rate correction + * [Eiger] Set Rate correction * 0 disable correction, <0 set to default, >0 deadtime in ns */ void setRateCorrection(int64_t dead_time_ns, Positions pos = {}); + + /** [Jungfrau] TODO??? fix docs */ + void setAutoCompDisable(bool value, Positions pos = {}); + + Result getAutoCompDisable(Positions pos = {}) const; + + void setPowerChip(bool on, Positions pos = {}); + + Result getPowerChip(Positions pos = {}) const; + + /** + * Updates the firmware, detector server and then reboots detector + * controller blackfin. (Not Eiger) + * @param sname name of detector server binary + * @param hostname name of pc to tftp from + * @param fname programming file name + * @param pos detector positions + */ + void updateFirmwareAndServer(const std::string &sname, + const std::string &hostname, + const std::string &fname, Positions pos = {}); + + /** [not Eiger] TODO! is this needed?*/ + void rebootController(Positions pos = {}); + + /** Copy detector server to detector */ + void copyDetectorServer(const std::string &fname, + const std::string &hostname, Positions pos = {}); + + + /** [not Eiger] */ + void resetFPGA(Positions pos = {}); + + /** [not Eiger] */ + void programFPGA(const std::string &fname, Positions pos = {}); + + /** + * [Jungfrau] Set first storage cell of the series (Jungfrau) + * @param value storage cell index. Value can be 0 to 15. + */ + void setStoragecellStart(int cell, Positions pos = {}); + + Result getStorageCellStart(Positions pos = {}) const; + + }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 556eb28c0..8a6dd006b 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -1681,13 +1681,13 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param fname file name * @param detPos -1 for all detectors in list or specific detector position */ - void programFPGA(const std::string &fname, int detPos = -1); + void programFPGA(const std::string &fname, int detPos = -1); // /** * Resets FPGA (Not Eiger) * @param detPos -1 for all detectors in list or specific detector position */ - void resetFPGA(int detPos = -1); + void resetFPGA(int detPos = -1); // /** * Copies detector server from tftp and changes respawn server (Not Eiger) @@ -1696,13 +1696,13 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position */ void copyDetectorServer(const std::string &fname, - const std::string &hostname, int detPos = -1); + const std::string &hostname, int detPos = -1); // /** * Reboot detector controller (Not Eiger) * @param detPos -1 for all detectors in list or specific detector position */ - void rebootController(int detPos = -1); + void rebootController(int detPos = -1); // /** * Updates the firmware, detector server and then reboots detector @@ -1713,7 +1713,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position */ void update(const std::string &sname, const std::string &hostname, - const std::string &fname, int detPos = -1); + const std::string &fname, int detPos = -1); // /** * Power on/off Chip (Jungfrau) @@ -1721,7 +1721,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns OK or FAIL */ - int powerChip(int ival = -1, int detPos = -1); + int powerChip(int ival = -1, int detPos = -1); // /** * Automatic comparator disable (Jungfrau) @@ -1729,7 +1729,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns OK or FAIL */ - int setAutoComparatorDisableMode(int ival = -1, int detPos = -1); + int setAutoComparatorDisableMode(int ival = -1, int detPos = -1); // /** * Set Rate correction ( Eiger) @@ -1738,14 +1738,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * for current settings * @param detPos -1 for all detectors in list or specific detector position */ - void setRateCorrection(int64_t t = 0, int detPos = -1); + void setRateCorrection(int64_t t = 0, int detPos = -1); // /** * Get rate correction ( Eiger) * @param detPos -1 for all detectors in list or specific detector position * @returns 0 if rate correction disabled, > 0 otherwise (ns) */ - int64_t getRateCorrection(int detPos = -1); + int64_t getRateCorrection(int detPos = -1); // /** * Prints receiver configuration @@ -2230,6 +2230,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ void processData(); + /** + * Convert raw file + * @param fname name of pof file + * @param fpgasrc pointer in memory to read pof to + * @returns file size + */ + std::vector readPofFile(const std::string &fname); + private: /** * increments file index @@ -2370,13 +2378,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ int kbhit(); - /** - * Convert raw file - * @param fname name of pof file - * @param fpgasrc pointer in memory to read pof to - * @returns file size - */ - std::vector readPofFile(const std::string &fname); + /** * Convert a double holding time in seconds to an int64_t with nano seconds diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index d77c13647..01adb635b 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -209,7 +209,8 @@ Result Detector::getDetectorOffsets(Positions pos) const { } void Detector::setDetectorOffsets(defs::coordinates value, Positions pos) { - pimpl->Parallel(&slsDetector::setDetectorOffset, pos, value); + pimpl->Parallel(&slsDetector::setDetectorOffset, pos, + value); } Result Detector::getQuad(Positions pos) const { @@ -228,8 +229,6 @@ void Detector::setReadNLines(const int value, Positions pos) { pimpl->Parallel(&slsDetector::setReadNLines, pos, value); } - - // Erik Result Detector::getFramesCaughtByReceiver(Positions pos) const { return pimpl->Parallel(&slsDetector::getFramesCaughtByReceiver, pos); @@ -432,4 +431,56 @@ void Detector::setRateCorrection(int64_t dead_time_ns, Positions pos) { pimpl->Parallel(&slsDetector::setRateCorrection, pos, dead_time_ns); } +void Detector::setAutoCompDisable(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setAutoComparatorDisableMode, pos, + static_cast(value)); +} + +Result Detector::getAutoCompDisable(Positions pos) const { + return pimpl->Parallel(&slsDetector::setAutoComparatorDisableMode, pos, -1); +} + +void Detector::setPowerChip(bool on, Positions pos) { + pimpl->Parallel(&slsDetector::powerChip, pos, static_cast(on)); +} + +Result Detector::getPowerChip(Positions pos) const { + return pimpl->Parallel(&slsDetector::powerChip, pos, -1); +} + +void Detector::updateFirmwareAndServer(const std::string &sname, + const std::string &hostname, + const std::string &fname, + Positions pos) { + copyDetectorServer(fname, hostname, pos); + programFPGA(fname, pos); +} + +void Detector::rebootController(Positions pos) { + pimpl->Parallel(&slsDetector::rebootController, pos); +} + +void Detector::copyDetectorServer(const std::string &fname, + const std::string &hostname, Positions pos) { + pimpl->Parallel(&slsDetector::copyDetectorServer, pos, fname, hostname); +} + +void Detector::resetFPGA(Positions pos) { + pimpl->Parallel(&slsDetector::resetFPGA, pos); +} + +void Detector::programFPGA(const std::string &fname, Positions pos) { + FILE_LOG(logINFO) << "This can take awhile. Please be patient..."; + std::vector buffer = pimpl->readPofFile(fname); + pimpl->Parallel(&slsDetector::programFPGA, pos, buffer); +} + +void Detector::setStoragecellStart(int cell, Positions pos) { + pimpl->Parallel(&slsDetector::setStoragecellStart, pos, cell); +} + +Result Detector::getStorageCellStart(Positions pos) const { + return pimpl->Parallel(&slsDetector::setStoragecellStart, pos, -1); +} + } // namespace sls \ No newline at end of file From ca2c284017b38faf082df21d69ff57d90bc0e829 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Thu, 8 Aug 2019 16:55:37 +0200 Subject: [PATCH 027/108] WIP --- slsDetectorSoftware/include/Detector.h | 48 ++++++++++++++++--- .../include/multiSlsDetector.h | 8 ++-- slsDetectorSoftware/include/slsDetector.h | 4 +- slsDetectorSoftware/src/Detector.cpp | 22 ++++++++- slsDetectorSoftware/src/slsDetector.cpp | 4 +- 5 files changed, 71 insertions(+), 15 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index a8150b7b3..4fc40c7b4 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -295,28 +295,32 @@ class Detector { void setReadNLines(const int value, Positions pos = {}); /** - * Get Detector Control TCP port (for client communication with Detector control server) + * Get Detector Control TCP port (for client communication with Detector + * control server) * @param pos detector position * @returns control TCP port */ Result getControlPort(Positions pos = {}) const; /** - * Set Detector Control TCP port (for client communication with Detector control server) + * Set Detector Control TCP port (for client communication with Detector + * control server) * @param value port number * @param pos detector position */ void setControlPort(int value, Positions pos = {}); /** - * Get Detector Stop TCP port (for client communication with Detector Stop server) + * Get Detector Stop TCP port (for client communication with Detector Stop + * server) * @param pos detector position * @returns Stop TCP port */ Result getStopPort(Positions pos = {}) const; /** - * Set Detector Stop TCP port (for client communication with Detector Stop server) + * Set Detector Stop TCP port (for client communication with Detector Stop + * server) * @param value port number * @param pos detector position */ @@ -336,6 +340,39 @@ class Detector { */ void setReceiverPort(int value, Positions pos = {}); + /** + * Gets Lock for detector control server to this client IP + * @param pos detector position + * @returns lock + */ + Result getLockServer(Positions pos = {}); + + /** + * Sets Lock for detector control server to this client IP + * @param value lock + * @param pos detector position + */ + void setLockServer(bool value, Positions pos = {}); + + /** + * Get last client IP saved on detector server + * @param pos detector position + * @returns last client IP saved on detector server + */ + Result getLastClientIP(Positions pos = {}); + + /** + * Exit detector server + * @param pos detector position + */ + void exitServer(Positions pos = {}); + + /** + * Execute a command on the detector server + * @param value command + * @param pos detector position + */ + void execCommand(const std::string &value, Positions pos = {}); // Erik @@ -524,14 +561,13 @@ class Detector { void printReceiverConfiguration(Positions pos = {}) const; - /** [Eiger] * @returns deadtime in ns, 0 = disabled */ Result getRateCorrection(Positions pos = {}) const; /** - * [Eiger] Set Rate correction + * [Eiger] Set Rate correction * 0 disable correction, <0 set to default, >0 deadtime in ns */ void setRateCorrection(int64_t dead_time_ns, Positions pos = {}); diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index d659987b6..446c0d62b 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -557,27 +557,27 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns 1 for locked or 0 for unlocked */ - int lockServer(int p = -1, int detPos = -1); + int lockServer(int p = -1, int detPos = -1);// /** * Get last client IP saved on detector server * @param detPos -1 for all detectors in list or specific detector position * @returns last client IP saved on detector server */ - std::string getLastClientIP(int detPos = -1); + std::string getLastClientIP(int detPos = -1);// /** * Exit detector server * @param detPos -1 for all detectors in list or specific detector position */ - void exitServer(int detPos = -1); + void exitServer(int detPos = -1);// /** * Execute a command on the detector server * @param cmd command * @param detPos -1 for all detectors in list or specific detector position */ - void execCommand(const std::string &cmd, int detPos); + void execCommand(const std::string &cmd, int detPos);// /** * Load configuration from a configuration File diff --git a/slsDetectorSoftware/include/slsDetector.h b/slsDetectorSoftware/include/slsDetector.h index 300bdec08..516f43eab 100755 --- a/slsDetectorSoftware/include/slsDetector.h +++ b/slsDetectorSoftware/include/slsDetector.h @@ -484,9 +484,9 @@ class slsDetector : public virtual slsDetectorDefs { /** * Lock server for this client IP * @param p 0 to unlock, 1 to lock (-1 gets) - * @returns 1 for locked or 0 for unlocked + * @returns true for locked or false for unlocked */ - int lockServer(int lock = -1); + bool lockServer(int lock = -1); /** * Get last client IP saved on detector server diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index ea62ba2f7..99e7d8fd3 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -210,7 +210,8 @@ Result Detector::getDetectorOffsets(Positions pos) const { void Detector::setDetectorOffsets(defs::coordinates value, Positions pos) { pimpl->Parallel(&slsDetector::setDetectorOffsets, pos, value); - //pimpl->Parallel(&slsDetector::setDetectorOffset, pos, value); + // pimpl->Parallel(&slsDetector::setDetectorOffset, pos, + // value); } Result Detector::getQuad(Positions pos) const { @@ -253,6 +254,25 @@ void Detector::setReceiverPort(int value, Positions pos) { pimpl->Parallel(&slsDetector::setReceiverPort, pos, value); } +Result Detector::getLockServer(Positions pos) { + return pimpl->Parallel(&slsDetector::lockServer, pos, -1); +} + +void Detector::setLockServer(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::lockServer, pos, static_cast(value)); +} + +Result Detector::getLastClientIP(Positions pos) { + return pimpl->Parallel(&slsDetector::getLastClientIP, pos); +} + +void Detector::exitServer(Positions pos) { + pimpl->Parallel(&slsDetector::exitServer, pos); +} + +void Detector::execCommand(const std::string &value, Positions pos) { + pimpl->Parallel(&slsDetector::execCommand, pos, value); +} // Erik Result Detector::getFramesCaughtByReceiver(Positions pos) const { diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index 2b608b922..e79284da3 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -761,12 +761,12 @@ int slsDetector::getControlPort() const { return shm()->controlPort; } int slsDetector::getStopPort() const { return shm()->stopPort; } -int slsDetector::lockServer(int lock) { +bool slsDetector::lockServer(int lock) { int retval = -1; FILE_LOG(logDEBUG1) << "Setting detector server lock to " << lock; sendToDetector(F_LOCK_SERVER, lock, retval); FILE_LOG(logDEBUG1) << "Lock: " << retval; - return retval; + return (retval == 1 ? true : false); } std::string slsDetector::getLastClientIP() { From d1d730b779d0632d24055c3de103d81656ed0bde Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Thu, 8 Aug 2019 17:13:02 +0200 Subject: [PATCH 028/108] WIP --- slsDetectorSoftware/include/Detector.h | 66 +++++++++++++++++-- .../include/multiSlsDetector.h | 18 ++--- slsDetectorSoftware/src/Detector.cpp | 57 +++++++++++++++- 3 files changed, 124 insertions(+), 17 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 275469240..4f06d8f51 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -295,28 +295,32 @@ class Detector { void setReadNLines(const int value, Positions pos = {}); /** - * Get Detector Control TCP port (for client communication with Detector control server) + * Get Detector Control TCP port (for client communication with Detector + * control server) * @param pos detector position * @returns control TCP port */ Result getControlPort(Positions pos = {}) const; /** - * Set Detector Control TCP port (for client communication with Detector control server) + * Set Detector Control TCP port (for client communication with Detector + * control server) * @param value port number * @param pos detector position */ void setControlPort(int value, Positions pos = {}); /** - * Get Detector Stop TCP port (for client communication with Detector Stop server) + * Get Detector Stop TCP port (for client communication with Detector Stop + * server) * @param pos detector position * @returns Stop TCP port */ Result getStopPort(Positions pos = {}) const; /** - * Set Detector Stop TCP port (for client communication with Detector Stop server) + * Set Detector Stop TCP port (for client communication with Detector Stop + * server) * @param value port number * @param pos detector position */ @@ -336,7 +340,6 @@ class Detector { */ void setReceiverPort(int value, Positions pos = {}); - // Erik Result getFramesCaughtByReceiver(Positions pos = {}) const; @@ -563,7 +566,6 @@ class Detector { void copyDetectorServer(const std::string &fname, const std::string &hostname, Positions pos = {}); - /** [not Eiger] */ void resetFPGA(Positions pos = {}); @@ -578,7 +580,59 @@ class Detector { Result getStorageCellStart(Positions pos = {}) const; + /** [Jungfrau] 1 there was an temperature event */ + void setTemperatureEvent(int val, Positions pos = {}); + /** [Jungfrau] */ + Result getTemperatureEvent(Positions pos = {}) const; + + /** [Jungfrau] */ + void setTemperatureControl(bool enable, Positions pos = {}); + + /** [Jungfrau] */ + Result getTemperatureControl(Positions pos = {}) const; + + /** + * [Jungfrau]Set threshold temperature + * @param val value in millidegrees TODO! Verify + */ + void setThresholdTemperature(int temp, Positions pos = {}); + + Result getThresholdTemperature(Positions pos = {}) const; + + /** [Eiger] */ + void pulseChip(int n, Positions pos = {}); + + /** + * [Eiger] Pulse Pixel and move by a relative value + * @param n is number of times to pulse + * @param x is relative x value + * @param y is relative y value + */ + void pulsePixelNMove(int n, int x, int y, Positions pos = {}); + + /** + * [Eiger] Pulse Pixel + * @param n is number of times to pulse + * @param x is x coordinate + * @param y is y coordinate + * @param detPos -1 for all detectors in list or specific detector position + */ + void pulsePixel(int n, int x, int y, Positions pos = {}); + + /**[Eiger] Returns energies in eV where the module is trimmed */ + Result> getTrimEn(Positions pos = {}) const; + + /** [Eiger] Set the energies where the detector is trimmed */ + void setTrimEn(std::vector energies, Positions pos = {}); + + /** + * [Eiger] not 4 bit mode + * Fills in gap pixels in data + */ + void setGapPixelsEnable(bool enable, Positions pos = {}); + + Result getGapPixelEnable(Positions pos = {}) const; }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 945d15c6b..c3aedbb18 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -1601,7 +1601,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns number of trim energies */ - int setTrimEn(std::vector energies, int detPos = -1); + int setTrimEn(std::vector energies, int detPos = -1); // /** * Returns the number of trim energies and their value (Eiger) @@ -1609,7 +1609,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns vector of trim energies */ - std::vector getTrimEn(int detPos = -1); + std::vector getTrimEn(int detPos = -1); // /** * Pulse Pixel (Eiger) @@ -1618,7 +1618,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param y is y coordinate * @param detPos -1 for all detectors in list or specific detector position */ - void pulsePixel(int n = 0, int x = 0, int y = 0, int detPos = -1); + void pulsePixel(int n = 0, int x = 0, int y = 0, int detPos = -1); // /** * Pulse Pixel and move by a relative value (Eiger) @@ -1627,14 +1627,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param y is relative y value * @param detPos -1 for all detectors in list or specific detector position */ - void pulsePixelNMove(int n = 0, int x = 0, int y = 0, int detPos = -1); + void pulsePixelNMove(int n = 0, int x = 0, int y = 0, int detPos = -1);// /** * Pulse Chip (Eiger) * @param n is number of times to pulse * @param detPos -1 for all detectors in list or specific detector position */ - void pulseChip(int n = 0, int detPos = -1); + void pulseChip(int n = 0, int detPos = -1);// /** * Set/gets threshold temperature (Jungfrau) @@ -1642,7 +1642,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns threshold temperature in millidegrees */ - int setThresholdTemperature(int val = -1, int detPos = -1); + int setThresholdTemperature(int val = -1, int detPos = -1); // /** * Enables/disables temperature control (Jungfrau) @@ -1650,7 +1650,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns temperature control enable */ - int setTemperatureControl(int val = -1, int detPos = -1); + int setTemperatureControl(int val = -1, int detPos = -1); // /** * Resets/ gets over-temperature event (Jungfrau) @@ -1658,7 +1658,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns over-temperature event */ - int setTemperatureEvent(int val = -1, int detPos = -1); + int setTemperatureEvent(int val = -1, int detPos = -1); // /** * Set storage cell that stores first acquisition of the series (Jungfrau) @@ -1666,7 +1666,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the storage cell that stores the first acquisition of the series */ - int setStoragecellStart(int pos = -1, int detPos = -1); + int setStoragecellStart(int pos = -1, int detPos = -1);// /** * Programs FPGA with pof file (Not Eiger) diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 6e60ab8d5..3dab11eff 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -210,7 +210,8 @@ Result Detector::getDetectorOffsets(Positions pos) const { void Detector::setDetectorOffsets(defs::coordinates value, Positions pos) { pimpl->Parallel(&slsDetector::setDetectorOffsets, pos, value); - //pimpl->Parallel(&slsDetector::setDetectorOffset, pos, value); + // pimpl->Parallel(&slsDetector::setDetectorOffset, pos, + // value); } Result Detector::getQuad(Positions pos) const { @@ -253,7 +254,6 @@ void Detector::setReceiverPort(int value, Positions pos) { pimpl->Parallel(&slsDetector::setReceiverPort, pos, value); } - // Erik Result Detector::getFramesCaughtByReceiver(Positions pos) const { return pimpl->Parallel(&slsDetector::getFramesCaughtByReceiver, pos); @@ -508,4 +508,57 @@ Result Detector::getStorageCellStart(Positions pos) const { return pimpl->Parallel(&slsDetector::setStoragecellStart, pos, -1); } +void Detector::setTemperatureEvent(int val, Positions pos) { + pimpl->Parallel(&slsDetector::setTemperatureEvent, pos, val); +} + +Result Detector::getTemperatureEvent(Positions pos) const { + return pimpl->Parallel(&slsDetector::setTemperatureEvent, pos, -1); +} + +void Detector::setTemperatureControl(bool enable, Positions pos) { + pimpl->Parallel(&slsDetector::setTemperatureControl, pos, + static_cast(enable)); +} + +Result Detector::getTemperatureControl(Positions pos) const { + return pimpl->Parallel(&slsDetector::setTemperatureControl, pos, -1); +} + +void Detector::setThresholdTemperature(int temp, Positions pos) { + pimpl->Parallel(&slsDetector::setThresholdTemperature, pos, temp); +} + +Result Detector::getThresholdTemperature(Positions pos) const { + return pimpl->Parallel(&slsDetector::setThresholdTemperature, pos, -1); +} + +void Detector::pulseChip(int n, Positions pos){ + pimpl->Parallel(&slsDetector::pulseChip, pos, n); +} + +void Detector::pulsePixelNMove(int n, int x, int y, Positions pos){ + pimpl->Parallel(&slsDetector::pulsePixelNMove, pos, n, x, y); +} + +void Detector::pulsePixel(int n, int x, int y, Positions pos){ + pimpl->Parallel(&slsDetector::pulsePixel, pos, n, x, y); +} + +Result> Detector::getTrimEn(Positions pos) const{ + return pimpl->Parallel(&slsDetector::getTrimEn, pos); +} + +void Detector::setTrimEn(std::vector energies, Positions pos){ + pimpl->Parallel(&slsDetector::setTrimEn, pos, energies); +} + +void Detector::setGapPixelsEnable(bool enable, Positions pos){ + pimpl->Parallel(&slsDetector::enableGapPixels, pos, static_cast(enable)); +} + +Result Detector::getGapPixelEnable(Positions pos) const{ + return pimpl->Parallel(&slsDetector::enableGapPixels, pos, -1); +} + } // namespace sls \ No newline at end of file From c34190f9f2d633f6e63770b63f0fefd33da57c7e Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Thu, 8 Aug 2019 17:13:25 +0200 Subject: [PATCH 029/108] WIP --- slsDetectorSoftware/include/Detector.h | 77 +++++++++++++++++-- .../include/multiSlsDetector.h | 19 +++-- .../include/slsDetectorUsers.h | 3 +- slsDetectorSoftware/src/Detector.cpp | 40 +++++++++- slsDetectorSoftware/src/multiSlsDetector.cpp | 3 +- slsDetectorSoftware/src/slsDetectorUsers.cpp | 4 +- 6 files changed, 123 insertions(+), 23 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 09b4f8a69..106b5cbf9 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -345,7 +345,7 @@ class Detector { * @param pos detector position * @returns lock */ - Result getLockServer(Positions pos = {}); + Result getLockServer(Positions pos = {}) const; /** * Sets Lock for detector control server to this client IP @@ -359,7 +359,7 @@ class Detector { * @param pos detector position * @returns last client IP saved on detector server */ - Result getLastClientIP(Positions pos = {}); + Result getLastClientIP(Positions pos = {}) const; /** * Exit detector server @@ -374,6 +374,76 @@ class Detector { */ void execCommand(const std::string &value, Positions pos = {}); + /** + * Write current configuration to a file + * @param value configuration file name + */ + void writeConfigurationFile(const std::string &value); + + /** + * Get detector settings + * @param pos detector position + * @returns current settings + */ + Result getSettings(Positions pos = {}) const; + + /** + * Load detector settings from the settings file picked from the + * trimdir/settingsdir + * Eiger only stores in shared memory ( a get will + * overwrite this) For Eiger, one must use threshold + * @param value settings + * @param pos detector position + */ + void setSettings(defs::detectorSettings value, Positions pos = {}); + + /** + * Get threshold energy (Eiger) + * @param pos detector position + * @returns current threshold value for imod in ev (-1 failed) + */ + Result getThresholdEnergy(Positions pos = {}) const; + + /** + * Set threshold energy (Eiger) + * @param value threshold in eV + * @param sett ev. change settings + * @param tb 1 to include trimbits, 0 to exclude + * @param pos detector position + */ + void setThresholdEnergy(int value, defs::detectorSettings sett = defs::GET_SETTINGS, + int tb = 1, Positions pos = {}); + + /** + * Returns the detector trimbit/settings directory + * @param pos detector position + * @returns the trimbit/settings directory + */ + Result getSettingsDir(Positions pos = {}) const; + + /** + * Sets the detector trimbit/settings directory + * @param value trimbits/settings directory + * @param pos detector position + */ + void setSettingsDir(const std::string &value, Positions pos = {}); + + /** + * Loads the modules settings/trimbits reading from a specific file + * file name extension is automatically generated. + * @param value specific settings/trimbits file + * @param pos detector position + */ + void loadSettingsFile(const std::string &value, Positions pos = {}); + + /** + * Saves the modules settings/trimbits to a specific file + * file name extension is automatically generated. + * @param value specific settings/trimbits file + * @param pos detector position + */ + void saveSettingsFile(const std::string &value, Positions pos = {}); + // Erik Result getFramesCaughtByReceiver(Positions pos = {}) const; @@ -600,7 +670,6 @@ class Detector { void copyDetectorServer(const std::string &fname, const std::string &hostname, Positions pos = {}); - /** [not Eiger] */ void resetFPGA(Positions pos = {}); @@ -614,8 +683,6 @@ class Detector { void setStoragecellStart(int cell, Positions pos = {}); Result getStorageCellStart(Positions pos = {}) const; - - }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 20dce01e9..ddb3a5989 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -588,16 +588,15 @@ class multiSlsDetector : public virtual slsDetectorDefs { /** * Write current configuration to a file * @param fname configuration file name - * @returns OK or FAIL */ - int writeConfigurationFile(const std::string &fname); + void writeConfigurationFile(const std::string &fname);// /** * Get detector settings * @param detPos -1 for all detectors in list or specific detector position * @returns current settings */ - detectorSettings getSettings(int detPos = -1); + detectorSettings getSettings(int detPos = -1);// /** * Load detector settings from the settings file picked from the @@ -607,14 +606,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns current settings */ - detectorSettings setSettings(detectorSettings isettings, int detPos = -1); + detectorSettings setSettings(detectorSettings isettings, int detPos = -1);// /** * Get threshold energy (Eiger) * @param detPos -1 for all detectors in list or specific detector position * @returns current threshold value for imod in ev (-1 failed) */ - int getThresholdEnergy(int detPos = -1); + int getThresholdEnergy(int detPos = -1);// /** * Set threshold energy (Eiger) @@ -625,14 +624,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns current threshold value for imod in ev (-1 failed) */ int setThresholdEnergy(int e_eV, detectorSettings isettings = GET_SETTINGS, - int tb = 1, int detPos = -1); + int tb = 1, int detPos = -1);// /** * Returns the detector trimbit/settings directory * @param detPos -1 for all detectors in list or specific detector position * @returns the trimbit/settings directory */ - std::string getSettingsDir(int detPos = -1); + std::string getSettingsDir(int detPos = -1);// /** * Sets the detector trimbit/settings directory @@ -640,7 +639,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the trimbit/settings directory */ - std::string setSettingsDir(const std::string &directory, int detPos = -1); + std::string setSettingsDir(const std::string &directory, int detPos = -1);// /** * Loads the modules settings/trimbits reading from a specific file @@ -648,7 +647,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param fname specific settings/trimbits file * @param detPos -1 for all detectors in list or specific detector position */ - void loadSettingsFile(const std::string &fname, int detPos = -1); + void loadSettingsFile(const std::string &fname, int detPos = -1);// /** * Saves the modules settings/trimbits to a specific file @@ -656,7 +655,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param fname specific settings/trimbits file * @param detPos -1 for all detectors in list or specific detector position */ - void saveSettingsFile(const std::string &fname, int detPos = -1); + void saveSettingsFile(const std::string &fname, int detPos = -1);// /** * Get Detector run status diff --git a/slsDetectorSoftware/include/slsDetectorUsers.h b/slsDetectorSoftware/include/slsDetectorUsers.h index d05c0f96c..f3f5762d5 100755 --- a/slsDetectorSoftware/include/slsDetectorUsers.h +++ b/slsDetectorSoftware/include/slsDetectorUsers.h @@ -139,9 +139,8 @@ public: /** * Write current configuration to a file (for one time detector setup) * @param fname configuration file name - * @returns OK or FAIL */ - int writeConfigurationFile(const std::string& fname); + void writeConfigurationFile(const std::string& fname); /** * Loads the detector setup from file (current measurement setup) diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 9f66fe760..d945692a0 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -254,7 +254,7 @@ void Detector::setReceiverPort(int value, Positions pos) { pimpl->Parallel(&slsDetector::setReceiverPort, pos, value); } -Result Detector::getLockServer(Positions pos) { +Result Detector::getLockServer(Positions pos) const { return pimpl->Parallel(&slsDetector::lockServer, pos, -1); } @@ -262,7 +262,7 @@ void Detector::setLockServer(bool value, Positions pos) { pimpl->Parallel(&slsDetector::lockServer, pos, static_cast(value)); } -Result Detector::getLastClientIP(Positions pos) { +Result Detector::getLastClientIP(Positions pos) const { return pimpl->Parallel(&slsDetector::getLastClientIP, pos); } @@ -274,6 +274,42 @@ void Detector::execCommand(const std::string &value, Positions pos) { pimpl->Parallel(&slsDetector::execCommand, pos, value); } +void Detector::writeConfigurationFile(const std::string &value) { + pimpl->writeConfigurationFile(value); +} + +Result Detector::getSettings(Positions pos) const { + return pimpl->Parallel(&slsDetector::getSettings, pos); +} + +void Detector::setSettings(defs::detectorSettings value, Positions pos) { + pimpl->Parallel(&slsDetector::setSettings, pos, value); +} + +Result Detector::getThresholdEnergy(Positions pos) const { + return pimpl->Parallel(&slsDetector::getThresholdEnergy, pos); +} + +void Detector::setThresholdEnergy(int value, defs::detectorSettings sett, int tb, Positions pos) { + pimpl->Parallel(&slsDetector::setThresholdEnergy, pos, value, sett, tb); +} + +Result Detector::getSettingsDir(Positions pos) const { + return pimpl->Parallel(&slsDetector::getSettingsDir, pos); +} + +void Detector::setSettingsDir(const std::string &value, Positions pos) { + pimpl->Parallel(&slsDetector::setSettingsDir, pos, value); +} + +void Detector::loadSettingsFile(const std::string &value, Positions pos) { + pimpl->Parallel(&slsDetector::loadSettingsFile, pos, value); +} + +void Detector::saveSettingsFile(const std::string &value, Positions pos) { + pimpl->Parallel(&slsDetector::saveSettingsFile, pos, value); +} + // Erik Result Detector::getFramesCaughtByReceiver(Positions pos) const { return pimpl->Parallel(&slsDetector::getFramesCaughtByReceiver, pos); diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index cf772606f..14e54848b 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -880,7 +880,7 @@ void multiSlsDetector::readConfigurationFile(const std::string &fname) { input_file.close(); } -int multiSlsDetector::writeConfigurationFile(const std::string &fname) { +void multiSlsDetector::writeConfigurationFile(const std::string &fname) { // TODO! make exception safe! const std::vector header{"detsizechan", "hostname"}; std::ofstream outfile; @@ -901,7 +901,6 @@ int multiSlsDetector::writeConfigurationFile(const std::string &fname) { throw RuntimeError("Could not open configuration file " + fname + " for writing"); } - return OK; } slsDetectorDefs::detectorSettings multiSlsDetector::getSettings(int detPos) { diff --git a/slsDetectorSoftware/src/slsDetectorUsers.cpp b/slsDetectorSoftware/src/slsDetectorUsers.cpp index 5aa1aeabe..16499ad27 100755 --- a/slsDetectorSoftware/src/slsDetectorUsers.cpp +++ b/slsDetectorSoftware/src/slsDetectorUsers.cpp @@ -40,8 +40,8 @@ int slsDetectorUsers::readConfigurationFile(const std::string& fname){ } } -int slsDetectorUsers::writeConfigurationFile(const std::string& fname){ - return detector.writeConfigurationFile(fname); +void slsDetectorUsers::writeConfigurationFile(const std::string& fname){ + detector.writeConfigurationFile(fname); } int slsDetectorUsers::retrieveDetectorSetup(const std::string& fname){ From cc0f1d9fcd628e7c0d0568f4243feb2745958653 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Thu, 8 Aug 2019 17:34:25 +0200 Subject: [PATCH 030/108] WIP --- slsDetectorSoftware/include/Detector.h | 23 +++++++--- .../include/multiSlsDetector.h | 8 ++-- slsDetectorSoftware/src/Detector.cpp | 42 +++++++++++++++---- 3 files changed, 55 insertions(+), 18 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 0d9053c02..47fff64f5 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -411,7 +411,8 @@ class Detector { * @param tb 1 to include trimbits, 0 to exclude * @param pos detector position */ - void setThresholdEnergy(int value, defs::detectorSettings sett = defs::GET_SETTINGS, + void setThresholdEnergy(int value, + defs::detectorSettings sett = defs::GET_SETTINGS, int tb = 1, Positions pos = {}); /** @@ -707,7 +708,7 @@ class Detector { /** [Eiger] */ void pulseChip(int n, Positions pos = {}); - /** + /** * [Eiger] Pulse Pixel and move by a relative value * @param n is number of times to pulse * @param x is relative x value @@ -730,13 +731,25 @@ class Detector { /** [Eiger] Set the energies where the detector is trimmed */ void setTrimEn(std::vector energies, Positions pos = {}); - /** - * [Eiger] not 4 bit mode + /** + * [Eiger] not 4 bit mode * Fills in gap pixels in data - */ + */ void setGapPixelsEnable(bool enable, Positions pos = {}); Result getGapPixelEnable(Positions pos = {}) const; + + /**[Eiger] */ + void setAllTrimbits(int value, Positions pos = {}); + + /** [Eiger] TODO! only Eiger? */ + void setFlippedData(defs::dimension d, bool flipped, Positions pos = {}); + + Result getFlippedData(defs::dimension d, Positions pos = {}) const; + + void setRxPadDeactivatedMod(bool pad, Positions pos = {}); + + Result getRxPadDeactivatedMod(Positions pos = {}) const; }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 11eb78113..ae04851fc 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -1564,7 +1564,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns 1 for flipped, else 0 */ - int getFlippedData(dimension d = X, int detPos = -1); + int getFlippedData(dimension d = X, int detPos = -1); // /** * Sets the enable which determines if @@ -1574,7 +1574,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns enable flipped data across x or y axis */ - int setFlippedData(dimension d = X, int value = -1, int detPos = -1); + int setFlippedData(dimension d = X, int value = -1, int detPos = -1); // /** * Sets all the trimbits to a particular value (Eiger) @@ -1582,7 +1582,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns OK or FAIL */ - int setAllTrimbits(int val, int detPos = -1); + int setAllTrimbits(int val, int detPos = -1); // /** * Enable gap pixels, only for Eiger and for 8,16 and 32 bit mode. (Eiger) @@ -1590,7 +1590,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param val 1 sets, 0 unsets, -1 gets * @returns gap pixel enable or -1 for error */ - int enableGapPixels(int val = -1, int detPos = -1); + int enableGapPixels(int val = -1, int detPos = -1); // /** * Sets the number of trim energies and their value (Eiger) diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 17652bedd..26fdfb559 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -290,7 +290,8 @@ Result Detector::getThresholdEnergy(Positions pos) const { return pimpl->Parallel(&slsDetector::getThresholdEnergy, pos); } -void Detector::setThresholdEnergy(int value, defs::detectorSettings sett, int tb, Positions pos) { +void Detector::setThresholdEnergy(int value, defs::detectorSettings sett, + int tb, Positions pos) { pimpl->Parallel(&slsDetector::setThresholdEnergy, pos, value, sett, tb); } @@ -589,32 +590,55 @@ Result Detector::getThresholdTemperature(Positions pos) const { return pimpl->Parallel(&slsDetector::setThresholdTemperature, pos, -1); } -void Detector::pulseChip(int n, Positions pos){ +void Detector::pulseChip(int n, Positions pos) { pimpl->Parallel(&slsDetector::pulseChip, pos, n); } -void Detector::pulsePixelNMove(int n, int x, int y, Positions pos){ +void Detector::pulsePixelNMove(int n, int x, int y, Positions pos) { pimpl->Parallel(&slsDetector::pulsePixelNMove, pos, n, x, y); } -void Detector::pulsePixel(int n, int x, int y, Positions pos){ +void Detector::pulsePixel(int n, int x, int y, Positions pos) { pimpl->Parallel(&slsDetector::pulsePixel, pos, n, x, y); } -Result> Detector::getTrimEn(Positions pos) const{ +Result> Detector::getTrimEn(Positions pos) const { return pimpl->Parallel(&slsDetector::getTrimEn, pos); } -void Detector::setTrimEn(std::vector energies, Positions pos){ +void Detector::setTrimEn(std::vector energies, Positions pos) { pimpl->Parallel(&slsDetector::setTrimEn, pos, energies); } -void Detector::setGapPixelsEnable(bool enable, Positions pos){ - pimpl->Parallel(&slsDetector::enableGapPixels, pos, static_cast(enable)); +void Detector::setGapPixelsEnable(bool enable, Positions pos) { + pimpl->Parallel(&slsDetector::enableGapPixels, pos, + static_cast(enable)); } -Result Detector::getGapPixelEnable(Positions pos) const{ +Result Detector::getGapPixelEnable(Positions pos) const { return pimpl->Parallel(&slsDetector::enableGapPixels, pos, -1); } +void Detector::setAllTrimbits(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setAllTrimbits, pos, value); +} + +void Detector::setFlippedData(defs::dimension d, bool flipped, Positions pos) { + pimpl->Parallel(&slsDetector::setFlippedData, pos, d, + static_cast(flipped)); +} + +Result Detector::getFlippedData(defs::dimension d, Positions pos) const { + return pimpl->Parallel(&slsDetector::getFlippedData, pos, d); +} + +void Detector::setRxPadDeactivatedMod(bool pad, Positions pos) { + pimpl->Parallel(&slsDetector::setDeactivatedRxrPaddingMode, pos, + static_cast(pad)); +} + +Result Detector::getRxPadDeactivatedMod(Positions pos) const { + return pimpl->Parallel(&slsDetector::setDeactivatedRxrPaddingMode, pos, -1); +} + } // namespace sls \ No newline at end of file From e76900ca9ae5330e73371b62287942fc2c6d70d7 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Thu, 8 Aug 2019 17:40:35 +0200 Subject: [PATCH 031/108] WIP --- slsDetectorSoftware/include/Detector.h | 13 +++++++++++++ slsDetectorSoftware/src/Detector.cpp | 8 ++++++++ 2 files changed, 21 insertions(+) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 47fff64f5..88ced96ad 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -747,9 +747,22 @@ class Detector { Result getFlippedData(defs::dimension d, Positions pos = {}) const; + /** + * [Eiger] Set deactivated Receiver padding mode + * @param padding padding option for deactivated receiver. Can be true + * (padding), false (no padding) + */ void setRxPadDeactivatedMod(bool pad, Positions pos = {}); Result getRxPadDeactivatedMod(Positions pos = {}) const; + + /** + * [Eiger] Activates/Deactivates the detector + * @param true = active or false inactive + */ + void setActive(bool active, Positions pos = {}); + + Result getActive(Positions pos = {}) const; }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 26fdfb559..cd8316918 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -641,4 +641,12 @@ Result Detector::getRxPadDeactivatedMod(Positions pos) const { return pimpl->Parallel(&slsDetector::setDeactivatedRxrPaddingMode, pos, -1); } +void Detector::setActive(bool active, Positions pos){ + pimpl->Parallel(&slsDetector::activate, pos, static_cast(active)); +} + +Result Detector::getActive(Positions pos) const{ + pimpl->Parallel(&slsDetector::activate, pos, -1); +} + } // namespace sls \ No newline at end of file From 6080e90bbbd390bb2e526707f16cde2bd34f50fc Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Thu, 8 Aug 2019 18:08:33 +0200 Subject: [PATCH 032/108] WIP --- slsDetectorSoftware/include/Detector.h | 56 +++++++++++++++++++++++++- slsDetectorSoftware/src/Detector.cpp | 47 ++++++++++++++++++++- 2 files changed, 99 insertions(+), 4 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 106b5cbf9..4a5572a24 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -193,7 +193,7 @@ class Detector { * Get Detector type as an enum * @returns detector type */ - defs::detectorType getDetectorTypeAsEnum() const; + defs::detectorType getDetectorType() const; /** * Get Detector type as an enum @@ -411,7 +411,8 @@ class Detector { * @param tb 1 to include trimbits, 0 to exclude * @param pos detector position */ - void setThresholdEnergy(int value, defs::detectorSettings sett = defs::GET_SETTINGS, + void setThresholdEnergy(int value, + defs::detectorSettings sett = defs::GET_SETTINGS, int tb = 1, Positions pos = {}); /** @@ -444,6 +445,57 @@ class Detector { */ void saveSettingsFile(const std::string &value, Positions pos = {}); + /** + * Get Detector run status + * @param pos detector position + * @returns status + */ + Result getRunStatus(Positions pos = {}); + + /** + * Prepares detector for acquisition (Eiger) + */ + void prepareAcquisition(); + + /** + * Start detector acquisition (Non blocking) + */ + void startAcquisition(); + + /** + * Stop detector acquisition + */ + void stopAcquisition(); + + /** + * Give an internal software trigger to the detector (Eiger only) + * @param pos detector position + */ + void sendSoftwareTrigger(Positions pos = {}); + + /** + * Start detector acquisition and read all data (Blocking until end of + * acquisition) + */ + void startAndReadAll(); + + /** + * Start readout (without exposure or interrupting exposure) (Eiger store in + * ram) + */ + void startReadOut(); + + /** + * Requests and receives all data from the detector (Eiger store in ram) + */ + void readAll(); + + /** + * Configures in detector the destination for UDP packets + * @param pos detector position + */ + void configureMAC(Positions pos = {}); + // Erik Result getFramesCaughtByReceiver(Positions pos = {}) const; diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index d945692a0..e42cb1028 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -157,7 +157,7 @@ void Detector::setHostname(const std::vector &value) { pimpl->setHostname(value); } -defs::detectorType Detector::getDetectorTypeAsEnum() const { +defs::detectorType Detector::getDetectorType() const { return pimpl->getDetectorTypeAsEnum(); } @@ -290,7 +290,8 @@ Result Detector::getThresholdEnergy(Positions pos) const { return pimpl->Parallel(&slsDetector::getThresholdEnergy, pos); } -void Detector::setThresholdEnergy(int value, defs::detectorSettings sett, int tb, Positions pos) { +void Detector::setThresholdEnergy(int value, defs::detectorSettings sett, + int tb, Positions pos) { pimpl->Parallel(&slsDetector::setThresholdEnergy, pos, value, sett, tb); } @@ -310,6 +311,48 @@ void Detector::saveSettingsFile(const std::string &value, Positions pos) { pimpl->Parallel(&slsDetector::saveSettingsFile, pos, value); } +Result Detector::getRunStatus(Positions pos) { + return pimpl->Parallel(&slsDetector::getRunStatus, pos); +} + +void Detector::prepareAcquisition() { + pimpl->Parallel(&slsDetector::prepareAcquisition, {}); +} + +void Detector::startAcquisition() { + if (getDetectorType() == defs::EIGER) { + prepareAcquisition(); + } + pimpl->Parallel(&slsDetector::startAcquisition, {}); +} + +void Detector::stopAcquisition() { + pimpl->Parallel(&slsDetector::stopAcquisition, {}); +} + +void Detector::sendSoftwareTrigger(Positions pos) { + pimpl->Parallel(&slsDetector::sendSoftwareTrigger, pos); +} + +void Detector::startAndReadAll() { + if (getDetectorType() == defs::EIGER) { + prepareAcquisition(); + } + pimpl->Parallel(&slsDetector::startAndReadAll, {}); +} + +void Detector::startReadOut() { + pimpl->Parallel(&slsDetector::startReadOut, {}); +} + +void Detector::readAll() { + pimpl->Parallel(&slsDetector::readAll, {}); +} + +void Detector::configureMAC(Positions pos) { + pimpl->Parallel(&slsDetector::configureMAC, pos); +} + // Erik Result Detector::getFramesCaughtByReceiver(Positions pos) const { return pimpl->Parallel(&slsDetector::getFramesCaughtByReceiver, pos); From 0bd6563e4515d550efb84ed9c16509bc28a1d32b Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Thu, 8 Aug 2019 18:09:38 +0200 Subject: [PATCH 033/108] WIP --- slsDetectorSoftware/include/multiSlsDetector.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index ae04851fc..9826b9477 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -662,51 +662,51 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns status */ - runStatus getRunStatus(int detPos = -1); + runStatus getRunStatus(int detPos = -1);// /** * Prepares detector for acquisition (Eiger) * @param detPos -1 for all detectors in list or specific detector position */ - void prepareAcquisition(int detPos = -1); + void prepareAcquisition(int detPos = -1);// /** * Start detector acquisition (Non blocking) * @param detPos -1 for all detectors in list or specific detector position */ - void startAcquisition(int detPos = -1); + void startAcquisition(int detPos = -1);// /** * Stop detector acquisition * @param detPos -1 for all detectors in list or specific detector position */ - void stopAcquisition(int detPos = -1); + void stopAcquisition(int detPos = -1);// /** * Give an internal software trigger to the detector (Eiger only) * @param detPos -1 for all detectors in list or specific detector position */ - void sendSoftwareTrigger(int detPos = -1); + void sendSoftwareTrigger(int detPos = -1);// /** * Start detector acquisition and read all data (Blocking until end of * acquisition) * @param detPos -1 for all detectors in list or specific detector position */ - void startAndReadAll(int detPos = -1); + void startAndReadAll(int detPos = -1);// /** * Start readout (without exposure or interrupting exposure) (Eiger store in * ram) * @param detPos -1 for all detectors in list or specific detector position */ - void startReadOut(int detPos = -1); + void startReadOut(int detPos = -1);// /** * Requests and receives all data from the detector (Eiger store in ram) * @param detPos -1 for all detectors in list or specific detector position */ - void readAll(int detPos = -1); + void readAll(int detPos = -1);// /** * Configures in detector the destination for UDP packets From 5292075a0acfbf0f4aeab1974b4bd17a5aa41fad Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Fri, 9 Aug 2019 09:35:02 +0200 Subject: [PATCH 034/108] WIP --- slsDetectorSoftware/include/Detector.h | 27 +++++++++++++ .../include/multiSlsDetector.h | 16 ++++---- slsDetectorSoftware/src/Detector.cpp | 38 ++++++++++++++++++- 3 files changed, 72 insertions(+), 9 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 732e3ee7a..d5e8919eb 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -814,6 +814,33 @@ class Detector { void setActive(bool active, Positions pos = {}); Result getActive(Positions pos = {}) const; + + /** [Gotthard][Jungfrau][CTB] not possible to read back*/ + void writeAdcRegister(uint32_t addr, uint32_t value, Positions pos = {}); + + /** [CTB] How much digital data in bytes is skipped */ + Result getReceiverDbitOffset(Positions pos = {}) const; + + /** [CTB] Set how many bytes of digital data to skip */ + void setReceiverDbitOffset(int value, Positions pos = {}); + + /** [CTB] Which of the bits 0-63 to save*/ + Result> getReceiverDbitList(Positions pos = {}) const; + + /** [CTB] Which of the bits 0-63 to save*/ + void setReceiverDbitList(std::vector list, Positions pos = {}); + + /** [CTB] */ + Result getExternalSampling(Positions pos = {}) const; + + /** [CTB] */ + void setExternalSampling(bool value, Positions pos = {}); + + /** [CTB] */ + Result getExternalSamplingSource(Positions pos = {}) const; + + /** [CTB] Value between 0-63 */ + void setExternalSamplingSource(int value, Positions pos = {}); }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 9826b9477..33cd3778b 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -1494,42 +1494,42 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param value external sampling source (Option: 0-63) * @param detPos -1 for all detectors in list or specific detector position */ - void setExternalSampling(bool value, int detPos = -1); + void setExternalSampling(bool value, int detPos = -1); // /** * Get external sampling source (CTB only) * @param detPos -1 for all detectors in list or specific detector position * @returns external sampling enable */ - int getExternalSampling(int detPos = -1); + int getExternalSampling(int detPos = -1); // /** * Set external sampling enable (CTB only) * @param list external sampling source (Option: 0-63) * @param detPos -1 for all detectors in list or specific detector position */ - void setReceiverDbitList(std::vector list, int detPos = -1); + void setReceiverDbitList(std::vector list, int detPos = -1); // /** * Get external sampling source (CTB only) * @param detPos -1 for all detectors in list or specific detector position * @returns external sampling enable */ - std::vector getReceiverDbitList(int detPos = -1); + std::vector getReceiverDbitList(int detPos = -1); // /** * Set digital data offset in bytes (CTB only) * @param value digital data offset in bytes * @param detPos -1 for all detectors in list or specific detector position */ - void setReceiverDbitOffset(int value, int detPos = -1); + void setReceiverDbitOffset(int value, int detPos = -1); // /** * Get digital data offset in bytes (CTB only) * @param detPos -1 for all detectors in list or specific detector position * @returns digital data offset in bytes */ - int getReceiverDbitOffset(int detPos = -1); + int getReceiverDbitOffset(int detPos = -1); // /** * Write to ADC register (Gotthard, Jungfrau, ChipTestBoard). For expert @@ -1538,7 +1538,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param val value * @param detPos -1 for all detectors in list or specific detector position */ - void writeAdcRegister(uint32_t addr, uint32_t val, int detPos = -1); + void writeAdcRegister(uint32_t addr, uint32_t val, int detPos = -1); // /** * Activates/Deactivates the detector (Eiger only) @@ -1546,7 +1546,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns 0 (inactive) or 1 (active)for activate mode */ - int activate(int const enable = -1, int detPos = -1); + int activate(int const enable = -1, int detPos = -1); // /** * Set deactivated Receiver padding mode (Eiger only) diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index c1736160e..1598c9c4c 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -688,7 +688,43 @@ void Detector::setActive(bool active, Positions pos){ } Result Detector::getActive(Positions pos) const{ - pimpl->Parallel(&slsDetector::activate, pos, -1); + return pimpl->Parallel(&slsDetector::activate, pos, -1); +} + +void Detector::writeAdcRegister(uint32_t addr, uint32_t value, Positions pos){ + pimpl->Parallel(&slsDetector::writeAdcRegister, pos, addr, value); +} + +Result Detector::getReceiverDbitOffset(Positions pos) const{ + return pimpl->Parallel(&slsDetector::getReceiverDbitOffset, pos); +} + +void Detector::setReceiverDbitOffset(int value, Positions pos){ + pimpl->Parallel(&slsDetector::setReceiverDbitOffset, pos, value); +} + +Result> Detector::getReceiverDbitList(Positions pos) const{ + return pimpl->Parallel(&slsDetector::getReceiverDbitList, pos); +} + +void Detector::setReceiverDbitList(std::vector list, Positions pos){ + pimpl->Parallel(&slsDetector::setReceiverDbitList, pos, list); +} + +Result Detector::getExternalSampling(Positions pos) const{ + return pimpl->Parallel(&slsDetector::getExternalSampling, pos); +} + +void Detector::setExternalSampling(bool value, Positions pos){ + pimpl->Parallel(&slsDetector::setExternalSampling, pos, value); +} + +Result Detector::getExternalSamplingSource(Positions pos) const{ + return pimpl->Parallel(&slsDetector::getExternalSamplingSource, pos); +} + +void Detector::setExternalSamplingSource(int value, Positions pos){ + pimpl->Parallel(&slsDetector::setExternalSamplingSource, pos, value); } } // namespace sls \ No newline at end of file From dfbf7ab39a2195f416a0299a3a5f4e28a02acf31 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Fri, 9 Aug 2019 11:00:12 +0200 Subject: [PATCH 035/108] tsquash --- slsDetectorSoftware/include/Result.h | 10 ++++- .../include/multiSlsDetector.h | 6 ++- slsDetectorSoftware/src/Detector.cpp | 40 ++++++++++--------- slsDetectorSoftware/src/multiSlsDetector.cpp | 10 +++++ slsDetectorSoftware/tests/test-Result.cpp | 11 +++++ slsSupportLib/include/sls_detector_defs.h | 12 ++++++ 6 files changed, 69 insertions(+), 20 deletions(-) diff --git a/slsDetectorSoftware/include/Result.h b/slsDetectorSoftware/include/Result.h index 33ce0c04a..9127ddfc1 100644 --- a/slsDetectorSoftware/include/Result.h +++ b/slsDetectorSoftware/include/Result.h @@ -105,11 +105,19 @@ template > class Result { */ T squash() const { return Squash(vec); } + T tsquash(const std::string &error_msg) { + if (equal()) + return vec.front(); + else + throw RuntimeError(error_msg); + } /** * If all elements are equal return the front value, otherwise * return the supplied default value */ - T squash(T default_value) const { return Squash(vec, default_value); } + T squash(const T &default_value) const { + return Squash(vec, default_value); + } /** Test whether all elements of the result are equal */ bool equal() const noexcept { return allEqual(vec); } diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 33cd3778b..fca6716e9 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -1487,7 +1487,9 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns external sampling source */ - int getExternalSamplingSource(int detPos = -1); + int getExternalSamplingSource(int detPos = -1); // + + /** * Set external sampling enable (CTB only) @@ -1592,6 +1594,8 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ int enableGapPixels(int val = -1, int detPos = -1); // + + void setGapPixelsEnable(bool enable, sls::Positions pos = {}); /** * Sets the number of trim energies and their value (Eiger) * diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 1598c9c4c..64e76d565 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -345,9 +345,7 @@ void Detector::startReadOut() { pimpl->Parallel(&slsDetector::startReadOut, {}); } -void Detector::readAll() { - pimpl->Parallel(&slsDetector::readAll, {}); -} +void Detector::readAll() { pimpl->Parallel(&slsDetector::readAll, {}); } void Detector::configureMAC(Positions pos) { pimpl->Parallel(&slsDetector::configureMAC, pos); @@ -565,7 +563,14 @@ Result Detector::getAutoCompDisable(Positions pos) const { } void Detector::setPowerChip(bool on, Positions pos) { - pimpl->Parallel(&slsDetector::powerChip, pos, static_cast(on)); + if (on && pimpl->getNumberOfDetectors() > 3) { + for (int i = 0; i != pimpl->getNumberOfDetectors(); ++i) { + pimpl->powerChip(static_cast(on), i); + usleep(1000 * 1000); + } + } else { + pimpl->Parallel(&slsDetector::powerChip, pos, static_cast(on)); + } } Result Detector::getPowerChip(Positions pos) const { @@ -653,8 +658,7 @@ void Detector::setTrimEn(std::vector energies, Positions pos) { } void Detector::setGapPixelsEnable(bool enable, Positions pos) { - pimpl->Parallel(&slsDetector::enableGapPixels, pos, - static_cast(enable)); + pimpl->setGapPixelsEnable(enable, pos); } Result Detector::getGapPixelEnable(Positions pos) const { @@ -683,47 +687,47 @@ Result Detector::getRxPadDeactivatedMod(Positions pos) const { return pimpl->Parallel(&slsDetector::setDeactivatedRxrPaddingMode, pos, -1); } -void Detector::setActive(bool active, Positions pos){ +void Detector::setActive(bool active, Positions pos) { pimpl->Parallel(&slsDetector::activate, pos, static_cast(active)); } -Result Detector::getActive(Positions pos) const{ +Result Detector::getActive(Positions pos) const { return pimpl->Parallel(&slsDetector::activate, pos, -1); } -void Detector::writeAdcRegister(uint32_t addr, uint32_t value, Positions pos){ +void Detector::writeAdcRegister(uint32_t addr, uint32_t value, Positions pos) { pimpl->Parallel(&slsDetector::writeAdcRegister, pos, addr, value); } -Result Detector::getReceiverDbitOffset(Positions pos) const{ +Result Detector::getReceiverDbitOffset(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverDbitOffset, pos); } -void Detector::setReceiverDbitOffset(int value, Positions pos){ +void Detector::setReceiverDbitOffset(int value, Positions pos) { pimpl->Parallel(&slsDetector::setReceiverDbitOffset, pos, value); } -Result> Detector::getReceiverDbitList(Positions pos) const{ +Result> Detector::getReceiverDbitList(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverDbitList, pos); } -void Detector::setReceiverDbitList(std::vector list, Positions pos){ +void Detector::setReceiverDbitList(std::vector list, Positions pos) { pimpl->Parallel(&slsDetector::setReceiverDbitList, pos, list); } -Result Detector::getExternalSampling(Positions pos) const{ +Result Detector::getExternalSampling(Positions pos) const { return pimpl->Parallel(&slsDetector::getExternalSampling, pos); } -void Detector::setExternalSampling(bool value, Positions pos){ +void Detector::setExternalSampling(bool value, Positions pos) { pimpl->Parallel(&slsDetector::setExternalSampling, pos, value); } -Result Detector::getExternalSamplingSource(Positions pos) const{ +Result Detector::getExternalSamplingSource(Positions pos) const { return pimpl->Parallel(&slsDetector::getExternalSamplingSource, pos); } - -void Detector::setExternalSamplingSource(int value, Positions pos){ + +void Detector::setExternalSamplingSource(int value, Positions pos) { pimpl->Parallel(&slsDetector::setExternalSamplingSource, pos, value); } diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index 14e54848b..9288cc168 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -2747,6 +2747,16 @@ int multiSlsDetector::enableGapPixels(int val, int detPos) { return ret; } +void multiSlsDetector::setGapPixelsEnable(bool enable, Positions pos){ + Parallel(&slsDetector::enableGapPixels, pos, static_cast(enable)); + + // update data bytes incl gap pixels + auto r2 = serialCall(&slsDetector::getDataBytesInclGapPixels); + multi_shm()->dataBytesInclGapPixels = sls::sum(r2); + updateOffsets(); + +} + int multiSlsDetector::setTrimEn(std::vector energies, int detPos) { if (detPos >= 0) { return detectors[detPos]->setTrimEn(energies); diff --git a/slsDetectorSoftware/tests/test-Result.cpp b/slsDetectorSoftware/tests/test-Result.cpp index 73e3878df..88fb762bc 100644 --- a/slsDetectorSoftware/tests/test-Result.cpp +++ b/slsDetectorSoftware/tests/test-Result.cpp @@ -2,6 +2,7 @@ #include "catch.hpp" #include +#include using sls::Result; @@ -73,3 +74,13 @@ TEST_CASE("equal", "[n2]"){ res.push_back(1.3); REQUIRE(res.equal() == false); } + +TEST_CASE("throws for tsquash", "[n2]"){ + Result res{1,2,3}; + REQUIRE_THROWS(res.tsquash("something is wrong")); +} + +TEST_CASE("", "[n2]"){ + Result res{"hej", "hej", "hej"}; + REQUIRE(res.squash() == "hej"); +} \ No newline at end of file diff --git a/slsSupportLib/include/sls_detector_defs.h b/slsSupportLib/include/sls_detector_defs.h index ec3d5022f..d94ba4401 100755 --- a/slsSupportLib/include/sls_detector_defs.h +++ b/slsSupportLib/include/sls_detector_defs.h @@ -68,6 +68,8 @@ // typedef char mystring[MAX_STR_LENGTH]; + + #ifdef __cplusplus class slsDetectorDefs { public: @@ -1300,3 +1302,13 @@ typedef struct { #else } sls_detector_module; #endif + + +#ifdef __cplusplus +//TODO! discuss this +#include //hmm... but currently no way around +namespace sls{ +using Positions = const std::vector &; +using defs = slsDetectorDefs; +} +#endif \ No newline at end of file From 5a483eaf29961017818f7ac45fef313883909651 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Fri, 9 Aug 2019 11:11:29 +0200 Subject: [PATCH 036/108] WIP, new eiger serveR --- .../bin/eigerDetectorServer_developer | Bin 302608 -> 302608 bytes .../slsDetectorServer_funcs.c | 1 - slsDetectorSoftware/include/Detector.h | 110 +++++++++++++++++- .../include/multiSlsDetector.h | 35 ++---- slsDetectorSoftware/include/slsDetector.h | 8 +- .../include/slsDetectorUsers.h | 10 +- slsDetectorSoftware/src/Detector.cpp | 84 +++++++++++-- slsDetectorSoftware/src/multiSlsDetector.cpp | 68 ++++------- slsDetectorSoftware/src/slsDetector.cpp | 1 - .../src/slsDetectorCommand.cpp | 18 +-- slsDetectorSoftware/src/slsDetectorUsers.cpp | 4 - slsSupportLib/include/sls_detector_defs.h | 7 +- slsSupportLib/include/versionAPI.h | 2 +- 13 files changed, 230 insertions(+), 118 deletions(-) diff --git a/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer b/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer index eaf92f6b2e697771bcd0d3e5262b5ba82392f865..c054a083a3a560132f2fd493ca3c5565a4ada65c 100755 GIT binary patch delta 37453 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 getNumberOfFrames() const; + + /** + * Set number of Frames + * @param value number of Frames + */ + void setNumberOfFrames(int64_t value); + + /** + * Get number of Cycles + * @returns number of Cycles + */ + Result getNumberOfCycles() const; + + /** + * Set number of Cycles + * @param value number of Cycles + */ + void setNumberOfCycles(int64_t value); + + /** + * Get number of additional storage cells (Jungfrau) + * @returns number of additional storage cells + */ + Result getNumberOfStorageCells() const; + + /** + * Set number of additional storage cells (Jungfrau) + * @param value number of additional storage cells + */ + void setNumberOfStorageCells(int64_t value); + + /** + * Get number of analog samples (CTB) + * @param pos detector position + * @returns number of analog samples + */ + Result getNumberOfAnalogSamples(Positions pos = {}) const; + + /** + * Set number of analog samples (CTB) + * @param value number of analog samples (CTB) + * @param pos detector position + */ + void setNumberOfAnalogSamples(int64_t value, Positions pos = {}); + + /** + * Get number of digital samples (CTB) + * @param pos detector position + * @returns number of digital samples + */ + Result getNumberOfDigitalSamples(Positions pos = {}) const; + + /** + * Set number of digital samples (CTB) + * @param value number of digital samples (CTB) + * @param pos detector position + */ + void setNumberOfDigitalSamples(int64_t value, Positions pos = {}); + + /** + * Get delay after trigger in ns(Gotthard, Jungfrau) + * @param pos detector position + * @returns delay after trigger in ns + */ + Result getDelayAfterTrigger(Positions pos = {}) const; + + /** + * Set delay after trigger (Gotthard, Jungfrau) + * @param value delay after trigger in ns + * @param pos detector position + */ + void setDelayAfterTrigger(ns value, Positions pos = {}); + + /** + * Get sub frame dead time in ns (Eiger in 32 bit mode) + * @param pos detector position + * @returns delay after trigger in ns + */ + Result getSubFrameDeadTime(Positions pos = {}) const; + + /** + * Set sub frame dead time after trigger (Eiger in 32 bit mode) + * @param value delay after trigger in ns + * @param pos detector position + */ + void setSubFrameDeadTime(ns value, Positions pos = {}); + + /** + * Get storage cell delay (Jungfrau) + * @param pos detector position + * @returns storage cell delay in ns. Range: (0-1638375 ns (resolution of + * 25ns) + */ + Result getStorageCellDelay(Positions pos = {}) const; + + /** + * Set storage cell delay (Jungfrau) + * @param value storage cell delay in ns. Range: (0-1638375 ns (resolution + * of 25ns) + * @param pos detector position + */ + void setStorageCellDelay(ns value, Positions pos = {}); + // Erik Result getFramesCaughtByReceiver(Positions pos = {}) const; diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 9826b9477..69695075c 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -15,7 +15,7 @@ class detectorData; #include #include -#define MULTI_SHMAPIVERSION 0x190807 +#define MULTI_SHMAPIVERSION 0x190809 #define MULTI_SHMVERSION 0x190807 #define SHORT_STRING_LENGTH 50 #define DATE_LENGTH 30 @@ -84,9 +84,6 @@ struct sharedMultiSlsDetector { * one dimension */ int maxNumberOfChannelsPerDetector[2]; - /** timer values */ - int64_t timerValue[slsDetectorDefs::timerIndex::MAX_TIMERS]; - /** flag for acquiring */ bool acquiringFlag; @@ -712,7 +709,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * Configures in detector the destination for UDP packets * @param detPos -1 for all detectors in list or specific detector position */ - void configureMAC(int detPos = -1); + void configureMAC(int detPos = -1); // /** * Set starting frame number for the next acquisition @@ -731,12 +728,12 @@ class multiSlsDetector : public virtual slsDetectorDefs { /** * Set/get timer value (not all implemented for all detectors) * @param index timer index - * @param t time in ns or number of...(e.g. frames, gates, probes) + * @param t time in ns or number of...(e.g. frames, probes) * @param detPos -1 for all detectors in list or specific detector position - * @returns timer set value in ns or number of...(e.g. frames, gates, + * @returns timer set value in ns or number of...(e.g. frames, * probes) */ - int64_t setTimer(timerIndex index, int64_t t = -1, int detPos = -1); + int64_t setTimer(timerIndex index, int64_t t = -1, int detPos = -1); // /** * Set/get exposure time @@ -766,7 +763,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns delay after trigger in ns, or s if specified */ double setDelayAfterTrigger(double t = -1, bool inseconds = false, - int detPos = -1); + int detPos = -1);// /** * (Advanced users) @@ -788,7 +785,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns sub frame dead time in ns, or s if specified */ double setSubFrameExposureDeadTime(double t = -1, bool inseconds = false, - int detPos = -1); + int detPos = -1);// /** * Set/get number of frames @@ -796,7 +793,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns number of frames */ - int64_t setNumberOfFrames(int64_t t = -1, int detPos = -1); + int64_t setNumberOfFrames(int64_t t = -1, int detPos = -1);// /** * Set/get number of cycles @@ -804,15 +801,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns number of cycles */ - int64_t setNumberOfCycles(int64_t t = -1, int detPos = -1); - - /** - * Set/get number of gates (none of the detectors at the moment) - * @param t number of gates (-1 gets) - * @param detPos -1 for all detectors in list or specific detector position - * @returns number of gates - */ - int64_t setNumberOfGates(int64_t t = -1, int detPos = -1); + int64_t setNumberOfCycles(int64_t t = -1, int detPos = -1);// /** * Set/get number of additional storage cells (Jungfrau) @@ -820,7 +809,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns number of additional storage cells */ - int64_t setNumberOfStorageCells(int64_t t = -1, int detPos = -1); + int64_t setNumberOfStorageCells(int64_t t = -1, int detPos = -1);// /** * Get measured period between previous two frames (EIGER) @@ -844,9 +833,9 @@ class multiSlsDetector : public virtual slsDetectorDefs { * Set/get timer value left in acquisition (not all implemented for all * detectors) * @param index timer index - * @param t time in ns or number of...(e.g. frames, gates, probes) + * @param t time in ns or number of...(e.g. frames, probes) * @param detPos -1 for all detectors in list or specific detector position - * @returns timer set value in ns or number of...(e.g. frames, gates, + * @returns timer set value in ns or number of...(e.g. frames, * probes) */ int64_t getTimeLeft(timerIndex index, int detPos = -1); diff --git a/slsDetectorSoftware/include/slsDetector.h b/slsDetectorSoftware/include/slsDetector.h index 516f43eab..9a270306a 100755 --- a/slsDetectorSoftware/include/slsDetector.h +++ b/slsDetectorSoftware/include/slsDetector.h @@ -658,8 +658,8 @@ class slsDetector : public virtual slsDetectorDefs { /** * Set/get timer value (not all implemented for all detectors) * @param index timer index - * @param t time in ns or number of...(e.g. frames, gates, probes) - * @returns timer set value in ns or number of...(e.g. frames, gates, + * @param t time in ns or number of...(e.g. frames, probes) + * @returns timer set value in ns or number of...(e.g. frames, * probes) */ int64_t setTimer(timerIndex index, int64_t t = -1); @@ -668,8 +668,8 @@ class slsDetector : public virtual slsDetectorDefs { * Set/get timer value left in acquisition (not all implemented for all * detectors) * @param index timer index - * @param t time in ns or number of...(e.g. frames, gates, probes) - * @returns timer set value in ns or number of...(e.g. frames, gates, + * @param t time in ns or number of...(e.g. frames, probes) + * @returns timer set value in ns or number of...(e.g. frames, * probes) */ int64_t getTimeLeft(timerIndex index) const; diff --git a/slsDetectorSoftware/include/slsDetectorUsers.h b/slsDetectorSoftware/include/slsDetectorUsers.h index f3f5762d5..1b93f9445 100755 --- a/slsDetectorSoftware/include/slsDetectorUsers.h +++ b/slsDetectorSoftware/include/slsDetectorUsers.h @@ -358,14 +358,6 @@ public: */ int64_t setNumberOfCycles(int64_t t = -1, int detPos = -1); - /** - * Set/get number of gates (none of the detectors at the moment) - * @param t number of gates (-1 gets) - * @param detPos -1 for all detectors in list or specific detector position - * @returns number of gates - */ - int64_t setNumberOfGates(int64_t t = -1, int detPos = -1); - /** * Set/get number of additional storage cells (Jungfrau) * @param t number of additional storage cells. Default is 0. (-1 gets) @@ -396,7 +388,7 @@ public: * Set/get timing mode * @param pol timing mode (-1 gets) * Options (slsDetectorDefs::externalCommunicationMode) - * (Eiger: AUTO_TIMING, TRIGGER_EXPOSURE, BURST_TRIGGER, GATE_FIX_NUMBER) + * (Eiger: AUTO_TIMING, TRIGGER_EXPOSURE, BURST_TRIGGER, GATED) * (Jungfrau: AUTO_TIMING, TRIGGER_EXPOSURE) * (Gotthard: AUTO_TIMING, TRIGGER_EXPOSURE) * @param detPos -1 for all detectors in list or specific detector position diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index c1736160e..ddf4797f7 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -326,9 +326,7 @@ void Detector::startAcquisition() { pimpl->Parallel(&slsDetector::startAcquisition, {}); } -void Detector::stopAcquisition() { - pimpl->Parallel(&slsDetector::stopAcquisition, {}); -} +void Detector::stopAcquisition() { pimpl->stopAcquisition(); } void Detector::sendSoftwareTrigger(Positions pos) { pimpl->Parallel(&slsDetector::sendSoftwareTrigger, pos); @@ -345,14 +343,82 @@ void Detector::startReadOut() { pimpl->Parallel(&slsDetector::startReadOut, {}); } -void Detector::readAll() { - pimpl->Parallel(&slsDetector::readAll, {}); -} +void Detector::readAll() { pimpl->Parallel(&slsDetector::readAll, {}); } void Detector::configureMAC(Positions pos) { pimpl->Parallel(&slsDetector::configureMAC, pos); } +Result Detector::getNumberOfFrames() const { + return pimpl->Parallel(&slsDetector::setTimer, {}, defs::FRAME_NUMBER, -1); +} + +void Detector::setNumberOfFrames(int64_t value) { + pimpl->Parallel(&slsDetector::setTimer, {}, defs::FRAME_NUMBER, value); +} + +Result Detector::getNumberOfCycles() const { + return pimpl->Parallel(&slsDetector::setTimer, {}, defs::CYCLES_NUMBER, -1); +} + +void Detector::setNumberOfCycles(int64_t value) { + pimpl->Parallel(&slsDetector::setTimer, {}, defs::CYCLES_NUMBER, value); +} + +Result Detector::getNumberOfStorageCells() const { + return pimpl->Parallel(&slsDetector::setTimer, {}, defs::STORAGE_CELL_NUMBER, -1); +} + +void Detector::setNumberOfStorageCells(int64_t value) { + pimpl->Parallel(&slsDetector::setTimer, {}, defs::STORAGE_CELL_NUMBER, value); +} + +Result Detector::getNumberOfAnalogSamples(Positions pos) const { + return pimpl->Parallel(&slsDetector::setTimer, pos, defs::ANALOG_SAMPLES, -1); +} + +void Detector::setNumberOfAnalogSamples(int64_t value, Positions pos) { + pimpl->Parallel(&slsDetector::setTimer, pos, defs::ANALOG_SAMPLES, value); +} + +Result Detector::getNumberOfDigitalSamples(Positions pos) const { + return pimpl->Parallel(&slsDetector::setTimer, pos, defs::DIGITAL_SAMPLES, -1); +} + +void Detector::setNumberOfDigitalSamples(int64_t value, Positions pos) { + pimpl->Parallel(&slsDetector::setTimer, pos, defs::DIGITAL_SAMPLES, value); +} + +Result Detector::getDelayAfterTrigger(Positions pos) const { + return pimpl->Parallel(&slsDetector::setTimer, pos, + defs::DELAY_AFTER_TRIGGER, -1); +} + +void Detector::setDelayAfterTrigger(ns value, Positions pos) { + pimpl->Parallel(&slsDetector::setTimer, pos, defs::DELAY_AFTER_TRIGGER, + value.count()); +} + +Result Detector::getSubFrameDeadTime(Positions pos) const { + return pimpl->Parallel(&slsDetector::setTimer, pos, defs::SUBFRAME_DEADTIME, + -1); +} + +void Detector::setSubFrameDeadTime(ns value, Positions pos) { + pimpl->Parallel(&slsDetector::setTimer, pos, defs::SUBFRAME_DEADTIME, + value.count()); +} + +Result Detector::getStorageCellDelay(Positions pos) const { + return pimpl->Parallel(&slsDetector::setTimer, pos, + defs::STORAGE_CELL_DELAY, -1); +} + +void Detector::setStorageCellDelay(ns value, Positions pos) { + pimpl->Parallel(&slsDetector::setTimer, pos, defs::STORAGE_CELL_DELAY, + value.count()); +} + // Erik Result Detector::getFramesCaughtByReceiver(Positions pos) const { return pimpl->Parallel(&slsDetector::getFramesCaughtByReceiver, pos); @@ -683,12 +749,12 @@ Result Detector::getRxPadDeactivatedMod(Positions pos) const { return pimpl->Parallel(&slsDetector::setDeactivatedRxrPaddingMode, pos, -1); } -void Detector::setActive(bool active, Positions pos){ +void Detector::setActive(bool active, Positions pos) { pimpl->Parallel(&slsDetector::activate, pos, static_cast(active)); } -Result Detector::getActive(Positions pos) const{ - pimpl->Parallel(&slsDetector::activate, pos, -1); +Result Detector::getActive(Positions pos) const { + return pimpl->Parallel(&slsDetector::activate, pos, -1); } } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index 14e54848b..ca9221a06 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -287,10 +287,6 @@ void multiSlsDetector::initializeDetectorStructure() { multi_shm()->numberOfChannelInclGapPixels[Y] = 0; multi_shm()->maxNumberOfChannelsPerDetector[X] = 0; multi_shm()->maxNumberOfChannelsPerDetector[Y] = 0; - for (int64_t &i : multi_shm()->timerValue) { - i = 0; - } - multi_shm()->acquiringFlag = false; multi_shm()->receiver_upstream = false; } @@ -1144,41 +1140,12 @@ uint64_t multiSlsDetector::getStartingFrameNumber(int detPos) { int64_t multiSlsDetector::setTimer(timerIndex index, int64_t t, int detPos) { // single if (detPos >= 0) { - // error for setting values individually - // FIXME: what else? and error code - if (t != -1) { - switch (index) { - case FRAME_NUMBER: - case CYCLES_NUMBER: - case STORAGE_CELL_NUMBER: - throw RuntimeError("Cannot set number of frames, cycles or " - "storage cells individually."); - default: - break; - } - } return detectors[detPos]->setTimer(index, t); } // multi auto r = parallelCall(&slsDetector::setTimer, index, t); - int64_t ret = sls::minusOneIfDifferent(r); - - // set progress - if (t != -1) { - switch (index) { - case FRAME_NUMBER: - case CYCLES_NUMBER: - case STORAGE_CELL_NUMBER: - setTotalProgress(); - break; - default: - break; - } - } - - multi_shm()->timerValue[index] = ret; - return ret; + return sls::minusOneIfDifferent(r); } int64_t multiSlsDetector::secondsToNanoSeconds(double t) { @@ -1239,10 +1206,6 @@ int64_t multiSlsDetector::setNumberOfCycles(int64_t t, int detPos) { return setTimer(CYCLES_NUMBER, t, detPos); } -int64_t multiSlsDetector::setNumberOfGates(int64_t t, int detPos) { - return setTimer(GATES_NUMBER, t, detPos); -} - int64_t multiSlsDetector::setNumberOfStorageCells(int64_t t, int detPos) { return setTimer(STORAGE_CELL_NUMBER, t, detPos); } @@ -4189,16 +4152,28 @@ void multiSlsDetector::registerDataCallback( int multiSlsDetector::setTotalProgress() { int nf = 1, nc = 1, ns = 1; - if (multi_shm()->timerValue[FRAME_NUMBER] != 0) { - nf = multi_shm()->timerValue[FRAME_NUMBER]; + Result temp = Parallel(&slsDetector::setTimer, {}, FRAME_NUMBER, -1); + if (!temp.equal()) { + throw RuntimeError("Inconsistent number of frames"); + } + nf = temp.squash(); + + temp = Parallel(&slsDetector::setTimer, {}, CYCLES_NUMBER, -1); + if (!temp.equal()) { + throw RuntimeError("Inconsistent number of cycles"); + } + nc = temp.squash(); + + if (getDetectorTypeAsEnum() == JUNGFRAU) { + temp = Parallel(&slsDetector::setTimer, {}, STORAGE_CELL_NUMBER, -1); + if (!temp.equal()) { + throw RuntimeError("Inconsistent number of additional storage cells"); + } + ns = temp.squash() + 1; } - if (multi_shm()->timerValue[CYCLES_NUMBER] > 0) { - nc = multi_shm()->timerValue[CYCLES_NUMBER]; - } - - if (multi_shm()->timerValue[STORAGE_CELL_NUMBER] > 0) { - ns = multi_shm()->timerValue[STORAGE_CELL_NUMBER] + 1; + if (nf == 0 || nc == 0) { + throw RuntimeError("Number of frames or cycles is 0"); } totalProgress = nf * nc * ns; @@ -4259,6 +4234,7 @@ int multiSlsDetector::acquire() { stopReceiver(); } } + setTotalProgress(); startProcessingThread(); diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index e79284da3..0f23a319a 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -325,7 +325,6 @@ void slsDetector::initializeDetectorStructure(detectorType type) { shm()->timerValue[ACQUISITION_TIME] = 0; shm()->timerValue[FRAME_PERIOD] = 0; shm()->timerValue[DELAY_AFTER_TRIGGER] = 0; - shm()->timerValue[GATES_NUMBER] = 0; shm()->timerValue[CYCLES_NUMBER] = 1; shm()->timerValue[ACTUAL_TIME] = 0; shm()->timerValue[MEASUREMENT_TIME] = 0; diff --git a/slsDetectorSoftware/src/slsDetectorCommand.cpp b/slsDetectorSoftware/src/slsDetectorCommand.cpp index 4f1153667..112fe18ed 100755 --- a/slsDetectorSoftware/src/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp @@ -378,9 +378,8 @@ slsDetectorCommand::slsDetectorCommand(multiSlsDetector *det) { ++i; /*! \page config - - extsig [flag] sets/gets the mode of the external signal. Options: \c off, \c gate_in_active_high, \c gate_in_active_low, \c trigger_in_rising_edge, \c trigger_in_falling_edge, - \c ro_trigger_in_rising_edge, \c ro_trigger_in_falling_edge, \c gate_out_active_high, \c gate_out_active_low, \c trigger_out_rising_edge, \c trigger_out_falling_edge, \c ro_trigger_out_rising_edge, - \c ro_trigger_out_falling_edge. \n Used in GOTTHARDonly. \c Returns \c (string) + - extsig [flag] sets/gets the mode of the external signal. Options: \c off, \c trigger_in_rising_edge, \c trigger_in_falling_edge, + \c trigger_out_rising_edge, \c trigger_out_falling_edge\n Used in GOTTHARDonly. \c Returns \c (string) */ descrToFuncMap[i].m_pFuncName = "extsig"; /* find command! */ descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdAdvanced; @@ -577,13 +576,6 @@ slsDetectorCommand::slsDetectorCommand(multiSlsDetector *det) { descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdTimer; ++i; - /*! \page timing - - gates [i] sets/gets number of gates. Used in GOTTHARD only. \c Returns \c (long long int) - */ - descrToFuncMap[i].m_pFuncName = "gates"; - descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdTimer; - ++i; - /*! \page timing - frames [i] sets/gets number of frames. If \c timing is not \c auto, then it is the number of frames per cycle/trigger. \c Returns \c (long long int) */ @@ -4333,8 +4325,6 @@ std::string slsDetectorCommand::cmdTimer(int narg, const char * const args[], in index = SUBFRAME_DEADTIME; else if (cmd == "delay") index = DELAY_AFTER_TRIGGER; - else if (cmd == "gates") - index = GATES_NUMBER; else if (cmd == "frames") index = FRAME_NUMBER; else if (cmd == "cycles") @@ -4825,7 +4815,7 @@ std::string slsDetectorCommand::helpAdvanced(int action) { std::ostringstream os; if (action == PUT_ACTION || action == HELP_ACTION) { - os << "extsig mode \t sets the mode of the external signal. can be \n \t \t \t off, \n \t \t \t gate_in_active_high, \n \t \t \t gate_in_active_low, \n \t \t \t trigger_in_rising_edge, \n \t \t \t trigger_in_falling_edge, \n \t \t \t ro_trigger_in_rising_edge, \n \t \t \t ro_trigger_in_falling_edge, \n \t \t \t gate_out_active_high, \n \t \t \t gate_out_active_low, \n \t \t \t trigger_out_rising_edge, \n \t \t \t trigger_out_falling_edge, \n \t \t \t ro_trigger_out_rising_edge, \n \t \t \t ro_trigger_out_falling_edge" << std::endl; + os << "extsig mode \t sets the mode of the external signal. can be \n \t \t \t off, \n \t \t \t trigger_in_rising_edge, \n \t \t \t trigger_in_falling_edge, \n \t \t \t trigger_out_rising_edge, \n \t \t \t trigger_out_falling_edge" << std::endl; os << "flags mode \t sets the readout flags to mode. can be none, storeinram, tot, continous, parallel, nonparallel, digital, analog_digital, overlow, nooverflow, unknown." << std::endl; os << "interruptsubframe flag \t sets the interrupt subframe flag. Setting it to 1 will interrupt the last subframe at the required exposure time. By default, this is disabled and set to 0, ie. it will wait for the last sub frame to finish exposing. Used for EIGER in 32 bit mode only." << std::endl; os << "readnlines f \t sets the number of rows to read out per half module. Options: 1 - 256 (Not all values as it depends on dynamic range and 10GbE enabled). Used for EIGER only. " << std::endl; @@ -4841,7 +4831,7 @@ std::string slsDetectorCommand::helpAdvanced(int action) { } if (action == GET_ACTION || action == HELP_ACTION) { - os << "extsig \t gets the mode of the external signal. can be \n \t \t \t off, \n \t \t \t gate_in_active_high, \n \t \t \t gate_in_active_low, \n \t \t \t trigger_in_rising_edge, \n \t \t \t trigger_in_falling_edge, \n \t \t \t ro_trigger_in_rising_edge, \n \t \t \t ro_trigger_in_falling_edge, \n \t \t \t gate_out_active_high, \n \t \t \t gate_out_active_low, \n \t \t \t trigger_out_rising_edge, \n \t \t \t trigger_out_falling_edge, \n \t \t \t ro_trigger_out_rising_edge, \n \t \t \t ro_trigger_out_falling_edge" << std::endl; + os << "extsig \t gets the mode of the external signal. can be \n \t \t \t off, \n \t \t \t trigger_in_rising_edge, \n \t \t \t trigger_in_falling_edge, \n \t \t \t trigger_out_rising_edge, \n \t \t \t trigger_out_falling_edge" << std::endl; os << "flags \t gets the readout flags. can be none, storeinram, tot, continous, parallel, nonparallel, digital, analog_digital, overflow, nooverflow, unknown" << std::endl; os << "interruptsubframe \t gets the interrupt subframe flag. Setting it to 1 will interrupt the last subframe at the required exposure time. By default, this is disabled and set to 0, ie. it will wait for the last sub frame to finish exposing. Used for EIGER in 32 bit mode only." << std::endl; os << "readnlines \t gets the number of rows to read out per half module. Used for EIGER only. " << std::endl; diff --git a/slsDetectorSoftware/src/slsDetectorUsers.cpp b/slsDetectorSoftware/src/slsDetectorUsers.cpp index 16499ad27..36f115d37 100755 --- a/slsDetectorSoftware/src/slsDetectorUsers.cpp +++ b/slsDetectorSoftware/src/slsDetectorUsers.cpp @@ -159,10 +159,6 @@ int64_t slsDetectorUsers::setNumberOfCycles(int64_t t, int detPos){ return detector.setNumberOfCycles(t, detPos); } -int64_t slsDetectorUsers::setNumberOfGates(int64_t t, int detPos){ - return detector.setNumberOfGates(t, detPos); -} - int64_t slsDetectorUsers::setNumberOfStorageCells(int64_t t, int detPos) { return detector.setNumberOfStorageCells(t, detPos); } diff --git a/slsSupportLib/include/sls_detector_defs.h b/slsSupportLib/include/sls_detector_defs.h index ec3d5022f..673e32715 100755 --- a/slsSupportLib/include/sls_detector_defs.h +++ b/slsSupportLib/include/sls_detector_defs.h @@ -106,7 +106,6 @@ class slsDetectorDefs { FRAME_PERIOD, /**< period between exposures */ DELAY_AFTER_TRIGGER, /**< delay between trigger and start of exposure or readout (in triggered mode) */ - GATES_NUMBER, /**< number of gates per frame (in gated mode) */ CYCLES_NUMBER, /**< number of cycles: total number of acquisitions is number or frames*number of cycles */ ACTUAL_TIME, /**< Actual time of the detector's internal timer */ @@ -918,12 +917,12 @@ format /** returns std::string from timer index \param s can be FRAME_NUMBER,ACQUISITION_TIME,FRAME_PERIOD, - DELAY_AFTER_TRIGGER,GATES_NUMBER, CYCLES_NUMBER, + DELAY_AFTER_TRIGGER, CYCLES_NUMBER, ACTUAL_TIME,MEASUREMENT_TIME, PROGRESS,FRAMES_FROM_START,FRAMES_FROM_START_PG,ANALOG_SAMPLES,DIGITAL_SAMPLES,SUBFRAME_ACQUISITION_TIME,STORAGE_CELL_NUMBER, SUBFRAME_DEADTIME \returns std::string frame_number,acquisition_time,frame_period, - delay_after_trigger,gates_number, cycles_number, + delay_after_trigger, cycles_number, actual_time,measurement_time, progress,frames_from_start,frames_from_start_pg,analog_samples, digital_samples,subframe_acquisition_time,storage_cell_number, SUBFRAME_DEADTIME @@ -938,8 +937,6 @@ format return std::string("frame_period"); case DELAY_AFTER_TRIGGER: return std::string("delay_after_trigger"); - case GATES_NUMBER: - return std::string("gates_number"); case CYCLES_NUMBER: return std::string("cycles_number"); case ACTUAL_TIME: diff --git a/slsSupportLib/include/versionAPI.h b/slsSupportLib/include/versionAPI.h index 25e8a6332..d95e414ac 100644 --- a/slsSupportLib/include/versionAPI.h +++ b/slsSupportLib/include/versionAPI.h @@ -7,4 +7,4 @@ #define APIRECEIVER 0x190722 #define APIGUI 0x190723 #define APIJUNGFRAU 0x190730 -#define APIEIGER 0x190806 +#define APIEIGER 0x190807 From fc78bb9384a1c9377cb8aa729be7b558934ee88e Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Fri, 9 Aug 2019 11:40:57 +0200 Subject: [PATCH 037/108] Parallel returns Result --- sample/useResult.cpp | 2 +- slsDetectorSoftware/include/Detector.h | 17 ++++++++++++++++- slsDetectorSoftware/include/Result.h | 8 +++++--- .../include/multiSlsDetector.h | 19 ++++++++++--------- slsDetectorSoftware/src/Detector.cpp | 18 ++++++++++++++++++ 5 files changed, 50 insertions(+), 14 deletions(-) diff --git a/sample/useResult.cpp b/sample/useResult.cpp index 08de0b04f..cf7cf89c7 100644 --- a/sample/useResult.cpp +++ b/sample/useResult.cpp @@ -40,7 +40,7 @@ auto main() -> int { std::cout << "res.squash(-1): " << res.squash(-1) << '\n'; std::cout << "res3.squash(-1): " << res3.squash(-1) << '\n'; - std::vector ivec{1, 3, 5}; + Result ivec{1, 3, 5}; Result nres(ivec); // for (const auto& i : ivec) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index d5e8919eb..8bab640d8 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -495,7 +495,7 @@ class Detector { * @param pos detector position */ void configureMAC(Positions pos = {}); - + // Erik Result getFramesCaughtByReceiver(Positions pos = {}) const; @@ -841,6 +841,21 @@ class Detector { /** [CTB] Value between 0-63 */ void setExternalSamplingSource(int value, Positions pos = {}); + + /** [CTB] */ + uint32_t getADCInvert() const; + + /** [CTB]*/ + void setADCInvert(uint32_t value); + + /** [CTB]*/ + uint32_t getADCEnableMask(int detPos = -1); + + /** [CTB]*/ + void setADCEnableMask(uint32_t mask); + + /** [CTB]*/ + uint32_t getADCEnableMask() const; }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/include/Result.h b/slsDetectorSoftware/include/Result.h index 9127ddfc1..193b37db6 100644 --- a/slsDetectorSoftware/include/Result.h +++ b/slsDetectorSoftware/include/Result.h @@ -31,12 +31,13 @@ template > class Result { Result() = default; Result(std::initializer_list list) : vec(list){}; + /** Custom constructor from integer type to Result or Result */ template ::value && (std::is_same::value || std::is_same::value)>::type> - Result(const std::vector &from) { + Result(const Result &from) { vec.reserve(from.size()); for (const auto &item : from) vec.push_back(T(item)); @@ -47,7 +48,7 @@ template > class Result { std::is_integral::value && (std::is_same::value || std::is_same::value)>::type> - Result(std::vector &from) { + Result(Result &from) { vec.reserve(from.size()); for (const auto &item : from) vec.push_back(T(item)); @@ -58,7 +59,7 @@ template > class Result { std::is_integral::value && (std::is_same::value || std::is_same::value)>::type> - Result(std::vector &&from) { + Result(Result &&from) { vec.reserve(from.size()); for (const auto &item : from) vec.push_back(T(item)); @@ -90,6 +91,7 @@ template > class Result { auto empty() const noexcept -> decltype(vec.empty()) { return vec.empty(); } auto front() -> decltype(vec.front()) { return vec.front(); } auto front() const -> decltype(vec.front()) { return vec.front(); } + void reserve(size_type new_cap) { vec.reserve(new_cap); } template auto push_back(V value) -> decltype(vec.push_back(value)) { diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index fca6716e9..15bdd6824 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -3,6 +3,7 @@ #include "SharedMemory.h" #include "logger.h" #include "sls_detector_defs.h" +#include "Result.h" class slsDetector; class ZmqSocket; @@ -113,7 +114,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { template struct NonDeduced { using type = CT; }; template - std::vector Parallel(RT (slsDetector::*somefunc)(CT...), + sls::Result Parallel(RT (slsDetector::*somefunc)(CT...), std::vector positions, typename NonDeduced::type... Args) { @@ -130,7 +131,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { futures.push_back(std::async(std::launch::async, somefunc, detectors[i].get(), Args...)); } - std::vector result; + sls::Result result; result.reserve(positions.size()); for (auto &i : futures) { result.push_back(i.get()); @@ -139,7 +140,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { } template - std::vector Parallel(RT (slsDetector::*somefunc)(CT...) const, + sls::Result Parallel(RT (slsDetector::*somefunc)(CT...) const, std::vector positions, typename NonDeduced::type... Args) const { @@ -156,7 +157,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { futures.push_back(std::async(std::launch::async, somefunc, detectors[i].get(), Args...)); } - std::vector result; + sls::Result result; result.reserve(positions.size()); for (auto &i : futures) { result.push_back(i.get()); @@ -1452,35 +1453,35 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param mask ADC Enable mask * @param detPos -1 for all detectors in list or specific detector position */ - void setADCEnableMask(uint32_t mask, int detPos = -1); + void setADCEnableMask(uint32_t mask, int detPos = -1); // /** * Get ADC Enable Mask (CTB, Moench) * @param detPos -1 for all detectors in list or specific detector position * @returns ADC Enable mask */ - uint32_t getADCEnableMask(int detPos = -1); + uint32_t getADCEnableMask(int detPos = -1); // /** * Set ADC invert register (CTB, Moench) * @param value ADC invert value * @param detPos -1 for all detectors in list or specific detector position */ - void setADCInvert(uint32_t value, int detPos = -1); + void setADCInvert(uint32_t value, int detPos = -1); // /** * Get ADC invert register (CTB, Moench) * @param detPos -1 for all detectors in list or specific detector position * @returns ADC invert value */ - uint32_t getADCInvert(int detPos = -1); + uint32_t getADCInvert(int detPos = -1); // /** * Set external sampling source (CTB only) * @param value external sampling source (Option: 0-63) * @param detPos -1 for all detectors in list or specific detector position */ - void setExternalSamplingSource(int value, int detPos = -1); + void setExternalSamplingSource(int value, int detPos = -1); // /** * Get external sampling source (CTB only) diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 64e76d565..5ab26a845 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -731,4 +731,22 @@ void Detector::setExternalSamplingSource(int value, Positions pos) { pimpl->Parallel(&slsDetector::setExternalSamplingSource, pos, value); } +uint32_t Detector::getADCInvert() const { + auto res = pimpl->Parallel(&slsDetector::getADCInvert, {}); + return res.tsquash("Different Values for function getADCInvert"); +} + +void Detector::setADCInvert(uint32_t value) { + pimpl->Parallel(&slsDetector::setADCInvert, {}, value); +} + +uint32_t Detector::getADCEnableMask() const { + return pimpl->Parallel(&slsDetector::getADCEnableMask, {}) + .tsquash("Values of ADC enable mask cannot be different"); +} + +void Detector::setADCEnableMask(uint32_t mask) { + pimpl->Parallel(&slsDetector::setADCEnableMask, {}, mask); +} + } // namespace sls \ No newline at end of file From bdfdd5dbdae89a9f1e8458bfb07e8ca991096f95 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Fri, 9 Aug 2019 11:55:27 +0200 Subject: [PATCH 038/108] WIP --- slsDetectorSoftware/include/Detector.h | 126 ++++++++++++++++-- .../include/multiSlsDetector.h | 6 +- slsDetectorSoftware/src/Detector.cpp | 112 +++++++++++----- 3 files changed, 195 insertions(+), 49 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 403fc8671..09f68284d 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -115,14 +115,6 @@ class Detector { Result getFileOverWrite(Positions pos = {}) const; void setFileOverWrite(bool value, Positions pos = {}); - // Time - Result getExptime(Positions pos = {}) const; - void setExptime(ns t, Positions pos = {}); - Result getSubExptime(Positions pos = {}) const; - void setSubExptime(ns t, Positions pos = {}); - Result getPeriod(Positions pos = {}) const; - void setPeriod(ns t, Positions pos = {}); - // dhanya /** * Get multidetector Id @@ -560,6 +552,33 @@ class Detector { */ void setNumberOfDigitalSamples(int64_t value, Positions pos = {}); + /** + * Get exposure time in ns + * @param pos detector position + * @returns exposure time in ns + */ + Result getExptime(Positions pos = {}) const; + + /** + * Set exposure time in ns + * @param value exposure time in ns + * @param pos detector position + */ + void setExptime(ns t, Positions pos = {}); + + /** + * Get period in ns + * @param pos detector position + * @returns period in ns + */ + Result getPeriod(Positions pos = {}) const; + + /** + * Set period in ns + * @param value period in ns + * @param pos detector position + */ + void setPeriod(ns t, Positions pos = {}); /** * Get delay after trigger in ns(Gotthard, Jungfrau) * @param pos detector position @@ -574,19 +593,32 @@ class Detector { */ void setDelayAfterTrigger(ns value, Positions pos = {}); + /** + * Get sub frame exposure time in ns (Eiger in 32 bit mode) + * @param pos detector position + * @returns sub frame exposure time in ns + */ + Result getSubExptime(Positions pos = {}) const; + + /** + * Set sub frame exposure time after trigger (Eiger in 32 bit mode) + * @param value sub frame exposure time in ns + * @param pos detector position + */ + void setSubExptime(ns t, Positions pos = {}); /** * Get sub frame dead time in ns (Eiger in 32 bit mode) * @param pos detector position - * @returns delay after trigger in ns + * @returns sub frame dead time in ns */ - Result getSubFrameDeadTime(Positions pos = {}) const; + Result getSubDeadTime(Positions pos = {}) const; /** * Set sub frame dead time after trigger (Eiger in 32 bit mode) - * @param value delay after trigger in ns + * @param value sub frame dead time in ns * @param pos detector position */ - void setSubFrameDeadTime(ns value, Positions pos = {}); + void setSubDeadTime(ns value, Positions pos = {}); /** * Get storage cell delay (Jungfrau) @@ -604,6 +636,76 @@ class Detector { */ void setStorageCellDelay(ns value, Positions pos = {}); + /** + * Get number of Frames left (Gotthard, Jungfrau, CTB) + * @param pos detector position + * @returns number of Frames left + */ + Result getNumberOfFramesLeft(Positions pos = {}) const; + + /** + * Get number of Cycles left (Gotthard, Jungfrau, CTB) + * @param pos detector position + * @returns number of Cycles left + */ + Result getNumberOfCyclesLeft(Positions pos = {}) const; + /** + * Get exposure time left in ns (Gotthard) + * @param pos detector position + * @returns exposure time left in ns + */ + Result getExptimeLeft(Positions pos = {}) const; + + /** + * Get period left in ns (Gotthard, Jungfrau, CTB) + * @param pos detector position + * @returns period left in ns + */ + Result getPeriodLeft(Positions pos = {}) const; + + /** + * Get delay after trigger left in ns(Gotthard, Jungfrau, CTB) + * @param pos detector position + * @returns delay after trigger left in ns + */ + Result getDelayAfterTriggerLeft(Positions pos = {}) const; + + /** + * Get number of frames from start up of detector (Jungfrau, CTB) + * @param pos detector position + * @returns number of frames from start up of detector + */ + Result getNumberOfFramesFromStart(Positions pos = {}) const; + + /** + * Get time from detector start in ns (Jungfrau, CTB) + * @param pos detector position + * @returns time from detector start in ns + */ + Result getActualTime(Positions pos = {}) const; + + /** + * Get timestamp at a frame start in ns(Jungfrau, CTB) + * @param pos detector position + * @returns timestamp at a frame start in ns + */ + Result getMeasurementTime(Positions pos = {}) const; + + /** + * Get measured period between previous two frames in ns (Eiger) + * @param pos detector position + * @returns measured period between previous two frames in ns + */ + Result getMeasuredPeriod(Positions pos = {}) const; + + /** + * Get measured sub frame period between previous two frames in ns (Eiger in + * 32 bit mode) + * @param pos detector position + * @returns measured sub frame period between previous two frames in ns + */ + Result getMeasuredSubFramePeriod(Positions pos = {}) const; + // Erik Result getFramesCaughtByReceiver(Positions pos = {}) const; diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 1cf4076a0..34315ceaf 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -818,7 +818,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns sub frame dead time in ns, or s if specified */ - double getMeasuredPeriod(bool inseconds = false, int detPos = -1); + double getMeasuredPeriod(bool inseconds = false, int detPos = -1);// /** * Get sub period between previous two sub frames in 32 bit mode (EIGER) @@ -827,7 +827,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns sub frame dead time in ns, or s if specified */ - double getMeasuredSubFramePeriod(bool inseconds = false, int detPos = -1); + double getMeasuredSubFramePeriod(bool inseconds = false, int detPos = -1);// /** * Set/get timer value left in acquisition (not all implemented for all @@ -838,7 +838,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns timer set value in ns or number of...(e.g. frames, * probes) */ - int64_t getTimeLeft(timerIndex index, int detPos = -1); + int64_t getTimeLeft(timerIndex index, int detPos = -1);// /** * Set speed diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 4741a3bdd..b7812920f 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -51,11 +51,6 @@ Result Detector::getRegister(uint32_t addr, Positions pos) { return pimpl->Parallel(&slsDetector::readRegister, pos, addr); } -Result Detector::getExptime(Positions pos) const { - return pimpl->Parallel(&slsDetector::setTimer, pos, defs::ACQUISITION_TIME, - -1); -} - Result Detector::getStartingFrameNumber(Positions pos) const { return pimpl->Parallel(&slsDetector::getStartingFrameNumber, pos); } @@ -63,29 +58,6 @@ void Detector::setStartingFrameNumber(uint64_t value, Positions pos) { pimpl->Parallel(&slsDetector::setStartingFrameNumber, pos, value); } -void Detector::setExptime(ns t, Positions pos) { - pimpl->Parallel(&slsDetector::setTimer, pos, defs::ACQUISITION_TIME, - t.count()); -} - -Result Detector::getSubExptime(Positions pos) const { - return pimpl->Parallel(&slsDetector::setTimer, pos, - defs::SUBFRAME_ACQUISITION_TIME, -1); -} - -void Detector::setSubExptime(ns t, Positions pos) { - pimpl->Parallel(&slsDetector::setTimer, pos, - defs::SUBFRAME_ACQUISITION_TIME, t.count()); -} - -Result Detector::getPeriod(Positions pos) const { - return pimpl->Parallel(&slsDetector::setTimer, pos, defs::FRAME_PERIOD, -1); -} - -void Detector::setPeriod(ns t, Positions pos) { - pimpl->Parallel(&slsDetector::setTimer, pos, defs::FRAME_PERIOD, t.count()); -} - // File void Detector::setFileName(const std::string &fname, Positions pos) { pimpl->Parallel(&slsDetector::setFileName, pos, fname); @@ -366,15 +338,18 @@ void Detector::setNumberOfCycles(int64_t value) { } Result Detector::getNumberOfStorageCells() const { - return pimpl->Parallel(&slsDetector::setTimer, {}, defs::STORAGE_CELL_NUMBER, -1); + return pimpl->Parallel(&slsDetector::setTimer, {}, + defs::STORAGE_CELL_NUMBER, -1); } void Detector::setNumberOfStorageCells(int64_t value) { - pimpl->Parallel(&slsDetector::setTimer, {}, defs::STORAGE_CELL_NUMBER, value); + pimpl->Parallel(&slsDetector::setTimer, {}, defs::STORAGE_CELL_NUMBER, + value); } Result Detector::getNumberOfAnalogSamples(Positions pos) const { - return pimpl->Parallel(&slsDetector::setTimer, pos, defs::ANALOG_SAMPLES, -1); + return pimpl->Parallel(&slsDetector::setTimer, pos, defs::ANALOG_SAMPLES, + -1); } void Detector::setNumberOfAnalogSamples(int64_t value, Positions pos) { @@ -382,13 +357,32 @@ void Detector::setNumberOfAnalogSamples(int64_t value, Positions pos) { } Result Detector::getNumberOfDigitalSamples(Positions pos) const { - return pimpl->Parallel(&slsDetector::setTimer, pos, defs::DIGITAL_SAMPLES, -1); + return pimpl->Parallel(&slsDetector::setTimer, pos, defs::DIGITAL_SAMPLES, + -1); } void Detector::setNumberOfDigitalSamples(int64_t value, Positions pos) { pimpl->Parallel(&slsDetector::setTimer, pos, defs::DIGITAL_SAMPLES, value); } +Result Detector::getExptime(Positions pos) const { + return pimpl->Parallel(&slsDetector::setTimer, pos, defs::ACQUISITION_TIME, + -1); +} + +void Detector::setExptime(ns t, Positions pos) { + pimpl->Parallel(&slsDetector::setTimer, pos, defs::ACQUISITION_TIME, + t.count()); +} + +Result Detector::getPeriod(Positions pos) const { + return pimpl->Parallel(&slsDetector::setTimer, pos, defs::FRAME_PERIOD, -1); +} + +void Detector::setPeriod(ns t, Positions pos) { + pimpl->Parallel(&slsDetector::setTimer, pos, defs::FRAME_PERIOD, t.count()); +} + Result Detector::getDelayAfterTrigger(Positions pos) const { return pimpl->Parallel(&slsDetector::setTimer, pos, defs::DELAY_AFTER_TRIGGER, -1); @@ -399,12 +393,22 @@ void Detector::setDelayAfterTrigger(ns value, Positions pos) { value.count()); } -Result Detector::getSubFrameDeadTime(Positions pos) const { +Result Detector::getSubExptime(Positions pos) const { + return pimpl->Parallel(&slsDetector::setTimer, pos, + defs::SUBFRAME_ACQUISITION_TIME, -1); +} + +void Detector::setSubExptime(ns t, Positions pos) { + pimpl->Parallel(&slsDetector::setTimer, pos, + defs::SUBFRAME_ACQUISITION_TIME, t.count()); +} + +Result Detector::getSubDeadTime(Positions pos) const { return pimpl->Parallel(&slsDetector::setTimer, pos, defs::SUBFRAME_DEADTIME, -1); } -void Detector::setSubFrameDeadTime(ns value, Positions pos) { +void Detector::setSubDeadTime(ns value, Positions pos) { pimpl->Parallel(&slsDetector::setTimer, pos, defs::SUBFRAME_DEADTIME, value.count()); } @@ -419,6 +423,46 @@ void Detector::setStorageCellDelay(ns value, Positions pos) { value.count()); } +Result Detector::getNumberOfFramesLeft(Positions pos) const { + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::FRAME_NUMBER); +} + +Result Detector::getNumberOfCyclesLeft(Positions pos) const { + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::CYCLES_NUMBER); +} + +Result Detector::getExptimeLeft(Positions pos) const { + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::ACQUISITION_TIME); +} + +Result Detector::getPeriodLeft(Positions pos) const { + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::FRAME_PERIOD); +} + +Result Detector::getDelayAfterTriggerLeft(Positions pos) const { + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::DELAY_AFTER_TRIGGER); +} + +Result Detector::getNumberOfFramesFromStart(Positions pos) const { + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::FRAMES_FROM_START); +} + +Result Detector::getActualTime(Positions pos) const { + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::ACTUAL_TIME); +} + +Result Detector::getMeasurementTime(Positions pos) const { + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::MEASUREMENT_TIME); +} + +Result Detector::getMeasuredPeriod(Positions pos) const { + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::MEASURED_PERIOD); +}; + +Result Detector::getMeasuredSubFramePeriod(Positions pos) const { + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::MEASURED_SUBPERIOD); +}; + // Erik Result Detector::getFramesCaughtByReceiver(Positions pos) const { return pimpl->Parallel(&slsDetector::getFramesCaughtByReceiver, pos); From a3c5c1641732ae5477a4390a7b802053b300d9ca Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Fri, 9 Aug 2019 12:01:01 +0200 Subject: [PATCH 039/108] WIP --- slsDetectorSoftware/include/Result.h | 4 +++ slsDetectorSoftware/src/multiSlsDetector.cpp | 31 +++++--------------- 2 files changed, 12 insertions(+), 23 deletions(-) diff --git a/slsDetectorSoftware/include/Result.h b/slsDetectorSoftware/include/Result.h index 193b37db6..9d5f2ae7e 100644 --- a/slsDetectorSoftware/include/Result.h +++ b/slsDetectorSoftware/include/Result.h @@ -107,6 +107,10 @@ template > class Result { */ T squash() const { return Squash(vec); } + /** + * If all elements are equal it returns the front value + * otherwise throws an exception with custom message provided + */ T tsquash(const std::string &error_msg) { if (equal()) return vec.front(); diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index 58fd11603..4a451ba1d 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -4160,34 +4160,19 @@ void multiSlsDetector::registerDataCallback( } int multiSlsDetector::setTotalProgress() { - int nf = 1, nc = 1, ns = 1; - - Result temp = Parallel(&slsDetector::setTimer, {}, FRAME_NUMBER, -1); - if (!temp.equal()) { - throw RuntimeError("Inconsistent number of frames"); - } - nf = temp.squash(); - - temp = Parallel(&slsDetector::setTimer, {}, CYCLES_NUMBER, -1); - if (!temp.equal()) { - throw RuntimeError("Inconsistent number of cycles"); - } - nc = temp.squash(); - - if (getDetectorTypeAsEnum() == JUNGFRAU) { - temp = Parallel(&slsDetector::setTimer, {}, STORAGE_CELL_NUMBER, -1); - if (!temp.equal()) { - throw RuntimeError("Inconsistent number of additional storage cells"); - } - ns = temp.squash() + 1; - } - + int nf = Parallel(&slsDetector::setTimer, {}, FRAME_NUMBER, -1).tsquash("Inconsistent number of frames"); + int nc = Parallel(&slsDetector::setTimer, {}, CYCLES_NUMBER, -1).tsquash("Inconsistent number of cycles"); if (nf == 0 || nc == 0) { throw RuntimeError("Number of frames or cycles is 0"); } - totalProgress = nf * nc * ns; + int ns = 1; + if (getDetectorTypeAsEnum() == JUNGFRAU) { + ns = Parallel(&slsDetector::setTimer, {}, STORAGE_CELL_NUMBER, -1).tsquash("Inconsistent number of additional storage cells"); + ++ns; + } + totalProgress = nf * nc * ns; FILE_LOG(logDEBUG1) << "nf " << nf << " nc " << nc << " ns " << ns; FILE_LOG(logDEBUG1) << "Set total progress " << totalProgress << std::endl; return totalProgress; From 1a60b59a48f8358ba306241ca690895719bdbbd3 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Fri, 9 Aug 2019 12:11:42 +0200 Subject: [PATCH 040/108] size --- slsDetectorGui/src/qTabAdvanced.cpp | 2 +- slsDetectorGui/src/qTabDataOutput.cpp | 4 ++-- slsDetectorGui/src/qTabDebugging.cpp | 2 +- slsDetectorGui/src/qTabDeveloper.cpp | 4 ++-- slsDetectorSoftware/include/Detector.h | 2 +- slsDetectorSoftware/include/multiSlsDetector.h | 6 +----- slsDetectorSoftware/include/multiSlsDetectorClient.h | 2 +- slsDetectorSoftware/include/slsDetectorUsers.h | 2 +- slsDetectorSoftware/src/Detector.cpp | 8 ++++---- slsDetectorSoftware/src/multiSlsDetector.cpp | 10 +++++----- slsDetectorSoftware/src/slsDetectorCommand.cpp | 2 +- slsDetectorSoftware/src/slsDetectorUsers.cpp | 4 ++-- 12 files changed, 22 insertions(+), 26 deletions(-) diff --git a/slsDetectorGui/src/qTabAdvanced.cpp b/slsDetectorGui/src/qTabAdvanced.cpp index 9efa24faf..0faad922a 100755 --- a/slsDetectorGui/src/qTabAdvanced.cpp +++ b/slsDetectorGui/src/qTabAdvanced.cpp @@ -124,7 +124,7 @@ void qTabAdvanced::PopulateDetectors() { SLOT(SetDetector(int))); comboDetector->clear(); - for (int i = 0; i < myDet->getNumberOfDetectors(); ++i) + for (int i = 0; i < myDet->size(); ++i) comboDetector->addItem(QString(myDet->getHostname(i).c_str())); comboDetector->setCurrentIndex(0); diff --git a/slsDetectorGui/src/qTabDataOutput.cpp b/slsDetectorGui/src/qTabDataOutput.cpp index 58942a86f..da7b9d55b 100755 --- a/slsDetectorGui/src/qTabDataOutput.cpp +++ b/slsDetectorGui/src/qTabDataOutput.cpp @@ -80,8 +80,8 @@ void qTabDataOutput::PopulateDetectors() { comboDetector->clear(); comboDetector->addItem("All"); - if (myDet->getNumberOfDetectors() > 1) { - for (int i = 0; i < myDet->getNumberOfDetectors(); ++i) + if (myDet->size() > 1) { + for (int i = 0; i < myDet->size(); ++i) comboDetector->addItem(QString(myDet->getHostname(i).c_str())); } } diff --git a/slsDetectorGui/src/qTabDebugging.cpp b/slsDetectorGui/src/qTabDebugging.cpp index 936efcba5..a62373c50 100755 --- a/slsDetectorGui/src/qTabDebugging.cpp +++ b/slsDetectorGui/src/qTabDebugging.cpp @@ -55,7 +55,7 @@ void qTabDebugging::PopulateDetectors() { FILE_LOG(logDEBUG) << "Populating detectors"; comboDetector->clear(); - for (int i = 0; i < myDet->getNumberOfDetectors(); ++i) { + for (int i = 0; i < myDet->size(); ++i) { comboDetector->addItem(QString(myDet->getHostname(i).c_str())); } } diff --git a/slsDetectorGui/src/qTabDeveloper.cpp b/slsDetectorGui/src/qTabDeveloper.cpp index e62f5ac4c..7326740ad 100755 --- a/slsDetectorGui/src/qTabDeveloper.cpp +++ b/slsDetectorGui/src/qTabDeveloper.cpp @@ -124,8 +124,8 @@ void qTabDeveloper::PopulateDetectors() { comboDetector->clear(); comboDetector->addItem("All"); - if (myDet->getNumberOfDetectors() > 1) { - for (int i = 0; i < myDet->getNumberOfDetectors(); ++i) + if (myDet->size() > 1) { + for (int i = 0; i < myDet->size(); ++i) comboDetector->addItem(QString(myDet->getHostname(i).c_str())); } comboDetector->setCurrentIndex(0); diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index c9f080aef..ae35ccbd6 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -205,7 +205,7 @@ class Detector { * Returns the total number of detectors in the multidetector structure * @returns total number of detectors in the multidetector structure */ - int getTotalNumberOfDetectors() const; + int size() const; /** * Returns the number of detectors in the multidetector structure diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 0383b3ea5..8fa7c3a55 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -381,7 +381,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * Returns the number of detectors in the multidetector structure * @returns number of detectors */ - int getNumberOfDetectors() const;// + int size() const;// /** * Returns number of detectors in dimension d @@ -872,10 +872,6 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ int getDataBytes(int detPos = -1); - /** - * Returns the number of detectors in the multi structure*/ - size_t size() const { return detectors.size(); } - /** * Set/get dacs value * @param val value (in V) diff --git a/slsDetectorSoftware/include/multiSlsDetectorClient.h b/slsDetectorSoftware/include/multiSlsDetectorClient.h index e370d4905..c627d1813 100755 --- a/slsDetectorSoftware/include/multiSlsDetectorClient.h +++ b/slsDetectorSoftware/include/multiSlsDetectorClient.h @@ -101,7 +101,7 @@ class multiSlsDetectorClient { return; } } - if (parser.detector_id() >= detPtr->getNumberOfDetectors()) { + if (parser.detector_id() >= detPtr->size()) { os << "position is out of bounds.\n"; return; } diff --git a/slsDetectorSoftware/include/slsDetectorUsers.h b/slsDetectorSoftware/include/slsDetectorUsers.h index 1b93f9445..734aabbc8 100755 --- a/slsDetectorSoftware/include/slsDetectorUsers.h +++ b/slsDetectorSoftware/include/slsDetectorUsers.h @@ -99,7 +99,7 @@ public: * Returns the number of detectors in the multidetector structure * @returns number of detectors */ - int getNumberOfDetectors() const; + int size() const; /** * Returns the maximum number of channels of all detectors diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 7002fe296..014f14fd0 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -142,8 +142,8 @@ Result Detector::getDetectorTypeAsString(Positions pos) const { return pimpl->Parallel(&slsDetector::getDetectorTypeAsString, pos); } -int Detector::getTotalNumberOfDetectors() const { - return pimpl->getNumberOfDetectors(); +int Detector::size() const { + return pimpl->size(); } defs::coordinates Detector::getNumberOfDetectors() const { @@ -675,8 +675,8 @@ Result Detector::getAutoCompDisable(Positions pos) const { } void Detector::setPowerChip(bool on, Positions pos) { - if (on && pimpl->getNumberOfDetectors() > 3) { - for (int i = 0; i != pimpl->getNumberOfDetectors(); ++i) { + if (on && pimpl->size() > 3) { + for (int i = 0; i != pimpl->size(); ++i) { pimpl->powerChip(static_cast(on), i); usleep(1000 * 1000); } diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index 4a451ba1d..843fb1f41 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -660,7 +660,7 @@ std::string multiSlsDetector::getDetectorTypeAsString(int detPos) { return sls::concatenateIfDifferent(r); } -int multiSlsDetector::getNumberOfDetectors() const { return detectors.size(); } +int multiSlsDetector::size() const { return detectors.size(); } int multiSlsDetector::getNumberOfDetectors(dimension d) const { return multi_shm()->numberOfDetector[d]; @@ -747,7 +747,7 @@ void multiSlsDetector::setDetectorOffset(dimension d, int off, int detPos) { int multiSlsDetector::getQuad(int detPos) { int retval = detectors[0]->getQuad(); - if (retval && getNumberOfDetectors() > 1) { + if (retval && size() > 1) { throw RuntimeError("Quad type is available only for 1 Eiger Quad Half " "module, but it Quad is enabled for 1st readout"); } @@ -755,7 +755,7 @@ int multiSlsDetector::getQuad(int detPos) { } void multiSlsDetector::setQuad(const bool enable, int detPos) { - if (enable && getNumberOfDetectors() > 1) { + if (enable && size() > 1) { throw RuntimeError("Cannot set Quad type as it is available only for 1 " "Eiger Quad Half module."); } @@ -2238,7 +2238,7 @@ void multiSlsDetector::setROI(int n, ROI roiLimits[], int detPos) { ymin = roiLimits[i].ymin; ymax = roiLimits[i].ymax; - if (getNumberOfDetectors() > 1) { + if (size() > 1) { // check roi max values idet = decodeNChannel(xmax, ymax, channelX, channelY); FILE_LOG(logDEBUG1) << "Decoded Channel max vals: " << std::endl @@ -2885,7 +2885,7 @@ int multiSlsDetector::powerChip(int ival, int detPos) { } // multi delayed call for safety - if (ival >= 0 && getNumberOfDetectors() > 3) { + if (ival >= 0 && size() > 3) { std::vector r; r.reserve(detectors.size()); for (auto &d : detectors) { diff --git a/slsDetectorSoftware/src/slsDetectorCommand.cpp b/slsDetectorSoftware/src/slsDetectorCommand.cpp index 112fe18ed..c2a00202f 100755 --- a/slsDetectorSoftware/src/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp @@ -2175,7 +2175,7 @@ std::string slsDetectorCommand::cmdAcquire(int narg, const char * const args[], if (action == HELP_ACTION) { return helpAcquire(HELP_ACTION); } - if (!myDet->getNumberOfDetectors()) { + if (!myDet->size()) { FILE_LOG(logERROR) << "This shared memory has no detectors added. Aborting."; return std::string("acquire failed"); } diff --git a/slsDetectorSoftware/src/slsDetectorUsers.cpp b/slsDetectorSoftware/src/slsDetectorUsers.cpp index 36f115d37..f4b83b178 100755 --- a/slsDetectorSoftware/src/slsDetectorUsers.cpp +++ b/slsDetectorSoftware/src/slsDetectorUsers.cpp @@ -4,8 +4,8 @@ -int slsDetectorUsers::getNumberOfDetectors() const { - return detector.getNumberOfDetectors(); +int slsDetectorUsers::size() const { + return detector.size(); } int slsDetectorUsers::getMaximumDetectorSize(int &nx, int &ny){ From 2f61764fd7e82f21bae21ab3a95d2c6de4867c84 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Fri, 9 Aug 2019 14:08:21 +0200 Subject: [PATCH 041/108] WIP --- slsDetectorSoftware/include/Detector.h | 56 ++++++++++++- .../include/multiSlsDetector.h | 20 ++--- slsDetectorSoftware/src/Detector.cpp | 84 +++++++++++++++++-- 3 files changed, 141 insertions(+), 19 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index cbaeed1bf..3522c36d3 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -950,6 +950,7 @@ class Detector { /** [CTB] Value between 0-63 */ void setExternalSamplingSource(int value, Positions pos = {}); + // TODO! does any of them need the option to take positions /** [CTB] */ uint32_t getADCInvert() const; @@ -957,13 +958,62 @@ class Detector { void setADCInvert(uint32_t value); /** [CTB]*/ - uint32_t getADCEnableMask(int detPos = -1); + uint32_t getADCEnableMask() const; /** [CTB]*/ void setADCEnableMask(uint32_t mask); - /** [CTB]*/ - uint32_t getADCEnableMask() const; + /** [Gotthard] */ + Result getCounterBit(Positions pos = {}) const; + + /** [Gotthard] possible values? */ + void setCounterBit(int i, Positions pos = {}); + + /** + * [Gotthard] startACQ = 1 to start acq after resetting counter + * TODO! does it make sense to call one detector? + * + */ + void resetCounterBlock(int startACQ = 0, Positions pos = {}); + + // TODO getROI, setROI, verifyMinMaxROI + + // writeCounterBlockFile + + void loadImageToDetector(defs::imageType index, const std::string &fname, + Positions pos = {}); + + /** [Gotthard] + * @param value 1 to set or 0 to clear the digital test bit -1? + */ + Result digitalTest(defs::digitalTestMode mode, int ival = -1, + Positions pos = {}); + + /** [Eiger] */ + void setFlowControl10G(bool enable, Positions pos = {}); + + /** [Eiger] */ + Result getFlowControl10G(Positions pos = {}) const; + + Result + getReceiverRealUDPSocketBufferSize(Positions pos = {}) const; + + Result getReceiverUDPSocketBufferSize(Positions pos = {}) const; + + void setReceiverUDPSocketBufferSize(int64_t udpsockbufsize, + Positions pos = {}); + + /** [Moench] TODO! How do we do this best??? Can be refactored to something + * else? Use a generic zmq message passing system... + * For now limiting to all detectors working the same*/ + int setDetectorMode(defs::detectorModeType value); + int setFrameMode(defs::frameModeType value); + int setDetectorMinMaxEnergyThreshold(const int index, int value); + + void setAdditionalJsonHeader(const std::string &jsonheader, + Positions pos = {}); + + Result getAdditionalJsonHeader(Positions pos = {}) const; }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index d5d8e81e4..ca3d904b4 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -1297,7 +1297,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ std::string setAdditionalJsonParameter(const std::string &key, const std::string &value, - int detPos = -1); + int detPos = -1); // /** * Returns the additional json header parameter value @@ -1307,7 +1307,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * empty if no parameter found in additional json header */ std::string getAdditionalJsonParameter(const std::string &key, - int detPos = -1); + int detPos = -1); // /** * Sets the detector minimum/maximum energy threshold in processor (for @@ -1318,7 +1318,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * error in computing json parameter value) */ int setDetectorMinMaxEnergyThreshold(const int index, int value, - int detPos = -1); + int detPos = -1); // /** * Sets the frame mode in processor (Moench only) @@ -1345,21 +1345,21 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns receiver udp socket buffer size */ int64_t setReceiverUDPSocketBufferSize(int64_t udpsockbufsize = -1, - int detPos = -1); + int detPos = -1); // /** * Returns the receiver UDP socket buffer size * @param detPos -1 for all detectors in list or specific detector position * @returns the receiver UDP socket buffer size */ - int64_t getReceiverUDPSocketBufferSize(int detPos = -1); + int64_t getReceiverUDPSocketBufferSize(int detPos = -1); // /** * Returns the receiver real UDP socket buffer size * @param detPos -1 for all detectors in list or specific detector position * @returns the receiver real UDP socket buffer size */ - int64_t getReceiverRealUDPSocketBufferSize(int detPos = -1); + int64_t getReceiverRealUDPSocketBufferSize(int detPos = -1); // /** (users only) * Set 10GbE Flow Control (Eiger) @@ -1367,7 +1367,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns 10GbE flow Control */ - int setFlowControl10G(int enable = -1, int detPos = -1); + int setFlowControl10G(int enable = -1, int detPos = -1); // /** * Execute a digital test (Gotthard) @@ -1385,7 +1385,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position */ void loadImageToDetector(imageType index, const std::string &fname, - int detPos = -1); + int detPos = -1); // /** * Writes the counter memory block from the detector (Gotthard) @@ -1401,7 +1401,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param startACQ is 1 to start acquisition after resetting counter * @param detPos -1 for all detectors in list or specific detector position */ - void resetCounterBlock(int startACQ = 0, int detPos = -1); + void resetCounterBlock(int startACQ = 0, int detPos = -1); // /** * Set/get counter bit in detector (Gotthard) @@ -1410,7 +1410,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the counter bit in detector */ - int setCounterBit(int i = -1, int detPos = -1); + int setCounterBit(int i = -1, int detPos = -1); // /** * Ensures that min is less than max in both dimensions (Gotthard) diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 6e163a465..0efdd723f 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -366,15 +366,18 @@ void Detector::setNumberOfCycles(int64_t value) { } Result Detector::getNumberOfStorageCells() const { - return pimpl->Parallel(&slsDetector::setTimer, {}, defs::STORAGE_CELL_NUMBER, -1); + return pimpl->Parallel(&slsDetector::setTimer, {}, + defs::STORAGE_CELL_NUMBER, -1); } void Detector::setNumberOfStorageCells(int64_t value) { - pimpl->Parallel(&slsDetector::setTimer, {}, defs::STORAGE_CELL_NUMBER, value); + pimpl->Parallel(&slsDetector::setTimer, {}, defs::STORAGE_CELL_NUMBER, + value); } Result Detector::getNumberOfAnalogSamples(Positions pos) const { - return pimpl->Parallel(&slsDetector::setTimer, pos, defs::ANALOG_SAMPLES, -1); + return pimpl->Parallel(&slsDetector::setTimer, pos, defs::ANALOG_SAMPLES, + -1); } void Detector::setNumberOfAnalogSamples(int64_t value, Positions pos) { @@ -382,7 +385,8 @@ void Detector::setNumberOfAnalogSamples(int64_t value, Positions pos) { } Result Detector::getNumberOfDigitalSamples(Positions pos) const { - return pimpl->Parallel(&slsDetector::setTimer, pos, defs::DIGITAL_SAMPLES, -1); + return pimpl->Parallel(&slsDetector::setTimer, pos, defs::DIGITAL_SAMPLES, + -1); } void Detector::setNumberOfDigitalSamples(int64_t value, Positions pos) { @@ -800,8 +804,8 @@ void Detector::setExternalSamplingSource(int value, Positions pos) { } uint32_t Detector::getADCInvert() const { - auto res = pimpl->Parallel(&slsDetector::getADCInvert, {}); - return res.tsquash("Different Values for function getADCInvert"); + return pimpl->Parallel(&slsDetector::getADCInvert, {}) + .tsquash("Different Values for function getADCInvert"); } void Detector::setADCInvert(uint32_t value) { @@ -817,4 +821,72 @@ void Detector::setADCEnableMask(uint32_t mask) { pimpl->Parallel(&slsDetector::setADCEnableMask, {}, mask); } +Result Detector::getCounterBit(Positions pos) const { + return pimpl->Parallel(&slsDetector::setCounterBit, pos, -1); +} + +void Detector::setCounterBit(int i, Positions pos) { + pimpl->Parallel(&slsDetector::setCounterBit, pos, i); +} + +void Detector::resetCounterBlock(int startACQ, Positions pos) { + pimpl->Parallel(&slsDetector::resetCounterBlock, pos, startACQ); +} + +void Detector::loadImageToDetector(defs::imageType index, + const std::string &fname, Positions pos) { + // TODO! optimize away multiple loads + pimpl->Parallel(&slsDetector::loadImageToDetector, pos, index, fname); +} + +Result Detector::digitalTest(defs::digitalTestMode mode, int ival, + Positions pos) { + return pimpl->Parallel(&slsDetector::digitalTest, pos, mode, ival); +} + +void Detector::setFlowControl10G(bool enable, Positions pos) { + pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, + defs::FLOW_CONTROL_10G, static_cast(enable)); +} + +Result Detector::getFlowControl10G(Positions pos) const { + return pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, + defs::FLOW_CONTROL_10G, -1); +} + +Result +Detector::getReceiverRealUDPSocketBufferSize(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverRealUDPSocketBufferSize, + pos); +} + +Result Detector::getReceiverUDPSocketBufferSize(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverUDPSocketBufferSize, pos); +} + +void Detector::setReceiverUDPSocketBufferSize(int64_t udpsockbufsize, + Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverUDPSocketBufferSize, pos, + udpsockbufsize); +} + +int Detector::setDetectorMode(defs::detectorModeType value) { + return pimpl->setDetectorMode(value); +} +int Detector::setFrameMode(defs::frameModeType value) { + return pimpl->setFrameMode(value); +} +int Detector::setDetectorMinMaxEnergyThreshold(const int index, int value) { + return pimpl->setDetectorMinMaxEnergyThreshold(index, value); +} + +void Detector::setAdditionalJsonHeader(const std::string &jsonheader, + Positions pos) { + pimpl->Parallel(&slsDetector::setAdditionalJsonHeader, pos, jsonheader); +} + +Result Detector::getAdditionalJsonHeader(Positions pos) const { + return pimpl->Parallel(&slsDetector::getAdditionalJsonHeader, pos); +} + } // namespace sls \ No newline at end of file From 991319477480b090d481934803d08b104b4ae7be Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Fri, 9 Aug 2019 14:28:18 +0200 Subject: [PATCH 042/108] WIP --- slsDetectorSoftware/include/Detector.h | 120 +++++++++++++++++++++++++ slsDetectorSoftware/src/Detector.cpp | 102 ++++++++++++++++++--- 2 files changed, 211 insertions(+), 11 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index ae35ccbd6..f9755bb5e 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -706,6 +706,126 @@ class Detector { */ Result getMeasuredSubFramePeriod(Positions pos = {}) const; + /** + * Get speed (Eiger, Jungfrau) + * @param pos detector position + * @returns speed (0 full speed, 1 half speed, 2 quarter speed) + */ + Result getSpeed(Positions pos = {}) const; + + /** + * Set speed (Eiger, Jungfrau) + * @param value speed (0 full speed, 1 half speed, 2 quarter speed) + * @param pos detector position + */ + void setSpeed(int value, Positions pos = {}); + + /** + * Get ADC Phase (Gotthard, Jungfrau, CTB) + * @param inDeg in degrees (Jungfrau, CTB) + * @returns ADC Phase + */ + Result getADCPhase(bool inDeg, Positions pos = {}) const; + + /** + * Set sADC Phase (Gotthard, Jungfrau, CTB) + * @param value ADC Phase + * @param inDeg in degrees (Jungfrau, CTB) + */ + void setADCPhase(int value, bool inDeg, Positions pos = {}); + + /** + * Get Max ADC Phase Shift (Jungfrau, CTB) + * @returns Max ADC Phase Shift + */ + Result getMaxADCPhaseShift(Positions pos = {}) const; + + /** + * Get DBIT Phase (Jungfrau, CTB) + * @param inDeg in degrees + * @returns DBIT Phase + */ + Result getDBITPhase(bool inDeg, Positions pos = {}) const; + + /** + * Set DBIT Phase (CTB) + * @param value DBIT Phase + * @param inDeg in degrees + */ + void setDBITPhase(int value, bool inDeg, Positions pos = {}); + + /** + * Get Max DBIT Phase Shift (CTB) + * @returns Max DBIT Phase Shift + */ + Result getMaxDBITPhaseShift(Positions pos = {}) const; + + /** + * Get ADC Clock in MHz (CTB) + * @returns ADC Clock in MHz + */ + Result getADCClock(Positions pos = {}) const; + + /** + * Set ADC Clock in MHz (CTB) + * @param value ADC Clock in MHz + */ + void setADCClock(int value, Positions pos = {}); + + /** + * Get DBIT Clock in MHz (CTB) + * @returns DBIT Clock in MHz + */ + Result getDBITClock(Positions pos = {}) const; + + /** + * Set DBIT Clock in MHz (CTB) + * @param value DBIT Clock in MHz + */ + void setDBITClock(int value, Positions pos = {}); + + /** + * Get RUN Clock in MHz (CTB) + * @returns RUN Clock in MHz + */ + Result getRUNClock(Positions pos = {}) const; + + /** + * Set RUN Clock in MHz (CTB) + * @param value RUN Clock in MHz + */ + void setRUNClock(int value, Positions pos = {}); + + /** + * Get SYNC Clock in MHz (CTB) + * @returns SYNC Clock in MHz + */ + Result getSYNCClock(Positions pos = {}) const; + + /** + * Get ADC Pipeline (CTB) + * @returns ADC Pipeline + */ + Result getADCPipeline(Positions pos = {}) const; + + /** + * Set ADC Pipeline (CTB) + * @param value ADC Pipeline + */ + void setADCPipeline(int value, Positions pos = {}); + + /** + * Get DBIT Pipeline (CTB) + * @returns DBIT Pipeline + */ + Result getDBITPipeline(Positions pos = {}) const; + + /** + * Set DBIT Pipeline (CTB) + * @param value DBIT Pipeline + */ + void setDBITPipeline(int value, Positions pos = {}); + // Erik Result getFramesCaughtByReceiver(Positions pos = {}) const; diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 014f14fd0..e4f2d70b5 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -142,9 +142,7 @@ Result Detector::getDetectorTypeAsString(Positions pos) const { return pimpl->Parallel(&slsDetector::getDetectorTypeAsString, pos); } -int Detector::size() const { - return pimpl->size(); -} +int Detector::size() const { return pimpl->size(); } defs::coordinates Detector::getNumberOfDetectors() const { defs::coordinates coord; @@ -432,7 +430,8 @@ Result Detector::getNumberOfCyclesLeft(Positions pos) const { } Result Detector::getExptimeLeft(Positions pos) const { - return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::ACQUISITION_TIME); + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, + defs::ACQUISITION_TIME); } Result Detector::getPeriodLeft(Positions pos) const { @@ -440,11 +439,13 @@ Result Detector::getPeriodLeft(Positions pos) const { } Result Detector::getDelayAfterTriggerLeft(Positions pos) const { - return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::DELAY_AFTER_TRIGGER); + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, + defs::DELAY_AFTER_TRIGGER); } Result Detector::getNumberOfFramesFromStart(Positions pos) const { - return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::FRAMES_FROM_START); + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, + defs::FRAMES_FROM_START); } Result Detector::getActualTime(Positions pos) const { @@ -452,16 +453,95 @@ Result Detector::getActualTime(Positions pos) const { } Result Detector::getMeasurementTime(Positions pos) const { - return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::MEASUREMENT_TIME); + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, + defs::MEASUREMENT_TIME); } Result Detector::getMeasuredPeriod(Positions pos) const { - return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::MEASURED_PERIOD); -}; + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, + defs::MEASURED_PERIOD); +} Result Detector::getMeasuredSubFramePeriod(Positions pos) const { - return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::MEASURED_SUBPERIOD); -}; + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, + defs::MEASURED_SUBPERIOD); +} + +Result Detector::getSpeed(Positions pos) const { + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::CLOCK_DIVIDER, -1, 0); +} + +void Detector::setSpeed(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setSpeed, pos, defs::CLOCK_DIVIDER, value, 0); +} + +Result Detector::getADCPhase(bool inDeg, Positions pos) const { + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_PHASE, -1, inDeg); +} + +void Detector::setADCPhase(int value, bool inDeg, Positions pos) { + pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_PHASE, value, inDeg); +} + +Result Detector::getMaxADCPhaseShift(Positions pos) const { + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::MAX_ADC_PHASE_SHIFT, -1, 0); +} + +Result Detector::getDBITPhase(bool inDeg, Positions pos) const { + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PHASE, -1, inDeg); +} + +void Detector::setDBITPhase(int value, bool inDeg, Positions pos) { + pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PHASE, value, inDeg); +} + +Result Detector::getMaxDBITPhaseShift(Positions pos) const { + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::MAX_DBIT_PHASE_SHIFT, -1, 0); +} + +Result Detector::getADCClock(Positions pos) const { + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_CLOCK, -1, 0); +} + +void Detector::setADCClock(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_CLOCK, value, 0); +} + +Result Detector::getDBITClock(Positions pos) const { + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_CLOCK, -1, 0); +} + +void Detector::setDBITClock(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_CLOCK, value, 0); +} + +Result Detector::getRUNClock(Positions pos) const { + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::CLOCK_DIVIDER, -1, 0); +} + +void Detector::setRUNClock(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setSpeed, pos, defs::CLOCK_DIVIDER, value, 0); +} + +Result Detector::getSYNCClock(Positions pos) const { + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::SYNC_CLOCK, -1, 0); +} + +Result Detector::getADCPipeline(Positions pos) const { + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_PIPELINE, -1, 0); +} + +void Detector::setADCPipeline(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_PIPELINE, value, 0); +} + +Result Detector::getDBITPipeline(Positions pos) const { + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PIPELINE, -1, 0); +} + +void Detector::setDBITPipeline(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PIPELINE, value, 0); +} // Erik Result Detector::getFramesCaughtByReceiver(Positions pos) const { From 2ac421365d2a2bc7c8403628230805af6224d1f3 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Fri, 9 Aug 2019 14:28:32 +0200 Subject: [PATCH 043/108] WIP --- slsDetectorSoftware/include/multiSlsDetector.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 8fa7c3a55..63bb8da30 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -853,7 +853,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns value of speed set */ int setSpeed(speedVariable index, int value = -1, int mode = 0, - int detPos = -1); + int detPos = -1);// /** * Set/get dynamic range and updates the number of dataBytes From 6b363a16feceefcb41d0600e625aa0e1ab60963b Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Fri, 9 Aug 2019 14:45:07 +0200 Subject: [PATCH 044/108] WIP --- python/src/DetectorPythonInterface.h | 24 ++++---- slsDetectorSoftware/include/Detector.h | 24 +++++++- .../include/multiSlsDetector.h | 16 ++--- slsDetectorSoftware/src/Detector.cpp | 61 ++++++++++++++++--- slsDetectorSoftware/src/multiSlsDetector.cpp | 3 +- 5 files changed, 97 insertions(+), 31 deletions(-) diff --git a/python/src/DetectorPythonInterface.h b/python/src/DetectorPythonInterface.h index a91f2ec96..9f8b3efc0 100755 --- a/python/src/DetectorPythonInterface.h +++ b/python/src/DetectorPythonInterface.h @@ -156,7 +156,7 @@ class DetectorPythonInterface { return g; } - int getNumberOfDetectors() { return det.getNumberOfDetectors(); } + int getNumberOfDetectors() { return det.size(); } std::string getRunStatus() { auto s = det.getRunStatus(); @@ -234,7 +234,7 @@ class DetectorPythonInterface { } void setRateCorrection(std::vector tau) { - for (int i = 0; i < det.getNumberOfDetectors(); ++i) + for (size_t i = 0; i < det.size(); ++i) det.setRateCorrection(tau[i], i); } @@ -334,7 +334,7 @@ class DetectorPythonInterface { std::vector getMeasuredPeriod() { std::vector mp; - for (int i = 0; i < det.getNumberOfDetectors(); ++i) { + for (size_t i = 0; i < det.size(); ++i) { auto t = det.getTimeLeft(slsDetectorDefs::MEASURED_PERIOD, i); mp.push_back(static_cast(t) * 1E-9); } @@ -342,7 +342,7 @@ class DetectorPythonInterface { } std::vector getMeasuredSubPeriod() { std::vector mp; - for (int i = 0; i < det.getNumberOfDetectors(); ++i) { + for (size_t i = 0; i < det.size(); ++i) { auto t = det.getTimeLeft(slsDetectorDefs::MEASURED_SUBPERIOD, i); mp.push_back(static_cast(t) * 1E-9); } @@ -550,7 +550,7 @@ class DetectorPythonInterface { std::vector getDetectorType() { std::vector detector_type; - for (int i = 0; i < det.getNumberOfDetectors(); ++i) { + for (size_t i = 0; i < det.size(); ++i) { detector_type.push_back(det.getDetectorTypeAsString(i)); } return detector_type; @@ -577,8 +577,8 @@ class DetectorPythonInterface { // detectors return a vector of strings std::vector getReceiverStreamingPort() { std::vector vec; - vec.reserve(det.getNumberOfDetectors()); - for (int i = 0; i < det.getNumberOfDetectors(); ++i) { + vec.reserve(det.size()); + for (size_t i = 0; i < det.size(); ++i) { vec.push_back(det.getReceiverStreamingPort(i)); } return vec; @@ -590,8 +590,8 @@ class DetectorPythonInterface { std::vector getReceiverUDPPort() { std::vector vec; - vec.reserve(det.getNumberOfDetectors()); - for (int i = 0; i < det.getNumberOfDetectors(); ++i) { + vec.reserve(det.size()); + for (size_t i = 0; i < det.size(); ++i) { vec.push_back(det.getReceiverUDPPort(i)); } return vec; @@ -599,8 +599,8 @@ class DetectorPythonInterface { std::vector getReceiverUDPPort2() { std::vector vec; - vec.reserve(det.getNumberOfDetectors()); - for (int i = 0; i < det.getNumberOfDetectors(); ++i) { + vec.reserve(det.size()); + for (size_t i = 0; i < det.size(); ++i) { vec.push_back(det.getReceiverUDPPort2(i)); } return vec; @@ -990,7 +990,7 @@ void DetectorPythonInterface::setReadoutFlag(const std::string flag_name) { std::vector DetectorPythonInterface::getRateCorrection() { std::vector rate_corr; - for (int i = 0; i < det.getNumberOfDetectors(); ++i) { + for (size_t i = 0; i < det.size(); ++i) { rate_corr.push_back(det.getRateCorrection(i)); } return rate_corr; diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index a964543f2..da29ee2e1 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -1113,9 +1113,31 @@ class Detector { int setDetectorMinMaxEnergyThreshold(const int index, int value); void setAdditionalJsonHeader(const std::string &jsonheader, - Positions pos = {}); + Positions pos = {}); Result getAdditionalJsonHeader(Positions pos = {}) const; + + Result getAdditionalJsonParameter(const std::string &key, + Positions pos = {}) const; + + void setAdditionalJsonParameter(const std::string &key, + const std::string &value, + Positions pos = {}); + + // TODO these should probably be the same + Result getReceiverStreamingIP(Positions pos = {}) const; + + void setReceiverDataStreamingOutIP(const std::string &ip, + Positions pos = {}); + + Result getClientStreamingIP(Positions pos = {}) const; + + // TODO these should probably be the same + void setClientDataStreamingInIP(const std::string &ip, Positions pos = {}); + + Result getReceiverStreamingPort(Positions pos = {}) const; + + // void setReceiverDataStreamingOutPort(int i = -1, int detPos = -1); }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 8e73c61fd..91dfd1a16 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -381,7 +381,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * Returns the number of detectors in the multidetector structure * @returns number of detectors */ - int size() const;// + size_t size() const;// /** * Returns number of detectors in dimension d @@ -1225,7 +1225,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position */ void setClientDataStreamingInIP(const std::string &ip = "", - int detPos = -1); + int detPos = -1); // /** * Returns the client zmq ip @@ -1234,7 +1234,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the client zmq ip */ - std::string getClientStreamingIP(int detPos = -1); + std::string getClientStreamingIP(int detPos = -1); // /** * (advanced users) @@ -1244,7 +1244,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position */ void setReceiverDataStreamingOutIP(const std::string &ip = "", - int detPos = -1); + int detPos = -1); // /** * Returns the receiver zmq ip @@ -1253,7 +1253,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the receiver zmq ip */ - std::string getReceiverStreamingIP(int detPos = -1); + std::string getReceiverStreamingIP(int detPos = -1); // /** * Sets the transmission delay for left, right or entire frame @@ -1264,7 +1264,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns transmission delay */ int setDetectorNetworkParameter(networkParameter index, int delay, - int detPos = -1); + int detPos = -1); //maybe not needed in API /** * Sets the additional json header @@ -1273,14 +1273,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns additional json header, default is empty */ std::string setAdditionalJsonHeader(const std::string &jsonheader, - int detPos = -1); + int detPos = -1); // /** * Returns the additional json header * @param detPos -1 for all detectors in list or specific detector position * @returns the additional json header, default is empty */ - std::string getAdditionalJsonHeader(int detPos = -1); + std::string getAdditionalJsonHeader(int detPos = -1); // /** * Sets the value for the additional json header parameter if found, else diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 2f13d1bd4..962fceb47 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -142,9 +142,7 @@ Result Detector::getDetectorTypeAsString(Positions pos) const { return pimpl->Parallel(&slsDetector::getDetectorTypeAsString, pos); } -int Detector::size() const { - return pimpl->size(); -} +int Detector::size() const { return pimpl->size(); } defs::coordinates Detector::getNumberOfDetectors() const { defs::coordinates coord; @@ -432,7 +430,8 @@ Result Detector::getNumberOfCyclesLeft(Positions pos) const { } Result Detector::getExptimeLeft(Positions pos) const { - return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::ACQUISITION_TIME); + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, + defs::ACQUISITION_TIME); } Result Detector::getPeriodLeft(Positions pos) const { @@ -440,11 +439,13 @@ Result Detector::getPeriodLeft(Positions pos) const { } Result Detector::getDelayAfterTriggerLeft(Positions pos) const { - return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::DELAY_AFTER_TRIGGER); + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, + defs::DELAY_AFTER_TRIGGER); } Result Detector::getNumberOfFramesFromStart(Positions pos) const { - return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::FRAMES_FROM_START); + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, + defs::FRAMES_FROM_START); } Result Detector::getActualTime(Positions pos) const { @@ -452,15 +453,18 @@ Result Detector::getActualTime(Positions pos) const { } Result Detector::getMeasurementTime(Positions pos) const { - return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::MEASUREMENT_TIME); + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, + defs::MEASUREMENT_TIME); } Result Detector::getMeasuredPeriod(Positions pos) const { - return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::MEASURED_PERIOD); + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, + defs::MEASURED_PERIOD); }; Result Detector::getMeasuredSubFramePeriod(Positions pos) const { - return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::MEASURED_SUBPERIOD); + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, + defs::MEASURED_SUBPERIOD); }; // Erik @@ -929,4 +933,43 @@ Result Detector::getAdditionalJsonHeader(Positions pos) const { return pimpl->Parallel(&slsDetector::getAdditionalJsonHeader, pos); } +Result Detector::getAdditionalJsonParameter(const std::string &key, + Positions pos) const { + return pimpl->Parallel(&slsDetector::getAdditionalJsonParameter, pos, key); +} + +void Detector::setAdditionalJsonParameter(const std::string &key, + const std::string &value, + Positions pos) { + pimpl->Parallel(&slsDetector::setAdditionalJsonParameter, pos, key, value); +} + +Result Detector::getReceiverStreamingIP(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverStreamingIP, pos); +} + +void Detector::setReceiverDataStreamingOutIP(const std::string &ip, + Positions pos) { + // TODO! probably in one call + pimpl->Parallel(&slsDetector::setReceiverStreamingIP, pos, ip); + pimpl->Parallel(&slsDetector::enableDataStreamingFromReceiver, pos, 0); + pimpl->Parallel(&slsDetector::enableDataStreamingFromReceiver, pos, 1); +} + +Result Detector::getClientStreamingIP(Positions pos) const { + return pimpl->Parallel(&slsDetector::getClientStreamingIP, pos); +} + +void Detector::setClientDataStreamingInIP(const std::string &ip, + Positions pos) { + // TODO! probably in one call + pimpl->Parallel(&slsDetector::setClientStreamingIP, pos, ip); + pimpl->enableDataStreamingToClient(0); + pimpl->enableDataStreamingToClient(1); +} + +Result Detector::getReceiverStreamingPort(Positions pos) const{ + return pimpl->Parallel(&slsDetector::getReceiverStreamingPort, pos); +} + } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index 843fb1f41..7b1f4c2c3 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -660,7 +660,7 @@ std::string multiSlsDetector::getDetectorTypeAsString(int detPos) { return sls::concatenateIfDifferent(r); } -int multiSlsDetector::size() const { return detectors.size(); } +size_t multiSlsDetector::size() const { return detectors.size(); } int multiSlsDetector::getNumberOfDetectors(dimension d) const { return multi_shm()->numberOfDetector[d]; @@ -1946,6 +1946,7 @@ void multiSlsDetector::setReceiverDataStreamingOutIP(const std::string &ip, } } + std::string multiSlsDetector::getReceiverStreamingIP(int detPos) { // single if (detPos >= 0) { From 56703c48867089c3045c3c40781b754ac4c1b519 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Fri, 9 Aug 2019 15:20:53 +0200 Subject: [PATCH 045/108] WIP --- slsDetectorSoftware/include/Detector.h | 35 ++++++- .../include/multiSlsDetector.h | 20 ++-- slsDetectorSoftware/src/Detector.cpp | 93 ++++++++++++++++--- 3 files changed, 122 insertions(+), 26 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 88bf5162f..beed21c63 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -854,7 +854,7 @@ class Detector { // TODO! // int enableDataStreamingToClient(int enable = -1); - // int enableDataStreamingFromReceiver(int enable = -1, int detPos = -1) + void enableDataStreamingFromReceiver(bool enable, Positions pos = {}); /** [TODO! All?] */ void setTenGigaEnabled(bool value, Positions pos = {}); @@ -1257,7 +1257,38 @@ class Detector { Result getReceiverStreamingPort(Positions pos = {}) const; - // void setReceiverDataStreamingOutPort(int i = -1, int detPos = -1); + /** Single detector or all since ports are calculated*/ + void setReceiverDataStreamingOutPort(int port, int module_id = -1); + + Result getClientStreamingPort(Positions pos = {}) const; + + /** Single detector or all since ports are calculated*/ + void setClientDataStreamingInPort(int port, int module_id = -1); + + /** [Jungfrau] */ + Result getSelectedUDPInterface(Positions pos = {}) const; + + /** + * [Jungfrau] + * @param interface interface to select, either 1 or 2 + * */ + void selectUDPInterface(int interface, Positions pos = {}); + + Result getNumberofUDPInterfaces(Positions pos = {}) const; + + void setNumberofUDPInterfaces(int n, Positions pos = {}); + + /** [Eiger][Jungfrau] */ + Result getReceiverUDPPort2(Positions pos = {}) const; + + /** [Eiger][Jungfrau] */ + void setReceiverUDPPort2(int udpport, Positions pos = {}); + + /** [Eiger][Jungfrau] */ + Result getReceiverUDPPort(Positions pos = {}) const; + + /** [Eiger][Jungfrau] */ + void setReceiverUDPPort(int udpport, Positions pos = {}); }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index a74ba2862..73195e606 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -1120,14 +1120,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the receiver UDP port */ - int setReceiverUDPPort(int udpport, int detPos = -1); + int setReceiverUDPPort(int udpport, int detPos = -1); // /** * Returns the receiver UDP port * @param detPos -1 for all detectors in list or specific detector position * @returns the receiver UDP port */ - int getReceiverUDPPort(int detPos = -1) const; + int getReceiverUDPPort(int detPos = -1) const; // /** * Sets the receiver UDP port 2 (Eiger and Jungfrau only) @@ -1135,7 +1135,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the receiver UDP port 2 */ - int setReceiverUDPPort2(int udpport, int detPos = -1); + int setReceiverUDPPort2(int udpport, int detPos = -1); // /** * Returns the receiver UDP port 2 of same interface (Eiger and Jungfrau @@ -1143,7 +1143,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the receiver UDP port 2 of same interface */ - int getReceiverUDPPort2(int detPos = -1) const; + int getReceiverUDPPort2(int detPos = -1) const; // /** * Sets the number of UDP interfaces to stream data from detector (Jungfrau @@ -1152,7 +1152,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the number of interfaces */ - int setNumberofUDPInterfaces(int n, int detPos = -1); + int setNumberofUDPInterfaces(int n, int detPos = -1); // /** * Returns the number of UDP interfaces to stream data from detector @@ -1160,7 +1160,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the number of interfaces */ - int getNumberofUDPInterfaces(int detPos = -1) const; + int getNumberofUDPInterfaces(int detPos = -1) const; // /** * Selects the UDP interfaces to stream data from detector. Effective only @@ -1177,7 +1177,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the interface selected */ - int getSelectedUDPInterface(int detPos = -1) const; + int getSelectedUDPInterface(int detPos = -1) const; // /** * (advanced users) @@ -1196,7 +1196,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the client zmq port */ - int getClientStreamingPort(int detPos = -1); + int getClientStreamingPort(int detPos = -1); // /** * (advanced users) @@ -1206,7 +1206,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * individual detectors using i * @param detPos -1 for all detectors in list or specific detector position */ - void setReceiverDataStreamingOutPort(int i = -1, int detPos = -1); + void setReceiverDataStreamingOutPort(int i = -1, int detPos = -1); // /** * Returns the receiver zmq port @@ -1215,7 +1215,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the receiver zmq port */ - int getReceiverStreamingPort(int detPos = -1); + int getReceiverStreamingPort(int detPos = -1); // /** * (advanced users) diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 80e6f40d7..9825a9a14 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -468,7 +468,8 @@ Result Detector::getMeasuredSubFramePeriod(Positions pos) const { } Result Detector::getSpeed(Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::CLOCK_DIVIDER, -1, 0); + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::CLOCK_DIVIDER, -1, + 0); } void Detector::setSpeed(int value, Positions pos) { @@ -476,7 +477,8 @@ void Detector::setSpeed(int value, Positions pos) { } Result Detector::getADCPhase(bool inDeg, Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_PHASE, -1, inDeg); + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_PHASE, -1, + inDeg); } void Detector::setADCPhase(int value, bool inDeg, Positions pos) { @@ -484,19 +486,23 @@ void Detector::setADCPhase(int value, bool inDeg, Positions pos) { } Result Detector::getMaxADCPhaseShift(Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::MAX_ADC_PHASE_SHIFT, -1, 0); + return pimpl->Parallel(&slsDetector::setSpeed, pos, + defs::MAX_ADC_PHASE_SHIFT, -1, 0); } Result Detector::getDBITPhase(bool inDeg, Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PHASE, -1, inDeg); + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PHASE, -1, + inDeg); } void Detector::setDBITPhase(int value, bool inDeg, Positions pos) { - pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PHASE, value, inDeg); + pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PHASE, value, + inDeg); } Result Detector::getMaxDBITPhaseShift(Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::MAX_DBIT_PHASE_SHIFT, -1, 0); + return pimpl->Parallel(&slsDetector::setSpeed, pos, + defs::MAX_DBIT_PHASE_SHIFT, -1, 0); } Result Detector::getADCClock(Positions pos) const { @@ -508,7 +514,8 @@ void Detector::setADCClock(int value, Positions pos) { } Result Detector::getDBITClock(Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_CLOCK, -1, 0); + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_CLOCK, -1, + 0); } void Detector::setDBITClock(int value, Positions pos) { @@ -516,7 +523,8 @@ void Detector::setDBITClock(int value, Positions pos) { } Result Detector::getRUNClock(Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::CLOCK_DIVIDER, -1, 0); + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::CLOCK_DIVIDER, -1, + 0); } void Detector::setRUNClock(int value, Positions pos) { @@ -524,11 +532,13 @@ void Detector::setRUNClock(int value, Positions pos) { } Result Detector::getSYNCClock(Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::SYNC_CLOCK, -1, 0); + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::SYNC_CLOCK, -1, + 0); } Result Detector::getADCPipeline(Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_PIPELINE, -1, 0); + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_PIPELINE, -1, + 0); } void Detector::setADCPipeline(int value, Positions pos) { @@ -536,7 +546,8 @@ void Detector::setADCPipeline(int value, Positions pos) { } Result Detector::getDBITPipeline(Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PIPELINE, -1, 0); + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PIPELINE, -1, + 0); } void Detector::setDBITPipeline(int value, Positions pos) { @@ -572,6 +583,11 @@ Result Detector::getReceiverStreamingTimer(Positions pos) const { return pimpl->Parallel(&slsDetector::setReceiverStreamingTimer, pos, -1); } +void Detector::enableDataStreamingFromReceiver(bool enable, Positions pos) { + pimpl->Parallel(&slsDetector::enableDataStreamingFromReceiver, pos, + static_cast(enable)); +} + void Detector::setTenGigaEnabled(bool value, Positions pos) { pimpl->Parallel(&slsDetector::enableTenGigabitEthernet, pos, static_cast(value)); @@ -1028,8 +1044,8 @@ void Detector::setReceiverDataStreamingOutIP(const std::string &ip, Positions pos) { // TODO! probably in one call pimpl->Parallel(&slsDetector::setReceiverStreamingIP, pos, ip); - pimpl->Parallel(&slsDetector::enableDataStreamingFromReceiver, pos, 0); - pimpl->Parallel(&slsDetector::enableDataStreamingFromReceiver, pos, 1); + enableDataStreamingFromReceiver(false, pos); + enableDataStreamingFromReceiver(true, pos); } Result Detector::getClientStreamingIP(Positions pos) const { @@ -1044,8 +1060,57 @@ void Detector::setClientDataStreamingInIP(const std::string &ip, pimpl->enableDataStreamingToClient(1); } -Result Detector::getReceiverStreamingPort(Positions pos) const{ +Result Detector::getReceiverStreamingPort(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverStreamingPort, pos); } +void Detector::setReceiverDataStreamingOutPort(int port, int module_id) { + pimpl->setReceiverDataStreamingOutPort(port, module_id); +} + +Result Detector::getClientStreamingPort(Positions pos) const { + return pimpl->Parallel(&slsDetector::getClientStreamingPort, pos); +} + +void Detector::setClientDataStreamingInPort(int port, int module_id) { + pimpl->setClientDataStreamingInPort(port, module_id); +} + +Result Detector::getSelectedUDPInterface(Positions pos) const { + return pimpl->Parallel(&slsDetector::getSelectedUDPInterface, pos); +} + +void Detector::selectUDPInterface(int interface, Positions pos) { + pimpl->Parallel(&slsDetector::selectUDPInterface, pos, interface); +} + +Result Detector::getNumberofUDPInterfaces(Positions pos) const { + return pimpl->Parallel(&slsDetector::getNumberofUDPInterfaces, pos); +} + +void Detector::setNumberofUDPInterfaces(int n, Positions pos) { + pimpl->Parallel(&slsDetector::setNumberofUDPInterfaces, pos, n); + + pimpl->enableDataStreamingToClient(0); + pimpl->enableDataStreamingToClient(1); + enableDataStreamingFromReceiver(false, pos); + enableDataStreamingFromReceiver(true, pos); +} + +Result Detector::getReceiverUDPPort2(Positions pos) const{ + pimpl->Parallel(&slsDetector::getReceiverUDPPort2, pos); +} + +void Detector::setReceiverUDPPort2(int udpport, Positions pos){ + pimpl->Parallel(&slsDetector::setReceiverUDPPort2, pos, udpport); +} + +Result Detector::getReceiverUDPPort(Positions pos) const{ + pimpl->Parallel(&slsDetector::getReceiverUDPPort2, pos); +} + +void Detector::setReceiverUDPPort(int udpport, Positions pos){ + pimpl->Parallel(&slsDetector::setReceiverUDPPort2, pos, udpport); +} + } // namespace sls \ No newline at end of file From 206740efd6fc3c96fc09362b31c7f19816a57909 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Fri, 9 Aug 2019 15:35:33 +0200 Subject: [PATCH 046/108] WIP --- slsDetectorSoftware/include/Detector.h | 9 +++++++-- slsDetectorSoftware/src/Detector.cpp | 7 +++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index beed21c63..01210f044 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -8,8 +8,7 @@ class multiSlsDetector; namespace sls { using ns = std::chrono::nanoseconds; -using Positions = const std::vector &; -using defs = slsDetectorDefs; +class MacAddr; /** * \class Detector @@ -1289,6 +1288,12 @@ class Detector { /** [Eiger][Jungfrau] */ void setReceiverUDPPort(int udpport, Positions pos = {}); + + /** [Jungfrau] */ + Result getReceiverUDPMAC2(Positions pos = {}) const; + + /** [Jungfrau] */ + void setReceiverUDPMAC2(const std::string &udpmac, Positions pos = {}); }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 9825a9a14..b8de96c73 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -1113,4 +1113,11 @@ void Detector::setReceiverUDPPort(int udpport, Positions pos){ pimpl->Parallel(&slsDetector::setReceiverUDPPort2, pos, udpport); } +Result Detector::getReceiverUDPMAC2(Positions pos) const{ + return pimpl->Parallel(&slsDetector::getReceiverUDPMAC2, pos); +} + +void Detector::setReceiverUDPMAC2(const std::string &udpmac, Positions pos){ + pimpl->Parallel(&slsDetector::setReceiverUDPMAC2, pos, udpmac); +} } // namespace sls \ No newline at end of file From dea402a7e718fe8055362f860b483eacd7f87842 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Fri, 9 Aug 2019 16:12:26 +0200 Subject: [PATCH 047/108] WIP --- slsDetectorSoftware/include/Detector.h | 44 +++++++++- .../include/multiSlsDetector.h | 32 ++++---- slsDetectorSoftware/src/Detector.cpp | 81 ++++++++++++++++--- 3 files changed, 130 insertions(+), 27 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 01210f044..1c2b92da9 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -9,6 +9,7 @@ class multiSlsDetector; namespace sls { using ns = std::chrono::nanoseconds; class MacAddr; +class IpAddr; /** * \class Detector @@ -1274,7 +1275,6 @@ class Detector { void selectUDPInterface(int interface, Positions pos = {}); Result getNumberofUDPInterfaces(Positions pos = {}) const; - void setNumberofUDPInterfaces(int n, Positions pos = {}); /** [Eiger][Jungfrau] */ @@ -1292,8 +1292,48 @@ class Detector { /** [Jungfrau] */ Result getReceiverUDPMAC2(Positions pos = {}) const; - /** [Jungfrau] */ + /** [Jungfrau] */ void setReceiverUDPMAC2(const std::string &udpmac, Positions pos = {}); + + Result getReceiverUDPMAC(Positions pos = {}) const; + void setReceiverUDPMAC(const std::string &udpmac, Positions pos = {}); + + /** [Jungfrau] */ + Result getReceiverUDPIP2(Positions pos = {}) const; + + /** [Jungfrau] */ + void setReceiverUDPIP2(const std::string &udpip, Positions pos = {}); + + Result getReceiverUDPIP(Positions pos = {}) const; + void setReceiverUDPIP(const std::string &udpip, Positions pos = {}); + + Result getReceiverHostname(Positions pos = {}) const; + + /** + * Validates and sets the receiver. + * Also updates the receiver with all the shared memory parameters + * significant for the receiver Also configures the detector to the receiver + * as UDP destination + * @param receiver receiver hostname or IP address */ + void setReceiverHostname(const std::string &receiver, Positions pos = {}); + + /** [Jungfrau] */ + Result getDetectorIP2(Positions pos = {}) const; + + /** [Jungfrau] */ + void setDetectorIP2(const std::string &detectorIP, Positions pos = {}); + + Result getDetectorIP(Positions pos = {}) const; + void setDetectorIP(const std::string &detectorIP, Positions pos = {}); + + Result getDetectorMAC(Positions pos = {}) const; + void setDetectorMAC(const std::string &detectorMAC, Positions pos = {}); + + /** [Jungfrau] */ + Result getDetectorMAC2(Positions pos = {}) const; + + /** [Jungfrau] */ + void setDetectorMAC2(const std::string &detectorMAC, Positions pos = {}); }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 73195e606..14cd4b1f8 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -976,14 +976,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the detector MAC address */ - std::string setDetectorMAC(const std::string &detectorMAC, int detPos = -1); + std::string setDetectorMAC(const std::string &detectorMAC, int detPos = -1); // /** * Returns the detector MAC address * @param detPos -1 for all detectors in list or specific detector position * @returns the detector MAC address */ - std::string getDetectorMAC(int detPos = -1); + std::string getDetectorMAC(int detPos = -1); // /** * Validates the format of the detector MAC address (bottom half) and sets @@ -993,14 +993,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns the detector MAC address (bottom half) */ std::string setDetectorMAC2(const std::string &detectorMAC, - int detPos = -1); + int detPos = -1); // /** * Returns the detector MAC address (bottom half) Jungfrau only * @param detPos -1 for all detectors in list or specific detector position * @returns the detector MAC address (bottom half) */ - std::string getDetectorMAC2(int detPos = -1); + std::string getDetectorMAC2(int detPos = -1); // /** * Validates the format of the detector IP address and sets it @@ -1008,14 +1008,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the detector IP address */ - std::string setDetectorIP(const std::string &detectorIP, int detPos = -1); + std::string setDetectorIP(const std::string &detectorIP, int detPos = -1); // /** * Returns the detector IP address * @param detPos -1 for all detectors in list or specific detector position * @returns the detector IP address */ - std::string getDetectorIP(int detPos = -1) const; + std::string getDetectorIP(int detPos = -1) const; // /** * Validates the format of the detector IP address (bottom half) and sets it @@ -1024,14 +1024,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the detector IP address (bottom half) */ - std::string setDetectorIP2(const std::string &detectorIP, int detPos = -1); + std::string setDetectorIP2(const std::string &detectorIP, int detPos = -1); // /** * Returns the detector IP address (bottom half) Jungfrau only * @param detPos -1 for all detectors in list or specific detector position * @returns the detector IP address (bottom half) */ - std::string getDetectorIP2(int detPos = -1) const; + std::string getDetectorIP2(int detPos = -1) const; // /** * Validates and sets the receiver. @@ -1043,14 +1043,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns the receiver IP address from shared memory */ std::string setReceiverHostname(const std::string &receiver, - int detPos = -1); + int detPos = -1); // /** * Returns the receiver IP address * @param detPos -1 for all detectors in list or specific detector position * @returns the receiver IP address */ - std::string getReceiverHostname(int detPos = -1) const; + std::string getReceiverHostname(int detPos = -1) const; // /** * Validates the format of the receiver UDP IP address and sets it @@ -1058,14 +1058,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the receiver UDP IP address */ - std::string setReceiverUDPIP(const std::string &udpip, int detPos = -1); + std::string setReceiverUDPIP(const std::string &udpip, int detPos = -1); // /** * Returns the receiver UDP IP address * @param detPos -1 for all detectors in list or specific detector position * @returns the receiver UDP IP address */ - std::string getReceiverUDPIP(int detPos = -1) const; + std::string getReceiverUDPIP(int detPos = -1) const; // /** * Validates the format of the receiver UDP IP address (bottom half) and @@ -1074,14 +1074,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the receiver UDP IP address (bottom half) */ - std::string setReceiverUDPIP2(const std::string &udpip, int detPos = -1); + std::string setReceiverUDPIP2(const std::string &udpip, int detPos = -1); // /** * Returns the receiver UDP IP address (bottom half) Jungfrau only * @param detPos -1 for all detectors in list or specific detector position * @returns the receiver UDP IP address (bottom half) */ - std::string getReceiverUDPIP2(int detPos = -1) const; + std::string getReceiverUDPIP2(int detPos = -1) const; // /** * Validates the format of the receiver UDP MAC address and sets it @@ -1089,14 +1089,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the receiver UDP MAC address */ - std::string setReceiverUDPMAC(const std::string &udpmac, int detPos = -1); + std::string setReceiverUDPMAC(const std::string &udpmac, int detPos = -1);// /** * Returns the receiver UDP MAC address * @param detPos -1 for all detectors in list or specific detector position * @returns the receiver UDP MAC address */ - std::string getReceiverUDPMAC(int detPos = -1) const; + std::string getReceiverUDPMAC(int detPos = -1) const; // /** * Validates the format of the receiver UDP MAC address (bottom half) and diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index b8de96c73..ceea070c4 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -1097,27 +1097,90 @@ void Detector::setNumberofUDPInterfaces(int n, Positions pos) { enableDataStreamingFromReceiver(true, pos); } -Result Detector::getReceiverUDPPort2(Positions pos) const{ - pimpl->Parallel(&slsDetector::getReceiverUDPPort2, pos); +Result Detector::getReceiverUDPPort2(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverUDPPort2, pos); } -void Detector::setReceiverUDPPort2(int udpport, Positions pos){ +void Detector::setReceiverUDPPort2(int udpport, Positions pos) { pimpl->Parallel(&slsDetector::setReceiverUDPPort2, pos, udpport); } -Result Detector::getReceiverUDPPort(Positions pos) const{ - pimpl->Parallel(&slsDetector::getReceiverUDPPort2, pos); +Result Detector::getReceiverUDPPort(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverUDPPort, pos); } -void Detector::setReceiverUDPPort(int udpport, Positions pos){ - pimpl->Parallel(&slsDetector::setReceiverUDPPort2, pos, udpport); +void Detector::setReceiverUDPPort(int udpport, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverUDPPort, pos, udpport); } -Result Detector::getReceiverUDPMAC2(Positions pos) const{ +Result Detector::getReceiverUDPMAC2(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverUDPMAC2, pos); } -void Detector::setReceiverUDPMAC2(const std::string &udpmac, Positions pos){ +void Detector::setReceiverUDPMAC2(const std::string &udpmac, Positions pos) { pimpl->Parallel(&slsDetector::setReceiverUDPMAC2, pos, udpmac); } + +Result Detector::getReceiverUDPMAC(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverUDPMAC, pos); +} + +void Detector::setReceiverUDPMAC(const std::string &udpmac, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverUDPMAC, pos, udpmac); +} + +Result Detector::getReceiverUDPIP2(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverUDPIP2, pos); +} + +void Detector::setReceiverUDPIP2(const std::string &udpip, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverUDPIP2, pos, udpip); +} + +Result Detector::getReceiverUDPIP(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverUDPIP, pos); +} + +void Detector::setReceiverUDPIP(const std::string &udpip, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverUDPIP, pos, udpip); +} + +Result Detector::getReceiverHostname(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverHostname, pos); +} + +void Detector::setReceiverHostname(const std::string &receiver, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverHostname, pos, receiver); +} + +Result Detector::getDetectorIP2(Positions pos) const{ + return pimpl->Parallel(&slsDetector::getDetectorIP2, pos); +} + +void Detector::setDetectorIP2(const std::string &detectorIP, Positions pos){ + pimpl->Parallel(&slsDetector::setDetectorIP2, pos, detectorIP); +} + +Result Detector::getDetectorIP(Positions pos) const{ + return pimpl->Parallel(&slsDetector::getDetectorIP, pos); +} + +void Detector::setDetectorIP(const std::string &detectorIP, Positions pos){ + pimpl->Parallel(&slsDetector::setDetectorIP, pos, detectorIP); +} + +Result Detector::getDetectorMAC(Positions pos) const{ + return pimpl->Parallel(&slsDetector::getDetectorMAC, pos); +} +void Detector::setDetectorMAC(const std::string &detectorMAC, Positions pos){ + pimpl->Parallel(&slsDetector::setDetectorMAC, pos, detectorMAC); +} + +Result Detector::getDetectorMAC2(Positions pos) const{ + return pimpl->Parallel(&slsDetector::getDetectorMAC2, pos); +} +void Detector::setDetectorMAC2(const std::string &detectorMAC, Positions pos){ + pimpl->Parallel(&slsDetector::setDetectorMAC2, pos, detectorMAC); +} + } // namespace sls \ No newline at end of file From 4a97dd0ebad39fe7452de43c3122d185e33a1d38 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Fri, 9 Aug 2019 16:16:15 +0200 Subject: [PATCH 048/108] WIP --- slsDetectorSoftware/include/Detector.h | 84 ++++++++- .../include/multiSlsDetector.h | 19 +- slsDetectorSoftware/include/slsDetector.h | 2 + slsDetectorSoftware/src/Detector.cpp | 173 ++++++++++++++++-- slsDetectorSoftware/src/multiSlsDetector.cpp | 47 +---- slsDetectorSoftware/src/slsDetector.cpp | 4 + 6 files changed, 263 insertions(+), 66 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 2bc8a533d..753798e81 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -826,6 +826,88 @@ class Detector { */ void setDBITPipeline(int value, Positions pos = {}); + Result getDynamicRange(Positions pos = {}) const; + + /** + * (Eiger: + * Options: 4, 8, 16, 32 + * If i is 32, also sets clkdivider to 2, if 16, sets clkdivider to 1) + */ + void setDynamicRange(int value); + + Result getHighVoltage(Positions pos = {}) const; + + /** + * (Gotthard Options: 0, 90, 110, 120, 150, 180, 200) + * (Jungfrau, CTB Options: 0, 60 - 200) + * (Eiger Options: 0 - 200) + */ + void setHighVoltage(int value, Positions pos = {}); + + /** + * (Eiger) + */ + Result getIODelay(Positions pos = {}) const; + + /** + * (Eiger) + */ + void setIODelay(int value, Positions pos = {}); + + /** + * (Degrees) + * (Gotthard Options: TEMPERATURE_ADC, TEMPERATURE_FPGA) + * (Jungfrau Options: TEMPERATURE_ADC, TEMPERATURE_FPGA) + * (Eiger Options: TEMPERATURE_FPGA, TEMPERATURE_FPGAEXT, TEMPERATURE_10GE, + * TEMPERATURE_DCDC, TEMPERATURE_SODL, TEMPERATURE_SODR, TEMPERATURE_FPGA2, + * TEMPERATURE_FPGA3) (CTB Options: SLOW_ADC_TEMP) + */ + Result getTemp(defs::dacIndex index, Positions pos = {}) const; + + /** + * (CTB mV) + */ + Result getVrefVoltage(bool mV, Positions pos = {}) const; + + /** + * (CTB mV) + */ + void setVrefVoltage(int value, bool mV, Positions pos = {}); + + /** + * (CTB mV Options: V_LIMIT, V_POWER_A, V_POWER_B, V_POWER_C, + * V_POWER_D, V_POWER_IO, V_POWER_CHIP)) + */ + Result getVoltage(defs::dacIndex index, Positions pos = {}) const; + + /** + * (CTB mV Options: V_LIMIT, V_POWER_A, V_POWER_B, V_POWER_C, + * V_POWER_D, V_POWER_IO, V_POWER_CHIP) + */ + void setVoltage(int value, defs::dacIndex index, Positions pos = {}); + + /** + * (CTB mV Options: V_POWER_A, V_POWER_B, V_POWER_C, V_POWER_D, V_POWER_IO, + * V_POWER_CHIP) + */ + Result getMeasuredVoltage(defs::dacIndex index, + Positions pos = {}) const; + + /** + * (CTB mA Options: I_POWER_A, I_POWER_B, I_POWER_C, I_POWER_D, I_POWER_IO) + */ + Result getMeasuredCurrent(defs::dacIndex index, + Positions pos = {}) const; + + /** + * (CTB Options: SLOW_ADC0 - SLOW_ADC7) + */ + Result getSlowADC(defs::dacIndex index, Positions pos = {}) const; + + Result getDAC(defs::dacIndex index, bool mV, Positions pos = {}) const; + + void setDAC(int value, defs::dacIndex index, bool mV, Positions pos = {}); + // Erik Result getFramesCaughtByReceiver(Positions pos = {}) const; @@ -1233,7 +1315,7 @@ class Detector { int setDetectorMinMaxEnergyThreshold(const int index, int value); void setAdditionalJsonHeader(const std::string &jsonheader, - Positions pos = {}); + Positions pos = {}); Result getAdditionalJsonHeader(Positions pos = {}) const; }; diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 4c8c85544..f177782f8 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -56,12 +56,6 @@ struct sharedMultiSlsDetector { /** Number of detectors operated at once */ int numberOfDetector[2]; - /** size of the data that are transfered from all detectors */ - int dataBytes; - - /** data bytes including gap pixels transferred from all detectors */ - int dataBytesInclGapPixels; - /** total number of channels for all detectors */ int numberOfChannels; @@ -863,14 +857,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns current dynamic range */ - int setDynamicRange(int dr = -1, int detPos = -1); - - /** - * Recalculated number of data bytes for multi detector - * @param detPos -1 for all detectors in list or specific detector position - * @returns tota number of data bytes for multi detector - */ - int getDataBytes(int detPos = -1); + int setDynamicRange(int dr = -1, int detPos = -1);// /** * Set/get dacs value @@ -880,7 +867,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns current DAC value */ - int setDAC(int val, dacIndex index, int mV, int detPos = -1); + int setDAC(int val, dacIndex index, int mV, int detPos = -1);// /** * Get adc value @@ -889,7 +876,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns current adc value (temperature for eiger and jungfrau in * millidegrees) */ - int getADC(dacIndex index, int detPos = -1); + int getADC(dacIndex index, int detPos = -1);// /** * Set/get timing mode diff --git a/slsDetectorSoftware/include/slsDetector.h b/slsDetectorSoftware/include/slsDetector.h index 9a270306a..cd9cc01e8 100755 --- a/slsDetectorSoftware/include/slsDetector.h +++ b/slsDetectorSoftware/include/slsDetector.h @@ -696,6 +696,8 @@ class slsDetector : public virtual slsDetectorDefs { */ int setDynamicRange(int n = -1); + int getDynamicRangeFromShm(); + /** * Recalculated number of data bytes * @returns tota number of data bytes diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 0cee028d1..7f288e641 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -468,7 +468,8 @@ Result Detector::getMeasuredSubFramePeriod(Positions pos) const { } Result Detector::getSpeed(Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::CLOCK_DIVIDER, -1, 0); + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::CLOCK_DIVIDER, -1, + 0); } void Detector::setSpeed(int value, Positions pos) { @@ -476,7 +477,8 @@ void Detector::setSpeed(int value, Positions pos) { } Result Detector::getADCPhase(bool inDeg, Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_PHASE, -1, inDeg); + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_PHASE, -1, + inDeg); } void Detector::setADCPhase(int value, bool inDeg, Positions pos) { @@ -484,19 +486,23 @@ void Detector::setADCPhase(int value, bool inDeg, Positions pos) { } Result Detector::getMaxADCPhaseShift(Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::MAX_ADC_PHASE_SHIFT, -1, 0); + return pimpl->Parallel(&slsDetector::setSpeed, pos, + defs::MAX_ADC_PHASE_SHIFT, -1, 0); } Result Detector::getDBITPhase(bool inDeg, Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PHASE, -1, inDeg); + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PHASE, -1, + inDeg); } void Detector::setDBITPhase(int value, bool inDeg, Positions pos) { - pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PHASE, value, inDeg); + pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PHASE, value, + inDeg); } Result Detector::getMaxDBITPhaseShift(Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::MAX_DBIT_PHASE_SHIFT, -1, 0); + return pimpl->Parallel(&slsDetector::setSpeed, pos, + defs::MAX_DBIT_PHASE_SHIFT, -1, 0); } Result Detector::getADCClock(Positions pos) const { @@ -508,7 +514,8 @@ void Detector::setADCClock(int value, Positions pos) { } Result Detector::getDBITClock(Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_CLOCK, -1, 0); + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_CLOCK, -1, + 0); } void Detector::setDBITClock(int value, Positions pos) { @@ -516,7 +523,8 @@ void Detector::setDBITClock(int value, Positions pos) { } Result Detector::getRUNClock(Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::CLOCK_DIVIDER, -1, 0); + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::CLOCK_DIVIDER, -1, + 0); } void Detector::setRUNClock(int value, Positions pos) { @@ -524,11 +532,13 @@ void Detector::setRUNClock(int value, Positions pos) { } Result Detector::getSYNCClock(Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::SYNC_CLOCK, -1, 0); + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::SYNC_CLOCK, -1, + 0); } Result Detector::getADCPipeline(Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_PIPELINE, -1, 0); + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_PIPELINE, -1, + 0); } void Detector::setADCPipeline(int value, Positions pos) { @@ -536,13 +546,154 @@ void Detector::setADCPipeline(int value, Positions pos) { } Result Detector::getDBITPipeline(Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PIPELINE, -1, 0); + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PIPELINE, -1, + 0); } void Detector::setDBITPipeline(int value, Positions pos) { pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PIPELINE, value, 0); } +Result Detector::getDynamicRange(Positions pos) const { + return pimpl->Parallel(&slsDetector::setDynamicRange, pos, -1); +} + +void Detector::setDynamicRange(int value) { pimpl->setDynamicRange(value); } + +Result Detector::getHighVoltage(Positions pos) const { + return pimpl->Parallel(&slsDetector::setDAC, pos, -1, defs::HIGH_VOLTAGE, + 0); +} + +void Detector::setHighVoltage(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setDAC, pos, value, defs::HIGH_VOLTAGE, 0); +} + +Result Detector::getIODelay(Positions pos) const { + return pimpl->Parallel(&slsDetector::setDAC, pos, -1, defs::IO_DELAY, 0); +} + +void Detector::setIODelay(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setDAC, pos, value, defs::IO_DELAY, 0); +} + +Result Detector::getTemp(defs::dacIndex index, Positions pos) const { + switch (index) { + case defs::TEMPERATURE_ADC: + case defs::TEMPERATURE_FPGA: + case defs::TEMPERATURE_FPGAEXT: + case defs::TEMPERATURE_10GE: + case defs::TEMPERATURE_DCDC: + case defs::TEMPERATURE_SODL: + case defs::TEMPERATURE_SODR: + case defs::TEMPERATURE_FPGA2: + case defs::TEMPERATURE_FPGA3: + case defs::SLOW_ADC_TEMP: + break; + default: + throw RuntimeError("Unknown Temperature Index"); + } + auto res = pimpl->Parallel(&slsDetector::getADC, pos, index); + switch (getDetectorType()) { + case defs::EIGER: + case defs::JUNGFRAU: + for (auto it : pos) { + it /= 1000; + } + break; + default: + break; + } + return res; +} + +Result Detector::getVrefVoltage(bool mV, Positions pos) const { + return pimpl->Parallel(&slsDetector::setDAC, pos, -1, defs::ADC_VPP, mV); +} + +void Detector::setVrefVoltage(int value, bool mV, Positions pos) { + pimpl->Parallel(&slsDetector::setDAC, pos, value, defs::ADC_VPP, mV); +} + +Result Detector::getVoltage(defs::dacIndex index, Positions pos) const { + switch (index) { + case defs::V_LIMIT: + case defs::V_POWER_A: + case defs::V_POWER_B: + case defs::V_POWER_C: + case defs::V_POWER_D: + case defs::V_POWER_IO: + case defs::V_POWER_CHIP: + break; + default: + throw RuntimeError("Unknown Voltage Index"); + } + return pimpl->Parallel(&slsDetector::setDAC, pos, -1, index, 1); +} + +void Detector::setVoltage(int value, defs::dacIndex index, Positions pos) { + switch (index) { + case defs::V_LIMIT: + case defs::V_POWER_A: + case defs::V_POWER_B: + case defs::V_POWER_C: + case defs::V_POWER_D: + case defs::V_POWER_IO: + case defs::V_POWER_CHIP: + break; + default: + throw RuntimeError("Unknown Voltage Index"); + } + pimpl->Parallel(&slsDetector::setDAC, pos, value, index, 1); +} + +Result Detector::getMeasuredVoltage(defs::dacIndex index, + Positions pos) const { + switch (index) { + case defs::V_POWER_A: + case defs::V_POWER_B: + case defs::V_POWER_C: + case defs::V_POWER_D: + case defs::V_POWER_IO: + case defs::V_POWER_CHIP: + break; + default: + throw RuntimeError("Unknown Voltage Index"); + } + return pimpl->Parallel(&slsDetector::getADC, pos, index); +} + +Result Detector::getMeasuredCurrent(defs::dacIndex index, + Positions pos) const { + switch (index) { + case defs::I_POWER_A: + case defs::I_POWER_B: + case defs::I_POWER_C: + case defs::I_POWER_D: + case defs::I_POWER_IO: + break; + default: + throw RuntimeError("Unknown Current Index"); + } + return pimpl->Parallel(&slsDetector::getADC, pos, index); +} + +Result Detector::getSlowADC(defs::dacIndex index, Positions pos) const { + if (index < defs::SLOW_ADC0 || index > defs::SLOW_ADC7) { + throw RuntimeError("Unknown Slow ADC Index"); + } + return pimpl->Parallel(&slsDetector::getADC, pos, index); +} + +Result Detector::getDAC(defs::dacIndex index, bool mV, + Positions pos) const { + return pimpl->Parallel(&slsDetector::setDAC, pos, -1, index, mV); +} + +void Detector::setDAC(int value, defs::dacIndex index, bool mV, Positions pos) { + pimpl->Parallel(&slsDetector::setDAC, pos, value, index, mV); +} + // Erik Result Detector::getFramesCaughtByReceiver(Positions pos) const { return pimpl->Parallel(&slsDetector::getFramesCaughtByReceiver, pos); diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index 843fb1f41..919159bd6 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -278,8 +278,6 @@ void multiSlsDetector::initializeDetectorStructure() { multi_shm()->multiDetectorType = GENERIC; multi_shm()->numberOfDetector[X] = 0; multi_shm()->numberOfDetector[Y] = 0; - multi_shm()->dataBytes = 0; - multi_shm()->dataBytesInclGapPixels = 0; multi_shm()->numberOfChannels = 0; multi_shm()->numberOfChannel[X] = 0; multi_shm()->numberOfChannel[Y] = 0; @@ -624,9 +622,6 @@ void multiSlsDetector::addSlsDetector(const std::string &hostname) { detectors.push_back( sls::make_unique(type, multiId, pos, false)); multi_shm()->numberOfDetectors = detectors.size(); - multi_shm()->dataBytes += detectors[pos]->getDataBytes(); - multi_shm()->dataBytesInclGapPixels += - detectors[pos]->getDataBytesInclGapPixels(); multi_shm()->numberOfChannels += detectors[pos]->getTotalNumberOfChannels(); detectors[pos]->setHostname(hostname); @@ -1264,22 +1259,18 @@ int multiSlsDetector::setDynamicRange(int dr, int detPos) { } // multi + int prevValue = -1; + auto temp = Parallel(&slsDetector::getDynamicRangeFromShm, {}); + if (temp.equal()) { + prevValue = temp.squash(); + } + auto r = parallelCall(&slsDetector::setDynamicRange, dr); int ret = sls::minusOneIfDifferent(r); - // update shm - int prevValue = multi_shm()->dataBytes; - int prevGValue = multi_shm()->dataBytesInclGapPixels; - multi_shm()->dataBytes = 0; - multi_shm()->dataBytesInclGapPixels = 0; - for (auto &d : detectors) { - multi_shm()->dataBytes += d->getDataBytes(); - multi_shm()->dataBytesInclGapPixels += d->getDataBytesInclGapPixels(); - } - - // if there was a change FIXME:add dr to sls shm and check that instead - if ((prevValue != multi_shm()->dataBytes) || - (prevGValue != multi_shm()->dataBytesInclGapPixels)) { + + // change in dr + if (dr != -1 && dr != prevValue) { updateOffsets(); @@ -1312,17 +1303,6 @@ int multiSlsDetector::setDynamicRange(int dr, int detPos) { return ret; } -int multiSlsDetector::getDataBytes(int detPos) { - // single - if (detPos >= 0) { - return detectors[detPos]->getDataBytes(); - } - - // multi - auto r = parallelCall(&slsDetector::getDataBytes); - return sls::sum(r); -} - int multiSlsDetector::setDAC(int val, dacIndex index, int mV, int detPos) { // single if (detPos >= 0) { @@ -2699,12 +2679,7 @@ int multiSlsDetector::enableGapPixels(int val, int detPos) { auto r = parallelCall(&slsDetector::enableGapPixels, val); int ret = sls::minusOneIfDifferent(r); - // update data bytes incl gap pixels if (val != -1) { - auto r2 = serialCall(&slsDetector::getDataBytesInclGapPixels); - multi_shm()->dataBytesInclGapPixels = sls::sum(r2); - - // update updateOffsets(); } return ret; @@ -2713,11 +2688,7 @@ int multiSlsDetector::enableGapPixels(int val, int detPos) { void multiSlsDetector::setGapPixelsEnable(bool enable, Positions pos){ Parallel(&slsDetector::enableGapPixels, pos, static_cast(enable)); - // update data bytes incl gap pixels - auto r2 = serialCall(&slsDetector::getDataBytesInclGapPixels); - multi_shm()->dataBytesInclGapPixels = sls::sum(r2); updateOffsets(); - } int multiSlsDetector::setTrimEn(std::vector energies, int detPos) { diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index 0f23a319a..37ef4f634 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -1539,6 +1539,10 @@ int slsDetector::setDynamicRange(int n) { return shm()->dynamicRange; } +int slsDetector::getDynamicRangeFromShm() { + return shm()->dynamicRange; +} + int slsDetector::getDataBytes() { return shm()->dataBytes; } int slsDetector::getDataBytesInclGapPixels() { From 6a89e3e1a59ab3df4bfbff372d0c937ea7385c8a Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Fri, 9 Aug 2019 16:35:26 +0200 Subject: [PATCH 049/108] WIP --- python/src/experimental.cpp | 2 +- slsDetectorSoftware/include/Detector.h | 17 +++++++---- .../include/multiSlsDetector.h | 2 +- slsDetectorSoftware/src/Detector.cpp | 30 +++++++++++++------ 4 files changed, 34 insertions(+), 17 deletions(-) diff --git a/python/src/experimental.cpp b/python/src/experimental.cpp index b8ae33d4f..c7cb0db91 100644 --- a/python/src/experimental.cpp +++ b/python/src/experimental.cpp @@ -35,7 +35,7 @@ void init_experimental(py::module &m) { py::arg() = Positions{}) .def("clearBit", &Detector::clearBit, py::arg(), py::arg(), py::arg() = Positions{}) - .def("getRegister", &Detector::getRegister, py::arg(), + .def("readRegister", &Detector::readRegister, py::arg(), py::arg() = Positions{}) .def("getStartingFrameNumber", &Detector::getStartingFrameNumber, diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 1c2b92da9..928e8214d 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -81,12 +81,9 @@ class Detector { */ void setBit(uint32_t addr, int bitnr, Positions pos = {}); - /** - * Reads 32 bit register from detector - * @param addr address of the register - * @returns value read from register - */ - Result getRegister(uint32_t addr, Positions pos = {}); + + Result readRegister(uint32_t addr, Positions pos = {}) const; + void writeRegister(uint32_t addr, uint32_t val, Positions pos = {}); /************************************************** * * @@ -1324,9 +1321,11 @@ class Detector { void setDetectorIP2(const std::string &detectorIP, Positions pos = {}); Result getDetectorIP(Positions pos = {}) const; + void setDetectorIP(const std::string &detectorIP, Positions pos = {}); Result getDetectorMAC(Positions pos = {}) const; + void setDetectorMAC(const std::string &detectorMAC, Positions pos = {}); /** [Jungfrau] */ @@ -1334,6 +1333,12 @@ class Detector { /** [Jungfrau] */ void setDetectorMAC2(const std::string &detectorMAC, Positions pos = {}); + + /** [Eiger] */ + Result getInterruptSubframe(Positions pos = {}) const; + + /** [Eiger] when set the last subframe is interrupted at end of acq*/ + void setInterruptSubframe(const bool enable, Positions pos = {}); }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 14cd4b1f8..4a33a3a34 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -942,7 +942,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns value read after writing */ - uint32_t writeRegister(uint32_t addr, uint32_t val, int detPos = -1); + uint32_t writeRegister(uint32_t addr, uint32_t val, int detPos = -1); // /** * Read from a register. For Advanced users diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index ceea070c4..b0ccdbf7c 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -47,7 +47,11 @@ void Detector::clearBit(uint32_t addr, int bitnr, Positions pos) { void Detector::setBit(uint32_t addr, int bitnr, Positions pos) { pimpl->Parallel(&slsDetector::setBit, pos, addr, bitnr); } -Result Detector::getRegister(uint32_t addr, Positions pos) { +void Detector::writeRegister(uint32_t addr, uint32_t val, Positions pos) { + pimpl->Parallel(&slsDetector::writeRegister, pos, addr, val); +} + +Result Detector::readRegister(uint32_t addr, Positions pos) const { return pimpl->Parallel(&slsDetector::readRegister, pos, addr); } @@ -1153,34 +1157,42 @@ void Detector::setReceiverHostname(const std::string &receiver, Positions pos) { pimpl->Parallel(&slsDetector::setReceiverHostname, pos, receiver); } -Result Detector::getDetectorIP2(Positions pos) const{ +Result Detector::getDetectorIP2(Positions pos) const { return pimpl->Parallel(&slsDetector::getDetectorIP2, pos); } -void Detector::setDetectorIP2(const std::string &detectorIP, Positions pos){ +void Detector::setDetectorIP2(const std::string &detectorIP, Positions pos) { pimpl->Parallel(&slsDetector::setDetectorIP2, pos, detectorIP); } -Result Detector::getDetectorIP(Positions pos) const{ +Result Detector::getDetectorIP(Positions pos) const { return pimpl->Parallel(&slsDetector::getDetectorIP, pos); } -void Detector::setDetectorIP(const std::string &detectorIP, Positions pos){ +void Detector::setDetectorIP(const std::string &detectorIP, Positions pos) { pimpl->Parallel(&slsDetector::setDetectorIP, pos, detectorIP); } -Result Detector::getDetectorMAC(Positions pos) const{ +Result Detector::getDetectorMAC(Positions pos) const { return pimpl->Parallel(&slsDetector::getDetectorMAC, pos); } -void Detector::setDetectorMAC(const std::string &detectorMAC, Positions pos){ +void Detector::setDetectorMAC(const std::string &detectorMAC, Positions pos) { pimpl->Parallel(&slsDetector::setDetectorMAC, pos, detectorMAC); } -Result Detector::getDetectorMAC2(Positions pos) const{ +Result Detector::getDetectorMAC2(Positions pos) const { return pimpl->Parallel(&slsDetector::getDetectorMAC2, pos); } -void Detector::setDetectorMAC2(const std::string &detectorMAC, Positions pos){ +void Detector::setDetectorMAC2(const std::string &detectorMAC, Positions pos) { pimpl->Parallel(&slsDetector::setDetectorMAC2, pos, detectorMAC); } +Result Detector::getInterruptSubframe(Positions pos) const { + return pimpl->Parallel(&slsDetector::getInterruptSubframe, pos); +} + +void Detector::setInterruptSubframe(const bool enable, Positions pos){ + pimpl->Parallel(&slsDetector::setInterruptSubframe, pos, enable); +} + } // namespace sls \ No newline at end of file From b2d39d4785b911b9fee1dc18a7fe7387d8486c89 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Fri, 9 Aug 2019 17:19:12 +0200 Subject: [PATCH 050/108] WIP done --- slsDetectorGui/src/qTabAdvanced.cpp | 2 +- slsDetectorGui/src/qTabDataOutput.cpp | 2 +- slsDetectorGui/src/qTabDebugging.cpp | 2 +- slsDetectorGui/src/qTabDeveloper.cpp | 2 +- slsDetectorSoftware/include/Detector.h | 48 ++++++++++ .../include/multiSlsDetector.h | 6 +- .../include/multiSlsDetectorClient.h | 2 +- slsDetectorSoftware/src/Detector.cpp | 80 ++++++++++++++++- .../src/slsDetectorCommand.cpp | 7 +- slsSupportLib/include/sls_detector_defs.h | 87 ++----------------- 10 files changed, 142 insertions(+), 96 deletions(-) diff --git a/slsDetectorGui/src/qTabAdvanced.cpp b/slsDetectorGui/src/qTabAdvanced.cpp index 0faad922a..f1924f06e 100755 --- a/slsDetectorGui/src/qTabAdvanced.cpp +++ b/slsDetectorGui/src/qTabAdvanced.cpp @@ -124,7 +124,7 @@ void qTabAdvanced::PopulateDetectors() { SLOT(SetDetector(int))); comboDetector->clear(); - for (int i = 0; i < myDet->size(); ++i) + for (unsigned int i = 0; i < myDet->size(); ++i) comboDetector->addItem(QString(myDet->getHostname(i).c_str())); comboDetector->setCurrentIndex(0); diff --git a/slsDetectorGui/src/qTabDataOutput.cpp b/slsDetectorGui/src/qTabDataOutput.cpp index da7b9d55b..afe65f3c3 100755 --- a/slsDetectorGui/src/qTabDataOutput.cpp +++ b/slsDetectorGui/src/qTabDataOutput.cpp @@ -81,7 +81,7 @@ void qTabDataOutput::PopulateDetectors() { comboDetector->clear(); comboDetector->addItem("All"); if (myDet->size() > 1) { - for (int i = 0; i < myDet->size(); ++i) + for (unsigned int i = 0; i < myDet->size(); ++i) comboDetector->addItem(QString(myDet->getHostname(i).c_str())); } } diff --git a/slsDetectorGui/src/qTabDebugging.cpp b/slsDetectorGui/src/qTabDebugging.cpp index a62373c50..b9666f465 100755 --- a/slsDetectorGui/src/qTabDebugging.cpp +++ b/slsDetectorGui/src/qTabDebugging.cpp @@ -55,7 +55,7 @@ void qTabDebugging::PopulateDetectors() { FILE_LOG(logDEBUG) << "Populating detectors"; comboDetector->clear(); - for (int i = 0; i < myDet->size(); ++i) { + for (unsigned int i = 0; i < myDet->size(); ++i) { comboDetector->addItem(QString(myDet->getHostname(i).c_str())); } } diff --git a/slsDetectorGui/src/qTabDeveloper.cpp b/slsDetectorGui/src/qTabDeveloper.cpp index 7326740ad..122c4daf0 100755 --- a/slsDetectorGui/src/qTabDeveloper.cpp +++ b/slsDetectorGui/src/qTabDeveloper.cpp @@ -125,7 +125,7 @@ void qTabDeveloper::PopulateDetectors() { comboDetector->clear(); comboDetector->addItem("All"); if (myDet->size() > 1) { - for (int i = 0; i < myDet->size(); ++i) + for (unsigned int i = 0; i < myDet->size(); ++i) comboDetector->addItem(QString(myDet->getHostname(i).c_str())); } comboDetector->setCurrentIndex(0); diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 97a2ba2e6..2ec121fed 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -908,6 +908,54 @@ class Detector { void setDAC(int value, defs::dacIndex index, bool mV, Positions pos = {}); + Result getTimingMode(Positions pos = {}) const; + + /** + * (Gotthard, Jungfrau, CTB Options: AUTO_TIMING, TRIGGER_EXPOSURE) + * (Eiger Options: AUTO_TIMING, TRIGGER_EXPOSURE, GATED, BURST_TRIGGER) + */ + void setTimingMode(defs::externalCommunicationMode value, Positions pos = {}); + + /** + * (Gotthard) + */ + Result getExternalSignalFlags(Positions pos = {}) const; + + /** + * (Gotthard Options: TRIGGER_IN_RISING_EDGE, TRIGGER_IN_FALLING_EDGE) + */ + void setExternalSignalFlags(defs::externalSignalFlag value, Positions pos = {}); + + /** + * (Eiger) + */ + Result getParallelMode(Positions pos = {}) const; + + /** + * (Eiger) + */ + void setParallelMode(bool value, Positions pos = {}); + + /** + * (Eiger) + */ + Result getOverFlowMode(Positions pos = {}) const; + + /** + * (Eiger) + */ + void setOverFlowMode(bool value, Positions pos = {}); + + /** + * (CTB Options: NORMAL_READOUT = 0, DIGITAL_ONLY = 1, ANALOG_AND_DIGITAL = 2) + */ + Result getSignalType(Positions pos = {}) const; + + /** + * (CTB Options: NORMAL_READOUT = 0, DIGITAL_ONLY = 1, ANALOG_AND_DIGITAL = 2) + */ + void setSignalType(int value, Positions pos = {}); + // Erik Result getFramesCaughtByReceiver(Positions pos = {}) const; diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index a5929c2f5..d9b36a25e 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -886,7 +886,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ externalCommunicationMode setExternalCommunicationMode( externalCommunicationMode pol = GET_EXTERNAL_COMMUNICATION_MODE, - int detPos = -1); + int detPos = -1);// /** * Set/get external signal flags (to specify triggerinrising edge etc) @@ -897,7 +897,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ externalSignalFlag setExternalSignalFlags(externalSignalFlag pol = GET_EXTERNAL_SIGNAL_FLAG, - int detPos = -1); + int detPos = -1);// /** * Set/get readout flags (Eiger, Mythen) @@ -906,7 +906,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns readout flag */ - int setReadOutFlags(readOutFlags flag = GET_READOUT_FLAGS, int detPos = -1); + int setReadOutFlags(readOutFlags flag = GET_READOUT_FLAGS, int detPos = -1);// /** * Set Interrupt last sub frame (Only for Eiger) diff --git a/slsDetectorSoftware/include/multiSlsDetectorClient.h b/slsDetectorSoftware/include/multiSlsDetectorClient.h index c627d1813..e72e61332 100755 --- a/slsDetectorSoftware/include/multiSlsDetectorClient.h +++ b/slsDetectorSoftware/include/multiSlsDetectorClient.h @@ -101,7 +101,7 @@ class multiSlsDetectorClient { return; } } - if (parser.detector_id() >= detPtr->size()) { + if (parser.detector_id() >= static_cast(detPtr->size())) { os << "position is out of bounds.\n"; return; } diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 4f1ccdd86..c78da583a 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -597,7 +597,7 @@ Result Detector::getTemp(defs::dacIndex index, Positions pos) const { switch (getDetectorType()) { case defs::EIGER: case defs::JUNGFRAU: - for (auto it : pos) { + for (auto &it : res) { it /= 1000; } break; @@ -694,6 +694,82 @@ void Detector::setDAC(int value, defs::dacIndex index, bool mV, Positions pos) { pimpl->Parallel(&slsDetector::setDAC, pos, value, index, mV); } + Result Detector::getTimingMode(Positions pos) const { + return pimpl->Parallel(&slsDetector::setExternalCommunicationMode, pos, defs::GET_EXTERNAL_COMMUNICATION_MODE); + } + + void Detector::setTimingMode(defs::externalCommunicationMode value, Positions pos) { + pimpl->Parallel(&slsDetector::setExternalCommunicationMode, pos, value); + } + + Result Detector::getExternalSignalFlags(Positions pos) const { + return pimpl->Parallel(&slsDetector::setExternalSignalFlags, pos, defs::GET_EXTERNAL_SIGNAL_FLAG); + } + + void Detector::setExternalSignalFlags(defs::externalSignalFlag value, Positions pos) { + pimpl->Parallel(&slsDetector::setExternalSignalFlags, pos, value); + } + + Result Detector::getParallelMode(Positions pos) const { + auto res = pimpl->Parallel(&slsDetector::setReadOutFlags, pos, defs::GET_READOUT_FLAGS); + Result booleanRes; + for (unsigned int i = 0; i < res.size(); ++i) { + booleanRes[i] = (res[i] & defs::PARALLEL) ? true : false; + } + return booleanRes; + } + + void Detector::setParallelMode(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setReadOutFlags, pos, value ? defs::PARALLEL : defs::NONPARALLEL); + } + + Result Detector::getOverFlowMode(Positions pos) const { + auto res = pimpl->Parallel(&slsDetector::setReadOutFlags, pos, defs::GET_READOUT_FLAGS); + Result booleanRes; + for (unsigned int i = 0; i < res.size(); ++i) { + booleanRes[i] = (res[i] & defs::SHOW_OVERFLOW) ? true : false; + } + return booleanRes; + } + + void Detector::setOverFlowMode(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setReadOutFlags, pos, value ? defs::SHOW_OVERFLOW : defs::NOOVERFLOW); + } + + Result Detector::getSignalType(Positions pos) const { + auto res = pimpl->Parallel(&slsDetector::setReadOutFlags, pos, defs::GET_READOUT_FLAGS); + for (auto &it : res) { + if (it & defs::ANALOG_AND_DIGITAL) { + it = 2; + } else if (it & defs::DIGITAL_ONLY) { + it = 1; + } else if (it == defs::NORMAL_READOUT) { + it = 0; + } else { + throw RuntimeError("Unknown Signal Type"); + } + } + return res; + } + + void Detector::setSignalType(int value, Positions pos) { + defs::readOutFlags flag; + switch (value) { + case 0: + flag = defs::NORMAL_READOUT; + break; + case 1: + flag = defs::DIGITAL_ONLY; + break; + case 2: + flag = defs::ANALOG_AND_DIGITAL; + break; + default: + throw RuntimeError("Unknown Signal Type"); + } + pimpl->Parallel(&slsDetector::setReadOutFlags, pos, flag); + } + // Erik Result Detector::getFramesCaughtByReceiver(Positions pos) const { return pimpl->Parallel(&slsDetector::getFramesCaughtByReceiver, pos); @@ -912,7 +988,7 @@ Result Detector::getAutoCompDisable(Positions pos) const { void Detector::setPowerChip(bool on, Positions pos) { if (on && pimpl->size() > 3) { - for (int i = 0; i != pimpl->size(); ++i) { + for (unsigned int i = 0; i != pimpl->size(); ++i) { pimpl->powerChip(static_cast(on), i); usleep(1000 * 1000); } diff --git a/slsDetectorSoftware/src/slsDetectorCommand.cpp b/slsDetectorSoftware/src/slsDetectorCommand.cpp index c2a00202f..5243ef95b 100755 --- a/slsDetectorSoftware/src/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp @@ -378,8 +378,7 @@ slsDetectorCommand::slsDetectorCommand(multiSlsDetector *det) { ++i; /*! \page config - - extsig [flag] sets/gets the mode of the external signal. Options: \c off, \c trigger_in_rising_edge, \c trigger_in_falling_edge, - \c trigger_out_rising_edge, \c trigger_out_falling_edge\n Used in GOTTHARDonly. \c Returns \c (string) + - extsig [flag] sets/gets the mode of the external signal. Options: \c trigger_in_rising_edge, \c trigger_in_falling_edge. Used in GOTTHARDonly. \c Returns \c (string) */ descrToFuncMap[i].m_pFuncName = "extsig"; /* find command! */ descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdAdvanced; @@ -4815,7 +4814,7 @@ std::string slsDetectorCommand::helpAdvanced(int action) { std::ostringstream os; if (action == PUT_ACTION || action == HELP_ACTION) { - os << "extsig mode \t sets the mode of the external signal. can be \n \t \t \t off, \n \t \t \t trigger_in_rising_edge, \n \t \t \t trigger_in_falling_edge, \n \t \t \t trigger_out_rising_edge, \n \t \t \t trigger_out_falling_edge" << std::endl; + os << "extsig mode \t sets the mode of the external signal. can be trigger_out_rising_edge, trigger_out_falling_edge. Gotthard only" << std::endl; os << "flags mode \t sets the readout flags to mode. can be none, storeinram, tot, continous, parallel, nonparallel, digital, analog_digital, overlow, nooverflow, unknown." << std::endl; os << "interruptsubframe flag \t sets the interrupt subframe flag. Setting it to 1 will interrupt the last subframe at the required exposure time. By default, this is disabled and set to 0, ie. it will wait for the last sub frame to finish exposing. Used for EIGER in 32 bit mode only." << std::endl; os << "readnlines f \t sets the number of rows to read out per half module. Options: 1 - 256 (Not all values as it depends on dynamic range and 10GbE enabled). Used for EIGER only. " << std::endl; @@ -4831,7 +4830,7 @@ std::string slsDetectorCommand::helpAdvanced(int action) { } if (action == GET_ACTION || action == HELP_ACTION) { - os << "extsig \t gets the mode of the external signal. can be \n \t \t \t off, \n \t \t \t trigger_in_rising_edge, \n \t \t \t trigger_in_falling_edge, \n \t \t \t trigger_out_rising_edge, \n \t \t \t trigger_out_falling_edge" << std::endl; + os << "extsig \t gets the mode of the external signal. can be trigger_in_rising_edge, trigger_in_falling_edge. Gotthard only" << std::endl; os << "flags \t gets the readout flags. can be none, storeinram, tot, continous, parallel, nonparallel, digital, analog_digital, overflow, nooverflow, unknown" << std::endl; os << "interruptsubframe \t gets the interrupt subframe flag. Setting it to 1 will interrupt the last subframe at the required exposure time. By default, this is disabled and set to 0, ie. it will wait for the last sub frame to finish exposing. Used for EIGER in 32 bit mode only." << std::endl; os << "readnlines \t gets the number of rows to read out per half module. Used for EIGER only. " << std::endl; diff --git a/slsSupportLib/include/sls_detector_defs.h b/slsSupportLib/include/sls_detector_defs.h index 141ccd768..e224a319f 100755 --- a/slsSupportLib/include/sls_detector_defs.h +++ b/slsSupportLib/include/sls_detector_defs.h @@ -673,108 +673,31 @@ format }; /** returns std::string from external signal type index - \param f can be SIGNAL_OFF, GATE_IN_ACTIVE_HIGH, GATE_IN_ACTIVE_LOW, - TRIGGER_IN_RISING_EDGE, TRIGGER_IN_FALLING_EDGE, - RO_TRIGGER_IN_RISING_EDGE, RO_TRIGGER_IN_FALLING_EDGE, - GATE_OUT_ACTIVE_HIGH, GATE_OUT_ACTIVE_LOW, =TRIGGER_OUT_RISING_EDGE, - TRIGGER_OUT_FALLING_EDGE, RO_TRIGGER_OUT_RISING_EDGE, - RO_TRIGGER_OUT_FALLING_EDGE, OUTPUT_LOW, OUTPUT_HIGH, - MASTER_SLAVE_SYNCHRONIZATION, GET_EXTERNAL_SIGNAL_FLAG \returns - std::string off, gate_in_active_high, gate_in_active_low, - trigger_in_rising_edge, trigger_in_falling_edge, - ro_trigger_in_rising_edge, ro_trigger_in_falling_edge, - gate_out_active_high, gate_out_active_low, trigger_out_rising_edge, - trigger_out_falling_edge, ro_trigger_out_rising_edge, - ro_trigger_out_falling_edge, gnd, vcc, sync, unknown + \param f can be TRIGGER_IN_RISING_EDGE, TRIGGER_IN_FALLING_EDGE, + \returns std::string trigger_in_rising_edge, trigger_in_falling_edge, unknown */ static std::string externalSignalType(externalSignalFlag f) { switch (f) { - case SIGNAL_OFF: - return std::string("off"); - case GATE_IN_ACTIVE_HIGH: - return std::string("gate_in_active_high"); - case GATE_IN_ACTIVE_LOW: - return std::string("gate_in_active_low"); case TRIGGER_IN_RISING_EDGE: return std::string("trigger_in_rising_edge"); case TRIGGER_IN_FALLING_EDGE: return std::string("trigger_in_falling_edge"); - case RO_TRIGGER_IN_RISING_EDGE: - return std::string("ro_trigger_in_rising_edge"); - case RO_TRIGGER_IN_FALLING_EDGE: - return std::string("ro_trigger_in_falling_edge"); - case GATE_OUT_ACTIVE_HIGH: - return std::string("gate_out_active_high"); - case GATE_OUT_ACTIVE_LOW: - return std::string("gate_out_active_low"); - case TRIGGER_OUT_RISING_EDGE: - return std::string("trigger_out_rising_edge"); - case TRIGGER_OUT_FALLING_EDGE: - return std::string("trigger_out_falling_edge"); - case RO_TRIGGER_OUT_RISING_EDGE: - return std::string("ro_trigger_out_rising_edge"); - case RO_TRIGGER_OUT_FALLING_EDGE: - return std::string("ro_trigger_out_falling_edge"); - case MASTER_SLAVE_SYNCHRONIZATION: - return std::string("sync"); - case OUTPUT_LOW: - return std::string("gnd"); - case OUTPUT_HIGH: - return std::string("vcc"); default: return std::string("unknown"); } }; /** returns external signal type index from std::string - \param sval off, gate_in_active_high, gate_in_active_low, - trigger_in_rising_edge, trigger_in_falling_edge, - ro_trigger_in_rising_edge, ro_trigger_in_falling_edge, - gate_out_active_high, gate_out_active_low, trigger_out_rising_edge, - trigger_out_falling_edge, ro_trigger_out_rising_edge, - ro_trigger_out_falling_edge, gnd, vcc, sync, unknown \returns can be - SIGNAL_OFF, GATE_IN_ACTIVE_HIGH, GATE_IN_ACTIVE_LOW, - TRIGGER_IN_RISING_EDGE, TRIGGER_IN_FALLING_EDGE, - RO_TRIGGER_IN_RISING_EDGE, RO_TRIGGER_IN_FALLING_EDGE, - GATE_OUT_ACTIVE_HIGH, GATE_OUT_ACTIVE_LOW, TRIGGER_OUT_RISING_EDGE, - TRIGGER_OUT_FALLING_EDGE, RO_TRIGGER_OUT_RISING_EDGE, - RO_TRIGGER_OUT_FALLING_EDGE, OUTPUT_LOW, OUTPUT_HIGH, - MASTER_SLAVE_SYNCHRONIZATION, GET_EXTERNAL_SIGNAL_FLAG (if unknown) + \param sval trigger_in_rising_edge, trigger_in_falling_edge, unknown + \returns can be TRIGGER_IN_RISING_EDGE, TRIGGER_IN_FALLING_EDGE, + GET_EXTERNAL_SIGNAL_FLAG (if unknown) */ static externalSignalFlag externalSignalType(std::string sval) { - if (sval == "off") - return SIGNAL_OFF; - if (sval == "gate_in_active_high") - return GATE_IN_ACTIVE_HIGH; - if (sval == "gate_in_active_low") - return GATE_IN_ACTIVE_LOW; if (sval == "trigger_in_rising_edge") return TRIGGER_IN_RISING_EDGE; if (sval == "trigger_in_falling_edge") return TRIGGER_IN_FALLING_EDGE; - if (sval == "ro_trigger_in_rising_edge") - return RO_TRIGGER_IN_RISING_EDGE; - if (sval == "ro_trigger_in_falling_edge") - return RO_TRIGGER_IN_FALLING_EDGE; - if (sval == "gate_out_active_high") - return GATE_OUT_ACTIVE_HIGH; - if (sval == "gate_out_active_low") - return GATE_OUT_ACTIVE_LOW; - if (sval == "trigger_out_rising_edge") - return TRIGGER_OUT_RISING_EDGE; - if (sval == "trigger_out_falling_edge") - return TRIGGER_OUT_FALLING_EDGE; - if (sval == "ro_trigger_out_rising_edge") - return RO_TRIGGER_OUT_RISING_EDGE; - if (sval == "ro_trigger_out_falling_edge") - return RO_TRIGGER_OUT_FALLING_EDGE; - if (sval == "sync") - return MASTER_SLAVE_SYNCHRONIZATION; - if (sval == "gnd") - return OUTPUT_LOW; - if (sval == "vcc") - return OUTPUT_HIGH; return GET_EXTERNAL_SIGNAL_FLAG; }; From f982a59a7cfbf5adef2d73b4a2a501b8ccada4c1 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Fri, 9 Aug 2019 18:02:12 +0200 Subject: [PATCH 051/108] minor --- slsDetectorServers/eigerDetectorServer/Beb.c | 4 ++-- .../bin/eigerDetectorServer_developer | Bin 302608 -> 302608 bytes slsSupportLib/include/versionAPI.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/slsDetectorServers/eigerDetectorServer/Beb.c b/slsDetectorServers/eigerDetectorServer/Beb.c index 7461e2df0..caa9e9857 100755 --- a/slsDetectorServers/eigerDetectorServer/Beb.c +++ b/slsDetectorServers/eigerDetectorServer/Beb.c @@ -1010,8 +1010,8 @@ int Beb_RequestNImages(unsigned int beb_number, int ten_gig, unsigned int dst_nu unsigned int packet_size = ten_gig ? 0x200 : 0x80; // 4k or 1k packets FILE_LOG(logDEBUG1, ("----Beb_RequestNImages Start----\n")); - FILE_LOG(logDEBUG1, ("beb_number:%X, ten_gig:%X,dst_number:%X, npackets:%X, " - "Beb_bit_mode:%X, header_size:%X, nimages:%d, test_just_send_out_packets_no_wait:%X\n", + FILE_LOG(logINFO, ("beb_number:%d, ten_gig:%d,dst_number:%d, npackets:%d, " + "Beb_bit_mode:%d, header_size:%d, nimages:%d, test_just_send_out_packets_no_wait:%d\n", beb_number, ten_gig, dst_number, npackets, Beb_bit_mode, header_size, nimages, test_just_send_out_packets_no_wait)); diff --git a/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer b/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer index c054a083a3a560132f2fd493ca3c5565a4ada65c..f79ce81f4e10757be6b2c605237aed6d07bc9d3f 100755 GIT binary patch delta 19695 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 S9opdIvFszzEY;9F;r{^8*mD#B delta 19462 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 Date: Mon, 12 Aug 2019 11:29:38 +0200 Subject: [PATCH 052/108] tests for Result --- slsDetectorSoftware/tests/test-Result.cpp | 99 ++++++++++++++++------- slsSupportLib/tests/CMakeLists.txt | 1 + slsSupportLib/tests/test-TypeTraits.cpp | 10 +++ 3 files changed, 81 insertions(+), 29 deletions(-) create mode 100644 slsSupportLib/tests/test-TypeTraits.cpp diff --git a/slsDetectorSoftware/tests/test-Result.cpp b/slsDetectorSoftware/tests/test-Result.cpp index 88fb762bc..8b1872791 100644 --- a/slsDetectorSoftware/tests/test-Result.cpp +++ b/slsDetectorSoftware/tests/test-Result.cpp @@ -1,18 +1,21 @@ #include "Result.h" +#include "TypeTraits.h" #include "catch.hpp" - -#include #include using sls::Result; -TEST_CASE("Default construction", "[detector][n2]") { +TEST_CASE("Result looks and behaves like a standard container") { + REQUIRE(sls::is_container>::value == true); +} + +TEST_CASE("Default construction is possible and gives an empty result") { Result res; REQUIRE(res.size() == 0); REQUIRE(res.empty() == true); } -TEST_CASE("Initializer list construction", "[n2]") { +TEST_CASE("Result can be constructed from std::initializer_list") { Result res{1, 2, 5}; REQUIRE(res.empty() == false); REQUIRE(res.size() == 3); @@ -21,7 +24,7 @@ TEST_CASE("Initializer list construction", "[n2]") { REQUIRE(res[2] == 5); } -TEST_CASE("Construct with value and number", "[n2]") { +TEST_CASE("Like vector it can be constructed from size and value") { Result res(5, 7); REQUIRE(res.size() == 5); REQUIRE(res[0] == 7); @@ -31,56 +34,94 @@ TEST_CASE("Construct with value and number", "[n2]") { REQUIRE(res[4] == 7); } -TEST_CASE("Squash empty", "[n2]") { +TEST_CASE("Calling squash on an empty Result produces default value") { Result res; REQUIRE(res.squash() == 0.); + + Result res2; + REQUIRE(res2.squash() == 0u); + + Result res3; + REQUIRE(res3.squash() == ""); } -TEST_CASE("Squash gives either value or default constructed value", "[n2]") { +TEST_CASE("When equal squash gives the front value") { Result res{3, 3, 3}; REQUIRE(res.squash() == 3); +} - res.push_back(5); +TEST_CASE("When elements are not equal squash gives default value") { + Result res{3, 3, 3, 5}; REQUIRE(res.squash() == 0); +} + +TEST_CASE("String compare with squash") { + Result res{"hej", "hej", "hej"}; + REQUIRE(res.squash() == "hej"); +} + +TEST_CASE("tsquash throws for different elements") { + Result res{1, 2, 3}; + REQUIRE_THROWS(res.tsquash("something is wrong")); +} + +TEST_CASE("tsquash returns front element when equal") { + Result res{"word", "word"}; + REQUIRE(res.tsquash("error") == "word"); +} + +TEST_CASE("When provided squash gives default value if elements differ") { + Result res{5, 5, 5}; + REQUIRE(res.squash(-1) == 5); + + res.push_back(7); // adding a different value REQUIRE(res.squash(-1) == -1); } -TEST_CASE("Updating an element", "[n2]") { - +TEST_CASE("It is possible to update elements by index access") { Result res{1, 2, 3}; - REQUIRE(res[0] == 1); - REQUIRE(res[1] == 2); - REQUIRE(res[2] == 3); - res[0] = 5; REQUIRE(res[0] == 5); REQUIRE(res[1] == 2); REQUIRE(res[2] == 3); } -TEST_CASE("equal", "[n2]"){ +TEST_CASE("Check if elements are equal") { Result res; + REQUIRE(res.equal() == false); // no elements to compare - // There are no elements to compare - REQUIRE(res.equal() == false); - - //all (the one) elements are equal - res.push_back(1.2); + res.push_back(1.2); // one element "all" equal REQUIRE(res.equal() == true); - res.push_back(1.2); + res.push_back(1.2); // two elements REQUIRE(res.equal() == true); - res.push_back(1.3); + res.push_back(1.3); // three elements 1.2, 1.2, 1.3 REQUIRE(res.equal() == false); } -TEST_CASE("throws for tsquash", "[n2]"){ - Result res{1,2,3}; - REQUIRE_THROWS(res.tsquash("something is wrong")); +TEST_CASE("Result can be converted to std::vector") { + Result res{1, 2, 3, 4, 5}; + std::vector vec{1, 2, 3, 4, 5}; + std::vector vec2 = res; + REQUIRE(vec2 == vec); } -TEST_CASE("", "[n2]"){ - Result res{"hej", "hej", "hej"}; - REQUIRE(res.squash() == "hej"); -} \ No newline at end of file +TEST_CASE("Result can be printed using <<") { + Result res{1, 2, 3}; + std::ostringstream os; + os << res; + REQUIRE(os.str() == "[1, 2, 3]"); +} + +TEST_CASE("Convert from Result to Result") { + // This function is used when the detector class + // returns time as integers + using ns = std::chrono::nanoseconds; + Result res{10, 50, 236}; + + Result res2 = res; + REQUIRE(res2[0] == ns(10)); + REQUIRE(res2[1] == ns(50)); + REQUIRE(res2[2] == ns(236)); +} diff --git a/slsSupportLib/tests/CMakeLists.txt b/slsSupportLib/tests/CMakeLists.txt index 4490ec18b..2d131a537 100755 --- a/slsSupportLib/tests/CMakeLists.txt +++ b/slsSupportLib/tests/CMakeLists.txt @@ -8,4 +8,5 @@ target_sources(tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/test-Sockets.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-FixedCapacityContainer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-ToString.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test-TypeTraits.cpp ) \ No newline at end of file diff --git a/slsSupportLib/tests/test-TypeTraits.cpp b/slsSupportLib/tests/test-TypeTraits.cpp new file mode 100644 index 000000000..20f1c7e9f --- /dev/null +++ b/slsSupportLib/tests/test-TypeTraits.cpp @@ -0,0 +1,10 @@ +#include "catch.hpp" +#include "TypeTraits.h" +#include +#include + +TEST_CASE("something", "[n3]"){ + + CHECK(sls::is_container>::value == true); + CHECK(sls::is_container>::value == true); +} \ No newline at end of file From f78a98797f233d1457afbd9362db339780ccac54 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Mon, 12 Aug 2019 11:53:23 +0200 Subject: [PATCH 053/108] more testing --- slsDetectorSoftware/tests/test-Result.cpp | 9 ++++++ slsSupportLib/include/TypeTraits.h | 15 ++++++++- slsSupportLib/tests/test-TypeTraits.cpp | 37 +++++++++++++++++++++-- 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/slsDetectorSoftware/tests/test-Result.cpp b/slsDetectorSoftware/tests/test-Result.cpp index 8b1872791..352df0f68 100644 --- a/slsDetectorSoftware/tests/test-Result.cpp +++ b/slsDetectorSoftware/tests/test-Result.cpp @@ -34,6 +34,15 @@ TEST_CASE("Like vector it can be constructed from size and value") { REQUIRE(res[4] == 7); } +TEST_CASE("Result can be iterated using modern syntax"){ + Result res{0,1,2,3,4,5}; + + int i = 0; + for (const auto& r:res) + REQUIRE(r == i++); + +} + TEST_CASE("Calling squash on an empty Result produces default value") { Result res; REQUIRE(res.squash() == 0.); diff --git a/slsSupportLib/include/TypeTraits.h b/slsSupportLib/include/TypeTraits.h index 2a5409e78..b7297389c 100644 --- a/slsSupportLib/include/TypeTraits.h +++ b/slsSupportLib/include/TypeTraits.h @@ -4,7 +4,7 @@ namespace sls { /** - * Type trait to check if atemplate parameter is a std::chrono::duration + * Type trait to check if a template parameter is a std::chrono::duration */ template @@ -22,6 +22,19 @@ struct is_duration().zero())>, void>::type> : public std::true_type {}; +/** + * Has str method + */ +template struct has_str : std::false_type {}; + +template struct has_str_helper {}; + +template +struct has_str().str())>, + void>::type> : public std::true_type {}; + /** * Type trait to evaluate if template parameter is * complying with a standard container diff --git a/slsSupportLib/tests/test-TypeTraits.cpp b/slsSupportLib/tests/test-TypeTraits.cpp index 20f1c7e9f..042eee3ac 100644 --- a/slsSupportLib/tests/test-TypeTraits.cpp +++ b/slsSupportLib/tests/test-TypeTraits.cpp @@ -1,10 +1,41 @@ -#include "catch.hpp" #include "TypeTraits.h" -#include +#include "catch.hpp" #include +#include +#include +#include -TEST_CASE("something", "[n3]"){ +//Dummy classes only used here for testing +class DummyWithStr { + public: + std::string str(); +}; + +class DummyNoStr { + public: + std::string somethingelse(); +}; + +TEST_CASE("sls::is_container") { CHECK(sls::is_container>::value == true); CHECK(sls::is_container>::value == true); +} + +TEST_CASE("Check for str() method") { + REQUIRE(sls::has_str::value == true); + REQUIRE(sls::has_str::value == false); +} + +TEST_CASE("Check for str() on ostream") { + REQUIRE(sls::has_str::value == true); +} + +TEST_CASE("sls::is_duration"){ + REQUIRE(sls::is_duration::value == true); + REQUIRE(sls::is_duration::value == true); + REQUIRE(sls::is_duration::value == true); + + REQUIRE(sls::is_duration::value == false); + REQUIRE(sls::is_duration>::value == false); } \ No newline at end of file From c36dfc3992dbff1245d0d03181c493c7bf608fcb Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Mon, 12 Aug 2019 12:09:44 +0200 Subject: [PATCH 054/108] even more tests --- slsSupportLib/CMakeLists.txt | 1 - slsSupportLib/include/ToString.h | 4 +- slsSupportLib/src/ToString.cpp | 18 --------- slsSupportLib/tests/test-ToString.cpp | 56 ++++++++++++++++----------- 4 files changed, 36 insertions(+), 43 deletions(-) delete mode 100644 slsSupportLib/src/ToString.cpp diff --git a/slsSupportLib/CMakeLists.txt b/slsSupportLib/CMakeLists.txt index 21ebdfa71..20380e13c 100755 --- a/slsSupportLib/CMakeLists.txt +++ b/slsSupportLib/CMakeLists.txt @@ -7,7 +7,6 @@ set(SOURCES src/ServerSocket.cpp src/ServerInterface2.cpp src/network_utils.cpp - src/ToString.cpp ) set(HEADERS diff --git a/slsSupportLib/include/ToString.h b/slsSupportLib/include/ToString.h index 8acd31a29..b032151e5 100644 --- a/slsSupportLib/include/ToString.h +++ b/slsSupportLib/include/ToString.h @@ -19,8 +19,8 @@ namespace sls { -std::string ToString(const std::vector &vec, - const char delimiter = ' '); +// std::string ToString(const std::vector &vec, +// const char delimiter = ' '); /** Convert std::chrono::duration with specified output unit */ template diff --git a/slsSupportLib/src/ToString.cpp b/slsSupportLib/src/ToString.cpp deleted file mode 100644 index 541ce2829..000000000 --- a/slsSupportLib/src/ToString.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "ToString.h" - -namespace sls { - -std::string ToString(const std::vector &vec, - const char delimiter) { - std::ostringstream os; - if (vec.empty()) - return os.str(); - auto it = vec.cbegin(); - os << *it++; - if (vec.size() > 1) { - while (it != vec.cend()) - os << delimiter << *it++; - } - return os.str(); -} -} // namespace sls \ No newline at end of file diff --git a/slsSupportLib/tests/test-ToString.cpp b/slsSupportLib/tests/test-ToString.cpp index f080003b0..6ec8c3f4f 100644 --- a/slsSupportLib/tests/test-ToString.cpp +++ b/slsSupportLib/tests/test-ToString.cpp @@ -2,10 +2,16 @@ #include "ToString.h" #include "catch.hpp" #include -using namespace sls; +#include -TEST_CASE("Integer conversions", "[support][now]"){ +// using namespace sls; +using sls::ToString; +using sls::StringTo; +using namespace sls::time; + + +TEST_CASE("Integer conversions", "[support]"){ REQUIRE(ToString(0) == "0"); REQUIRE(ToString(1) == "1"); REQUIRE(ToString(-1) == "-1"); @@ -14,7 +20,8 @@ TEST_CASE("Integer conversions", "[support][now]"){ } -TEST_CASE("floating point conversions", "[support][now]"){ +TEST_CASE("floating point conversions", "[support]"){ + //Should strip trailing zeros REQUIRE(ToString(0.) == "0"); REQUIRE(ToString(1.) == "1"); REQUIRE(ToString(-1.) == "-1"); @@ -28,33 +35,33 @@ TEST_CASE("floating point conversions", "[support][now]"){ } -TEST_CASE("conversion from duration to string", "[support][now]") { - REQUIRE(ToString(time::ns(150)) == "150ns"); - REQUIRE(ToString(time::ms(783)) == "0.783s"); - REQUIRE(ToString(time::ms(783), "ms") == "783ms"); - REQUIRE(ToString(time::us(0)) == "0ns"); // Defaults to the lowest unit - REQUIRE(ToString(time::us(0), "s") == "0s"); - REQUIRE(ToString(time::s(-1)) == "-1s"); - REQUIRE(ToString(time::us(-100)) == "-100us"); +TEST_CASE("conversion from duration to string", "[support]") { + REQUIRE(ToString(ns(150)) == "150ns"); + REQUIRE(ToString(ms(783)) == "0.783s"); + REQUIRE(ToString(ms(783), "ms") == "783ms"); + REQUIRE(ToString(us(0)) == "0ns"); // Defaults to the lowest unit + REQUIRE(ToString(us(0), "s") == "0s"); + REQUIRE(ToString(s(-1)) == "-1s"); + REQUIRE(ToString(us(-100)) == "-100us"); } -TEST_CASE("string to std::chrono::duration", "[support][now]") { - REQUIRE(StringTo("150", "ns") == time::ns(150)); - REQUIRE(StringTo("150ns") == time::ns(150)); - REQUIRE(StringTo("150s") == time::s(150)); - REQUIRE(StringTo("3 s") == time::s(3)); +TEST_CASE("string to std::chrono::duration", "[support]") { + REQUIRE(StringTo("150", "ns") == ns(150)); + REQUIRE(StringTo("150ns") == ns(150)); + REQUIRE(StringTo("150s") == s(150)); + REQUIRE(StringTo("3 s") == s(3)); - REQUIRE_THROWS(StringTo("5xs")); - REQUIRE_THROWS(StringTo("asvn")); + REQUIRE_THROWS(StringTo("5xs")); + REQUIRE_THROWS(StringTo("asvn")); } -TEST_CASE("Convert vector of time", "[support][now]"){ - std::vector vec{time::ns(150), time::us(10), time::ns(600)}; +TEST_CASE("Convert vector of time", "[support]"){ + std::vector vec{ns(150), us(10), ns(600)}; REQUIRE(ToString(vec) == "[150ns, 10us, 600ns]"); REQUIRE(ToString(vec, "ns") == "[150ns, 10000ns, 600ns]"); } -TEST_CASE("Vector of int", "[support][now]"){ +TEST_CASE("Vector of int", "[support]"){ std::vector vec; REQUIRE(ToString(vec) == "[]"); @@ -69,7 +76,7 @@ TEST_CASE("Vector of int", "[support][now]"){ } -TEST_CASE("Vector of double", "[support][now]"){ +TEST_CASE("Vector of double", "[support]"){ std::vector vec; REQUIRE(ToString(vec) == "[]"); @@ -81,5 +88,10 @@ TEST_CASE("Vector of double", "[support][now]"){ vec.push_back(-5669.325005); REQUIRE(ToString(vec) == "[1.3, 5669.325, -5669.325005]"); +} + +TEST_CASE("Array"){ + std::array arr{1,2,3}; + REQUIRE(ToString(arr) == "[1, 2, 3]"); } \ No newline at end of file From 95751766cd7ff5d83e1a6d156cb8e122a5a69389 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Mon, 12 Aug 2019 14:15:25 +0200 Subject: [PATCH 055/108] WIP --- slsDetectorSoftware/include/Detector.h | 490 ++++++----- .../include/multiSlsDetector.h | 18 +- slsDetectorSoftware/src/Detector.cpp | 775 +++++++++++------- slsDetectorSoftware/src/multiSlsDetector.cpp | 23 +- .../src/slsDetectorCommand.cpp | 2 +- 5 files changed, 779 insertions(+), 529 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 4a52610d6..3483ca37f 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -65,25 +65,9 @@ class Detector { // Bits and registers - /** - * Clears (sets to 0) bit number bitnr in register at addr. - * @param addr address of the register - * @param bitnr bit number to clear - * @param pos detector position - */ - void clearBit(uint32_t addr, int bitnr, Positions pos = {}); - - /** - * Sets bit number bitnr in register at addr to 1 - * @param addr address of the register - * @param bitnr bit number to clear - * @param pos detector position - */ - void setBit(uint32_t addr, int bitnr, Positions pos = {}); - Result readRegister(uint32_t addr, Positions pos = {}) const; - void writeRegister(uint32_t addr, uint32_t val, Positions pos = {}); + /************************************************** * * @@ -955,6 +939,273 @@ class Detector { // Erik + /** [Eiger] */ + Result getInterruptSubframe(Positions pos = {}) const; + + /** [Eiger] when set, the last subframe is interrupted at end of acq */ + void setInterruptSubframe(const bool enable, Positions pos = {}); + + Result readRegister(uint32_t addr, Positions pos = {}) const; + + void writeRegister(uint32_t addr, uint32_t val, Positions pos = {}); + + void setBit(uint32_t addr, int bitnr, Positions pos = {}); + + void clearBit(uint32_t addr, int bitnr, Positions pos = {}); + + Result getDetectorMAC(Positions pos = {}) const; + + void setDetectorMAC(const std::string &detectorMAC, Positions pos = {}); + + /** [Jungfrau] bottom half */ + Result getDetectorMAC2(Positions pos = {}) const; + + /** [Jungfrau] bottom half */ + void setDetectorMAC2(const std::string &detectorMAC, Positions pos = {}); + + Result getDetectorIP(Positions pos = {}) const; + + void setDetectorIP(const std::string &detectorIP, Positions pos = {}); + + /** [Jungfrau] bottom half */ + Result getDetectorIP2(Positions pos = {}) const; + + /** [Jungfrau] bottom half */ + void setDetectorIP2(const std::string &detectorIP, Positions pos = {}); + + Result getReceiverHostname(Positions pos = {}) const; + + /** + * Validates and sets the receiver. + * Updates local receiver cache parameters + * Configures the detector to the receiver as UDP destination + * @param receiver receiver hostname or IP address + */ + void setReceiverHostname(const std::string &receiver, Positions pos = {}); + + Result getReceiverUDPIP(Positions pos = {}) const; + void setReceiverUDPIP(const std::string &udpip, Positions pos = {}); + + /** [Jungfrau bottom half] */ + Result getReceiverUDPIP2(Positions pos = {}) const; + + /** [Jungfrau bottom half] */ + void setReceiverUDPIP2(const std::string &udpip, Positions pos = {}); + + Result getReceiverUDPMAC(Positions pos = {}) const; + void setReceiverUDPMAC(const std::string &udpmac, Positions pos = {}); + + /** [Jungfrau bottom half] */ + Result getReceiverUDPMAC2(Positions pos = {}) const; + /** [Jungfrau bottom half] */ + void setReceiverUDPMAC2(const std::string &udpmac, Positions pos = {}); + + Result getReceiverUDPPort(Positions pos = {}) const; + void setReceiverUDPPort(int udpport, Positions pos = {}); + + /** [Eiger right port][Jungfrau bottom half] */ + Result getReceiverUDPPort2(Positions pos = {}) const; + /** [Eiger right port][Jungfrau bottom half] */ + void setReceiverUDPPort2(int udpport, Positions pos = {}); + + /** [Jungfrau] */ + Result getNumberofUDPInterfaces(Positions pos = {}) const; + /** [Jungfrau] Also restarts client and receiver sockets */ + void setNumberofUDPInterfaces(int n, Positions pos = {}); + + /** [Jungfrau] */ + Result getSelectedUDPInterface(Positions pos = {}) const; + /** + * [Jungfrau: + * Effective only when number of interfaces is 1. + * Options: 0 (outer, default), 1(inner)] + */ + void selectUDPInterface(int interface, Positions pos = {}); + + Result getClientStreamingPort(Positions pos = {}) const; + /** + * pos can be for a single module or all modules, not a subset + * If pos for all modules, ports for each module is calculated (increments) + * Restarts client zmq sockets + */ + void setClientDataStreamingInPort(int port, Positions pos = {}); + + Result getReceiverStreamingPort(Positions pos = {}) const; + /** + * pos can be for a single module or all modules, not a subset + * If pos for all modules, ports for each module is calculated (increments) + * Restarts receiver zmq sockets + */ + void setReceiverDataStreamingOutPort(int port, Positions pos = {}); + + Result getClientStreamingIP(Positions pos = {}) const; + // TODO these should probably be the same ?? same as what? + void setClientDataStreamingInIP(const std::string &ip, Positions pos = {}); + + Result getReceiverStreamingIP(Positions pos = {}) const; + void setReceiverDataStreamingOutIP(const std::string &ip, + Positions pos = {}); + + /** [Eiger, Jungfrau] */ + Result getFlowControl10G(Positions pos = {}) const; + /** [Eiger, Jungfrau] */ + void setFlowControl10G(bool enable, Positions pos = {}); + + /** [Eiger, Jungfrau] */ + Result getTransmissionDelayFrame(Positions pos = {}) const; + /** + * [Jungfrau: Sets the transmission delay of the first UDP packet being streamed out of the module + * Options: 0 - 31, each value represenets 1 ms ] + * [Eiger: Sets the transmission delay of entire frame streamed out for both left and right UDP ports] + */ + void setTransmissionDelayFrame(int value, Positions pos = {}); + + /** [Eiger] */ + Result getTransmissionDelayLeft(Positions pos = {}) const; + /** + * [Eiger] + * Sets the transmission delay of first packet streamed ut of the left UDP port + */ + void setTransmissionDelayLeft(int value, Positions pos = {}); + + /** [Eiger] */ + Result getTransmissionDelayRight(Positions pos = {}) const; + /** + * [Eiger] + * Sets the transmission delay of first packet streamed ut of the right UDP port + */ + void setTransmissionDelayRight(int value, Positions pos = {}); + + /** [Moench] */ + Result getAdditionalJsonHeader(Positions pos = {}) const; + /** [Moench] */ + void setAdditionalJsonHeader(const std::string &jsonheader, + Positions pos = {}); + + /** [Moench] */ + Result getAdditionalJsonParameter(const std::string &key, + Positions pos = {}) const; + /** + * [Moench] + * Sets the value for additional json header parameter if found, + * else appends the parameter key and value + * The value cannot be empty + */ + void setAdditionalJsonParameter(const std::string &key, + const std::string &value, + Positions pos = {}); + + /** [Moench] TODO! How do we do this best??? Can be refactored to something + * else? Use a generic zmq message passing system... + * For now limiting to all detectors working the same*/ + /** [Moench: -1 if not found or cannot convert to int] */ + Result getDetectorMinMaxEnergyThreshold(const bool isEmax, Positions pos = {}) const; + /** [Moench] */ + void setDetectorMinMaxEnergyThreshold(const bool isEmax, const int value, Positions pos = {}); + /** [Moench: -1 if unknown mode] */ + Result getFrameMode(Positions pos = {}) const; + /** [Moench] */ + void setFrameMode(defs::frameModeType value, Positions pos = {}); + /** [Moench: -1 if unknown mode] */ + Result getDetectorMode(Positions pos = {}) const; + /** [Moench] */ + void setDetectorMode(defs::detectorModeType value, Positions pos = {}); + + /** [Gotthard] */ + Result getDigitalTestBit(Positions pos = {}); + /** [Gotthard] */ + Result setDigitalTestBit(const int value, Positions pos = {}); + /** [Gotthard, Jungfrau, CTB] */ + Result executeFirmwareTest(Positions pos = {}); + /** [Gotthard, Jungfrau, CTB] */ + Result executeBusTest(Positions pos = {}); + /** [Gotthard] subset modules not allowed */ + void loadDarkImage(const std::string &fname, Positions pos = {}); + /** [Gotthard] subset modules not allowed */ + void loadGainImage(const std::string &fname, Positions pos = {}); + /** + * [Gotthard] subset modules not allowed + * @param startACQ if start acq after reading counter + */ + void getCounterMemoryBlock(const std::string &fname, bool startACQ, Positions pos = {}); + /** + * [Gotthard] + * @param startACQ if start acq after resetting counter + * TODO! does it make sense to call one detector? + */ + void resetCounterBlock(bool startACQ, Positions pos = {}); + + /** [Eiger] */ + Result getCounterBit(Positions pos = {}) const; + /** [Eiger] If it is set, it resets chips completely (else partially) before an acquisition TODO: if it makes sense */ + void setCounterBit(bool value, Positions pos = {}); + + /** [Gotthard, CTB] subset modules not allowed */ + Result> getROI(Positions pos = {}) const; + /** + * [Gotthard Options: Only a single chip or all chips, only 1 ROI allowed] + * [CTB: multiple ROIs allowed] + * subset modules not allowed + */ + void setROI(std::vector value, Positions pos = {}); + + /** [CTB]*/ + Result getADCEnableMask(Positions pos = {}) const; + + /** [CTB]*/ + void setADCEnableMask(uint32_t mask, Positions pos = {}); + + /** [CTB] */ + Result getADCInvert(Positions pos = {}) const; + + /** [CTB]*/ + void setADCInvert(uint32_t value, Positions pos = {}); + + /** [CTB] */ + Result getExternalSamplingSource(Positions pos = {}) const; + + /** [CTB] Value between 0-63 */ + void setExternalSamplingSource(int value, Positions pos = {}); + + /** [CTB] */ + Result getExternalSampling(Positions pos = {}) const; + + /** [CTB] */ + void setExternalSampling(bool value, Positions pos = {}); + + /** [CTB] */ + Result> getReceiverDbitList(Positions pos = {}) const; + + /** [CTB] list contains the set of bits (0-63) to save */ + void setReceiverDbitList(std::vector list, Positions pos = {}); + + /** [CTB] */ + Result getReceiverDbitOffset(Positions pos = {}) const; + + /** [CTB] Set number of bytes of digital data to skip in the Receiver */ + void setReceiverDbitOffset(int value, Positions pos = {}); + + /** [Gotthard][Jungfrau][CTB] not possible to read back*/ + void writeAdcRegister(uint32_t addr, uint32_t value, Positions pos = {}); + + + + + + + + Result getReceiverUDPSocketBufferSize(Positions pos = {}) const; + void setReceiverUDPSocketBufferSize(int64_t udpsockbufsize, + Positions pos = {}); + Result + getReceiverRealUDPSocketBufferSize(Positions pos = {}) const; + + + + + + + Result getFramesCaughtByReceiver(Positions pos = {}) const; Result getReceiverCurrentFrameIndex(Positions pos = {}) const; @@ -979,9 +1230,11 @@ class Detector { /** [All] */ Result getReceiverStreamingTimer(Positions pos = {}) const; - // TODO! - // int enableDataStreamingToClient(int enable = -1); - void enableDataStreamingFromReceiver(bool enable, Positions pos = {}); + bool getDataStreamingToClient() const; + void setDataStreamingToClient(bool value); + + Result getDataStreamingFromReceiver(Positions pos = {}) const; + void setDataStreamingFromReceiver(bool value, Positions pos = {}); /** [TODO! All?] */ void setTenGigaEnabled(bool value, Positions pos = {}); @@ -1272,203 +1525,8 @@ class Detector { Result getActive(Positions pos = {}) const; - /** [Gotthard][Jungfrau][CTB] not possible to read back*/ - void writeAdcRegister(uint32_t addr, uint32_t value, Positions pos = {}); - /** [CTB] How much digital data in bytes is skipped */ - Result getReceiverDbitOffset(Positions pos = {}) const; - - /** [CTB] Set how many bytes of digital data to skip */ - void setReceiverDbitOffset(int value, Positions pos = {}); - - /** [CTB] Which of the bits 0-63 to save*/ - Result> getReceiverDbitList(Positions pos = {}) const; - - /** [CTB] Which of the bits 0-63 to save*/ - void setReceiverDbitList(std::vector list, Positions pos = {}); - - /** [CTB] */ - Result getExternalSampling(Positions pos = {}) const; - - /** [CTB] */ - void setExternalSampling(bool value, Positions pos = {}); - - /** [CTB] */ - Result getExternalSamplingSource(Positions pos = {}) const; - - /** [CTB] Value between 0-63 */ - void setExternalSamplingSource(int value, Positions pos = {}); - - // TODO! does any of them need the option to take positions - /** [CTB] */ - uint32_t getADCInvert() const; - - /** [CTB]*/ - void setADCInvert(uint32_t value); - - /** [CTB]*/ - uint32_t getADCEnableMask() const; - - /** [CTB]*/ - void setADCEnableMask(uint32_t mask); - - /** [Gotthard] */ - Result getCounterBit(Positions pos = {}) const; - - /** [Gotthard] possible values? */ - void setCounterBit(int i, Positions pos = {}); - - /** - * [Gotthard] startACQ = 1 to start acq after resetting counter - * TODO! does it make sense to call one detector? - * - */ - void resetCounterBlock(int startACQ = 0, Positions pos = {}); - - // TODO getROI, setROI, verifyMinMaxROI - - // writeCounterBlockFile - - void loadImageToDetector(defs::imageType index, const std::string &fname, - Positions pos = {}); - - /** [Gotthard] - * @param value 1 to set or 0 to clear the digital test bit -1? - */ - Result digitalTest(defs::digitalTestMode mode, int ival = -1, - Positions pos = {}); - - /** [Eiger] */ - void setFlowControl10G(bool enable, Positions pos = {}); - - /** [Eiger] */ - Result getFlowControl10G(Positions pos = {}) const; - - Result - getReceiverRealUDPSocketBufferSize(Positions pos = {}) const; - - Result getReceiverUDPSocketBufferSize(Positions pos = {}) const; - - void setReceiverUDPSocketBufferSize(int64_t udpsockbufsize, - Positions pos = {}); - - /** [Moench] TODO! How do we do this best??? Can be refactored to something - * else? Use a generic zmq message passing system... - * For now limiting to all detectors working the same*/ - int setDetectorMode(defs::detectorModeType value); - int setFrameMode(defs::frameModeType value); - int setDetectorMinMaxEnergyThreshold(const int index, int value); - - void setAdditionalJsonHeader(const std::string &jsonheader, - Positions pos = {}); - - Result getAdditionalJsonHeader(Positions pos = {}) const; - - Result getAdditionalJsonParameter(const std::string &key, - Positions pos = {}) const; - - void setAdditionalJsonParameter(const std::string &key, - const std::string &value, - Positions pos = {}); - - // TODO these should probably be the same - Result getReceiverStreamingIP(Positions pos = {}) const; - - void setReceiverDataStreamingOutIP(const std::string &ip, - Positions pos = {}); - - Result getClientStreamingIP(Positions pos = {}) const; - - // TODO these should probably be the same - void setClientDataStreamingInIP(const std::string &ip, Positions pos = {}); - - Result getReceiverStreamingPort(Positions pos = {}) const; - - /** Single detector or all since ports are calculated*/ - void setReceiverDataStreamingOutPort(int port, int module_id = -1); - - Result getClientStreamingPort(Positions pos = {}) const; - - /** Single detector or all since ports are calculated*/ - void setClientDataStreamingInPort(int port, int module_id = -1); - - /** [Jungfrau] */ - Result getSelectedUDPInterface(Positions pos = {}) const; - - /** - * [Jungfrau] - * @param interface interface to select, either 1 or 2 - * */ - void selectUDPInterface(int interface, Positions pos = {}); - - Result getNumberofUDPInterfaces(Positions pos = {}) const; - void setNumberofUDPInterfaces(int n, Positions pos = {}); - - /** [Eiger][Jungfrau] */ - Result getReceiverUDPPort2(Positions pos = {}) const; - - /** [Eiger][Jungfrau] */ - void setReceiverUDPPort2(int udpport, Positions pos = {}); - - /** [Eiger][Jungfrau] */ - Result getReceiverUDPPort(Positions pos = {}) const; - - /** [Eiger][Jungfrau] */ - void setReceiverUDPPort(int udpport, Positions pos = {}); - - /** [Jungfrau] */ - Result getReceiverUDPMAC2(Positions pos = {}) const; - - /** [Jungfrau] */ - void setReceiverUDPMAC2(const std::string &udpmac, Positions pos = {}); - - Result getReceiverUDPMAC(Positions pos = {}) const; - void setReceiverUDPMAC(const std::string &udpmac, Positions pos = {}); - - /** [Jungfrau] */ - Result getReceiverUDPIP2(Positions pos = {}) const; - - /** [Jungfrau] */ - void setReceiverUDPIP2(const std::string &udpip, Positions pos = {}); - - Result getReceiverUDPIP(Positions pos = {}) const; - void setReceiverUDPIP(const std::string &udpip, Positions pos = {}); - - Result getReceiverHostname(Positions pos = {}) const; - - /** - * Validates and sets the receiver. - * Also updates the receiver with all the shared memory parameters - * significant for the receiver Also configures the detector to the receiver - * as UDP destination - * @param receiver receiver hostname or IP address */ - void setReceiverHostname(const std::string &receiver, Positions pos = {}); - - /** [Jungfrau] */ - Result getDetectorIP2(Positions pos = {}) const; - - /** [Jungfrau] */ - void setDetectorIP2(const std::string &detectorIP, Positions pos = {}); - - Result getDetectorIP(Positions pos = {}) const; - - void setDetectorIP(const std::string &detectorIP, Positions pos = {}); - - Result getDetectorMAC(Positions pos = {}) const; - - void setDetectorMAC(const std::string &detectorMAC, Positions pos = {}); - - /** [Jungfrau] */ - Result getDetectorMAC2(Positions pos = {}) const; - - /** [Jungfrau] */ - void setDetectorMAC2(const std::string &detectorMAC, Positions pos = {}); - - /** [Eiger] */ - Result getInterruptSubframe(Positions pos = {}) const; - - /** [Eiger] when set the last subframe is interrupted at end of acq*/ - void setInterruptSubframe(const bool enable, Positions pos = {}); + }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index b209f1d2b..fb7395a2c 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -1387,7 +1387,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { void resetCounterBlock(int startACQ = 0, int detPos = -1); // /** - * Set/get counter bit in detector (Gotthard) + * Set/get counter bit in detector (Eiger) * @param i is -1 to get, 0 to reset and any other value to set the counter * bit * @param detPos -1 for all detectors in list or specific detector position @@ -1395,13 +1395,6 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ int setCounterBit(int i = -1, int detPos = -1); // - /** - * Ensures that min is less than max in both dimensions (Gotthard) - * @param n number of rois - * @param r array of rois - */ - void verifyMinMaxROI(int n, ROI r[]); - /** * Set ROI (Gotthard) * At the moment only one set allowed @@ -1976,7 +1969,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param enable 0 to disable, 1 to enable, -1 to get the value * @returns data streaming to client enable */ - int enableDataStreamingToClient(int enable = -1); + bool enableDataStreamingToClient(int enable = -1); /** * Enable or disable streaming data from receiver to client @@ -2283,6 +2276,13 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ void addSlsDetector(const std::string &hostname); + /** + * Ensures that min is less than max in both dimensions (Gotthard) + * @param n number of rois + * @param r array of rois + */ + void verifyMinMaxROI(int n, ROI r[]); + /** * add gap pixels to the image (only for Eiger in 4 bit mode) * @param image pointer to image without gap pixels diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 316ebf718..61e276d89 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -41,19 +41,9 @@ void Detector::setConfig(const std::string &fname) { pimpl->readConfigurationFile(fname); } -void Detector::clearBit(uint32_t addr, int bitnr, Positions pos) { - pimpl->Parallel(&slsDetector::clearBit, pos, addr, bitnr); -} -void Detector::setBit(uint32_t addr, int bitnr, Positions pos) { - pimpl->Parallel(&slsDetector::setBit, pos, addr, bitnr); -} -void Detector::writeRegister(uint32_t addr, uint32_t val, Positions pos) { - pimpl->Parallel(&slsDetector::writeRegister, pos, addr, val); -} -Result Detector::readRegister(uint32_t addr, Positions pos) const { - return pimpl->Parallel(&slsDetector::readRegister, pos, addr); -} + + Result Detector::getStartingFrameNumber(Positions pos) const { return pimpl->Parallel(&slsDetector::getStartingFrameNumber, pos); @@ -156,7 +146,7 @@ defs::coordinates Detector::getNumberOfDetectors() const { } Result Detector::getNumberOfChannels(Positions pos) const { - if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) { + if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) {// TODO: also check condition that pos.size == pimpl->size()?? for other occurences as well return {pimpl->getNumberOfChannels()}; } return pimpl->Parallel(&slsDetector::getNumberOfChannels, pos); @@ -775,6 +765,470 @@ void Detector::setDAC(int value, defs::dacIndex index, bool mV, Positions pos) { } // Erik +Result Detector::getInterruptSubframe(Positions pos) const { + return pimpl->Parallel(&slsDetector::getInterruptSubframe, pos); +} + +void Detector::setInterruptSubframe(const bool enable, Positions pos){ + pimpl->Parallel(&slsDetector::setInterruptSubframe, pos, enable); +} + +void Detector::writeRegister(uint32_t addr, uint32_t val, Positions pos) { + pimpl->Parallel(&slsDetector::writeRegister, pos, addr, val); +} + +Result Detector::readRegister(uint32_t addr, Positions pos) const { + return pimpl->Parallel(&slsDetector::readRegister, pos, addr); +} + +void Detector::setBit(uint32_t addr, int bitnr, Positions pos) { + pimpl->Parallel(&slsDetector::setBit, pos, addr, bitnr); +} + +void Detector::clearBit(uint32_t addr, int bitnr, Positions pos) { + pimpl->Parallel(&slsDetector::clearBit, pos, addr, bitnr); +} + +Result Detector::getDetectorMAC(Positions pos) const { + return pimpl->Parallel(&slsDetector::getDetectorMAC, pos); +} +void Detector::setDetectorMAC(const std::string &detectorMAC, Positions pos) { + pimpl->Parallel(&slsDetector::setDetectorMAC, pos, detectorMAC); +} + +Result Detector::getDetectorMAC2(Positions pos) const { + return pimpl->Parallel(&slsDetector::getDetectorMAC2, pos); +} +void Detector::setDetectorMAC2(const std::string &detectorMAC, Positions pos) { + pimpl->Parallel(&slsDetector::setDetectorMAC2, pos, detectorMAC); +} + +Result Detector::getDetectorIP(Positions pos) const { + return pimpl->Parallel(&slsDetector::getDetectorIP, pos); +} + +void Detector::setDetectorIP(const std::string &detectorIP, Positions pos) { + pimpl->Parallel(&slsDetector::setDetectorIP, pos, detectorIP); +} + +Result Detector::getDetectorIP2(Positions pos) const { + return pimpl->Parallel(&slsDetector::getDetectorIP2, pos); +} + +void Detector::setDetectorIP2(const std::string &detectorIP, Positions pos) { + pimpl->Parallel(&slsDetector::setDetectorIP2, pos, detectorIP); +} + +Result Detector::getReceiverHostname(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverHostname, pos); +} + +void Detector::setReceiverHostname(const std::string &receiver, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverHostname, pos, receiver); +} + +Result Detector::getReceiverUDPIP(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverUDPIP, pos); +} + +void Detector::setReceiverUDPIP(const std::string &udpip, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverUDPIP, pos, udpip); +} + +Result Detector::getReceiverUDPIP2(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverUDPIP2, pos); +} + +void Detector::setReceiverUDPIP2(const std::string &udpip, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverUDPIP2, pos, udpip); +} + +Result Detector::getReceiverUDPMAC(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverUDPMAC, pos); +} + +void Detector::setReceiverUDPMAC(const std::string &udpmac, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverUDPMAC, pos, udpmac); +} + +Result Detector::getReceiverUDPMAC2(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverUDPMAC2, pos); +} + +void Detector::setReceiverUDPMAC2(const std::string &udpmac, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverUDPMAC2, pos, udpmac); +} + +Result Detector::getReceiverUDPPort(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverUDPPort, pos); +} + +void Detector::setReceiverUDPPort(int udpport, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverUDPPort, pos, udpport); +} + +Result Detector::getReceiverUDPPort2(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverUDPPort2, pos); +} + +void Detector::setReceiverUDPPort2(int udpport, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverUDPPort2, pos, udpport); +} + +Result Detector::getNumberofUDPInterfaces(Positions pos) const { + return pimpl->Parallel(&slsDetector::getNumberofUDPInterfaces, pos); +} + +void Detector::setNumberofUDPInterfaces(int n, Positions pos) { + bool previouslyClientStreaming = getDataStreamingToClient(); + bool previouslyReceiverStreaming = getDataStreamingFromReceiver(pos).squash(false); + pimpl->Parallel(&slsDetector::setNumberofUDPInterfaces, pos, n); + // redo the zmq sockets if enabled + if (previouslyClientStreaming) { + setDataStreamingToClient(false); + setDataStreamingToClient(true); + } + if (previouslyReceiverStreaming) { + setDataStreamingFromReceiver(false, pos); + setDataStreamingFromReceiver(true, pos); + } +} + +Result Detector::getSelectedUDPInterface(Positions pos) const { + return pimpl->Parallel(&slsDetector::getSelectedUDPInterface, pos); +} + +void Detector::selectUDPInterface(int interface, Positions pos) { + pimpl->Parallel(&slsDetector::selectUDPInterface, pos, interface); +} + +Result Detector::getClientStreamingPort(Positions pos) const { + return pimpl->Parallel(&slsDetector::getClientStreamingPort, pos); +} + +void Detector::setClientDataStreamingInPort(int port, Positions pos) { + if (pos.size() > 1 && pos.size() < pimpl->size()) { + throw RuntimeError("Cannot set client streaming port to a subset of modules"); + } + pimpl->setClientDataStreamingInPort(port, pos.empty() ? -1 : pos[0]); +} + +Result Detector::getReceiverStreamingPort(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverStreamingPort, pos); +} + +void Detector::setReceiverDataStreamingOutPort(int port, Positions pos) { + if (pos.size() > 1 && pos.size() < pimpl->size()) { + throw RuntimeError("Cannot set receiver streaming port to a subset of modules"); + } + pimpl->setReceiverDataStreamingOutPort(port, pos.empty() ? -1 : pos[0]); +} + +Result Detector::getClientStreamingIP(Positions pos) const { + return pimpl->Parallel(&slsDetector::getClientStreamingIP, pos); +} + +void Detector::setClientDataStreamingInIP(const std::string &ip, + Positions pos) { + bool previouslyClientStreaming = getDataStreamingToClient(); + // TODO! probably in one call ?? + pimpl->Parallel(&slsDetector::setClientStreamingIP, pos, ip); + if (previouslyClientStreaming) { + setDataStreamingToClient(false); + setDataStreamingToClient(true); + } +} + +Result Detector::getReceiverStreamingIP(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverStreamingIP, pos); +} + +void Detector::setReceiverDataStreamingOutIP(const std::string &ip, + Positions pos) { + bool previouslyReceiverStreaming = getDataStreamingFromReceiver(pos).squash(false); + // TODO! probably in one call + pimpl->Parallel(&slsDetector::setReceiverStreamingIP, pos, ip); + if (previouslyReceiverStreaming) { + setDataStreamingFromReceiver(false, pos); + setDataStreamingFromReceiver(true, pos); + } +} + +Result Detector::getFlowControl10G(Positions pos) const { + return pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, + defs::FLOW_CONTROL_10G, -1); +} + +void Detector::setFlowControl10G(bool enable, Positions pos) { + pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, + defs::FLOW_CONTROL_10G, static_cast(enable)); +} + +Result Detector::getTransmissionDelayFrame(Positions pos) const { + return pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, + defs::DETECTOR_TXN_DELAY_FRAME, -1); +} + +void Detector::setTransmissionDelayFrame(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, + defs::DETECTOR_TXN_DELAY_FRAME, value); +} + +Result Detector::getTransmissionDelayLeft(Positions pos) const { + return pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, + defs::DETECTOR_TXN_DELAY_LEFT, -1); +} + +void Detector::setTransmissionDelayLeft(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, + defs::DETECTOR_TXN_DELAY_LEFT, value); +} + +Result Detector::getTransmissionDelayRight(Positions pos) const { + return pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, + defs::DETECTOR_TXN_DELAY_RIGHT, -1); +} + +void Detector::setTransmissionDelayRight(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, + defs::DETECTOR_TXN_DELAY_RIGHT, value); +} + +void Detector::setAdditionalJsonHeader(const std::string &jsonheader, + Positions pos) { + pimpl->Parallel(&slsDetector::setAdditionalJsonHeader, pos, jsonheader); +} + +Result Detector::getAdditionalJsonHeader(Positions pos) const { + return pimpl->Parallel(&slsDetector::getAdditionalJsonHeader, pos); +} + +Result Detector::getAdditionalJsonParameter(const std::string &key, + Positions pos) const { + return pimpl->Parallel(&slsDetector::getAdditionalJsonParameter, pos, key); +} + +void Detector::setAdditionalJsonParameter(const std::string &key, + const std::string &value, + Positions pos) { + pimpl->Parallel(&slsDetector::setAdditionalJsonParameter, pos, key, value); +} + +Result Detector::getDetectorMinMaxEnergyThreshold(const bool isEmax, Positions pos) const { + auto res = pimpl->Parallel(&slsDetector::getAdditionalJsonParameter, pos, isEmax ? "emax" : "emin"); + Result intResult; + try{ + for (unsigned int i = 0; i < res.size(); ++i) { + intResult[i] = stoi(res[i]); + } + } catch(...) { + throw RuntimeError("Cannot find or convert emin/emax string to integer"); + } + return intResult; +} + +void Detector::setDetectorMinMaxEnergyThreshold(const bool isEmax, const int value, Positions pos) { + pimpl->Parallel(&slsDetector::setAdditionalJsonParameter, pos, isEmax ? "emax" : "emin", std::to_string(value)); +} + +Result Detector::getFrameMode(Positions pos) const { + auto res = pimpl->Parallel(&slsDetector::getAdditionalJsonParameter, pos, "frameMode"); + Result intResult; + try{ + for (unsigned int i = 0; i < res.size(); ++i) { + intResult[i] = defs::getFrameModeType(res[i]); + } + } catch(...) { + throw RuntimeError("Cannot find or convert frameMode string to integer"); + } + return intResult; +} + +void Detector::setFrameMode(defs::frameModeType value, Positions pos) { + pimpl->Parallel(&slsDetector::setAdditionalJsonParameter, pos, "frameMode", defs::getFrameModeType(value)); +} + +Result Detector::getDetectorMode(Positions pos) const { + auto res = pimpl->Parallel(&slsDetector::getAdditionalJsonParameter, pos, "detectorMode"); + Result intResult; + try{ + for (unsigned int i = 0; i < res.size(); ++i) { + intResult[i] = defs::getDetectorModeType(res[i]); + } + } catch(...) { + throw RuntimeError("Cannot find or convert detectorMode string to integer"); + } + return intResult; +} + +void Detector::setDetectorMode(defs::detectorModeType value, Positions pos) { + pimpl->Parallel(&slsDetector::setAdditionalJsonParameter, pos, "detectorMode", defs::getDetectorModeType(value)); +} + +Result Detector::getDigitalTestBit(Positions pos) { + return pimpl->Parallel(&slsDetector::digitalTest, pos, defs::DIGITAL_BIT_TEST, -1); +} + +Result Detector::setDigitalTestBit(int value, Positions pos) { + return pimpl->Parallel(&slsDetector::digitalTest, pos, defs::DIGITAL_BIT_TEST, value); +} + +Result Detector::executeFirmwareTest(Positions pos) { + return pimpl->Parallel(&slsDetector::digitalTest, pos, defs::DETECTOR_FIRMWARE_TEST, -1); +} + +Result Detector::executeBusTest(Positions pos) { + return pimpl->Parallel(&slsDetector::digitalTest, pos, defs::DETECTOR_BUS_TEST, -1); +} + +void Detector::loadDarkImage(const std::string &fname, Positions pos) { + // TODO! optimize away multiple loads in multi + if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) { + pimpl->loadImageToDetector(defs::DARK_IMAGE, fname, -1); + } + if (pos.size() > 1) { + throw RuntimeError("Cannot load dark image on a subset of modules"); + } + pimpl->Parallel(&slsDetector::loadImageToDetector, pos, defs::DARK_IMAGE, fname); +} + +void Detector::loadGainImage(const std::string &fname, Positions pos) { + // TODO! optimize away multiple loadsin multi + if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) { + pimpl->loadImageToDetector(defs::GAIN_IMAGE, fname, -1); + } + if (pos.size() > 1) { + throw RuntimeError("Cannot load gain image on a subset of modules"); + } + pimpl->Parallel(&slsDetector::loadImageToDetector, pos, defs::GAIN_IMAGE, fname); +} + +void Detector::getCounterMemoryBlock(const std::string &fname, bool startACQ, Positions pos) { + if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) { + pimpl->writeCounterBlockFile(fname, static_cast(startACQ), -1); + } + if (pos.size() > 1) { + throw RuntimeError("Cannot load get counter memory block on a subset of modules"); + } + pimpl->Parallel(&slsDetector::writeCounterBlockFile, pos, fname, static_cast(startACQ)); +} + +void Detector::resetCounterBlock(bool startACQ, Positions pos) { + pimpl->Parallel(&slsDetector::resetCounterBlock, pos, static_cast(startACQ)); +} + +Result Detector::getCounterBit(Positions pos) const { + return pimpl->Parallel(&slsDetector::setCounterBit, pos, -1); +} + +void Detector::setCounterBit(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setCounterBit, pos, value); +} + +Result> Detector::getROI(Positions pos) const { + int n = 0; + if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) { + auto res = pimpl->getROI(n, -1); + std::vector arrayRes(n); + std::copy_n(res, n * sizeof(defs::ROI), arrayRes.begin()); + return arrayRes; + } else if (pos.size() > 1) { + throw RuntimeError("Cannot get roi from a subset of modules"); + } else { + auto res = pimpl->Parallel(&slsDetector::getROI, pos, n); + std::vector arrayRes(n); + std::copy_n(res, n * sizeof(defs::ROI), arrayRes.begin()); + return arrayRes; + } +} + +void Detector::setROI(std::vector value, Positions pos) { + if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) { + pimpl->setROI(static_cast(value.size()), value.data(), -1); + } else if (pos.size() > 1) { + throw RuntimeError("Cannot set roi to a subset of modules"); + } else { + pimpl->Parallel(&slsDetector::setROI, pos, static_cast(value.size()), value.data()); + } +} + +Result Detector::getADCEnableMask(Positions pos) const { + return pimpl->Parallel(&slsDetector::getADCEnableMask, pos); +} + +void Detector::setADCEnableMask(uint32_t mask, Positions pos) { + pimpl->Parallel(&slsDetector::setADCEnableMask, pos, mask); +} + +Result Detector::getADCInvert(Positions pos) const { + return pimpl->Parallel(&slsDetector::getADCInvert, pos); +} + +void Detector::setADCInvert(uint32_t value, Positions pos) { + pimpl->Parallel(&slsDetector::setADCInvert, pos, value); +} + +Result Detector::getExternalSamplingSource(Positions pos) const { + return pimpl->Parallel(&slsDetector::getExternalSamplingSource, pos); +} + +void Detector::setExternalSamplingSource(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setExternalSamplingSource, pos, value); +} + +Result Detector::getExternalSampling(Positions pos) const { + return pimpl->Parallel(&slsDetector::getExternalSampling, pos); +} + +void Detector::setExternalSampling(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setExternalSampling, pos, value); +} + +Result> Detector::getReceiverDbitList(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverDbitList, pos); +} + +void Detector::setReceiverDbitList(std::vector list, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverDbitList, pos, list); +} + +Result Detector::getReceiverDbitOffset(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverDbitOffset, pos); +} + +void Detector::setReceiverDbitOffset(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverDbitOffset, pos, value); +} + +void Detector::writeAdcRegister(uint32_t addr, uint32_t value, Positions pos) { + pimpl->Parallel(&slsDetector::writeAdcRegister, pos, addr, value); +} + + + + + + + +Result Detector::getReceiverUDPSocketBufferSize(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverUDPSocketBufferSize, pos); +} + +void Detector::setReceiverUDPSocketBufferSize(int64_t udpsockbufsize, + Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverUDPSocketBufferSize, pos, + udpsockbufsize); +} + +Result +Detector::getReceiverRealUDPSocketBufferSize(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverRealUDPSocketBufferSize, + pos); +} + + + + Result Detector::getFramesCaughtByReceiver(Positions pos) const { return pimpl->Parallel(&slsDetector::getFramesCaughtByReceiver, pos); } @@ -803,7 +1257,19 @@ Result Detector::getReceiverStreamingTimer(Positions pos) const { return pimpl->Parallel(&slsDetector::setReceiverStreamingTimer, pos, -1); } -void Detector::enableDataStreamingFromReceiver(bool enable, Positions pos) { +bool Detector::getDataStreamingToClient() const { + return pimpl->enableDataStreamingToClient(-1); +} + +void Detector::setDataStreamingToClient(bool enable) { + pimpl->enableDataStreamingToClient(static_cast(enable)); +} + +Result Detector::getDataStreamingFromReceiver(Positions pos) const { + return pimpl->Parallel(&slsDetector::enableDataStreamingFromReceiver, pos, -1); +} + +void Detector::setDataStreamingFromReceiver(bool enable, Positions pos) { pimpl->Parallel(&slsDetector::enableDataStreamingFromReceiver, pos, static_cast(enable)); } @@ -1123,292 +1589,11 @@ Result Detector::getActive(Positions pos) const { return pimpl->Parallel(&slsDetector::activate, pos, -1); } -void Detector::writeAdcRegister(uint32_t addr, uint32_t value, Positions pos) { - pimpl->Parallel(&slsDetector::writeAdcRegister, pos, addr, value); -} -Result Detector::getReceiverDbitOffset(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverDbitOffset, pos); -} -void Detector::setReceiverDbitOffset(int value, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverDbitOffset, pos, value); -} -Result> Detector::getReceiverDbitList(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverDbitList, pos); -} -void Detector::setReceiverDbitList(std::vector list, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverDbitList, pos, list); -} -Result Detector::getExternalSampling(Positions pos) const { - return pimpl->Parallel(&slsDetector::getExternalSampling, pos); -} -void Detector::setExternalSampling(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setExternalSampling, pos, value); -} - -Result Detector::getExternalSamplingSource(Positions pos) const { - return pimpl->Parallel(&slsDetector::getExternalSamplingSource, pos); -} - -void Detector::setExternalSamplingSource(int value, Positions pos) { - pimpl->Parallel(&slsDetector::setExternalSamplingSource, pos, value); -} - -uint32_t Detector::getADCInvert() const { - return pimpl->Parallel(&slsDetector::getADCInvert, {}) - .tsquash("Different Values for function getADCInvert"); -} - -void Detector::setADCInvert(uint32_t value) { - pimpl->Parallel(&slsDetector::setADCInvert, {}, value); -} - -uint32_t Detector::getADCEnableMask() const { - return pimpl->Parallel(&slsDetector::getADCEnableMask, {}) - .tsquash("Values of ADC enable mask cannot be different"); -} - -void Detector::setADCEnableMask(uint32_t mask) { - pimpl->Parallel(&slsDetector::setADCEnableMask, {}, mask); -} - -Result Detector::getCounterBit(Positions pos) const { - return pimpl->Parallel(&slsDetector::setCounterBit, pos, -1); -} - -void Detector::setCounterBit(int i, Positions pos) { - pimpl->Parallel(&slsDetector::setCounterBit, pos, i); -} - -void Detector::resetCounterBlock(int startACQ, Positions pos) { - pimpl->Parallel(&slsDetector::resetCounterBlock, pos, startACQ); -} - -void Detector::loadImageToDetector(defs::imageType index, - const std::string &fname, Positions pos) { - // TODO! optimize away multiple loads - pimpl->Parallel(&slsDetector::loadImageToDetector, pos, index, fname); -} - -Result Detector::digitalTest(defs::digitalTestMode mode, int ival, - Positions pos) { - return pimpl->Parallel(&slsDetector::digitalTest, pos, mode, ival); -} - -void Detector::setFlowControl10G(bool enable, Positions pos) { - pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, - defs::FLOW_CONTROL_10G, static_cast(enable)); -} - -Result Detector::getFlowControl10G(Positions pos) const { - return pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, - defs::FLOW_CONTROL_10G, -1); -} - -Result -Detector::getReceiverRealUDPSocketBufferSize(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverRealUDPSocketBufferSize, - pos); -} - -Result Detector::getReceiverUDPSocketBufferSize(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverUDPSocketBufferSize, pos); -} - -void Detector::setReceiverUDPSocketBufferSize(int64_t udpsockbufsize, - Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverUDPSocketBufferSize, pos, - udpsockbufsize); -} - -int Detector::setDetectorMode(defs::detectorModeType value) { - return pimpl->setDetectorMode(value); -} -int Detector::setFrameMode(defs::frameModeType value) { - return pimpl->setFrameMode(value); -} -int Detector::setDetectorMinMaxEnergyThreshold(const int index, int value) { - return pimpl->setDetectorMinMaxEnergyThreshold(index, value); -} - -void Detector::setAdditionalJsonHeader(const std::string &jsonheader, - Positions pos) { - pimpl->Parallel(&slsDetector::setAdditionalJsonHeader, pos, jsonheader); -} - -Result Detector::getAdditionalJsonHeader(Positions pos) const { - return pimpl->Parallel(&slsDetector::getAdditionalJsonHeader, pos); -} - -Result Detector::getAdditionalJsonParameter(const std::string &key, - Positions pos) const { - return pimpl->Parallel(&slsDetector::getAdditionalJsonParameter, pos, key); -} - -void Detector::setAdditionalJsonParameter(const std::string &key, - const std::string &value, - Positions pos) { - pimpl->Parallel(&slsDetector::setAdditionalJsonParameter, pos, key, value); -} - -Result Detector::getReceiverStreamingIP(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverStreamingIP, pos); -} - -void Detector::setReceiverDataStreamingOutIP(const std::string &ip, - Positions pos) { - // TODO! probably in one call - pimpl->Parallel(&slsDetector::setReceiverStreamingIP, pos, ip); - enableDataStreamingFromReceiver(false, pos); - enableDataStreamingFromReceiver(true, pos); -} - -Result Detector::getClientStreamingIP(Positions pos) const { - return pimpl->Parallel(&slsDetector::getClientStreamingIP, pos); -} - -void Detector::setClientDataStreamingInIP(const std::string &ip, - Positions pos) { - // TODO! probably in one call - pimpl->Parallel(&slsDetector::setClientStreamingIP, pos, ip); - pimpl->enableDataStreamingToClient(0); - pimpl->enableDataStreamingToClient(1); -} - -Result Detector::getReceiverStreamingPort(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverStreamingPort, pos); -} - -void Detector::setReceiverDataStreamingOutPort(int port, int module_id) { - pimpl->setReceiverDataStreamingOutPort(port, module_id); -} - -Result Detector::getClientStreamingPort(Positions pos) const { - return pimpl->Parallel(&slsDetector::getClientStreamingPort, pos); -} - -void Detector::setClientDataStreamingInPort(int port, int module_id) { - pimpl->setClientDataStreamingInPort(port, module_id); -} - -Result Detector::getSelectedUDPInterface(Positions pos) const { - return pimpl->Parallel(&slsDetector::getSelectedUDPInterface, pos); -} - -void Detector::selectUDPInterface(int interface, Positions pos) { - pimpl->Parallel(&slsDetector::selectUDPInterface, pos, interface); -} - -Result Detector::getNumberofUDPInterfaces(Positions pos) const { - return pimpl->Parallel(&slsDetector::getNumberofUDPInterfaces, pos); -} - -void Detector::setNumberofUDPInterfaces(int n, Positions pos) { - pimpl->Parallel(&slsDetector::setNumberofUDPInterfaces, pos, n); - - pimpl->enableDataStreamingToClient(0); - pimpl->enableDataStreamingToClient(1); - enableDataStreamingFromReceiver(false, pos); - enableDataStreamingFromReceiver(true, pos); -} - -Result Detector::getReceiverUDPPort2(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverUDPPort2, pos); -} - -void Detector::setReceiverUDPPort2(int udpport, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverUDPPort2, pos, udpport); -} - -Result Detector::getReceiverUDPPort(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverUDPPort, pos); -} - -void Detector::setReceiverUDPPort(int udpport, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverUDPPort, pos, udpport); -} - -Result Detector::getReceiverUDPMAC2(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverUDPMAC2, pos); -} - -void Detector::setReceiverUDPMAC2(const std::string &udpmac, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverUDPMAC2, pos, udpmac); -} - -Result Detector::getReceiverUDPMAC(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverUDPMAC, pos); -} - -void Detector::setReceiverUDPMAC(const std::string &udpmac, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverUDPMAC, pos, udpmac); -} - -Result Detector::getReceiverUDPIP2(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverUDPIP2, pos); -} - -void Detector::setReceiverUDPIP2(const std::string &udpip, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverUDPIP2, pos, udpip); -} - -Result Detector::getReceiverUDPIP(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverUDPIP, pos); -} - -void Detector::setReceiverUDPIP(const std::string &udpip, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverUDPIP, pos, udpip); -} - -Result Detector::getReceiverHostname(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverHostname, pos); -} - -void Detector::setReceiverHostname(const std::string &receiver, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverHostname, pos, receiver); -} - -Result Detector::getDetectorIP2(Positions pos) const { - return pimpl->Parallel(&slsDetector::getDetectorIP2, pos); -} - -void Detector::setDetectorIP2(const std::string &detectorIP, Positions pos) { - pimpl->Parallel(&slsDetector::setDetectorIP2, pos, detectorIP); -} - -Result Detector::getDetectorIP(Positions pos) const { - return pimpl->Parallel(&slsDetector::getDetectorIP, pos); -} - -void Detector::setDetectorIP(const std::string &detectorIP, Positions pos) { - pimpl->Parallel(&slsDetector::setDetectorIP, pos, detectorIP); -} - -Result Detector::getDetectorMAC(Positions pos) const { - return pimpl->Parallel(&slsDetector::getDetectorMAC, pos); -} -void Detector::setDetectorMAC(const std::string &detectorMAC, Positions pos) { - pimpl->Parallel(&slsDetector::setDetectorMAC, pos, detectorMAC); -} - -Result Detector::getDetectorMAC2(Positions pos) const { - return pimpl->Parallel(&slsDetector::getDetectorMAC2, pos); -} -void Detector::setDetectorMAC2(const std::string &detectorMAC, Positions pos) { - pimpl->Parallel(&slsDetector::setDetectorMAC2, pos, detectorMAC); -} - -Result Detector::getInterruptSubframe(Positions pos) const { - return pimpl->Parallel(&slsDetector::getInterruptSubframe, pos); -} - -void Detector::setInterruptSubframe(const bool enable, Positions pos){ - pimpl->Parallel(&slsDetector::setInterruptSubframe, pos, enable); -} } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index 7ef451e85..c5492c1ec 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -1726,7 +1726,7 @@ int multiSlsDetector::getReceiverUDPPort2(int detPos) const { int multiSlsDetector::setNumberofUDPInterfaces(int n, int detPos) { - int previouslyClientStreaming = enableDataStreamingToClient(); + bool previouslyClientStreaming = enableDataStreamingToClient(); int previouslyReceiverStreaming = enableDataStreamingFromReceiver(); // single @@ -1739,7 +1739,7 @@ int multiSlsDetector::setNumberofUDPInterfaces(int n, int detPos) { auto r = parallelCall(&slsDetector::setNumberofUDPInterfaces, n); // redo the zmq sockets - if (previouslyClientStreaming != 0) { + if (previouslyClientStreaming) { enableDataStreamingToClient(0); enableDataStreamingToClient(1); } @@ -1791,7 +1791,7 @@ int multiSlsDetector::getSelectedUDPInterface(int detPos) const { void multiSlsDetector::setClientDataStreamingInPort(int i, int detPos) { if (i >= 0) { - int prev_streaming = enableDataStreamingToClient(); + bool prev_streaming = enableDataStreamingToClient(); // single if (detPos >= 0) { @@ -1811,7 +1811,7 @@ void multiSlsDetector::setClientDataStreamingInPort(int i, int detPos) { } } - if (prev_streaming != 0) { + if (prev_streaming) { enableDataStreamingToClient(0); enableDataStreamingToClient(1); } @@ -1872,7 +1872,7 @@ int multiSlsDetector::getReceiverStreamingPort(int detPos) { void multiSlsDetector::setClientDataStreamingInIP(const std::string &ip, int detPos) { if (ip.length() != 0u) { - int prev_streaming = enableDataStreamingToClient(-1); + bool prev_streaming = enableDataStreamingToClient(-1); // single if (detPos >= 0) { @@ -1885,7 +1885,7 @@ void multiSlsDetector::setClientDataStreamingInIP(const std::string &ip, } } - if (prev_streaming != 0) { + if (prev_streaming) { enableDataStreamingToClient(0); enableDataStreamingToClient(1); } @@ -2142,6 +2142,13 @@ void multiSlsDetector::writeCounterBlockFile(const std::string &fname, imageVals + idet * detectors[idet]->getTotalNumberOfChannels(), startACQ); } + + if (writeDataFile(fname, nch, imageVals) < nch * (int)sizeof(short int)) { + throw RuntimeError( + "Could not open file to write or did not write enough data" + " in file to write counter block file from detector."); + } + } void multiSlsDetector::resetCounterBlock(int startACQ, int detPos) { @@ -3693,7 +3700,7 @@ int multiSlsDetector::setReceiverStreamingTimer(int time_in_ms, int detPos) { return sls::minusOneIfDifferent(r); } -int multiSlsDetector::enableDataStreamingToClient(int enable) { +bool multiSlsDetector::enableDataStreamingToClient(int enable) { if (enable >= 0) { // destroy data threads if (enable == 0) { @@ -3705,7 +3712,7 @@ int multiSlsDetector::enableDataStreamingToClient(int enable) { } } } - return static_cast(client_downstream); + return client_downstream; } int multiSlsDetector::enableDataStreamingFromReceiver(int enable, int detPos) { diff --git a/slsDetectorSoftware/src/slsDetectorCommand.cpp b/slsDetectorSoftware/src/slsDetectorCommand.cpp index 5243ef95b..7cd414911 100755 --- a/slsDetectorSoftware/src/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp @@ -235,7 +235,7 @@ slsDetectorCommand::slsDetectorCommand(multiSlsDetector *det) { ++i; /*! \page acquisition - - resmat i sets/resets counter bit in detector.gets the counter bit in detector ???? + - resmat i sets/resets counter bit in detector.gets the counter bit in Eiger */ descrToFuncMap[i].m_pFuncName = "resmat"; descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdCounter; From 8e2494729b9f43a929eb7df13f3e7a72b37df25b Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Mon, 12 Aug 2019 14:23:12 +0200 Subject: [PATCH 056/108] WIP --- .../include/FixedCapacityContainer.h | 235 +++++++----------- slsSupportLib/include/ToString.h | 11 +- slsSupportLib/include/TypeTraits.h | 21 ++ .../tests/test-FixedCapacityContainer.cpp | 20 ++ slsSupportLib/tests/test-ToString.cpp | 31 +-- slsSupportLib/tests/test-TypeTraits.cpp | 5 + 6 files changed, 167 insertions(+), 156 deletions(-) diff --git a/slsSupportLib/include/FixedCapacityContainer.h b/slsSupportLib/include/FixedCapacityContainer.h index d53136baa..443426336 100644 --- a/slsSupportLib/include/FixedCapacityContainer.h +++ b/slsSupportLib/include/FixedCapacityContainer.h @@ -4,176 +4,133 @@ #include #include +#include "TypeTraits.h" + namespace sls { template class FixedCapacityContainer { + public: + using size_type = typename std::array::size_type; + using value_type = typename std::array::value_type; + using iterator = typename std::array::iterator; + using const_iterator = typename std::array::const_iterator; + FixedCapacityContainer() = default; - explicit FixedCapacityContainer(std::initializer_list l); - explicit FixedCapacityContainer(const std::vector &v); + explicit FixedCapacityContainer(std::initializer_list l) { + current_size = l.size(); + std::copy(l.begin(), l.end(), data_.begin()); + } + + template ::value && + std::is_same::value>::type> + explicit FixedCapacityContainer(const V &v) { + if (v.size() > Capacity) { + throw std::runtime_error( + "Capacity needs to be same size or larger than vector"); + } + current_size = v.size(); + std::copy(v.begin(), v.end(), data_.begin()); + } template explicit FixedCapacityContainer( - const FixedCapacityContainer &other) noexcept; + const FixedCapacityContainer &other) noexcept { + static_assert(Capacity >= OtherCapacity, + "Container needs to be same size or larger"); + current_size = other.size(); + std::copy(other.cbegin(), other.cend(), data_.begin()); + } - FixedCapacityContainer &operator=(const std::vector &other); + FixedCapacityContainer &operator=(const std::vector &other) { + std::copy(other.begin(), other.end(), data_.begin()); + current_size = other.size(); + return *this; + } - bool operator==(const std::vector &other) const noexcept; - bool operator!=(const std::vector &other) const noexcept; + /** Compare FixedCapacityContainer with any other container*/ + template + typename std::enable_if::value, bool>::type + operator==(const V &other) const noexcept { + if (current_size != other.size()) { + return false; + } else { + for (size_t i = 0; i != current_size; ++i) { + if (data_[i] != other[i]) { + return false; + } + } + } + return true; + } - operator std::vector(){return std::vector(begin(), end());} + template + typename std::enable_if::value, bool>::type + operator!=(const V &other) const noexcept { + return !(*this == other); + } - template - bool operator==(const FixedCapacityContainer &other) const - noexcept; - - template - bool operator!=(const FixedCapacityContainer &other) const - noexcept; + operator std::vector() { return std::vector(begin(), end()); } T &operator[](size_t i) { return data_[i]; } const T &operator[](size_t i) const { return data_[i]; } - - constexpr size_t size() const noexcept { return size_; } - bool empty() const noexcept { return size_ == 0; } + constexpr size_type size() const noexcept { return current_size; } + bool empty() const noexcept { return current_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); + void push_back(const T &value) { + if (current_size == Capacity) { + throw std::runtime_error("Container is full"); + } else { + data_[current_size] = value; + ++current_size; + } + } + + void resize(size_t new_size) { + if (new_size > Capacity) { + throw std::runtime_error("Cannot resize beyond capacity"); + } else { + current_size = new_size; + } + } + + void erase(T *ptr) { + if (ptr >= begin() && ptr < end()) { + current_size = static_cast(ptr - begin()); + } else { + throw std::runtime_error("tried to erase with a ptr outside obj"); + } + } T &front() noexcept { return data_.front(); } - T &back() noexcept { return data_[size_ - 1]; } + T &back() noexcept { return data_[current_size - 1]; } constexpr const T &front() const noexcept { return data_.front(); } - constexpr const T &back() const noexcept { return data_[size_ - 1]; } + constexpr const T &back() const noexcept { return data_[current_size - 1]; } // iterators - 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_]; } + iterator begin() noexcept { return data_.begin(); } + const_iterator begin() const noexcept { return data_.begin(); } + iterator end() noexcept { return &data_[current_size]; } + const_iterator end() const noexcept { return &data_[current_size]; } + const_iterator cbegin() const noexcept { return data_.cbegin(); } + const_iterator cend() const noexcept { return &data_[current_size]; } private: - size_t size_{0}; + size_type current_size{}; std::array data_; } __attribute__((packed)); -/* Member functions */ -template -FixedCapacityContainer::FixedCapacityContainer( - std::initializer_list l) { - size_ = l.size(); - std::copy(l.begin(), l.end(), data_.begin()); -} - -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) { - throw std::runtime_error("Container is full"); - } else { - data_[size_] = value; - ++size_; - } -} -template -void FixedCapacityContainer::resize(size_t new_size) { - if (new_size > Capacity) { - throw std::runtime_error("Cannot resize beyond capacity"); - } else { - size_ = new_size; - } -} - -template -FixedCapacityContainer &FixedCapacityContainer:: -operator=(const std::vector &other) { - std::copy(other.begin(), other.end(), data_.begin()); - size_ = other.size(); - return *this; -} - -template -bool FixedCapacityContainer:: -operator==(const std::vector &other) const noexcept { - if (size_ != other.size()) { - return false; - } else { - for (size_t i = 0; i != size_; ++i) { - if (data_[i] != other[i]) { - return false; - } - } - } - return true; -} - -template -bool FixedCapacityContainer:: -operator!=(const std::vector &other) const noexcept { - return !(*this == other); -} - -template -template -bool FixedCapacityContainer:: -operator==(const FixedCapacityContainer &other) const - noexcept { - if (size_ != other.size()) { - return false; - } else { - for (size_t i = 0; i != size_; ++i) { - if (data_[i] != other[i]) { - return false; - } - } - } - return true; -} - -template -template -bool FixedCapacityContainer:: -operator!=(const FixedCapacityContainer &other) const - noexcept { - return !(*this == other); -} - -template -void FixedCapacityContainer::erase(T *ptr) { - if (ptr >= begin() && ptr < end()) { - size_ = static_cast(ptr - begin()); - } else { - throw std::runtime_error("tried to erase with a ptr outside obj"); - } -} - /* Free function concerning FixedCapacityContainer */ template -constexpr T *begin(FixedCapacityContainer &container) noexcept { +typename FixedCapacityContainer::iterator +begin(FixedCapacityContainer &container) noexcept { return container.begin(); } template -constexpr T *end(FixedCapacityContainer &container) noexcept { +typename FixedCapacityContainer::iterator +end(FixedCapacityContainer &container) noexcept { return container.end(); } diff --git a/slsSupportLib/include/ToString.h b/slsSupportLib/include/ToString.h index b032151e5..03d601fa3 100644 --- a/slsSupportLib/include/ToString.h +++ b/slsSupportLib/include/ToString.h @@ -2,9 +2,9 @@ /** * \file ToString.h - * + * * Conversion from various types to std::string - * + * */ #include "TimeHelper.h" @@ -137,4 +137,11 @@ template T StringTo(std::string t) { return StringTo(t, unit); } +/** For types with a .str() method use this for conversion */ +template +typename std::enable_if::value, std::string>::type +ToString(const T &obj) { + return obj.str(); +} + } // namespace sls diff --git a/slsSupportLib/include/TypeTraits.h b/slsSupportLib/include/TypeTraits.h index b7297389c..71d37e9ad 100644 --- a/slsSupportLib/include/TypeTraits.h +++ b/slsSupportLib/include/TypeTraits.h @@ -58,4 +58,25 @@ struct is_container< decltype(std::declval().empty())>, void>::type> : public std::true_type {}; + +/** + * Type trait to evaluate if template parameter is + * complying with a standard container + */ +template +struct is_light_container : std::false_type {}; + +template struct is_light_container_helper {}; + +template +struct is_light_container< + T, typename std::conditional< + false, + is_container_helper().size()), + decltype(std::declval().begin()), + decltype(std::declval().end())>, + void>::type> : public std::true_type {}; + } // namespace sls \ No newline at end of file diff --git a/slsSupportLib/tests/test-FixedCapacityContainer.cpp b/slsSupportLib/tests/test-FixedCapacityContainer.cpp index d4853cab7..4d3552e6f 100644 --- a/slsSupportLib/tests/test-FixedCapacityContainer.cpp +++ b/slsSupportLib/tests/test-FixedCapacityContainer.cpp @@ -1,8 +1,28 @@ #include "FixedCapacityContainer.h" #include "catch.hpp" +#include "TypeTraits.h" +#include +#include using sls::FixedCapacityContainer; +TEST_CASE("FixedCapacityContainer is a container"){ + REQUIRE(sls::is_container>::value == true); +} + + +TEST_CASE("Construct from vector"){ + std::vector vec{1,2,3}; + FixedCapacityContainer fcc{vec}; + REQUIRE(fcc == vec); +} + +TEST_CASE("Construct from array"){ + std::array arr{1,2,3}; + FixedCapacityContainer fcc{arr}; + REQUIRE(fcc == arr); +} + SCENARIO("FixedCapacityContainers can be sized and resized", "[support]") { GIVEN("A default constructed container") { diff --git a/slsSupportLib/tests/test-ToString.cpp b/slsSupportLib/tests/test-ToString.cpp index 6ec8c3f4f..dfc255d48 100644 --- a/slsSupportLib/tests/test-ToString.cpp +++ b/slsSupportLib/tests/test-ToString.cpp @@ -1,27 +1,25 @@ #include "TimeHelper.h" #include "ToString.h" +#include "network_utils.h" #include "catch.hpp" -#include #include - +#include // using namespace sls; -using sls::ToString; using sls::StringTo; +using sls::ToString; using namespace sls::time; - -TEST_CASE("Integer conversions", "[support]"){ +TEST_CASE("Integer conversions", "[support]") { REQUIRE(ToString(0) == "0"); REQUIRE(ToString(1) == "1"); REQUIRE(ToString(-1) == "-1"); REQUIRE(ToString(100) == "100"); REQUIRE(ToString(589633100) == "589633100"); - } -TEST_CASE("floating point conversions", "[support]"){ - //Should strip trailing zeros +TEST_CASE("floating point conversions", "[support]") { + // Should strip trailing zeros REQUIRE(ToString(0.) == "0"); REQUIRE(ToString(1.) == "1"); REQUIRE(ToString(-1.) == "-1"); @@ -32,7 +30,6 @@ TEST_CASE("floating point conversions", "[support]"){ REQUIRE(ToString(2.35010) == "2.3501"); REQUIRE(ToString(5000) == "5000"); REQUIRE(ToString(5E15) == "5000000000000000"); - } TEST_CASE("conversion from duration to string", "[support]") { @@ -55,13 +52,13 @@ TEST_CASE("string to std::chrono::duration", "[support]") { REQUIRE_THROWS(StringTo("asvn")); } -TEST_CASE("Convert vector of time", "[support]"){ +TEST_CASE("Convert vector of time", "[support]") { std::vector vec{ns(150), us(10), ns(600)}; REQUIRE(ToString(vec) == "[150ns, 10us, 600ns]"); REQUIRE(ToString(vec, "ns") == "[150ns, 10000ns, 600ns]"); } -TEST_CASE("Vector of int", "[support]"){ +TEST_CASE("Vector of int", "[support]") { std::vector vec; REQUIRE(ToString(vec) == "[]"); @@ -73,10 +70,9 @@ TEST_CASE("Vector of int", "[support]"){ vec.push_back(5000); REQUIRE(ToString(vec) == "[1, 172, 5000]"); - } -TEST_CASE("Vector of double", "[support]"){ +TEST_CASE("Vector of double", "[support]") { std::vector vec; REQUIRE(ToString(vec) == "[]"); @@ -90,8 +86,13 @@ TEST_CASE("Vector of double", "[support]"){ REQUIRE(ToString(vec) == "[1.3, 5669.325, -5669.325005]"); } -TEST_CASE("Array"){ - std::array arr{1,2,3}; +TEST_CASE("Array") { + std::array arr{1, 2, 3}; REQUIRE(ToString(arr) == "[1, 2, 3]"); +} +TEST_CASE("Convert types with str method"){ + sls::IpAddr addr; + REQUIRE(ToString(addr) == "0.0.0.0"); + REQUIRE(ToString(sls::IpAddr{}) == "0.0.0.0"); } \ No newline at end of file diff --git a/slsSupportLib/tests/test-TypeTraits.cpp b/slsSupportLib/tests/test-TypeTraits.cpp index 042eee3ac..2234ca0ae 100644 --- a/slsSupportLib/tests/test-TypeTraits.cpp +++ b/slsSupportLib/tests/test-TypeTraits.cpp @@ -4,6 +4,7 @@ #include #include #include +#include //Dummy classes only used here for testing class DummyWithStr { @@ -38,4 +39,8 @@ TEST_CASE("sls::is_duration"){ REQUIRE(sls::is_duration::value == false); REQUIRE(sls::is_duration>::value == false); +} + +TEST_CASE("initializer list"){ + REQUIRE(sls::is_light_container>::value == true); } \ No newline at end of file From 0a34192a8d46fac899d3d9af7676ddb0aa8698ff Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Mon, 12 Aug 2019 15:57:55 +0200 Subject: [PATCH 057/108] WIP --- slsDetectorSoftware/include/Detector.h | 131 +++++++++++++------------ slsDetectorSoftware/src/Detector.cpp | 108 +++++++++++--------- 2 files changed, 129 insertions(+), 110 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 3483ca37f..803821718 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -1141,13 +1141,13 @@ class Detector { void setCounterBit(bool value, Positions pos = {}); /** [Gotthard, CTB] subset modules not allowed */ - Result> getROI(Positions pos = {}) const; + //Result> getROI(Positions pos = {}) const; /** * [Gotthard Options: Only a single chip or all chips, only 1 ROI allowed] * [CTB: multiple ROIs allowed] * subset modules not allowed */ - void setROI(std::vector value, Positions pos = {}); + //void setROI(std::vector value, Positions pos = {}); /** [CTB]*/ Result getADCEnableMask(Positions pos = {}) const; @@ -1188,13 +1188,65 @@ class Detector { /** [Gotthard][Jungfrau][CTB] not possible to read back*/ void writeAdcRegister(uint32_t addr, uint32_t value, Positions pos = {}); + /** [Eiger] */ + Result getActive(Positions pos = {}) const; + + /** [Eiger] */ + void setActive(bool active, Positions pos = {}); + + /** [Eiger] */ + Result getBottom(Positions pos = {}) const; + + /** [Eiger] for gui purposes */ + void setBottom(bool value, Positions pos = {}); + + /** [Eiger] + * @returns -1 if they are all different + */ + Result getAllTrimbits(Positions pos = {}) const; + + /**[Eiger] */ + void setAllTrimbits(int value, Positions pos = {}); + + /**[Eiger] */ + Result getGapPixelsEnable(Positions pos = {}) const; + + /** + * [Eiger] + * 4 bit mode not implemented in Receiver, but in client data call back + * Fills in gap pixels in data + */ + void setGapPixelsEnable(bool enable); + + /**[Eiger] Returns energies in eV where the module is trimmed */ + Result> getTrimEnergies(Positions pos = {}) const; + + /** [Eiger] Set the energies where the detector is trimmed */ + void setTrimEnergies(std::vector energies, Positions pos = {}); + + /** + * [Eiger] Pulse Pixel n times at x and y coordinates + */ + void pulsePixel(int n, int x, int y, Positions pos = {}); + + /** [Eiger] Pulse Pixel n times and move by a relative value of x and y coordinates */ + void pulsePixelNMove(int n, int x, int y, Positions pos = {}); + + /** [Eiger] Pulse chip n times */ + void pulseChip(int n, Positions pos = {}); + /** [Eiger] */ + Result getRxPadDeactivatedMod(Positions pos = {}) const; - + /** + * [Eiger] Set deactivated Receiver padding mode + */ + void setRxPadDeactivatedMod(bool pad, Positions pos = {}); Result getReceiverUDPSocketBufferSize(Positions pos = {}) const; + void setReceiverUDPSocketBufferSize(int64_t udpsockbufsize, Positions pos = {}); Result @@ -1466,67 +1518,22 @@ class Detector { Result getThresholdTemperature(Positions pos = {}) const; - /** [Eiger] */ - void pulseChip(int n, Positions pos = {}); - - /** - * [Eiger] Pulse Pixel and move by a relative value - * @param n is number of times to pulse - * @param x is relative x value - * @param y is relative y value - */ - void pulsePixelNMove(int n, int x, int y, Positions pos = {}); - - /** - * [Eiger] Pulse Pixel - * @param n is number of times to pulse - * @param x is x coordinate - * @param y is y coordinate - * @param detPos -1 for all detectors in list or specific detector position - */ - void pulsePixel(int n, int x, int y, Positions pos = {}); - - /**[Eiger] Returns energies in eV where the module is trimmed */ - Result> getTrimEn(Positions pos = {}) const; - - /** [Eiger] Set the energies where the detector is trimmed */ - void setTrimEn(std::vector energies, Positions pos = {}); - - /** - * [Eiger] not 4 bit mode - * Fills in gap pixels in data - */ - void setGapPixelsEnable(bool enable, Positions pos = {}); - - Result getGapPixelEnable(Positions pos = {}) const; - - /**[Eiger] */ - void setAllTrimbits(int value, Positions pos = {}); - - /** [Eiger] TODO! only Eiger? */ - void setFlippedData(defs::dimension d, bool flipped, Positions pos = {}); - - Result getFlippedData(defs::dimension d, Positions pos = {}) const; - - /** - * [Eiger] Set deactivated Receiver padding mode - * @param padding padding option for deactivated receiver. Can be true - * (padding), false (no padding) - */ - void setRxPadDeactivatedMod(bool pad, Positions pos = {}); - - Result getRxPadDeactivatedMod(Positions pos = {}) const; - - /** - * [Eiger] Activates/Deactivates the detector - * @param true = active or false inactive - */ - void setActive(bool active, Positions pos = {}); - - Result getActive(Positions pos = {}) const; - + + + + + + + + + + + + + + }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 61e276d89..50e5613a5 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -1124,7 +1124,7 @@ Result Detector::getCounterBit(Positions pos) const { void Detector::setCounterBit(bool value, Positions pos) { pimpl->Parallel(&slsDetector::setCounterBit, pos, value); } - +/*TODO: Result> Detector::getROI(Positions pos) const { int n = 0; if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) { @@ -1150,7 +1150,7 @@ void Detector::setROI(std::vector value, Positions pos) { } else { pimpl->Parallel(&slsDetector::setROI, pos, static_cast(value.size()), value.data()); } -} +}*/ Result Detector::getADCEnableMask(Positions pos) const { return pimpl->Parallel(&slsDetector::getADCEnableMask, pos); @@ -1204,11 +1204,68 @@ void Detector::writeAdcRegister(uint32_t addr, uint32_t value, Positions pos) { pimpl->Parallel(&slsDetector::writeAdcRegister, pos, addr, value); } +Result Detector::getActive(Positions pos) const { + return pimpl->Parallel(&slsDetector::activate, pos, -1); +} + +void Detector::setActive(bool active, Positions pos) { + pimpl->Parallel(&slsDetector::activate, pos, static_cast(active)); +} + +Result Detector::getBottom(Positions pos) const { + return pimpl->Parallel(&slsDetector::getFlippedData, pos, defs::X); +} + +void Detector::setBottom(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setFlippedData, pos, defs::X, static_cast(value)); +} + +Result Detector::getAllTrimbits(Positions pos) const { + return pimpl->Parallel(&slsDetector::setAllTrimbits, pos, -1); +} + +void Detector::setAllTrimbits(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setAllTrimbits, pos, value); +} + +Result Detector::getGapPixelsEnable(Positions pos) const { + return pimpl->Parallel(&slsDetector::enableGapPixels, pos, -1); +} + +void Detector::setGapPixelsEnable(bool enable) { + pimpl->setGapPixelsEnable(enable, {}); +} + +Result> Detector::getTrimEnergies(Positions pos) const { + return pimpl->Parallel(&slsDetector::getTrimEn, pos); +} + +void Detector::setTrimEnergies(std::vector energies, Positions pos) { + pimpl->Parallel(&slsDetector::setTrimEn, pos, energies); +} + +void Detector::pulsePixel(int n, int x, int y, Positions pos) { + pimpl->Parallel(&slsDetector::pulsePixel, pos, n, x, y); +} + +void Detector::pulsePixelNMove(int n, int x, int y, Positions pos) { + pimpl->Parallel(&slsDetector::pulsePixelNMove, pos, n, x, y); +} + +void Detector::pulseChip(int n, Positions pos) { + pimpl->Parallel(&slsDetector::pulseChip, pos, n); +} +Result Detector::getRxPadDeactivatedMod(Positions pos) const { + return pimpl->Parallel(&slsDetector::setDeactivatedRxrPaddingMode, pos, -1); +} - +void Detector::setRxPadDeactivatedMod(bool pad, Positions pos) { + pimpl->Parallel(&slsDetector::setDeactivatedRxrPaddingMode, pos, + static_cast(pad)); +} Result Detector::getReceiverUDPSocketBufferSize(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverUDPSocketBufferSize, pos); @@ -1531,63 +1588,18 @@ Result Detector::getThresholdTemperature(Positions pos) const { return pimpl->Parallel(&slsDetector::setThresholdTemperature, pos, -1); } -void Detector::pulseChip(int n, Positions pos) { - pimpl->Parallel(&slsDetector::pulseChip, pos, n); -} -void Detector::pulsePixelNMove(int n, int x, int y, Positions pos) { - pimpl->Parallel(&slsDetector::pulsePixelNMove, pos, n, x, y); -} -void Detector::pulsePixel(int n, int x, int y, Positions pos) { - pimpl->Parallel(&slsDetector::pulsePixel, pos, n, x, y); -} -Result> Detector::getTrimEn(Positions pos) const { - return pimpl->Parallel(&slsDetector::getTrimEn, pos); -} -void Detector::setTrimEn(std::vector energies, Positions pos) { - pimpl->Parallel(&slsDetector::setTrimEn, pos, energies); -} -void Detector::setGapPixelsEnable(bool enable, Positions pos) { - pimpl->setGapPixelsEnable(enable, pos); -} -Result Detector::getGapPixelEnable(Positions pos) const { - return pimpl->Parallel(&slsDetector::enableGapPixels, pos, -1); -} -void Detector::setAllTrimbits(int value, Positions pos) { - pimpl->Parallel(&slsDetector::setAllTrimbits, pos, value); -} -void Detector::setFlippedData(defs::dimension d, bool flipped, Positions pos) { - pimpl->Parallel(&slsDetector::setFlippedData, pos, d, - static_cast(flipped)); -} -Result Detector::getFlippedData(defs::dimension d, Positions pos) const { - return pimpl->Parallel(&slsDetector::getFlippedData, pos, d); -} -void Detector::setRxPadDeactivatedMod(bool pad, Positions pos) { - pimpl->Parallel(&slsDetector::setDeactivatedRxrPaddingMode, pos, - static_cast(pad)); -} -Result Detector::getRxPadDeactivatedMod(Positions pos) const { - return pimpl->Parallel(&slsDetector::setDeactivatedRxrPaddingMode, pos, -1); -} -void Detector::setActive(bool active, Positions pos) { - pimpl->Parallel(&slsDetector::activate, pos, static_cast(active)); -} - -Result Detector::getActive(Positions pos) const { - return pimpl->Parallel(&slsDetector::activate, pos, -1); -} From 1008944a6a77c2c63a2831a00de3e3f81c2e53b5 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Mon, 12 Aug 2019 16:34:59 +0200 Subject: [PATCH 058/108] ROI workaroud --- slsDetectorSoftware/include/Result.h | 5 + slsDetectorSoftware/src/Detector.cpp | 306 ++++++++++++---------- slsDetectorSoftware/tests/test-Result.cpp | 16 ++ 3 files changed, 189 insertions(+), 138 deletions(-) diff --git a/slsDetectorSoftware/include/Result.h b/slsDetectorSoftware/include/Result.h index 9d5f2ae7e..54d19b1a5 100644 --- a/slsDetectorSoftware/include/Result.h +++ b/slsDetectorSoftware/include/Result.h @@ -98,6 +98,11 @@ template > class Result { vec.push_back(std::forward(value)); } + template + auto emplace_back(Args &&... args) -> decltype(vec.emplace_back(args...)){ + vec.emplace_back(std::forward(args)...); + } + auto operator[](size_type pos) -> decltype(vec[pos]) { return vec[pos]; } const_reference operator[](size_type pos) const { return vec[pos]; } diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 61e276d89..227670a06 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -41,10 +41,6 @@ void Detector::setConfig(const std::string &fname) { pimpl->readConfigurationFile(fname); } - - - - Result Detector::getStartingFrameNumber(Positions pos) const { return pimpl->Parallel(&slsDetector::getStartingFrameNumber, pos); } @@ -146,7 +142,10 @@ defs::coordinates Detector::getNumberOfDetectors() const { } Result Detector::getNumberOfChannels(Positions pos) const { - if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) {// TODO: also check condition that pos.size == pimpl->size()?? for other occurences as well + if (pos.empty() || + (pos.size() == 1 && + pos[0] == -1)) { // TODO: also check condition that pos.size == + // pimpl->size()?? for other occurences as well return {pimpl->getNumberOfChannels()}; } return pimpl->Parallel(&slsDetector::getNumberOfChannels, pos); @@ -688,88 +687,99 @@ void Detector::setDAC(int value, defs::dacIndex index, bool mV, Positions pos) { pimpl->Parallel(&slsDetector::setDAC, pos, value, index, mV); } - Result Detector::getTimingMode(Positions pos) const { - return pimpl->Parallel(&slsDetector::setExternalCommunicationMode, pos, defs::GET_EXTERNAL_COMMUNICATION_MODE); - } +Result +Detector::getTimingMode(Positions pos) const { + return pimpl->Parallel(&slsDetector::setExternalCommunicationMode, pos, + defs::GET_EXTERNAL_COMMUNICATION_MODE); +} - void Detector::setTimingMode(defs::externalCommunicationMode value, Positions pos) { - pimpl->Parallel(&slsDetector::setExternalCommunicationMode, pos, value); - } +void Detector::setTimingMode(defs::externalCommunicationMode value, + Positions pos) { + pimpl->Parallel(&slsDetector::setExternalCommunicationMode, pos, value); +} - Result Detector::getExternalSignalFlags(Positions pos) const { - return pimpl->Parallel(&slsDetector::setExternalSignalFlags, pos, defs::GET_EXTERNAL_SIGNAL_FLAG); - } +Result +Detector::getExternalSignalFlags(Positions pos) const { + return pimpl->Parallel(&slsDetector::setExternalSignalFlags, pos, + defs::GET_EXTERNAL_SIGNAL_FLAG); +} - void Detector::setExternalSignalFlags(defs::externalSignalFlag value, Positions pos) { - pimpl->Parallel(&slsDetector::setExternalSignalFlags, pos, value); - } +void Detector::setExternalSignalFlags(defs::externalSignalFlag value, + Positions pos) { + pimpl->Parallel(&slsDetector::setExternalSignalFlags, pos, value); +} - Result Detector::getParallelMode(Positions pos) const { - auto res = pimpl->Parallel(&slsDetector::setReadOutFlags, pos, defs::GET_READOUT_FLAGS); - Result booleanRes; - for (unsigned int i = 0; i < res.size(); ++i) { - booleanRes[i] = (res[i] & defs::PARALLEL) ? true : false; +Result Detector::getParallelMode(Positions pos) const { + auto res = pimpl->Parallel(&slsDetector::setReadOutFlags, pos, + defs::GET_READOUT_FLAGS); + Result booleanRes; + for (unsigned int i = 0; i < res.size(); ++i) { + booleanRes[i] = (res[i] & defs::PARALLEL) ? true : false; + } + return booleanRes; +} + +void Detector::setParallelMode(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setReadOutFlags, pos, + value ? defs::PARALLEL : defs::NONPARALLEL); +} + +Result Detector::getOverFlowMode(Positions pos) const { + auto res = pimpl->Parallel(&slsDetector::setReadOutFlags, pos, + defs::GET_READOUT_FLAGS); + Result booleanRes; + for (unsigned int i = 0; i < res.size(); ++i) { + booleanRes[i] = (res[i] & defs::SHOW_OVERFLOW) ? true : false; + } + return booleanRes; +} + +void Detector::setOverFlowMode(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setReadOutFlags, pos, + value ? defs::SHOW_OVERFLOW : defs::NOOVERFLOW); +} + +Result Detector::getSignalType(Positions pos) const { + auto res = pimpl->Parallel(&slsDetector::setReadOutFlags, pos, + defs::GET_READOUT_FLAGS); + for (auto &it : res) { + if (it & defs::ANALOG_AND_DIGITAL) { + it = 2; + } else if (it & defs::DIGITAL_ONLY) { + it = 1; + } else if (it == defs::NORMAL_READOUT) { + it = 0; + } else { + throw RuntimeError("Unknown Signal Type"); } - return booleanRes; } + return res; +} - void Detector::setParallelMode(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setReadOutFlags, pos, value ? defs::PARALLEL : defs::NONPARALLEL); - } - - Result Detector::getOverFlowMode(Positions pos) const { - auto res = pimpl->Parallel(&slsDetector::setReadOutFlags, pos, defs::GET_READOUT_FLAGS); - Result booleanRes; - for (unsigned int i = 0; i < res.size(); ++i) { - booleanRes[i] = (res[i] & defs::SHOW_OVERFLOW) ? true : false; - } - return booleanRes; - } - - void Detector::setOverFlowMode(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setReadOutFlags, pos, value ? defs::SHOW_OVERFLOW : defs::NOOVERFLOW); - } - - Result Detector::getSignalType(Positions pos) const { - auto res = pimpl->Parallel(&slsDetector::setReadOutFlags, pos, defs::GET_READOUT_FLAGS); - for (auto &it : res) { - if (it & defs::ANALOG_AND_DIGITAL) { - it = 2; - } else if (it & defs::DIGITAL_ONLY) { - it = 1; - } else if (it == defs::NORMAL_READOUT) { - it = 0; - } else { - throw RuntimeError("Unknown Signal Type"); - } - } - return res; - } - - void Detector::setSignalType(int value, Positions pos) { - defs::readOutFlags flag; - switch (value) { - case 0: - flag = defs::NORMAL_READOUT; - break; - case 1: - flag = defs::DIGITAL_ONLY; - break; - case 2: - flag = defs::ANALOG_AND_DIGITAL; - break; - default: - throw RuntimeError("Unknown Signal Type"); - } - pimpl->Parallel(&slsDetector::setReadOutFlags, pos, flag); +void Detector::setSignalType(int value, Positions pos) { + defs::readOutFlags flag; + switch (value) { + case 0: + flag = defs::NORMAL_READOUT; + break; + case 1: + flag = defs::DIGITAL_ONLY; + break; + case 2: + flag = defs::ANALOG_AND_DIGITAL; + break; + default: + throw RuntimeError("Unknown Signal Type"); } + pimpl->Parallel(&slsDetector::setReadOutFlags, pos, flag); +} // Erik Result Detector::getInterruptSubframe(Positions pos) const { return pimpl->Parallel(&slsDetector::getInterruptSubframe, pos); } -void Detector::setInterruptSubframe(const bool enable, Positions pos){ +void Detector::setInterruptSubframe(const bool enable, Positions pos) { pimpl->Parallel(&slsDetector::setInterruptSubframe, pos, enable); } @@ -881,7 +891,8 @@ Result Detector::getNumberofUDPInterfaces(Positions pos) const { void Detector::setNumberofUDPInterfaces(int n, Positions pos) { bool previouslyClientStreaming = getDataStreamingToClient(); - bool previouslyReceiverStreaming = getDataStreamingFromReceiver(pos).squash(false); + bool previouslyReceiverStreaming = + getDataStreamingFromReceiver(pos).squash(false); pimpl->Parallel(&slsDetector::setNumberofUDPInterfaces, pos, n); // redo the zmq sockets if enabled if (previouslyClientStreaming) { @@ -908,7 +919,8 @@ Result Detector::getClientStreamingPort(Positions pos) const { void Detector::setClientDataStreamingInPort(int port, Positions pos) { if (pos.size() > 1 && pos.size() < pimpl->size()) { - throw RuntimeError("Cannot set client streaming port to a subset of modules"); + throw RuntimeError( + "Cannot set client streaming port to a subset of modules"); } pimpl->setClientDataStreamingInPort(port, pos.empty() ? -1 : pos[0]); } @@ -919,9 +931,10 @@ Result Detector::getReceiverStreamingPort(Positions pos) const { void Detector::setReceiverDataStreamingOutPort(int port, Positions pos) { if (pos.size() > 1 && pos.size() < pimpl->size()) { - throw RuntimeError("Cannot set receiver streaming port to a subset of modules"); + throw RuntimeError( + "Cannot set receiver streaming port to a subset of modules"); } - pimpl->setReceiverDataStreamingOutPort(port, pos.empty() ? -1 : pos[0]); + pimpl->setReceiverDataStreamingOutPort(port, pos.empty() ? -1 : pos[0]); } Result Detector::getClientStreamingIP(Positions pos) const { @@ -930,7 +943,7 @@ Result Detector::getClientStreamingIP(Positions pos) const { void Detector::setClientDataStreamingInIP(const std::string &ip, Positions pos) { - bool previouslyClientStreaming = getDataStreamingToClient(); + bool previouslyClientStreaming = getDataStreamingToClient(); // TODO! probably in one call ?? pimpl->Parallel(&slsDetector::setClientStreamingIP, pos, ip); if (previouslyClientStreaming) { @@ -945,7 +958,8 @@ Result Detector::getReceiverStreamingIP(Positions pos) const { void Detector::setReceiverDataStreamingOutIP(const std::string &ip, Positions pos) { - bool previouslyReceiverStreaming = getDataStreamingFromReceiver(pos).squash(false); + bool previouslyReceiverStreaming = + getDataStreamingFromReceiver(pos).squash(false); // TODO! probably in one call pimpl->Parallel(&slsDetector::setReceiverStreamingIP, pos, ip); if (previouslyReceiverStreaming) { @@ -1014,71 +1028,87 @@ void Detector::setAdditionalJsonParameter(const std::string &key, pimpl->Parallel(&slsDetector::setAdditionalJsonParameter, pos, key, value); } -Result Detector::getDetectorMinMaxEnergyThreshold(const bool isEmax, Positions pos) const { - auto res = pimpl->Parallel(&slsDetector::getAdditionalJsonParameter, pos, isEmax ? "emax" : "emin"); +Result Detector::getDetectorMinMaxEnergyThreshold(const bool isEmax, + Positions pos) const { + auto res = pimpl->Parallel(&slsDetector::getAdditionalJsonParameter, pos, + isEmax ? "emax" : "emin"); Result intResult; - try{ + try { for (unsigned int i = 0; i < res.size(); ++i) { intResult[i] = stoi(res[i]); } - } catch(...) { - throw RuntimeError("Cannot find or convert emin/emax string to integer"); + } catch (...) { + throw RuntimeError( + "Cannot find or convert emin/emax string to integer"); } return intResult; } -void Detector::setDetectorMinMaxEnergyThreshold(const bool isEmax, const int value, Positions pos) { - pimpl->Parallel(&slsDetector::setAdditionalJsonParameter, pos, isEmax ? "emax" : "emin", std::to_string(value)); +void Detector::setDetectorMinMaxEnergyThreshold(const bool isEmax, + const int value, + Positions pos) { + pimpl->Parallel(&slsDetector::setAdditionalJsonParameter, pos, + isEmax ? "emax" : "emin", std::to_string(value)); } Result Detector::getFrameMode(Positions pos) const { - auto res = pimpl->Parallel(&slsDetector::getAdditionalJsonParameter, pos, "frameMode"); + auto res = pimpl->Parallel(&slsDetector::getAdditionalJsonParameter, pos, + "frameMode"); Result intResult; - try{ + try { for (unsigned int i = 0; i < res.size(); ++i) { intResult[i] = defs::getFrameModeType(res[i]); } - } catch(...) { - throw RuntimeError("Cannot find or convert frameMode string to integer"); + } catch (...) { + throw RuntimeError( + "Cannot find or convert frameMode string to integer"); } return intResult; } void Detector::setFrameMode(defs::frameModeType value, Positions pos) { - pimpl->Parallel(&slsDetector::setAdditionalJsonParameter, pos, "frameMode", defs::getFrameModeType(value)); + pimpl->Parallel(&slsDetector::setAdditionalJsonParameter, pos, "frameMode", + defs::getFrameModeType(value)); } Result Detector::getDetectorMode(Positions pos) const { - auto res = pimpl->Parallel(&slsDetector::getAdditionalJsonParameter, pos, "detectorMode"); + auto res = pimpl->Parallel(&slsDetector::getAdditionalJsonParameter, pos, + "detectorMode"); Result intResult; - try{ + try { for (unsigned int i = 0; i < res.size(); ++i) { intResult[i] = defs::getDetectorModeType(res[i]); } - } catch(...) { - throw RuntimeError("Cannot find or convert detectorMode string to integer"); + } catch (...) { + throw RuntimeError( + "Cannot find or convert detectorMode string to integer"); } return intResult; } void Detector::setDetectorMode(defs::detectorModeType value, Positions pos) { - pimpl->Parallel(&slsDetector::setAdditionalJsonParameter, pos, "detectorMode", defs::getDetectorModeType(value)); + pimpl->Parallel(&slsDetector::setAdditionalJsonParameter, pos, + "detectorMode", defs::getDetectorModeType(value)); } Result Detector::getDigitalTestBit(Positions pos) { - return pimpl->Parallel(&slsDetector::digitalTest, pos, defs::DIGITAL_BIT_TEST, -1); + return pimpl->Parallel(&slsDetector::digitalTest, pos, + defs::DIGITAL_BIT_TEST, -1); } Result Detector::setDigitalTestBit(int value, Positions pos) { - return pimpl->Parallel(&slsDetector::digitalTest, pos, defs::DIGITAL_BIT_TEST, value); + return pimpl->Parallel(&slsDetector::digitalTest, pos, + defs::DIGITAL_BIT_TEST, value); } Result Detector::executeFirmwareTest(Positions pos) { - return pimpl->Parallel(&slsDetector::digitalTest, pos, defs::DETECTOR_FIRMWARE_TEST, -1); + return pimpl->Parallel(&slsDetector::digitalTest, pos, + defs::DETECTOR_FIRMWARE_TEST, -1); } Result Detector::executeBusTest(Positions pos) { - return pimpl->Parallel(&slsDetector::digitalTest, pos, defs::DETECTOR_BUS_TEST, -1); + return pimpl->Parallel(&slsDetector::digitalTest, pos, + defs::DETECTOR_BUS_TEST, -1); } void Detector::loadDarkImage(const std::string &fname, Positions pos) { @@ -1089,7 +1119,8 @@ void Detector::loadDarkImage(const std::string &fname, Positions pos) { if (pos.size() > 1) { throw RuntimeError("Cannot load dark image on a subset of modules"); } - pimpl->Parallel(&slsDetector::loadImageToDetector, pos, defs::DARK_IMAGE, fname); + pimpl->Parallel(&slsDetector::loadImageToDetector, pos, defs::DARK_IMAGE, + fname); } void Detector::loadGainImage(const std::string &fname, Positions pos) { @@ -1100,21 +1131,26 @@ void Detector::loadGainImage(const std::string &fname, Positions pos) { if (pos.size() > 1) { throw RuntimeError("Cannot load gain image on a subset of modules"); } - pimpl->Parallel(&slsDetector::loadImageToDetector, pos, defs::GAIN_IMAGE, fname); + pimpl->Parallel(&slsDetector::loadImageToDetector, pos, defs::GAIN_IMAGE, + fname); } -void Detector::getCounterMemoryBlock(const std::string &fname, bool startACQ, Positions pos) { +void Detector::getCounterMemoryBlock(const std::string &fname, bool startACQ, + Positions pos) { if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) { pimpl->writeCounterBlockFile(fname, static_cast(startACQ), -1); } if (pos.size() > 1) { - throw RuntimeError("Cannot load get counter memory block on a subset of modules"); + throw RuntimeError( + "Cannot load get counter memory block on a subset of modules"); } - pimpl->Parallel(&slsDetector::writeCounterBlockFile, pos, fname, static_cast(startACQ)); + pimpl->Parallel(&slsDetector::writeCounterBlockFile, pos, fname, + static_cast(startACQ)); } void Detector::resetCounterBlock(bool startACQ, Positions pos) { - pimpl->Parallel(&slsDetector::resetCounterBlock, pos, static_cast(startACQ)); + pimpl->Parallel(&slsDetector::resetCounterBlock, pos, + static_cast(startACQ)); } Result Detector::getCounterBit(Positions pos) const { @@ -1126,29 +1162,38 @@ void Detector::setCounterBit(bool value, Positions pos) { } Result> Detector::getROI(Positions pos) const { - int n = 0; - if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) { - auto res = pimpl->getROI(n, -1); - std::vector arrayRes(n); - std::copy_n(res, n * sizeof(defs::ROI), arrayRes.begin()); - return arrayRes; - } else if (pos.size() > 1) { - throw RuntimeError("Cannot get roi from a subset of modules"); - } else { - auto res = pimpl->Parallel(&slsDetector::getROI, pos, n); - std::vector arrayRes(n); - std::copy_n(res, n * sizeof(defs::ROI), arrayRes.begin()); - return arrayRes; + //vector holding module_id for the modules that should be read + std::vector id_vec = [&]() { + if (pos.empty() || (pos.size() == 1 && pos[0] == -1)){ + std::vector tmp; + for(size_t i=0; i!= pimpl->size(); ++i) + tmp.push_back(i); + return tmp; + }else{ + return pos; + } + }(); + + //values to return + Result> res; + + //for each detector id get the ROI + for (const auto& i :id_vec){ + int n = 0; + auto ptr = pimpl->getROI(n, i); + res.emplace_back(ptr, ptr+n); } + return res; } void Detector::setROI(std::vector value, Positions pos) { if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) { pimpl->setROI(static_cast(value.size()), value.data(), -1); } else if (pos.size() > 1) { - throw RuntimeError("Cannot set roi to a subset of modules"); + throw RuntimeError("Cannot set roi to a subset of modules"); } else { - pimpl->Parallel(&slsDetector::setROI, pos, static_cast(value.size()), value.data()); + pimpl->Parallel(&slsDetector::setROI, pos, + static_cast(value.size()), value.data()); } } @@ -1204,12 +1249,6 @@ void Detector::writeAdcRegister(uint32_t addr, uint32_t value, Positions pos) { pimpl->Parallel(&slsDetector::writeAdcRegister, pos, addr, value); } - - - - - - Result Detector::getReceiverUDPSocketBufferSize(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverUDPSocketBufferSize, pos); } @@ -1226,9 +1265,6 @@ Detector::getReceiverRealUDPSocketBufferSize(Positions pos) const { pos); } - - - Result Detector::getFramesCaughtByReceiver(Positions pos) const { return pimpl->Parallel(&slsDetector::getFramesCaughtByReceiver, pos); } @@ -1266,7 +1302,8 @@ void Detector::setDataStreamingToClient(bool enable) { } Result Detector::getDataStreamingFromReceiver(Positions pos) const { - return pimpl->Parallel(&slsDetector::enableDataStreamingFromReceiver, pos, -1); + return pimpl->Parallel(&slsDetector::enableDataStreamingFromReceiver, pos, + -1); } void Detector::setDataStreamingFromReceiver(bool enable, Positions pos) { @@ -1589,11 +1626,4 @@ Result Detector::getActive(Positions pos) const { return pimpl->Parallel(&slsDetector::activate, pos, -1); } - - - - - - - } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/tests/test-Result.cpp b/slsDetectorSoftware/tests/test-Result.cpp index 352df0f68..06c2f10e5 100644 --- a/slsDetectorSoftware/tests/test-Result.cpp +++ b/slsDetectorSoftware/tests/test-Result.cpp @@ -134,3 +134,19 @@ TEST_CASE("Convert from Result to Result") { REQUIRE(res2[1] == ns(50)); REQUIRE(res2[2] == ns(236)); } + + +TEST_CASE("Result of vectors"){ + using VecVec = std::vector>; + VecVec vecvec{{1,2,3}, {4,5,6}}; + Result res{vecvec}; +} + +TEST_CASE("emplace back"){ + std::vector vec{1,2,3,4,5}; + Result> res; + res.emplace_back(vec.begin(), vec.end()); + REQUIRE(res.size() == 1); + REQUIRE(res[0].size() == 5); + REQUIRE(res[0] == vec); +} \ No newline at end of file From b52a8d2d61453c9cb19b32af286d9888ad5c41b6 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Mon, 12 Aug 2019 16:43:17 +0200 Subject: [PATCH 059/108] added missing const --- slsDetectorSoftware/src/Detector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index b4ba194eb..c55e3a98a 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -1163,7 +1163,7 @@ void Detector::setCounterBit(bool value, Positions pos) { Result> Detector::getROI(Positions pos) const { //vector holding module_id for the modules that should be read - std::vector id_vec = [&]() { + const std::vector id_vec = [&]() { if (pos.empty() || (pos.size() == 1 && pos[0] == -1)){ std::vector tmp; for(size_t i=0; i!= pimpl->size(); ++i) From 935f7bc960c23078a9cac1f993c0e8378ebaa13f Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Mon, 12 Aug 2019 17:17:13 +0200 Subject: [PATCH 060/108] WIP --- CMakeLists.txt | 8 ++-- .../include/FixedCapacityContainer.h | 39 ++++++++++--------- .../tests/test-FixedCapacityContainer.cpp | 27 +++++++++++++ 3 files changed, 52 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ab0c1dac6..a1a568e98 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,7 @@ 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) +option(SLS_BUILD_DOCS "Documentations" OFF) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) @@ -182,10 +183,11 @@ configure_file( .clang-tidy ) -add_subdirectory(sample) - -add_subdirectory(docs) +#add_subdirectory(sample) +if(SLS_BUILD_DOCS) + add_subdirectory(docs) +endif(SLS_BUILD_DOCS) diff --git a/slsSupportLib/include/FixedCapacityContainer.h b/slsSupportLib/include/FixedCapacityContainer.h index 443426336..ea409ec22 100644 --- a/slsSupportLib/include/FixedCapacityContainer.h +++ b/slsSupportLib/include/FixedCapacityContainer.h @@ -16,34 +16,28 @@ template class FixedCapacityContainer { using const_iterator = typename std::array::const_iterator; FixedCapacityContainer() = default; - explicit FixedCapacityContainer(std::initializer_list l) { - current_size = l.size(); + + explicit FixedCapacityContainer(std::initializer_list l) + : current_size(l.size()) { + size_check(l.size()); std::copy(l.begin(), l.end(), data_.begin()); } + /** Copy construct from another container */ template ::value && + is_container::value && std::is_same::value>::type> - explicit FixedCapacityContainer(const V &v) { - if (v.size() > Capacity) { - throw std::runtime_error( - "Capacity needs to be same size or larger than vector"); - } - current_size = v.size(); + FixedCapacityContainer(const V &v) : current_size(v.size()) { + size_check(v.size()); std::copy(v.begin(), v.end(), data_.begin()); } - template - explicit FixedCapacityContainer( - const FixedCapacityContainer &other) noexcept { - static_assert(Capacity >= OtherCapacity, - "Container needs to be same size or larger"); - current_size = other.size(); - std::copy(other.cbegin(), other.cend(), data_.begin()); - } - - FixedCapacityContainer &operator=(const std::vector &other) { + /** copy assignment from another container */ + template + typename std::enable_if::value, FixedCapacityContainer &>::type + operator=(const V &other) { + size_check(other.size()); std::copy(other.begin(), other.end(), data_.begin()); current_size = other.size(); return *this; @@ -119,6 +113,13 @@ template class FixedCapacityContainer { private: size_type current_size{}; std::array data_; + + void size_check(size_type s) const { + if (s > Capacity) { + throw std::runtime_error( + "Capacity needs to be same size or larger than vector"); + } + } } __attribute__((packed)); /* Free function concerning FixedCapacityContainer */ diff --git a/slsSupportLib/tests/test-FixedCapacityContainer.cpp b/slsSupportLib/tests/test-FixedCapacityContainer.cpp index 4d3552e6f..53ae2fbb8 100644 --- a/slsSupportLib/tests/test-FixedCapacityContainer.cpp +++ b/slsSupportLib/tests/test-FixedCapacityContainer.cpp @@ -17,12 +17,39 @@ TEST_CASE("Construct from vector"){ REQUIRE(fcc == vec); } +TEST_CASE("Copy construct from vector"){ + std::vector vec{1,2,3}; + FixedCapacityContainer fcc = vec; + REQUIRE(fcc == vec); +} + +TEST_CASE("Copy assignment from vector"){ + std::vector vec{1,2,3}; + FixedCapacityContainer fcc; + fcc = vec; + REQUIRE(fcc == vec); +} + + TEST_CASE("Construct from array"){ std::array arr{1,2,3}; FixedCapacityContainer fcc{arr}; REQUIRE(fcc == arr); } +TEST_CASE("Copy assign from array"){ + std::array arr{1,2,3}; + FixedCapacityContainer fcc; + fcc = arr; + REQUIRE(fcc == arr); +} + +TEST_CASE("Copy construct from array"){ + std::array arr{1,2,3}; + FixedCapacityContainer fcc = arr; + REQUIRE(fcc == arr); +} + SCENARIO("FixedCapacityContainers can be sized and resized", "[support]") { GIVEN("A default constructed container") { From f99ebc7f2129ec8bc58a51662e06443e384fdba6 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Mon, 12 Aug 2019 18:38:56 +0200 Subject: [PATCH 061/108] WIP --- slsDetectorSoftware/tests/test-Result.cpp | 15 +++ .../include/FixedCapacityContainer.h | 52 ++++---- .../tests/test-FixedCapacityContainer.cpp | 120 +++++++++++------- 3 files changed, 110 insertions(+), 77 deletions(-) diff --git a/slsDetectorSoftware/tests/test-Result.cpp b/slsDetectorSoftware/tests/test-Result.cpp index 06c2f10e5..ceb8f3d07 100644 --- a/slsDetectorSoftware/tests/test-Result.cpp +++ b/slsDetectorSoftware/tests/test-Result.cpp @@ -149,4 +149,19 @@ TEST_CASE("emplace back"){ REQUIRE(res.size() == 1); REQUIRE(res[0].size() == 5); REQUIRE(res[0] == vec); +} + +TEST_CASE("Free function begin end"){ + Result res{"ett", "nio", "sjutton"}; + REQUIRE(begin(res) == res.begin()); + REQUIRE(end(res) == res.end()); +} + +TEST_CASE("Sorting a Result"){ + Result res{4,5,1,3}; + std::sort(res.begin(), res.end()); + REQUIRE(res[0] == 1); + REQUIRE(res[1] == 3); + REQUIRE(res[2] == 4); + REQUIRE(res[3] == 5); } \ No newline at end of file diff --git a/slsSupportLib/include/FixedCapacityContainer.h b/slsSupportLib/include/FixedCapacityContainer.h index ea409ec22..f6b57caa9 100644 --- a/slsSupportLib/include/FixedCapacityContainer.h +++ b/slsSupportLib/include/FixedCapacityContainer.h @@ -1,11 +1,11 @@ #pragma once +#include "TypeTraits.h" #include #include +#include #include #include -#include "TypeTraits.h" - namespace sls { template class FixedCapacityContainer { @@ -15,6 +15,11 @@ template class FixedCapacityContainer { using iterator = typename std::array::iterator; using const_iterator = typename std::array::const_iterator; + private: + size_type current_size{}; + std::array data_; + + public: FixedCapacityContainer() = default; explicit FixedCapacityContainer(std::initializer_list l) @@ -28,14 +33,15 @@ template class FixedCapacityContainer { typename = typename std::enable_if< is_container::value && std::is_same::value>::type> - FixedCapacityContainer(const V &v) : current_size(v.size()) { + FixedCapacityContainer(const V &v) : current_size(v.size()) { size_check(v.size()); std::copy(v.begin(), v.end(), data_.begin()); } /** copy assignment from another container */ template - typename std::enable_if::value, FixedCapacityContainer &>::type + typename std::enable_if::value, + FixedCapacityContainer &>::type operator=(const V &other) { size_check(other.size()); std::copy(other.begin(), other.end(), data_.begin()); @@ -104,49 +110,37 @@ template class FixedCapacityContainer { // iterators iterator begin() noexcept { return data_.begin(); } + // auto begin() noexcept -> decltype(data_.begin()) { return data_.begin(); + // } const_iterator begin() const noexcept { return data_.begin(); } iterator end() noexcept { return &data_[current_size]; } const_iterator end() const noexcept { return &data_[current_size]; } const_iterator cbegin() const noexcept { return data_.cbegin(); } const_iterator cend() const noexcept { return &data_[current_size]; } - private: - size_type current_size{}; - std::array data_; - void size_check(size_type s) const { if (s > Capacity) { throw std::runtime_error( "Capacity needs to be same size or larger than vector"); } } + } __attribute__((packed)); -/* Free function concerning FixedCapacityContainer */ -template -typename FixedCapacityContainer::iterator -begin(FixedCapacityContainer &container) noexcept { - return container.begin(); -} - -template -typename FixedCapacityContainer::iterator -end(FixedCapacityContainer &container) noexcept { - return container.end(); -} - -template -bool operator==( - const std::vector &vec, +/** support flipped order compare */ +template +typename std::enable_if::value, bool>::type operator==( + const C &container, const FixedCapacityContainer &fixed_container) noexcept { - return fixed_container == vec; + return fixed_container.operator==(container); } -template -bool operator!=( - const std::vector &vec, +/** support flipped order compare */ +template +typename std::enable_if::value, bool>::type operator!=( + const C &container, const FixedCapacityContainer &fixed_container) noexcept { - return fixed_container != vec; + return fixed_container.operator!=(container); } } // namespace sls diff --git a/slsSupportLib/tests/test-FixedCapacityContainer.cpp b/slsSupportLib/tests/test-FixedCapacityContainer.cpp index 53ae2fbb8..3fc6089dc 100644 --- a/slsSupportLib/tests/test-FixedCapacityContainer.cpp +++ b/slsSupportLib/tests/test-FixedCapacityContainer.cpp @@ -1,55 +1,81 @@ #include "FixedCapacityContainer.h" -#include "catch.hpp" #include "TypeTraits.h" +#include "catch.hpp" -#include #include +#include using sls::FixedCapacityContainer; -TEST_CASE("FixedCapacityContainer is a container"){ - REQUIRE(sls::is_container>::value == true); +TEST_CASE("FixedCapacityContainer is a container") { + REQUIRE(sls::is_container>::value == true); } +TEST_CASE("Compare array and fixed capacity container") { + std::array arr{1, 2, 3}; + std::array arr2{1, 7, 3}; + FixedCapacityContainer fcc{1, 2, 3}; + REQUIRE(fcc == arr); + REQUIRE(arr == fcc); + REQUIRE_FALSE(fcc != arr); + REQUIRE_FALSE(arr != fcc); + REQUIRE_FALSE(fcc == arr2); + REQUIRE_FALSE(arr2 == fcc); +} -TEST_CASE("Construct from vector"){ - std::vector vec{1,2,3}; +TEST_CASE("Compare vector and fixed capacity container") { + std::vector vec{1, 2, 3}; + std::vector vec2{10, 2, 3}; + FixedCapacityContainer fcc{1, 2, 3}; + REQUIRE(fcc == vec); + REQUIRE(vec == fcc); + REQUIRE_FALSE(fcc != vec); + REQUIRE_FALSE(vec != fcc); + REQUIRE_FALSE(fcc == vec2); + REQUIRE_FALSE(vec2 == fcc); +} + +TEST_CASE("Construct from vector") { + std::vector vec{1, 2, 3}; FixedCapacityContainer fcc{vec}; REQUIRE(fcc == vec); } -TEST_CASE("Copy construct from vector"){ - std::vector vec{1,2,3}; +TEST_CASE("Copy construct from vector") { + std::vector vec{1, 2, 3}; FixedCapacityContainer fcc = vec; REQUIRE(fcc == vec); } -TEST_CASE("Copy assignment from vector"){ - std::vector vec{1,2,3}; +TEST_CASE("Copy assignment from vector") { + std::vector vec{1, 2, 3}; FixedCapacityContainer fcc; fcc = vec; REQUIRE(fcc == vec); } - -TEST_CASE("Construct from array"){ - std::array arr{1,2,3}; +TEST_CASE("Construct from array") { + std::array arr{1, 2, 3}; FixedCapacityContainer fcc{arr}; REQUIRE(fcc == arr); } -TEST_CASE("Copy assign from array"){ - std::array arr{1,2,3}; +TEST_CASE("Copy assign from array") { + std::array arr{1, 2, 3}; FixedCapacityContainer fcc; fcc = arr; REQUIRE(fcc == arr); } -TEST_CASE("Copy construct from array"){ - std::array arr{1,2,3}; +TEST_CASE("Copy construct from array") { + std::array arr{1, 2, 3}; FixedCapacityContainer fcc = arr; REQUIRE(fcc == arr); } +TEST_CASE("Free function and method gives the same iterators") { + FixedCapacityContainer fcc{1, 2, 3}; + REQUIRE(std::begin(fcc) == fcc.begin()); +} SCENARIO("FixedCapacityContainers can be sized and resized", "[support]") { GIVEN("A default constructed container") { @@ -57,7 +83,7 @@ SCENARIO("FixedCapacityContainers can be sized and resized", "[support]") { FixedCapacityContainer vec; REQUIRE(vec.empty()); - REQUIRE(vec.size() == 0); //NOLINT + REQUIRE(vec.size() == 0); // NOLINT REQUIRE(vec.capacity() == n_elem); REQUIRE(sizeof(vec) == sizeof(int) * n_elem + sizeof(size_t)); @@ -121,13 +147,12 @@ SCENARIO("FixedCapacityContainers can be sized and resized", "[support]") { WHEN("We try to resize beyond the capacity") { THEN("it throws") { CHECK_THROWS(vec.resize(25)); } } - WHEN("We call front and back"){ - THEN("They return referenced to the first and last element"){ + WHEN("We call front and back") { + THEN("They return referenced to the first and last element") { REQUIRE(vec.front() == 23); REQUIRE(&vec.front() == &vec[0]); REQUIRE(vec.back() == 11); REQUIRE(&vec.back() == &vec[2]); - } } } @@ -190,7 +215,8 @@ SCENARIO("Comparison of FixedCapacityContainers", "[support]") { } } -SCENARIO("Sorting, removing and other manipulation of a container", "[support]") { +SCENARIO("Sorting, removing and other manipulation of a container", + "[support]") { GIVEN("An unsorted container") { FixedCapacityContainer a{14, 12, 90, 12}; WHEN("We sort it") { @@ -202,23 +228,23 @@ SCENARIO("Sorting, removing and other manipulation of a container", "[support]") REQUIRE(a[3] == 90); } } - WHEN("Sorting is done using free function for begin and end") { - std::sort(begin(a), end(a)); - THEN("it also works") { - REQUIRE(a[0] == 12); - REQUIRE(a[1] == 12); - REQUIRE(a[2] == 14); - REQUIRE(a[3] == 90); - } - } - WHEN("Erasing elements of a certain value") { - a.erase(std::remove(begin(a), end(a), 12)); - THEN("all elements of that value are removed") { - REQUIRE(a.size() == 2); - REQUIRE(a[0] == 14); - REQUIRE(a[1] == 90); - } - } + // WHEN("Sorting is done using free function for begin and end") { + // std::sort(begin(a), end(a)); + // THEN("it also works") { + // REQUIRE(a[0] == 12); + // REQUIRE(a[1] == 12); + // REQUIRE(a[2] == 14); + // REQUIRE(a[3] == 90); + // } + // } + // WHEN("Erasing elements of a certain value") { + // a.erase(std::remove(begin(a), end(a), 12)); + // THEN("all elements of that value are removed") { + // REQUIRE(a.size() == 2); + // REQUIRE(a[0] == 14); + // REQUIRE(a[1] == 90); + // } + // } } } @@ -248,30 +274,28 @@ SCENARIO("Assigning containers to each other", "[support]") { REQUIRE(c[2] == 3); } } - WHEN("We create a const FixedCapacityContainer"){ + WHEN("We create a const FixedCapacityContainer") { const FixedCapacityContainer c(a); - THEN("The values are still the same using const operators"){ + 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); - } } } } -SCENARIO("Converting to vector", "[support]"){ - GIVEN("a FixedCapacityContainer"){ - FixedCapacityContainer a{1,2,3}; - WHEN("Converted into a vector"){ +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"){ + THEN("Data and size matches") { REQUIRE(a == b); REQUIRE(a.size() == b.size()); } } } } - From 25eccdffabf3c1ceb94177d8b6f74b8440a6c897 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Mon, 12 Aug 2019 18:57:53 +0200 Subject: [PATCH 062/108] WIP --- slsDetectorGui/src/qTabAdvanced.cpp | 2 +- slsDetectorSoftware/include/Detector.h | 524 +++++++------- .../include/multiSlsDetector.h | 52 +- slsDetectorSoftware/include/slsDetector.h | 9 +- slsDetectorSoftware/src/Detector.cpp | 648 +++++++++--------- slsDetectorSoftware/src/multiSlsDetector.cpp | 29 +- slsDetectorSoftware/src/slsDetector.cpp | 34 +- .../src/slsDetectorCommand.cpp | 5 +- 8 files changed, 649 insertions(+), 654 deletions(-) diff --git a/slsDetectorGui/src/qTabAdvanced.cpp b/slsDetectorGui/src/qTabAdvanced.cpp index f1924f06e..72eb07e23 100755 --- a/slsDetectorGui/src/qTabAdvanced.cpp +++ b/slsDetectorGui/src/qTabAdvanced.cpp @@ -332,7 +332,7 @@ void qTabAdvanced::SetDetector(int index) { GetRxrZMQPort(); GetRxrZMQIP(); - myDet->printReceiverConfiguration(logDEBUG); + FILE_LOG(logDEBUG) << myDet->printReceiverConfiguration(); } void qTabAdvanced::SetControlPort(int port) { diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 803821718..28e23b252 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -24,33 +24,12 @@ class Detector { Detector(int multi_id = 0); ~Detector(); - // Acquisition - - /** - * Blocking call, starts the receiver and detector. Acquired - * the number of frames set. - */ - void acquire(); - void startReceiver(Positions pos = {}); - void stopReceiver(Positions pos = {}); - - /** - * Get the acquiring flag. When true the detector blocks - * any attempt to start a new acquisition. - */ - bool getAcquiringFlag() const; - - /** - * Set the acquiring flag. This might have to done manually - * after an acquisition was aborted. - */ - void setAcquiringFlag(bool value); - - /** Read back the run status of the receiver */ - Result getReceiverStatus(Positions pos = {}); - - // Configuration + /************************************************** + * * + * CONFIG * + * * + * ************************************************/ /** * Frees the shared memory of this detector and all modules * belonging to it. @@ -58,45 +37,13 @@ class Detector { void freeSharedMemory(); void setConfig(const std::string &fname); Result getHostname(Positions pos = {}) const; - // void setHostname(Positions pos = {}); - - Result getStartingFrameNumber(Positions pos = {}) const; - void setStartingFrameNumber(uint64_t value, Positions pos); - - // Bits and registers - - - - - - /************************************************** - * * - * FILE, anything concerning file writing or * - * reading goes here * - * * - * ************************************************/ - /** - * Returns receiver file name prefix. The actual file name - * contains module id and file index as well. - * @param pos detector positions - * @returns file name prefix + * Frees shared memory and adds detectors to the list + * Also updates local detector cache + * @param name hostnames for the positions given */ - Result getFileName(Positions pos = {}) const; + void setHostname(const std::vector &value); - /** - * Sets the receiver file name prefix - * @param fname file name prefix - */ - void setFileName(const std::string &fname, Positions pos = {}); - Result getFilePath(Positions pos = {}) const; - void setFilePath(const std::string &fname, Positions pos = {}); - Result getFileWrite(Positions pos = {}) const; - void setFileWrite(bool value, Positions pos = {}); - Result getFileOverWrite(Positions pos = {}) const; - void setFileOverWrite(bool value, Positions pos = {}); - - // dhanya /** * Get multidetector Id * @returns multidetector Id @@ -155,13 +102,6 @@ class Detector { */ std::string getUserDetails() const; - /** - * Frees shared memory and adds detectors to the list - * Also updates local detector cache - * @param name hostnames for the positions given - */ - void setHostname(const std::vector &value); - /** * Get Detector type as an enum * @returns detector type @@ -505,6 +445,15 @@ class Detector { */ void setNumberOfStorageCells(int64_t value); + /** [Jungfrau] */ + Result getStorageCellStart(Positions pos = {}) const; + + /** + * [Jungfrau] Sets the storage cell storing the first acquisition of the series + * Options: 0-15 + */ + void setStoragecellStart(int cell, Positions pos = {}); + /** * Get number of analog samples (CTB) * @param pos detector position @@ -1235,6 +1184,191 @@ class Detector { /** [Eiger] Pulse chip n times */ void pulseChip(int n, Positions pos = {}); + /** [Jungfrau] */ + Result getThresholdTemperature(Positions pos = {}) const; + + /** + * [Jungfrau]Set threshold temperature + * If temperature crosses threshold temperature + * and temperature control is enabled, + * power to chip will be switched off and + * temperature event will be set + * @param val value in millidegrees TODO! Verify + */ + void setThresholdTemperature(int temp, Positions pos = {}); + + /** [Jungfrau] */ + Result getTemperatureControl(Positions pos = {}) const; + + /** [Jungfrau] */ + void setTemperatureControl(bool enable, Positions pos = {}); + + /** [Jungfrau] */ + Result getTemperatureEvent(Positions pos = {}) const; + + /** [Jungfrau] */ + void ResetTemperatureEvent(Positions pos = {}); + + /** [Jungfrau][CTB] */ + void programFPGA(const std::string &fname, Positions pos = {}); + + /** [Jungfrau][CTB] */ + void resetFPGA(Positions pos = {}); + + /** + * Copy detector server fname from tftp folder of hostname to detector + * Also changes respawn server, which is effective after a reboot. + */ + void copyDetectorServer(const std::string &fname, + const std::string &hostname, Positions pos = {}); + + /** [Jungfrau][Gotthard][CTB] */ + void rebootController(Positions pos = {}); + + /** + * [Jungfrau][Gotthard][CTB] + * Updates the firmware, detector server and then reboots detector + * controller blackfin. + * @param sname name of detector server binary found on tftp folder of host pc + * @param hostname name of pc to tftp from + * @param fname programming file name + * @param pos detector positions + */ + void updateFirmwareAndServer(const std::string &sname, + const std::string &hostname, + const std::string &fname, Positions pos = {}); + + /** [Jungfrau] */ + Result getPowerChip(Positions pos = {}) const; + + /** [Jungfrau] */ + void setPowerChip(bool on, Positions pos = {}); + + /** [Jungfrau] */ + Result getAutoCompDisable(Positions pos = {}) const; + + /** [Jungfrau] TODO??? fix docs ? */ + void setAutoCompDisable(bool value, Positions pos = {}); + + /** [Eiger] + * @returns deadtime in ns, 0 = disabled + */ + Result getRateCorrection(Positions pos = {}) const; + + /** + * [Eiger] Set Rate correction + * 0 disable correction, <0 set to default, >0 deadtime in ns + */ + void setRateCorrection(int64_t dead_time_ns, Positions pos = {}); + + /** [Eiger][Jungfrau] */ + Result getStartingFrameNumber(Positions pos = {}) const; + /** [Eiger][Jungfrau] */ + void setStartingFrameNumber(uint64_t value, Positions pos); + + /** [Eiger] */ + Result getTenGigaEnabled(Positions pos = {}) const; + /** [Eiger] */ + void setTenGigaEnabled(bool value, Positions pos = {}); + + /** [CTB] */ + Result getLEDEnable(Positions pos = {}) const; + /** [CTB] */ + void setLEDEnable(bool enable, Positions pos = {}); + + /** + * [CTB] Set Digital IO Delay + * cannot get + * @param digital IO mask to select the pins + * @param delay delay in ps(1 bit=25ps, max of 775 ps) + */ + void setDigitalIODelay(uint64_t pinMask, int delay, Positions pos = {}); + + /************************************************** + * * + * FILE, anything concerning file writing or * + * reading goes here * + * * + * ************************************************/ + Result getFileFormat(Positions pos = {}) const; + /** default binary, Options: BINARY, HDF5 (library must be compiled with this option) */ + void setFileFormat(defs::fileFormat f, Positions pos = {}); + Result getFilePath(Positions pos = {}) const; + void setFilePath(const std::string &fname, Positions pos = {}); + Result getFileNamePrefix(Positions pos = {}) const; + /** default run */ + void setFileNamePrefix(const std::string &fname, Positions pos = {}); + Result getFileIndex(Positions pos = {}) const; + void setFileIndex(int i, Positions pos = {}); + Result getFileWrite(Positions pos = {}) const; + /** default writes */ + void setFileWrite(bool value, Positions pos = {}); + Result getMasterFileWrite(Positions pos = {}) const; + void setMasterFileWrite(bool value, Positions pos = {}); + Result getFileOverWrite(Positions pos = {}) const; + /** default overwites */ + void setFileOverWrite(bool value, Positions pos = {}); + Result getFramesPerFile(Positions pos = {}) const; + void setFramesPerFile(int n, Positions pos = {}); + + + /************************************************** + * * + * RECEIVER CONFIG * + * * + * ************************************************/ + /** true when slsReceiver is used */ + Result getUseReceiverFlag(Positions pos = {}) const; + + Result printReceiverConfiguration(Positions pos = {}) const; + + Result getReceiverLock(Positions pos = {}); + + /** locks receiver server to client IP */ + void setReceiverLock(bool value, Positions pos = {}); + + Result getReceiverLastClientIP(Positions pos = {}) const; + + void exitReceiver(Positions pos = {}); + + void execReceiverCommand(const std::string &cmd, Positions pos = {}); + + Result getReceiverStreamingFrequency(Positions pos = {}) const; + /** @param freq nth frame streamed out of receiver. + * If 0, streaming timer is the timeout, + * after which current frame sent out. Default is 0 at 200 ms. + * For every frame, set freq to 1. + */ + void setReceiverStreamingFrequency(int freq, Positions pos = {}); + + Result getReceiverStreamingTimer(Positions pos = {}) const; + /** + * If receiver streaming frequency is 0 (default), then this timer between each + * data stream is set. Default is 200 ms. + */ + void setReceiverStreamingTimer(int time_in_ms, Positions pos = {}); + + bool getDataStreamingToClient() const; + void setDataStreamingToClient(bool value); + Result getDataStreamingFromReceiver(Positions pos = {}) const; + void setDataStreamingFromReceiver(bool value, Positions pos = {}); + + Result getReceiverFifoDepth(Positions pos = {}) const; + void setReceiverFifoDepth(int nframes, Positions pos = {}); + Result getReceiverSilentMode(Positions pos = {}) const; + void setReceiverSilentMode(bool value, Positions pos = {}); + + Result + getReceiverFrameDiscardPolicy(Positions pos = {}) const; + /** + * default NO_DISCARD + * Options: NO_DISCARD, DISCARD_EMPTY_FRAMES, DISCARD_PARTIAL_FRAMES + */ + void setReceiverFrameDiscardPolicy(defs::frameDiscardPolicy f, + Positions pos = {}); + Result getPartialFramesPadding(Positions pos = {}) const; + /** padding enabled */ + void setPartialFramesPadding(bool value, Positions pos = {}); /** [Eiger] */ Result getRxPadDeactivatedMod(Positions pos = {}) const; @@ -1252,271 +1386,147 @@ class Detector { Result getReceiverRealUDPSocketBufferSize(Positions pos = {}) const; + /************************************************** + * * + * ACQUISITION * + * * + * ************************************************/ + /** + * Blocking call, starts the receiver and detector. + * Increments file index if file write enabled. + * Acquired the number of frames set. + */ + void acquire(); + /** + * Get the acquiring flag. When true the detector blocks + * any attempt to start a new acquisition. + */ + bool getAcquiringFlag() const; + /** + * Set the acquiring flag. This might have to done manually + * after an acquisition was aborted. + */ + void setAcquiringFlag(bool value); - - + /** Receiver starts listening to UDP packets from detector */ + void startReceiver(Positions pos = {}); + /** Receiver stops listening to UDP packets from detector */ + void stopReceiver(Positions pos = {}); + /** Read back the run status of the receiver */ + Result getReceiverStatus(Positions pos = {}); Result getFramesCaughtByReceiver(Positions pos = {}) const; - Result getReceiverCurrentFrameIndex(Positions pos = {}) const; - void resetFramesCaught(Positions pos = {}); - // TODO! - // int createReceivingDataSockets(const bool destroy = false); - // void readFrameFromReceiver(); - - void setMasterFileWrite(bool value, Positions pos = {}); - - Result getMasterFileWrite(Positions pos = {}) const; - - void setReceiverStreamingFrequency(int freq = -1, int detPos = -1); - /** - * [All] If receiver streaming frequency is 0, then this timer between each - * data stream is set. Default is 500 ms. - */ - void setReceiverStreamingTimer(int time_in_ms = 500, Positions pos = {}); - - /** [All] */ - Result getReceiverStreamingTimer(Positions pos = {}) const; - - bool getDataStreamingToClient() const; - void setDataStreamingToClient(bool value); - - Result getDataStreamingFromReceiver(Positions pos = {}) const; - void setDataStreamingFromReceiver(bool value, Positions pos = {}); - - /** [TODO! All?] */ - void setTenGigaEnabled(bool value, Positions pos = {}); - - /** [TODO! All?] */ - Result getTenGigaEnabled(Positions pos = {}) const; - - /** [All] */ - void setReceiverFifoDepth(int nframes, Positions pos = {}); - - /** [All] */ - Result getReceiverFifoDepth(Positions pos = {}) const; - - /** [All] */ - void setReceiverSilentMode(bool value, Positions pos = {}); - - /** [All] */ - Result getReceiverSilentMode(Positions pos = {}) const; - + /************************************************** + * * + * PATTERN * + * * + * ************************************************/ + /** [CTB] */ void setPattern(const std::string &fname, Positions pos = {}); - /** [CTB] */ - void setPatternIOControl(uint64_t word, Positions pos = {}); - /** [CTB] */ Result getPatternIOControl(Positions pos = {}) const; /** [CTB] */ - void setPatternClockControl(uint64_t word, Positions pos = {}); + void setPatternIOControl(uint64_t word, Positions pos = {}); /** [CTB] */ Result getPatternClockControl(Positions pos = {}) const; + /** [CTB] */ + void setPatternClockControl(uint64_t word, Positions pos = {}); + /** - * [CTB] Writes a pattern word - * @param addr address of the word - * @param word word to be written, -1 reads the addr (same as + * [CTB] + * Caution: If word is -1 reads the addr (same as * executing the pattern) - * @param pos detector position - * @returns actual value */ void setPatternWord(int addr, uint64_t word, Positions pos = {}); - // TODO! Does this have side effects? - // uint64_t getPatternWord()... - /** - * [CTB] Sets the pattern or loop limits. - * @param level -1 complete pattern, 0,1,2, loop level - * @param start start address for level 0-2 - * @param stop stop address for level 0-2 - * @param n number of loops for level 0-2 - * @param pos detector position - */ - void setPatternLoops(int level, int start, int stop, int n, - Positions pos = {}); - - /** - * [CTB] Gets the pattern loop limits - * @param level -1 complete pattern, 0,1,2, loop level - * @param pos detector positions + * [CTB] + * Options: level: -1 (complete pattern) and 0-2 levels * @returns array of start address, stop address and number of loops */ Result> getPatternLoops(int level, Positions pos = {}) const; /** - * [CTB] Sets the wait address - * @param level 0,1,2, wait level - * @param addr wait address - * @param pos detector position - * @returns actual value + * [CTB] + * Options: start, stop, n : 0-2 + * level: -1 (complete pattern) and 0-2 levels */ - void setPatternWaitAddr(int level, int addr, Positions pos = {}); + void setPatternLoops(int level, int start, int stop, int n, + Positions pos = {}); /* [CTB] */ Result getPatternWaitAddr(int level, Positions pos = {}) const; /** - * [CTB] Sets the wait time - * @param level 0,1,2, wait level - * @param t wait time - * @param pos detector position + * [CTB] + * Options: level 0-2 */ - void setPatternWaitTime(int level, uint64_t t, Positions pos = {}); + void setPatternWaitAddr(int level, int addr, Positions pos = {}); /** [CTB] */ Result getPatternWaitTime(int level, Positions pos = {}) const; - /** [CTB] Sets the mask applied to every pattern. */ + /** + * [CTB] + * Options: level 0-2 + */ + void setPatternWaitTime(int level, uint64_t t, Positions pos = {}); + + /** [CTB] */ + Result getPatternMask(Positions pos = {}); + + /** [CTB] Sets the mask applied to every pattern to the selected bit mask */ void setPatternMask(uint64_t mask, Positions pos = {}); - /** [CTB] Gets the mask applied to every pattern. */ - Result getPatternMask(Positions pos = {}); + /** [CTB] */ + Result getPatternBitMask(Positions pos = {}) const; /** * [CTB] Sets the bitmask that the mask will be applied to for every - * pattern. - * @param mask mask to select bits + * pattern */ void setPatternBitMask(uint64_t mask, Positions pos = {}); - /** - * [CTB] Gets the bits that the mask will be applied to for every - * pattern - */ - Result getPatternBitMask(Positions pos = {}) const; - /** [CTB] Enable or disable the LED */ - void setLEDEnable(bool enable, Positions pos = {}); - /** [CTB] Get LED enable. */ - Result getLEDEnable(Positions pos = {}) const; - /** - * [CTB] Set Digital IO Delay - * @param digital IO mask to select the pins - * @param delay delay in ps(1 bit=25ps, max of 775 ps) - */ - void setDigitalIODelay(uint64_t pinMask, int delay, Positions pos = {}); - Result getFileIndex(Positions pos = {}) const; - void setFileIndex(int i, Positions pos = {}); + - Result getFileFormat(Positions pos = {}) const; + - void setFileFormat(defs::fileFormat f, Positions pos = {}); - Result getPartialFramesPadding(Positions pos = {}) const; - void setPartialFramesPadding(bool value, Positions pos = {}); - void setReceiverFrameDiscardPolicy(defs::frameDiscardPolicy f, - Positions pos = {}); - Result - getReceiverFrameDiscardPolicy(Positions pos = {}) const; - void setFramesPerFile(int n, Positions pos = {}); - Result getFramesPerFile(Positions pos = {}) const; - // void execReceiverCommand(const std::string &cmd, int detPos = -1); - // void exitReceiver(int detPos = -1); - Result getReceiverLastClientIP(Positions pos = {}) const; - void setReceiverLock(bool value, Positions pos = {}); - Result getReceiverLock(Positions pos = {}); - /** true when receiver is used otherwise false */ - Result getUseReceiverFlag(Positions pos = {}) const; - void printReceiverConfiguration(Positions pos = {}) const; - /** [Eiger] - * @returns deadtime in ns, 0 = disabled - */ - Result getRateCorrection(Positions pos = {}) const; - /** - * [Eiger] Set Rate correction - * 0 disable correction, <0 set to default, >0 deadtime in ns - */ - void setRateCorrection(int64_t dead_time_ns, Positions pos = {}); - /** [Jungfrau] TODO??? fix docs */ - void setAutoCompDisable(bool value, Positions pos = {}); - Result getAutoCompDisable(Positions pos = {}) const; - void setPowerChip(bool on, Positions pos = {}); - Result getPowerChip(Positions pos = {}) const; - /** - * Updates the firmware, detector server and then reboots detector - * controller blackfin. (Not Eiger) - * @param sname name of detector server binary - * @param hostname name of pc to tftp from - * @param fname programming file name - * @param pos detector positions - */ - void updateFirmwareAndServer(const std::string &sname, - const std::string &hostname, - const std::string &fname, Positions pos = {}); - /** [not Eiger] TODO! is this needed?*/ - void rebootController(Positions pos = {}); - - /** Copy detector server to detector */ - void copyDetectorServer(const std::string &fname, - const std::string &hostname, Positions pos = {}); - - /** [not Eiger] */ - void resetFPGA(Positions pos = {}); - - /** [not Eiger] */ - void programFPGA(const std::string &fname, Positions pos = {}); - - /** - * [Jungfrau] Set first storage cell of the series (Jungfrau) - * @param value storage cell index. Value can be 0 to 15. - */ - void setStoragecellStart(int cell, Positions pos = {}); - - Result getStorageCellStart(Positions pos = {}) const; - - /** [Jungfrau] 1 there was an temperature event */ - void setTemperatureEvent(int val, Positions pos = {}); - - /** [Jungfrau] */ - Result getTemperatureEvent(Positions pos = {}) const; - - /** [Jungfrau] */ - void setTemperatureControl(bool enable, Positions pos = {}); - - /** [Jungfrau] */ - Result getTemperatureControl(Positions pos = {}) const; - - /** - * [Jungfrau]Set threshold temperature - * @param val value in millidegrees TODO! Verify - */ - void setThresholdTemperature(int temp, Positions pos = {}); - - Result getThresholdTemperature(Positions pos = {}) const; diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index fb7395a2c..77dedac81 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -1638,14 +1638,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { int setStoragecellStart(int pos = -1, int detPos = -1);// /** - * Programs FPGA with pof file (Not Eiger) + * Programs FPGA with pof file (Jungfrau, CTB, Moench) * @param fname file name * @param detPos -1 for all detectors in list or specific detector position */ void programFPGA(const std::string &fname, int detPos = -1); // /** - * Resets FPGA (Not Eiger) + * Resets FPGA (Jungfrau, CTB, Moench) * @param detPos -1 for all detectors in list or specific detector position */ void resetFPGA(int detPos = -1); // @@ -1710,10 +1710,10 @@ class multiSlsDetector : public virtual slsDetectorDefs { /** * Prints receiver configuration - * @param level print level * @param detPos -1 for all detectors in list or specific detector position + * @returns receiver configuration */ - void printReceiverConfiguration(TLogLevel level = logINFO, int detPos = -1); // + std::string printReceiverConfiguration(int detPos = -1); // /** * Get receiver online status @@ -1886,19 +1886,6 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ void resetFramesCaught(int detPos = -1); // - /** - * Create Receiving Data Sockets - * @param destroy is true to destroy all the sockets - * @returns OK or FAIL - */ - int createReceivingDataSockets(const bool destroy = false); - - /** - * Reads frames from receiver through a constant socket - * Called during acquire() when call back registered or when using gui - */ - void readFrameFromReceiver(); - /** * Sets/Gets receiver file write enable * @param value 1 or 0 to set/reset file write enable @@ -1962,7 +1949,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns receiver streaming timer in ms */ - int setReceiverStreamingTimer(int time_in_ms = 500, int detPos = -1); // + int setReceiverStreamingTimer(int time_in_ms = 200, int detPos = -1); // /** * Enable data streaming to client @@ -2007,9 +1994,8 @@ class multiSlsDetector : public virtual slsDetectorDefs { * Opens pattern file and sends pattern (CTB/ Moench) * @param fname pattern file to open * @param detPos -1 for all detectors in list or specific detector position - * @returns OK/FAIL */ - int setPattern(const std::string &fname, int detPos = -1); // + void setPattern(const std::string &fname, int detPos = -1); // /** * Sets pattern IO control (CTB/ Moench) @@ -2192,12 +2178,6 @@ class multiSlsDetector : public virtual slsDetectorDefs { std::vector readPofFile(const std::string &fname); private: - /** - * increments file index - * @param detPos -1 for all detectors in list or specific detector position - * @returns the file index - */ - int incrementFileIndex(int detPos = -1); /** * Creates/open shared memory, initializes detector structure and members * Called by constructor/ set hostname / read config file @@ -2276,6 +2256,13 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ void addSlsDetector(const std::string &hostname); + /** + * increments file index + * @param detPos -1 for all detectors in list or specific detector position + * @returns the file index + */ + int incrementFileIndex(int detPos = -1); + /** * Ensures that min is less than max in both dimensions (Gotthard) * @param n number of rois @@ -2292,6 +2279,19 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ int processImageWithGapPixels(char *image, char *&gpImage); + /** + * Create Receiving Data Sockets + * @param destroy is true to destroy all the sockets + * @returns OK or FAIL + */ + int createReceivingDataSockets(const bool destroy = false); + + /** + * Reads frames from receiver through a constant socket + * Called during acquire() when call back registered or when using gui + */ + void readFrameFromReceiver(); + /** * Set total progress (total number of frames/images in an acquisition) * @returns total progress diff --git a/slsDetectorSoftware/include/slsDetector.h b/slsDetectorSoftware/include/slsDetector.h index cd9cc01e8..269e8cdc7 100755 --- a/slsDetectorSoftware/include/slsDetector.h +++ b/slsDetectorSoftware/include/slsDetector.h @@ -1461,9 +1461,9 @@ class slsDetector : public virtual slsDetectorDefs { /** * Prints receiver configuration - * @param level print level + * @returns receiver configuration */ - void printReceiverConfiguration(TLogLevel level = logINFO); + std::string printReceiverConfiguration(); /** * Gets the use receiver flag from shared memory @@ -1693,7 +1693,7 @@ class slsDetector : public virtual slsDetectorDefs { * @param time_in_ms timer between frames * @returns receiver streaming timer in ms */ - int setReceiverStreamingTimer(int time_in_ms = 500); + int setReceiverStreamingTimer(int time_in_ms = 200); /** * Enable or disable streaming data from receiver to client @@ -1734,9 +1734,8 @@ class slsDetector : public virtual slsDetectorDefs { /** * Opens pattern file and sends pattern to CTB * @param fname pattern file to open - * @returns OK/FAIL */ - int setPattern(const std::string &fname); + void setPattern(const std::string &fname); /** * Sets pattern IO control (CTB/ Moench) diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 50e5613a5..eaa654142 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -12,78 +12,21 @@ Detector::Detector(int multi_id) : pimpl(sls::make_unique(multi_id)) {} Detector::~Detector() = default; -// Acquisition -void Detector::acquire() { pimpl->acquire(); } - -void Detector::startReceiver(Positions pos) { - pimpl->Parallel(&slsDetector::startReceiver, pos); -} -void Detector::stopReceiver(Positions pos) { - pimpl->Parallel(&slsDetector::stopReceiver, pos); -} - -Result Detector::getReceiverStatus(Positions pos) { - return pimpl->Parallel(&slsDetector::getReceiverStatus, pos); -} - -bool Detector::getAcquiringFlag() const { return pimpl->getAcquiringFlag(); } - -void Detector::setAcquiringFlag(bool value) { pimpl->setAcquiringFlag(value); } - // Configuration -Result Detector::getHostname(Positions pos) const { - return pimpl->Parallel(&slsDetector::getHostname, pos); -} - void Detector::freeSharedMemory() { pimpl->freeSharedMemory(); } void Detector::setConfig(const std::string &fname) { pimpl->readConfigurationFile(fname); } - - - - -Result Detector::getStartingFrameNumber(Positions pos) const { - return pimpl->Parallel(&slsDetector::getStartingFrameNumber, pos); -} -void Detector::setStartingFrameNumber(uint64_t value, Positions pos) { - pimpl->Parallel(&slsDetector::setStartingFrameNumber, pos, value); +Result Detector::getHostname(Positions pos) const { + return pimpl->Parallel(&slsDetector::getHostname, pos); } -// File -void Detector::setFileName(const std::string &fname, Positions pos) { - pimpl->Parallel(&slsDetector::setFileName, pos, fname); -} -Result Detector::getFileName(Positions pos) const { - return pimpl->Parallel(&slsDetector::setFileName, pos, ""); +void Detector::setHostname(const std::vector &value) { + pimpl->setHostname(value); } -void Detector::setFilePath(const std::string &fpath, Positions pos) { - pimpl->Parallel(&slsDetector::setFilePath, pos, fpath); -} -Result Detector::getFilePath(Positions pos) const { - return pimpl->Parallel(&slsDetector::getFilePath, pos); -} - -void Detector::setFileWrite(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setFileWrite, pos, value); -} - -Result Detector::getFileWrite(Positions pos) const { - return pimpl->Parallel(&slsDetector::getFileWrite, pos); -} - -void Detector::setFileOverWrite(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setFileOverWrite, pos, value); -} - -Result Detector::getFileOverWrite(Positions pos) const { - return pimpl->Parallel(&slsDetector::getFileOverWrite, pos); -} - -// dhanya int Detector::getMultiId() const { return pimpl->getMultiId(); } void Detector::checkDetectorVersionCompatibility(Positions pos) const { @@ -119,10 +62,6 @@ Result Detector::getReceiverSoftwareVersion(Positions pos) const { std::string Detector::getUserDetails() const { return pimpl->getUserDetails(); } -void Detector::setHostname(const std::vector &value) { - pimpl->setHostname(value); -} - defs::detectorType Detector::getDetectorType() const { return pimpl->getDetectorTypeAsEnum(); } @@ -339,6 +278,15 @@ void Detector::setNumberOfStorageCells(int64_t value) { value); } +Result Detector::getStorageCellStart(Positions pos) const { + return pimpl->Parallel(&slsDetector::setStoragecellStart, pos, -1); +} + +void Detector::setStoragecellStart(int cell, Positions pos) { + pimpl->Parallel(&slsDetector::setStoragecellStart, pos, cell); +} + + Result Detector::getNumberOfAnalogSamples(Positions pos) const { return pimpl->Parallel(&slsDetector::setTimer, pos, defs::ANALOG_SAMPLES, -1); @@ -1256,7 +1204,281 @@ void Detector::pulseChip(int n, Positions pos) { pimpl->Parallel(&slsDetector::pulseChip, pos, n); } +Result Detector::getThresholdTemperature(Positions pos) const { + return pimpl->Parallel(&slsDetector::setThresholdTemperature, pos, -1); +} +void Detector::setThresholdTemperature(int temp, Positions pos) { + pimpl->Parallel(&slsDetector::setThresholdTemperature, pos, temp); +} + +Result Detector::getTemperatureControl(Positions pos) const { + return pimpl->Parallel(&slsDetector::setTemperatureControl, pos, -1); +} + +void Detector::setTemperatureControl(bool enable, Positions pos) { + pimpl->Parallel(&slsDetector::setTemperatureControl, pos, + static_cast(enable)); +} + +Result Detector::getTemperatureEvent(Positions pos) const { + return pimpl->Parallel(&slsDetector::setTemperatureEvent, pos, -1); +} + +void Detector::ResetTemperatureEvent(Positions pos) { + pimpl->Parallel(&slsDetector::setTemperatureEvent, pos, 0); +} + +void Detector::programFPGA(const std::string &fname, Positions pos) { + FILE_LOG(logINFO) << "Updating Firmware. This can take awhile. Please be patient..."; + std::vector buffer = pimpl->readPofFile(fname); + pimpl->Parallel(&slsDetector::programFPGA, pos, buffer); +} + +void Detector::resetFPGA(Positions pos) { + pimpl->Parallel(&slsDetector::resetFPGA, pos); +} + +void Detector::copyDetectorServer(const std::string &fname, + const std::string &hostname, Positions pos) { + pimpl->Parallel(&slsDetector::copyDetectorServer, pos, fname, hostname); + rebootController(pos); +} + +void Detector::rebootController(Positions pos) { + pimpl->Parallel(&slsDetector::rebootController, pos); +} + +void Detector::updateFirmwareAndServer(const std::string &sname, + const std::string &hostname, + const std::string &fname, + Positions pos) { + pimpl->Parallel(&slsDetector::copyDetectorServer, pos, fname, hostname); + programFPGA(fname, pos); + rebootController(pos); +} + +Result Detector::getPowerChip(Positions pos) const { + return pimpl->Parallel(&slsDetector::powerChip, pos, -1); +} + +void Detector::setPowerChip(bool on, Positions pos) { + if (on && pimpl->size() > 3) { + for (unsigned int i = 0; i != pimpl->size(); ++i) { + pimpl->powerChip(static_cast(on), i); + usleep(1000 * 1000); + } + } else { + pimpl->Parallel(&slsDetector::powerChip, pos, static_cast(on)); + } +} + +Result Detector::getAutoCompDisable(Positions pos) const { + return pimpl->Parallel(&slsDetector::setAutoComparatorDisableMode, pos, -1); +} + +void Detector::setAutoCompDisable(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setAutoComparatorDisableMode, pos, + static_cast(value)); +} + +Result Detector::getRateCorrection(Positions pos) const { + return pimpl->Parallel(&slsDetector::getRateCorrection, pos); +} + +void Detector::setRateCorrection(int64_t dead_time_ns, Positions pos) { + pimpl->Parallel(&slsDetector::setRateCorrection, pos, dead_time_ns); +} + +Result Detector::getStartingFrameNumber(Positions pos) const { + return pimpl->Parallel(&slsDetector::getStartingFrameNumber, pos); +} + +void Detector::setStartingFrameNumber(uint64_t value, Positions pos) { + pimpl->Parallel(&slsDetector::setStartingFrameNumber, pos, value); +} + +Result Detector::getTenGigaEnabled(Positions pos) const { + return pimpl->Parallel(&slsDetector::enableTenGigabitEthernet, pos, -1); +} + +void Detector::setTenGigaEnabled(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::enableTenGigabitEthernet, pos, + static_cast(value)); +} + +Result Detector::getLEDEnable(Positions pos) const { + return pimpl->Parallel(&slsDetector::setLEDEnable, pos, -1); +} + +void Detector::setLEDEnable(bool enable, Positions pos) { + pimpl->Parallel(&slsDetector::setLEDEnable, pos, static_cast(enable)); +} + +void Detector::setDigitalIODelay(uint64_t pinMask, int delay, Positions pos) { + pimpl->Parallel(&slsDetector::setDigitalIODelay, pos, pinMask, delay); +} +// File +Result Detector::getFileFormat(Positions pos) const { + return pimpl->Parallel(&slsDetector::getFileFormat, pos); +} + +void Detector::setFileFormat(defs::fileFormat f, Positions pos) { + pimpl->Parallel(&slsDetector::setFileFormat, pos, f); +} + +Result Detector::getFilePath(Positions pos) const { + return pimpl->Parallel(&slsDetector::getFilePath, pos); +} + +void Detector::setFilePath(const std::string &fpath, Positions pos) { + pimpl->Parallel(&slsDetector::setFilePath, pos, fpath); +} + +Result Detector::getFileNamePrefix(Positions pos) const { + return pimpl->Parallel(&slsDetector::setFileName, pos, ""); +} +void Detector::setFileNamePrefix(const std::string &fname, Positions pos) { + pimpl->Parallel(&slsDetector::setFileName, pos, fname); +} + +Result Detector::getFileIndex(Positions pos) const { + return pimpl->Parallel(&slsDetector::getFileIndex, pos); +} + +void Detector::setFileIndex(int i, Positions pos) { + pimpl->Parallel(&slsDetector::setFileIndex, pos, i); +} + +Result Detector::getFileWrite(Positions pos) const { + return pimpl->Parallel(&slsDetector::getFileWrite, pos); +} + +void Detector::setFileWrite(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setFileWrite, pos, value); +} + +void Detector::setMasterFileWrite(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setMasterFileWrite, pos, value); +} + +Result Detector::getMasterFileWrite(Positions pos) const { + return pimpl->Parallel(&slsDetector::getMasterFileWrite, pos); +} + +Result Detector::getFileOverWrite(Positions pos) const { + return pimpl->Parallel(&slsDetector::getFileOverWrite, pos); +} + +void Detector::setFileOverWrite(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setFileOverWrite, pos, value); +} + +Result Detector::getFramesPerFile(Positions pos) const { + return pimpl->Parallel(&slsDetector::getFramesPerFile, pos); +} + +void Detector::setFramesPerFile(int n, Positions pos) { + pimpl->Parallel(&slsDetector::setFramesPerFile, pos, n); +} + +// Receiver +Result Detector::getUseReceiverFlag(Positions pos) const { + return pimpl->Parallel(&slsDetector::getUseReceiverFlag, pos); +} + +Result Detector::printReceiverConfiguration(Positions pos) const { + return pimpl->Parallel(&slsDetector::printReceiverConfiguration, pos); +} + +Result Detector::getReceiverLock(Positions pos) { + return pimpl->Parallel(&slsDetector::lockReceiver, pos, -1); +} + +void Detector::setReceiverLock(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::lockReceiver, pos, static_cast(value)); +} + +Result Detector::getReceiverLastClientIP(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverLastClientIP, pos); +} + +void Detector::exitReceiver(Positions pos) { + pimpl->Parallel(&slsDetector::exitReceiver, pos); +} + +void Detector::execReceiverCommand(const std::string &cmd, Positions pos) { + pimpl->Parallel(&slsDetector::execReceiverCommand, pos, cmd); +} + +Result Detector::getReceiverStreamingFrequency(Positions pos) const { + return pimpl->Parallel(&slsDetector::setReceiverStreamingTimer, pos, -1); +} + +void Detector::setReceiverStreamingFrequency(int freq, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverStreamingFrequency, pos, freq); +} + +Result Detector::getReceiverStreamingTimer(Positions pos) const { + return pimpl->Parallel(&slsDetector::setReceiverStreamingTimer, pos, -1); +} + +void Detector::setReceiverStreamingTimer(int time_in_ms, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverStreamingTimer, pos, time_in_ms); +} + +bool Detector::getDataStreamingToClient() const { + return pimpl->enableDataStreamingToClient(-1); +} + +void Detector::setDataStreamingToClient(bool enable) { + pimpl->enableDataStreamingToClient(static_cast(enable)); +} + +Result Detector::getDataStreamingFromReceiver(Positions pos) const { + return pimpl->Parallel(&slsDetector::enableDataStreamingFromReceiver, pos, -1); +} + +void Detector::setDataStreamingFromReceiver(bool enable, Positions pos) { + pimpl->Parallel(&slsDetector::enableDataStreamingFromReceiver, pos, + static_cast(enable)); +} + +Result Detector::getReceiverFifoDepth(Positions pos) const { + return pimpl->Parallel(&slsDetector::setReceiverFifoDepth, pos, -1); +} + +void Detector::setReceiverFifoDepth(int nframes, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverFifoDepth, pos, nframes); +} + +Result Detector::getReceiverSilentMode(Positions pos) const { + return pimpl->Parallel(&slsDetector::setReceiverSilentMode, pos, -1); +} + +void Detector::setReceiverSilentMode(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverSilentMode, pos, + static_cast(value)); +} + +Result +Detector::getReceiverFrameDiscardPolicy(Positions pos) const { + return pimpl->Parallel(&slsDetector::setReceiverFramesDiscardPolicy, pos, + defs::GET_FRAME_DISCARD_POLICY); +} + +void Detector::setReceiverFrameDiscardPolicy(defs::frameDiscardPolicy f, + Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverFramesDiscardPolicy, pos, f); +} + +Result Detector::getPartialFramesPadding(Positions pos) const { + return pimpl->Parallel(&slsDetector::getPartialFramesPadding, pos); +} + +void Detector::setPartialFramesPadding(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setPartialFramesPadding, pos, value); +} Result Detector::getRxPadDeactivatedMod(Positions pos) const { return pimpl->Parallel(&slsDetector::setDeactivatedRxrPaddingMode, pos, -1); @@ -1283,8 +1505,23 @@ Detector::getReceiverRealUDPSocketBufferSize(Positions pos) const { pos); } +// Acquisition +void Detector::acquire() { pimpl->acquire(); } +bool Detector::getAcquiringFlag() const { return pimpl->getAcquiringFlag(); } +void Detector::setAcquiringFlag(bool value) { pimpl->setAcquiringFlag(value); } + +void Detector::startReceiver(Positions pos) { + pimpl->Parallel(&slsDetector::startReceiver, pos); +} +void Detector::stopReceiver(Positions pos) { + pimpl->Parallel(&slsDetector::stopReceiver, pos); +} + +Result Detector::getReceiverStatus(Positions pos) { + return pimpl->Parallel(&slsDetector::getReceiverStatus, pos); +} Result Detector::getFramesCaughtByReceiver(Positions pos) const { return pimpl->Parallel(&slsDetector::getFramesCaughtByReceiver, pos); @@ -1298,92 +1535,30 @@ void Detector::resetFramesCaught(Positions pos) { pimpl->Parallel(&slsDetector::resetFramesCaught, pos); } -void Detector::setMasterFileWrite(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setMasterFileWrite, pos, value); -} - -Result Detector::getMasterFileWrite(Positions pos) const { - return pimpl->Parallel(&slsDetector::getMasterFileWrite, pos); -} - -void Detector::setReceiverStreamingTimer(int time_in_ms, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverStreamingTimer, pos, time_in_ms); -} - -Result Detector::getReceiverStreamingTimer(Positions pos) const { - return pimpl->Parallel(&slsDetector::setReceiverStreamingTimer, pos, -1); -} - -bool Detector::getDataStreamingToClient() const { - return pimpl->enableDataStreamingToClient(-1); -} - -void Detector::setDataStreamingToClient(bool enable) { - pimpl->enableDataStreamingToClient(static_cast(enable)); -} - -Result Detector::getDataStreamingFromReceiver(Positions pos) const { - return pimpl->Parallel(&slsDetector::enableDataStreamingFromReceiver, pos, -1); -} - -void Detector::setDataStreamingFromReceiver(bool enable, Positions pos) { - pimpl->Parallel(&slsDetector::enableDataStreamingFromReceiver, pos, - static_cast(enable)); -} - -void Detector::setTenGigaEnabled(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::enableTenGigabitEthernet, pos, - static_cast(value)); -} - -Result Detector::getTenGigaEnabled(Positions pos) const { - return pimpl->Parallel(&slsDetector::enableTenGigabitEthernet, pos, -1); -} - -Result Detector::getReceiverFifoDepth(Positions pos) const { - return pimpl->Parallel(&slsDetector::setReceiverFifoDepth, pos, -1); -} - -void Detector::setReceiverFifoDepth(int nframes, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverFifoDepth, pos, nframes); -} - -Result Detector::getReceiverSilentMode(Positions pos) const { - return pimpl->Parallel(&slsDetector::setReceiverSilentMode, pos, -1); -} - -void Detector::setReceiverSilentMode(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverSilentMode, pos, - static_cast(value)); -} +// pattern void Detector::setPattern(const std::string &fname, Positions pos) { pimpl->Parallel(&slsDetector::setPattern, pos, fname); } -void Detector::setPatternIOControl(uint64_t word, Positions pos) { - pimpl->Parallel(&slsDetector::setPatternIOControl, pos, word); -} - Result Detector::getPatternIOControl(Positions pos) const { return pimpl->Parallel(&slsDetector::setPatternIOControl, pos, -1); } -void Detector::setPatternClockControl(uint64_t word, Positions pos) { - pimpl->Parallel(&slsDetector::setPatternClockControl, pos, word); +void Detector::setPatternIOControl(uint64_t word, Positions pos) { + pimpl->Parallel(&slsDetector::setPatternIOControl, pos, word); } Result Detector::getPatternClockControl(Positions pos) const { return pimpl->Parallel(&slsDetector::setPatternClockControl, pos, -1); } -void Detector::setPatternWord(int addr, uint64_t word, Positions pos) { - pimpl->Parallel(&slsDetector::setPatternWord, pos, addr, word); +void Detector::setPatternClockControl(uint64_t word, Positions pos) { + pimpl->Parallel(&slsDetector::setPatternClockControl, pos, word); } -void Detector::setPatternLoops(int level, int start, int stop, int n, - Positions pos) { - pimpl->Parallel(&slsDetector::setPatternLoops, pos, level, start, stop, n); +void Detector::setPatternWord(int addr, uint64_t word, Positions pos) { + pimpl->Parallel(&slsDetector::setPatternWord, pos, addr, word); } Result> Detector::getPatternLoops(int level, @@ -1392,220 +1567,41 @@ Result> Detector::getPatternLoops(int level, -1); } -void Detector::setPatternWaitAddr(int level, int addr, Positions pos) { - pimpl->Parallel(&slsDetector::setPatternWaitAddr, pos, level, addr); +void Detector::setPatternLoops(int level, int start, int stop, int n, + Positions pos) { + pimpl->Parallel(&slsDetector::setPatternLoops, pos, level, start, stop, n); } Result Detector::getPatternWaitAddr(int level, Positions pos) const { return pimpl->Parallel(&slsDetector::setPatternWaitAddr, pos, level, -1); } -void Detector::setPatternWaitTime(int level, uint64_t t, Positions pos) { - pimpl->Parallel(&slsDetector::setPatternWaitTime, pos, level, t); +void Detector::setPatternWaitAddr(int level, int addr, Positions pos) { + pimpl->Parallel(&slsDetector::setPatternWaitAddr, pos, level, addr); } Result Detector::getPatternWaitTime(int level, Positions pos) const { return pimpl->Parallel(&slsDetector::setPatternWaitTime, pos, level, -1); } +void Detector::setPatternWaitTime(int level, uint64_t t, Positions pos) { + pimpl->Parallel(&slsDetector::setPatternWaitTime, pos, level, t); +} + Result Detector::getPatternMask(Positions pos) { return pimpl->Parallel(&slsDetector::getPatternMask, pos); } -void Detector::setPatternBitMask(uint64_t mask, Positions pos) { - pimpl->Parallel(&slsDetector::setPatternBitMask, pos, mask); +void Detector::setPatternMask(uint64_t mask, Positions pos) { + pimpl->Parallel(&slsDetector::setPatternMask, pos, mask); } Result Detector::getPatternBitMask(Positions pos) const { return pimpl->Parallel(&slsDetector::getPatternBitMask, pos); } -void Detector::setLEDEnable(bool enable, Positions pos) { - pimpl->Parallel(&slsDetector::setLEDEnable, pos, static_cast(enable)); +void Detector::setPatternBitMask(uint64_t mask, Positions pos) { + pimpl->Parallel(&slsDetector::setPatternBitMask, pos, mask); } - -Result Detector::getLEDEnable(Positions pos) const { - return pimpl->Parallel(&slsDetector::setLEDEnable, pos, -1); -} - -void Detector::setDigitalIODelay(uint64_t pinMask, int delay, Positions pos) { - pimpl->Parallel(&slsDetector::setDigitalIODelay, pos, pinMask, delay); -} - -Result Detector::getFileIndex(Positions pos) const { - return pimpl->Parallel(&slsDetector::getFileIndex, pos); -} - -void Detector::setFileIndex(int i, Positions pos) { - pimpl->Parallel(&slsDetector::setFileIndex, pos, i); -} - -Result Detector::getFileFormat(Positions pos) const { - return pimpl->Parallel(&slsDetector::getFileFormat, pos); -} - -void Detector::setFileFormat(defs::fileFormat f, Positions pos) { - pimpl->Parallel(&slsDetector::setFileFormat, pos, f); -} - -Result Detector::getPartialFramesPadding(Positions pos) const { - return pimpl->Parallel(&slsDetector::getPartialFramesPadding, pos); -} - -void Detector::setPartialFramesPadding(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setPartialFramesPadding, pos, value); -} - -void Detector::setReceiverFrameDiscardPolicy(defs::frameDiscardPolicy f, - Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverFramesDiscardPolicy, pos, f); -} - -Result -Detector::getReceiverFrameDiscardPolicy(Positions pos) const { - return pimpl->Parallel(&slsDetector::setReceiverFramesDiscardPolicy, pos, - defs::GET_FRAME_DISCARD_POLICY); -} - -void Detector::setFramesPerFile(int n, Positions pos) { - pimpl->Parallel(&slsDetector::setFramesPerFile, pos, n); -} - -Result Detector::getFramesPerFile(Positions pos) const { - return pimpl->Parallel(&slsDetector::getFramesPerFile, pos); -} - -Result Detector::getReceiverLastClientIP(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverLastClientIP, pos); -} - -void Detector::setReceiverLock(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::lockReceiver, pos, static_cast(value)); -} - -Result Detector::getReceiverLock(Positions pos) { - return pimpl->Parallel(&slsDetector::lockReceiver, pos, -1); -} - -Result Detector::getUseReceiverFlag(Positions pos) const { - return pimpl->Parallel(&slsDetector::getUseReceiverFlag, pos); -} - -void Detector::printReceiverConfiguration(Positions pos) const { - pimpl->Parallel(&slsDetector::printReceiverConfiguration, pos, - TLogLevel::logINFO); -} - -Result Detector::getRateCorrection(Positions pos) const { - return pimpl->Parallel(&slsDetector::getRateCorrection, pos); -} - -void Detector::setRateCorrection(int64_t dead_time_ns, Positions pos) { - pimpl->Parallel(&slsDetector::setRateCorrection, pos, dead_time_ns); -} - -void Detector::setAutoCompDisable(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setAutoComparatorDisableMode, pos, - static_cast(value)); -} - -Result Detector::getAutoCompDisable(Positions pos) const { - return pimpl->Parallel(&slsDetector::setAutoComparatorDisableMode, pos, -1); -} - -void Detector::setPowerChip(bool on, Positions pos) { - if (on && pimpl->size() > 3) { - for (unsigned int i = 0; i != pimpl->size(); ++i) { - pimpl->powerChip(static_cast(on), i); - usleep(1000 * 1000); - } - } else { - pimpl->Parallel(&slsDetector::powerChip, pos, static_cast(on)); - } -} - -Result Detector::getPowerChip(Positions pos) const { - return pimpl->Parallel(&slsDetector::powerChip, pos, -1); -} - -void Detector::updateFirmwareAndServer(const std::string &sname, - const std::string &hostname, - const std::string &fname, - Positions pos) { - copyDetectorServer(fname, hostname, pos); - programFPGA(fname, pos); -} - -void Detector::rebootController(Positions pos) { - pimpl->Parallel(&slsDetector::rebootController, pos); -} - -void Detector::copyDetectorServer(const std::string &fname, - const std::string &hostname, Positions pos) { - pimpl->Parallel(&slsDetector::copyDetectorServer, pos, fname, hostname); -} - -void Detector::resetFPGA(Positions pos) { - pimpl->Parallel(&slsDetector::resetFPGA, pos); -} - -void Detector::programFPGA(const std::string &fname, Positions pos) { - FILE_LOG(logINFO) << "This can take awhile. Please be patient..."; - std::vector buffer = pimpl->readPofFile(fname); - pimpl->Parallel(&slsDetector::programFPGA, pos, buffer); -} - -void Detector::setStoragecellStart(int cell, Positions pos) { - pimpl->Parallel(&slsDetector::setStoragecellStart, pos, cell); -} - -Result Detector::getStorageCellStart(Positions pos) const { - return pimpl->Parallel(&slsDetector::setStoragecellStart, pos, -1); -} - -void Detector::setTemperatureEvent(int val, Positions pos) { - pimpl->Parallel(&slsDetector::setTemperatureEvent, pos, val); -} - -Result Detector::getTemperatureEvent(Positions pos) const { - return pimpl->Parallel(&slsDetector::setTemperatureEvent, pos, -1); -} - -void Detector::setTemperatureControl(bool enable, Positions pos) { - pimpl->Parallel(&slsDetector::setTemperatureControl, pos, - static_cast(enable)); -} - -Result Detector::getTemperatureControl(Positions pos) const { - return pimpl->Parallel(&slsDetector::setTemperatureControl, pos, -1); -} - -void Detector::setThresholdTemperature(int temp, Positions pos) { - pimpl->Parallel(&slsDetector::setThresholdTemperature, pos, temp); -} - -Result Detector::getThresholdTemperature(Positions pos) const { - return pimpl->Parallel(&slsDetector::setThresholdTemperature, pos, -1); -} - - - - - - - - - - - - - - - - - - - - } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index c5492c1ec..ef1f9c1e1 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -2910,16 +2910,15 @@ int64_t multiSlsDetector::getRateCorrection(int detPos) { return sls::minusOneIfDifferent(r); } -void multiSlsDetector::printReceiverConfiguration(TLogLevel level, int detPos) { +std::string multiSlsDetector::printReceiverConfiguration(int detPos) { // single if (detPos >= 0) { - return detectors[detPos]->printReceiverConfiguration(level); + return detectors[detPos]->printReceiverConfiguration(); } // multi - for (auto &d : detectors) { - d->printReceiverConfiguration(level); - } + auto r = parallelCall(&slsDetector::printReceiverConfiguration); + return sls::concatenateIfDifferent(r); } bool multiSlsDetector::getUseReceiverFlag(int detPos) { @@ -3761,24 +3760,14 @@ int multiSlsDetector::setReceiverSilentMode(int i, int detPos) { return sls::minusOneIfDifferent(r); } -int multiSlsDetector::setPattern(const std::string &fname, int detPos) { +void multiSlsDetector::setPattern(const std::string &fname, int detPos) { // single if (detPos >= 0) { - return detectors[detPos]->setPattern(fname); - } - FILE *fd = fopen(fname.c_str(), "r"); - if (fd == nullptr) { - throw RuntimeError("multiSlsDetector::setPattern: Could not open file"); - } else { - int addr{0}; - uint64_t word{0}; - while (fread(&word, sizeof(word), 1, fd) != 0u) { - serialCall(&slsDetector::setPatternWord, addr, word); - ++addr; - } - fclose(fd); - return addr; + detectors[detPos]->setPattern(fname); } + + // multi + parallelCall(&slsDetector::setPattern, fname); } uint64_t multiSlsDetector::setPatternIOControl(uint64_t word, int detPos) { diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index 37ef4f634..a8e373ad9 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -2264,7 +2264,7 @@ void slsDetector::setUDPConnection() { } else { throw ReceiverError("setUDPConnection: Receiver is OFFLINE"); } - printReceiverConfiguration(logDEBUG1); + FILE_LOG(logDEBUG1) << printReceiverConfiguration(); } int slsDetector::digitalTest(digitalTestMode mode, int ival) { @@ -2945,19 +2945,20 @@ void slsDetector::updateRateCorrection() { } } -void slsDetector::printReceiverConfiguration(TLogLevel level) { - FILE_LOG(level) << "#Detector " << detId << ":\n Receiver Hostname:\t" - << getReceiverHostname() - << "\nDetector UDP IP (Source):\t\t" << getDetectorIP() - << "\nDetector UDP IP2 (Source):\t\t" << getDetectorIP2() - << "\nDetector UDP MAC:\t\t" << getDetectorMAC() - << "\nDetector UDP MAC2:\t\t" << getDetectorMAC2() - << "\nReceiver UDP IP:\t" << getReceiverUDPIP() - << "\nReceiver UDP IP2:\t" << getReceiverUDPIP2() - << "\nReceiver UDP MAC:\t" << getReceiverUDPMAC() - << "\nReceiver UDP MAC2:\t" << getReceiverUDPMAC2() - << "\nReceiver UDP Port:\t" << getReceiverUDPPort() - << "\nReceiver UDP Port2:\t" << getReceiverUDPPort2(); +std::string slsDetector::printReceiverConfiguration() { + std::ostringstream os; + os << "#Detector " << detId << ":\n Receiver Hostname:\t" + << getReceiverHostname() << "\nDetector UDP IP (Source):\t\t" + << getDetectorIP() << "\nDetector UDP IP2 (Source):\t\t" + << getDetectorIP2() << "\nDetector UDP MAC:\t\t" << getDetectorMAC() + << "\nDetector UDP MAC2:\t\t" << getDetectorMAC2() + << "\nReceiver UDP IP:\t" << getReceiverUDPIP() + << "\nReceiver UDP IP2:\t" << getReceiverUDPIP2() + << "\nReceiver UDP MAC:\t" << getReceiverUDPMAC() + << "\nReceiver UDP MAC2:\t" << getReceiverUDPMAC2() + << "\nReceiver UDP Port:\t" << getReceiverUDPPort() + << "\nReceiver UDP Port2:\t" << getReceiverUDPPort2(); + return os.str(); } bool slsDetector::getUseReceiverFlag() const { return shm()->useReceiverFlag; } @@ -3439,7 +3440,7 @@ void slsDetector::restreamStopFromReceiver() { } } -int slsDetector::setPattern(const std::string &fname) { +void slsDetector::setPattern(const std::string &fname) { uint64_t word; uint64_t addr = 0; FILE *fd = fopen(fname.c_str(), "r"); @@ -3451,9 +3452,8 @@ int slsDetector::setPattern(const std::string &fname) { } fclose(fd); } else { - return -1; + throw RuntimeError("Could not open file to set pattern"); } - return addr; } uint64_t slsDetector::setPatternIOControl(uint64_t word) { diff --git a/slsDetectorSoftware/src/slsDetectorCommand.cpp b/slsDetectorSoftware/src/slsDetectorCommand.cpp index 7cd414911..3989a1d3a 100755 --- a/slsDetectorSoftware/src/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp @@ -4864,7 +4864,7 @@ std::string slsDetectorCommand::cmdConfiguration(int narg, const char * const ar } else if (cmd == "rx_printconfig") { if (action == PUT_ACTION) return std::string("cannot put"); - myDet->printReceiverConfiguration(logINFO, detPos); + FILE_LOG(logINFO) << myDet->printReceiverConfiguration(detPos); return std::string(""); } else if (cmd == "parameters") { if (action == PUT_ACTION) { @@ -5171,7 +5171,8 @@ std::string slsDetectorCommand::cmdPattern(int narg, const char * const args[], if (action == PUT_ACTION) { fname = std::string(args[1]); - os << myDet->setPattern(fname, detPos); + myDet->setPattern(fname, detPos); + os << "successful"; } else if (action == GET_ACTION) os << "Cannot get"; } else if (cmd == "patword") { From 160ce17a917e97251a6a5ebe4185901edc832e18 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Mon, 12 Aug 2019 19:54:44 +0200 Subject: [PATCH 063/108] WIP --- slsDetectorSoftware/include/Detector.h | 807 +++++------------- .../include/multiSlsDetector.h | 40 +- slsDetectorSoftware/src/Detector.cpp | 87 +- 3 files changed, 266 insertions(+), 668 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index ccea0e58e..969db6e87 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -27,7 +27,7 @@ class Detector { /************************************************** * * - * CONFIG * + * CONFIGURATIOn * * * * ************************************************/ /** @@ -39,410 +39,155 @@ class Detector { Result getHostname(Positions pos = {}) const; /** * Frees shared memory and adds detectors to the list - * Also updates local detector cache - * @param name hostnames for the positions given - */ + * Also updates local detector cache */ void setHostname(const std::vector &value); - /** - * Get multidetector Id - * @returns multidetector Id - */ int getMultiId() const; - /** - * Check version compatibility with detector software - * @param pos detector position - */ void checkDetectorVersionCompatibility(Positions pos = {}) const; - /** - * Check version compatibility with receiver software - * @param pos detector position - */ void checkReceiverVersionCompatibility(Positions pos = {}) const; - /** - * Get detector firmware version - * @param pos detector position - * @returns detector firmware version - */ Result getDetectorFirmwareVersion(Positions pos = {}) const; - /** - * Get detector server version - * @param pos detector position - * @returns detector server version - */ Result getDetectorServerVersion(Positions pos = {}) const; - /** - * Get detector serial number - * @param pos detector position - * @returns detector serial number - */ Result getDetectorSerialNumber(Positions pos = {}) const; - /** - * Get Client Software version - * @returns client software version - */ int64_t getClientSoftwareVersion() const; - /** - * Get Receiver software version - * @param pos detector position - * @return receiver software version - */ Result getReceiverSoftwareVersion(Positions pos = {}) const; - /** - * Get user details of shared memory - * @returns string with user details - */ - std::string getUserDetails() const; + /** Get user details of shared memory */ + std::string getUserDetailsFromSharedMemory() const; - /** - * Get Detector type as an enum - * @returns detector type - */ defs::detectorType getDetectorType() const; - /** - * Get Detector type as an enum - * @param pos detector position - * @returns detector type - */ Result getDetectorTypeAsEnum(Positions pos = {}) const; - /** - * Returns detector type as a string - * @param pos detector position - * @returns detector type as string - */ Result getDetectorTypeAsString(Positions pos = {}) const; - /** - * Returns the total number of detectors in the multidetector structure - * @returns total number of detectors in the multidetector structure - */ + /** @returns the total number of detectors in the multidetector structure */ int size() const; - /** - * Returns the number of detectors in the multidetector structure - * @returns number of detectors in the multidetector structure - */ defs::coordinates getNumberOfDetectors() const; - /** - * Returns the number of channels - * @param pos detector position - * @returns the number of channels - */ Result getNumberOfChannels(Positions pos = {}) const; - /** - * Returns the number of channels including gap pixels - * @param pos detector position - * @returns the number of channels including gap pixels - */ - Result + Result getNumberOfChannelsInclGapPixels(Positions pos = {}) const; - /** - * Returns the maximum number of channels of complete detector in both - * dimensions. -1 means no limit in this dimension. This value is used to - * calculate row and column offsets for each module. - * @returns the maximum number of channels of complete detector - */ defs::coordinates getMaxNumberOfChannels() const; /** * Sets the maximum number of channels of complete detector in both * dimensions. -1 means no limit in this dimension. This value is used to * calculate row and column offsets for each module. - * @param value the maximum number of channels of complete detector */ void setMaxNumberOfChannels(const defs::coordinates value); - /** - * Get Detector offset from shared memory (Gotthard only) - * @param pos detector position - * @returns offset in both dimensions - */ + /** [Gotthard] */ Result getDetectorOffsets(Positions pos = {}) const; - /** - * Set Detector offset in shared memory for each module - * @param value offset for detector in both dimensions - * @param pos detector position - */ + /** [Gotthard] */ void setDetectorOffsets(defs::coordinates value, Positions pos = {}); - /** - * Get Quad Type (Only for Eiger Quad detector hardware) - * @param pos detector position - * @returns quad type - */ + /** [Eiger with specific quad hardware] */ Result getQuad(Positions pos = {}) const; - /** - * Set Quad Type (Only for Eiger Quad detector hardware) - * @param enable true if quad type set, else false - * @param pos detector position - */ + /** [Eiger with specific quad hardware] */ void setQuad(const bool enable, Positions pos = {}); - /** - * Get number of rows to read out (Only for Eiger) - * @param pos detector position - * @returns number of lines - */ + /** [Eiger] */ Result getReadNLines(Positions pos = {}) const; - /** - * Set number of rows to read out (Only for Eiger) - * @param value number of lines - * @param pos detector position - */ + /** [Eiger] Number of lines to read out per half module + * Options: 0 - 256. Depending on dynamic range and + * 10 GbE enabled, only specific values are accepted + */ void setReadNLines(const int value, Positions pos = {}); - /** - * Get Detector Control TCP port (for client communication with Detector - * control server) - * @param pos detector position - * @returns control TCP port - */ - Result getControlPort(Positions pos = {}) const; + Result getControlPort(Positions pos = {}) const; - /** - * Set Detector Control TCP port (for client communication with Detector - * control server) - * @param value port number - * @param pos detector position - */ + /** Detector Control TCP port (for client communication with Detector + * control server) */ void setControlPort(int value, Positions pos = {}); - /** - * Get Detector Stop TCP port (for client communication with Detector Stop - * server) - * @param pos detector position - * @returns Stop TCP port - */ Result getStopPort(Positions pos = {}) const; - /** - * Set Detector Stop TCP port (for client communication with Detector Stop - * server) - * @param value port number - * @param pos detector position - */ + /** Detector Stop TCP port (for client communication with Detector Stop + * server) */ void setStopPort(int value, Positions pos = {}); - /** - * Get Receiver TCP port (for client communication with Receiver) - * @param pos detector position - * @returns Receiver TCP port - */ - Result getReceiverPort(Positions pos = {}) const; - - /** - * Set Receiver TCP port (for client communication with Receiver) - * @param value port number - * @param pos detector position - */ - void setReceiverPort(int value, Positions pos = {}); - - /** - * Gets Lock for detector control server to this client IP - * @param pos detector position - * @returns lock - */ Result getLockServer(Positions pos = {}) const; - /** - * Sets Lock for detector control server to this client IP - * @param value lock - * @param pos detector position - */ + /** Lock for detector control server to this client IP */ void setLockServer(bool value, Positions pos = {}); - /** - * Get last client IP saved on detector server - * @param pos detector position - * @returns last client IP saved on detector server - */ + /** Get last client IP saved on detector server */ Result getLastClientIP(Positions pos = {}) const; - /** - * Exit detector server - * @param pos detector position - */ void exitServer(Positions pos = {}); - /** - * Execute a command on the detector server - * @param value command - * @param pos detector position - */ + /** Execute a command on the detector server */ void execCommand(const std::string &value, Positions pos = {}); - /** - * Write current configuration to a file - * @param value configuration file name - */ void writeConfigurationFile(const std::string &value); - /** - * Get detector settings - * @param pos detector position - * @returns current settings - */ + /** [Not CTB] */ Result getSettings(Positions pos = {}) const; /** + * [Not CTB] * Load detector settings from the settings file picked from the * trimdir/settingsdir * Eiger only stores in shared memory ( a get will - * overwrite this) For Eiger, one must use threshold - * @param value settings - * @param pos detector position + * overwrite this) For Eiger, one must use setThresholdEnergy */ void setSettings(defs::detectorSettings value, Positions pos = {}); - /** - * Get threshold energy (Eiger) - * @param pos detector position - * @returns current threshold value for imod in ev (-1 failed) - */ + /** [Eiger] */ Result getThresholdEnergy(Positions pos = {}) const; /** - * Set threshold energy (Eiger) + * [Eiger] + * Set threshold energy * @param value threshold in eV * @param sett ev. change settings * @param tb 1 to include trimbits, 0 to exclude - * @param pos detector position */ void setThresholdEnergy(int value, defs::detectorSettings sett = defs::GET_SETTINGS, int tb = 1, Positions pos = {}); - /** - * Returns the detector trimbit/settings directory - * @param pos detector position - * @returns the trimbit/settings directory - */ Result getSettingsDir(Positions pos = {}) const; - /** - * Sets the detector trimbit/settings directory - * @param value trimbits/settings directory - * @param pos detector position - */ + /** [Not CTB] Sets the detector trimbit/settings directory */ void setSettingsDir(const std::string &value, Positions pos = {}); - /** - * Loads the modules settings/trimbits reading from a specific file - * file name extension is automatically generated. - * @param value specific settings/trimbits file - * @param pos detector position - */ + /** [Not CTB] Loads the modules settings/trimbits reading from a specific file + * file name extension is automatically generated from detector serial number */ void loadSettingsFile(const std::string &value, Positions pos = {}); - /** - * Saves the modules settings/trimbits to a specific file - * file name extension is automatically generated. - * @param value specific settings/trimbits file - * @param pos detector position - */ + /** [Not CTB] Saves the modules settings/trimbits to a specific file + * file name extension is automatically generated from detector serial number */ void saveSettingsFile(const std::string &value, Positions pos = {}); - /** - * Get Detector run status - * @param pos detector position - * @returns status - */ - Result getRunStatus(Positions pos = {}); - - /** - * Prepares detector for acquisition (Eiger) - */ - void prepareAcquisition(); - - /** - * Start detector acquisition (Non blocking) - */ - void startAcquisition(); - - /** - * Stop detector acquisition - */ - void stopAcquisition(); - - /** - * Give an internal software trigger to the detector (Eiger only) - * @param pos detector position - */ - void sendSoftwareTrigger(Positions pos = {}); - - /** - * Start detector acquisition and read all data (Blocking until end of - * acquisition) - */ - void startAndReadAll(); - - /** - * Start readout (without exposure or interrupting exposure) (Eiger store in - * ram) - */ - void startReadOut(); - - /** - * Requests and receives all data from the detector (Eiger store in ram) - */ - void readAll(); - - /** - * Configures in detector the destination for UDP packets - * @param pos detector position - */ + /** Configures in detector the destination for UDP packets */ void configureMAC(Positions pos = {}); - /** - * Get number of Frames - * @returns number of Frames - */ Result getNumberOfFrames() const; - /** - * Set number of Frames - * @param value number of Frames - */ void setNumberOfFrames(int64_t value); - /** - * Get number of Cycles - * @returns number of Cycles - */ Result getNumberOfCycles() const; - /** - * Set number of Cycles - * @param value number of Cycles - */ void setNumberOfCycles(int64_t value); - /** - * Get number of additional storage cells (Jungfrau) - * @returns number of additional storage cells - */ - Result getNumberOfStorageCells() const; + /** [Jungfrau] */ + Result getNumberOfAdditionalStorageCells() const; - /** - * Set number of additional storage cells (Jungfrau) - * @param value number of additional storage cells - */ + /** [Jungfrau] */ void setNumberOfStorageCells(int64_t value); /** [Jungfrau] */ @@ -454,384 +199,206 @@ class Detector { */ void setStoragecellStart(int cell, Positions pos = {}); - /** - * Get number of analog samples (CTB) - * @param pos detector position - * @returns number of analog samples - */ + /** [CTB] */ Result getNumberOfAnalogSamples(Positions pos = {}) const; - /** - * Set number of analog samples (CTB) - * @param value number of analog samples (CTB) - * @param pos detector position - */ + /** [CTB] */ void setNumberOfAnalogSamples(int64_t value, Positions pos = {}); - /** - * Get number of digital samples (CTB) - * @param pos detector position - * @returns number of digital samples - */ + /** [CTB] */ Result getNumberOfDigitalSamples(Positions pos = {}) const; - /** - * Set number of digital samples (CTB) - * @param value number of digital samples (CTB) - * @param pos detector position - */ + /** [CTB] */ void setNumberOfDigitalSamples(int64_t value, Positions pos = {}); - /** - * Get exposure time in ns - * @param pos detector position - * @returns exposure time in ns - */ Result getExptime(Positions pos = {}) const; - /** - * Set exposure time in ns - * @param value exposure time in ns - * @param pos detector position - */ void setExptime(ns t, Positions pos = {}); - /** - * Get period in ns - * @param pos detector position - * @returns period in ns - */ Result getPeriod(Positions pos = {}) const; - /** - * Set period in ns - * @param value period in ns - * @param pos detector position - */ void setPeriod(ns t, Positions pos = {}); - /** - * Get delay after trigger in ns(Gotthard, Jungfrau) - * @param pos detector position - * @returns delay after trigger in ns - */ + + /** [Gotthard][Jungfrau] */ Result getDelayAfterTrigger(Positions pos = {}) const; - /** - * Set delay after trigger (Gotthard, Jungfrau) - * @param value delay after trigger in ns - * @param pos detector position - */ + /** [Gotthard][Jungfrau] */ void setDelayAfterTrigger(ns value, Positions pos = {}); - /** - * Get sub frame exposure time in ns (Eiger in 32 bit mode) - * @param pos detector position - * @returns sub frame exposure time in ns - */ + /** [Eiger in 32 bit mode] */ Result getSubExptime(Positions pos = {}) const; - /** - * Set sub frame exposure time after trigger (Eiger in 32 bit mode) - * @param value sub frame exposure time in ns - * @param pos detector position - */ + /** [Eiger in 32 bit mode] */ void setSubExptime(ns t, Positions pos = {}); - /** - * Get sub frame dead time in ns (Eiger in 32 bit mode) - * @param pos detector position - * @returns sub frame dead time in ns - */ + + /** [Eiger in 32 bit mode] */ Result getSubDeadTime(Positions pos = {}) const; - /** - * Set sub frame dead time after trigger (Eiger in 32 bit mode) - * @param value sub frame dead time in ns - * @param pos detector position - */ + /** [Eiger in 32 bit mode] */ void setSubDeadTime(ns value, Positions pos = {}); - /** - * Get storage cell delay (Jungfrau) - * @param pos detector position - * @returns storage cell delay in ns. Range: (0-1638375 ns (resolution of - * 25ns) - */ + /** [Jungfrau] */ Result getStorageCellDelay(Positions pos = {}) const; - /** - * Set storage cell delay (Jungfrau) - * @param value storage cell delay in ns. Range: (0-1638375 ns (resolution - * of 25ns) - * @param pos detector position - */ + /** [Jungfrau] + * Options: (0-1638375 ns (resolution of 25ns) */ void setStorageCellDelay(ns value, Positions pos = {}); - /** - * Get number of Frames left (Gotthard, Jungfrau, CTB) - * @param pos detector position - * @returns number of Frames left - */ + /** [Gotthard][Jungfrau][CTB] */ Result getNumberOfFramesLeft(Positions pos = {}) const; - /** - * Get number of Cycles left (Gotthard, Jungfrau, CTB) - * @param pos detector position - * @returns number of Cycles left - */ + /** [Gotthard][Jungfrau][CTB] */ Result getNumberOfCyclesLeft(Positions pos = {}) const; - /** - * Get exposure time left in ns (Gotthard) - * @param pos detector position - * @returns exposure time left in ns - */ + + /** [Gotthard] */ Result getExptimeLeft(Positions pos = {}) const; - /** - * Get period left in ns (Gotthard, Jungfrau, CTB) - * @param pos detector position - * @returns period left in ns - */ + /** [Gotthard] */ Result getPeriodLeft(Positions pos = {}) const; - /** - * Get delay after trigger left in ns(Gotthard, Jungfrau, CTB) - * @param pos detector position - * @returns delay after trigger left in ns - */ + /** [Gotthard][Jungfrau][CTB] */ Result getDelayAfterTriggerLeft(Positions pos = {}) const; - /** - * Get number of frames from start up of detector (Jungfrau, CTB) - * @param pos detector position - * @returns number of frames from start up of detector - */ + /** [Gotthard][Jungfrau][CTB] */ Result getNumberOfFramesFromStart(Positions pos = {}) const; - /** - * Get time from detector start in ns (Jungfrau, CTB) - * @param pos detector position - * @returns time from detector start in ns - */ + /** [Jungfrau][CTB] Get time from detector start */ Result getActualTime(Positions pos = {}) const; - /** - * Get timestamp at a frame start in ns(Jungfrau, CTB) - * @param pos detector position - * @returns timestamp at a frame start in ns - */ + /** [Jungfrau][CTB] Get timestamp at a frame start */ Result getMeasurementTime(Positions pos = {}) const; - /** - * Get measured period between previous two frames in ns (Eiger) - * @param pos detector position - * @returns measured period between previous two frames in ns - */ + /** [Eiger] Get measured period between previous two frames */ Result getMeasuredPeriod(Positions pos = {}) const; - /** - * Get measured sub frame period between previous two frames in ns (Eiger in - * 32 bit mode) - * @param pos detector position - * @returns measured sub frame period between previous two frames in ns - */ + /** [Eiger] Get measured sub frame period between previous two frames */ Result getMeasuredSubFramePeriod(Positions pos = {}) const; - /** - * Get speed (Eiger, Jungfrau) - * @param pos detector position - * @returns speed (0 full speed, 1 half speed, 2 quarter speed) - */ + /** [Eiger][Jungfrau] */ Result getSpeed(Positions pos = {}) const; - /** - * Set speed (Eiger, Jungfrau) + /** [Eiger][Jungfrau] * @param value speed (0 full speed, 1 half speed, 2 quarter speed) - * @param pos detector position */ void setSpeed(int value, Positions pos = {}); - /** - * Get ADC Phase (Gotthard, Jungfrau, CTB) - * @param inDeg in degrees (Jungfrau, CTB) - * @returns ADC Phase - */ + /** [Gotthard][Jungfrau][CTB] */ Result getADCPhase(bool inDeg, Positions pos = {}) const; - /** - * Set sADC Phase (Gotthard, Jungfrau, CTB) - * @param value ADC Phase - * @param inDeg in degrees (Jungfrau, CTB) - */ + /** [Gotthard][Jungfrau][CTB] */ void setADCPhase(int value, bool inDeg, Positions pos = {}); - /** - * Get Max ADC Phase Shift (Jungfrau, CTB) - * @returns Max ADC Phase Shift - */ + /** [Jungfrau][CTB] */ Result getMaxADCPhaseShift(Positions pos = {}) const; - /** - * Get DBIT Phase (Jungfrau, CTB) - * @param inDeg in degrees - * @returns DBIT Phase - */ + /** [CTB] */ Result getDBITPhase(bool inDeg, Positions pos = {}) const; - /** - * Set DBIT Phase (CTB) - * @param value DBIT Phase - * @param inDeg in degrees - */ + /** [CTB] */ void setDBITPhase(int value, bool inDeg, Positions pos = {}); - /** - * Get Max DBIT Phase Shift (CTB) - * @returns Max DBIT Phase Shift - */ + /** [CTB] */ Result getMaxDBITPhaseShift(Positions pos = {}) const; - /** - * Get ADC Clock in MHz (CTB) - * @returns ADC Clock in MHz - */ + /** [CTB] */ Result getADCClock(Positions pos = {}) const; - /** - * Set ADC Clock in MHz (CTB) - * @param value ADC Clock in MHz - */ - void setADCClock(int value, Positions pos = {}); + /** [CTB] */ + void setADCClock(int value_in_MHz, Positions pos = {}); - /** - * Get DBIT Clock in MHz (CTB) - * @returns DBIT Clock in MHz - */ + /** [CTB] */ Result getDBITClock(Positions pos = {}) const; - /** - * Set DBIT Clock in MHz (CTB) - * @param value DBIT Clock in MHz - */ - void setDBITClock(int value, Positions pos = {}); + /** [CTB] */ + void setDBITClock(int value_in_MHz, Positions pos = {}); - /** - * Get RUN Clock in MHz (CTB) - * @returns RUN Clock in MHz - */ + /** [CTB] */ Result getRUNClock(Positions pos = {}) const; - /** - * Set RUN Clock in MHz (CTB) - * @param value RUN Clock in MHz - */ - void setRUNClock(int value, Positions pos = {}); + /** [CTB] */ + void setRUNClock(int value_in_MHz, Positions pos = {}); - /** - * Get SYNC Clock in MHz (CTB) - * @returns SYNC Clock in MHz - */ + /** [CTB] */ Result getSYNCClock(Positions pos = {}) const; - /** - * Get ADC Pipeline (CTB) - * @returns ADC Pipeline - */ + /** [CTB] */ Result getADCPipeline(Positions pos = {}) const; - /** - * Set ADC Pipeline (CTB) - * @param value ADC Pipeline - */ + /** [CTB] */ void setADCPipeline(int value, Positions pos = {}); - /** - * Get DBIT Pipeline (CTB) - * @returns DBIT Pipeline - */ + /** [CTB] */ Result getDBITPipeline(Positions pos = {}) const; - /** - * Set DBIT Pipeline (CTB) - * @param value DBIT Pipeline - */ + /** [CTB] */ void setDBITPipeline(int value, Positions pos = {}); Result getDynamicRange(Positions pos = {}) const; /** - * (Eiger: + * [Eiger] * Options: 4, 8, 16, 32 - * If i is 32, also sets clkdivider to 2, if 16, sets clkdivider to 1) + * If i is 32, also sets clkdivider to 2, if 16, sets clkdivider to 1 */ void setDynamicRange(int value); Result getHighVoltage(Positions pos = {}) const; /** - * (Gotthard Options: 0, 90, 110, 120, 150, 180, 200) - * (Jungfrau, CTB Options: 0, 60 - 200) - * (Eiger Options: 0 - 200) + * [Gotthard Options: 0, 90, 110, 120, 150, 180, 200] + * [Jungfrau, CTB Options: 0, 60 - 200] + * [Eiger Options: 0 - 200] */ void setHighVoltage(int value, Positions pos = {}); - /** - * (Eiger) - */ + /** [Eiger] */ Result getIODelay(Positions pos = {}) const; - /** - * (Eiger) - */ + /** [Eiger] */ void setIODelay(int value, Positions pos = {}); /** * (Degrees) - * (Gotthard Options: TEMPERATURE_ADC, TEMPERATURE_FPGA) - * (Jungfrau Options: TEMPERATURE_ADC, TEMPERATURE_FPGA) - * (Eiger Options: TEMPERATURE_FPGA, TEMPERATURE_FPGAEXT, TEMPERATURE_10GE, + * [Gotthard Options: TEMPERATURE_ADC, TEMPERATURE_FPGA] + * [Jungfrau Options: TEMPERATURE_ADC, TEMPERATURE_FPGA] + * [Eiger Options: TEMPERATURE_FPGA, TEMPERATURE_FPGAEXT, TEMPERATURE_10GE, * TEMPERATURE_DCDC, TEMPERATURE_SODL, TEMPERATURE_SODR, TEMPERATURE_FPGA2, - * TEMPERATURE_FPGA3) (CTB Options: SLOW_ADC_TEMP) + * TEMPERATURE_FPGA3) (CTB Options: SLOW_ADC_TEMP] */ Result getTemp(defs::dacIndex index, Positions pos = {}) const; - /** - * (CTB mV) - */ + /** [CTB] */ Result getVrefVoltage(bool mV, Positions pos = {}) const; - /** - * (CTB mV) - */ + /** [CTB] */ void setVrefVoltage(int value, bool mV, Positions pos = {}); - /** - * (CTB mV Options: V_LIMIT, V_POWER_A, V_POWER_B, V_POWER_C, - * V_POWER_D, V_POWER_IO, V_POWER_CHIP)) - */ + /** [CTB] */ Result getVoltage(defs::dacIndex index, Positions pos = {}) const; /** - * (CTB mV Options: V_LIMIT, V_POWER_A, V_POWER_B, V_POWER_C, - * V_POWER_D, V_POWER_IO, V_POWER_CHIP) + * [CTB] mV + * Options: V_LIMIT, V_POWER_A, V_POWER_B, V_POWER_C, + * V_POWER_D, V_POWER_IO, V_POWER_CHIP */ void setVoltage(int value, defs::dacIndex index, Positions pos = {}); /** - * (CTB mV Options: V_POWER_A, V_POWER_B, V_POWER_C, V_POWER_D, V_POWER_IO, - * V_POWER_CHIP) + * [CTB] mV + * Options: V_POWER_A, V_POWER_B, V_POWER_C, V_POWER_D, V_POWER_IO, + * V_POWER_CHIP */ Result getMeasuredVoltage(defs::dacIndex index, Positions pos = {}) const; /** - * (CTB mA Options: I_POWER_A, I_POWER_B, I_POWER_C, I_POWER_D, I_POWER_IO) + * [CTB] mA + * Options: I_POWER_A, I_POWER_B, I_POWER_C, I_POWER_D, I_POWER_IO */ Result getMeasuredCurrent(defs::dacIndex index, Positions pos = {}) const; - /** - * (CTB Options: SLOW_ADC0 - SLOW_ADC7) - */ + /** [CTB] Options: SLOW_ADC0 - SLOW_ADC7 */ Result getSlowADC(defs::dacIndex index, Positions pos = {}) const; Result getDAC(defs::dacIndex index, bool mV, Positions pos = {}) const; @@ -841,53 +408,35 @@ class Detector { Result getTimingMode(Positions pos = {}) const; /** - * (Gotthard, Jungfrau, CTB Options: AUTO_TIMING, TRIGGER_EXPOSURE) - * (Eiger Options: AUTO_TIMING, TRIGGER_EXPOSURE, GATED, BURST_TRIGGER) + * [Gotthard, Jungfrau, CTB Options: AUTO_TIMING, TRIGGER_EXPOSURE] + * [Eiger Options: AUTO_TIMING, TRIGGER_EXPOSURE, GATED, BURST_TRIGGER] */ void setTimingMode(defs::externalCommunicationMode value, Positions pos = {}); - /** - * (Gotthard) - */ + /** [Gotthard] */ Result getExternalSignalFlags(Positions pos = {}) const; - /** - * (Gotthard Options: TRIGGER_IN_RISING_EDGE, TRIGGER_IN_FALLING_EDGE) - */ + /** [Gotthard] Options: TRIGGER_IN_RISING_EDGE, TRIGGER_IN_FALLING_EDGE */ void setExternalSignalFlags(defs::externalSignalFlag value, Positions pos = {}); - /** - * (Eiger) - */ + /** [Eiger] */ Result getParallelMode(Positions pos = {}) const; - /** - * (Eiger) - */ + /** [Eiger] */ void setParallelMode(bool value, Positions pos = {}); - /** - * (Eiger) - */ + /** [Eiger] */ Result getOverFlowMode(Positions pos = {}) const; - /** - * (Eiger) - */ + /** [Eiger] */ void setOverFlowMode(bool value, Positions pos = {}); - /** - * (CTB Options: NORMAL_READOUT = 0, DIGITAL_ONLY = 1, ANALOG_AND_DIGITAL = 2) - */ + /** [CTB] */ Result getSignalType(Positions pos = {}) const; - /** - * (CTB Options: NORMAL_READOUT = 0, DIGITAL_ONLY = 1, ANALOG_AND_DIGITAL = 2) - */ + /** [CTB] Options: NORMAL_READOUT = 0, DIGITAL_ONLY = 1, ANALOG_AND_DIGITAL = 2 */ void setSignalType(int value, Positions pos = {}); - // Erik - /** [Eiger] */ Result getInterruptSubframe(Positions pos = {}) const; @@ -933,6 +482,7 @@ class Detector { void setReceiverHostname(const std::string &receiver, Positions pos = {}); Result getReceiverUDPIP(Positions pos = {}) const; + void setReceiverUDPIP(const std::string &udpip, Positions pos = {}); /** [Jungfrau bottom half] */ @@ -942,28 +492,34 @@ class Detector { void setReceiverUDPIP2(const std::string &udpip, Positions pos = {}); Result getReceiverUDPMAC(Positions pos = {}) const; + void setReceiverUDPMAC(const std::string &udpmac, Positions pos = {}); /** [Jungfrau bottom half] */ Result getReceiverUDPMAC2(Positions pos = {}) const; + /** [Jungfrau bottom half] */ void setReceiverUDPMAC2(const std::string &udpmac, Positions pos = {}); Result getReceiverUDPPort(Positions pos = {}) const; + void setReceiverUDPPort(int udpport, Positions pos = {}); /** [Eiger right port][Jungfrau bottom half] */ Result getReceiverUDPPort2(Positions pos = {}) const; + /** [Eiger right port][Jungfrau bottom half] */ void setReceiverUDPPort2(int udpport, Positions pos = {}); /** [Jungfrau] */ Result getNumberofUDPInterfaces(Positions pos = {}) const; + /** [Jungfrau] Also restarts client and receiver sockets */ void setNumberofUDPInterfaces(int n, Positions pos = {}); /** [Jungfrau] */ Result getSelectedUDPInterface(Positions pos = {}) const; + /** * [Jungfrau: * Effective only when number of interfaces is 1. @@ -988,20 +544,24 @@ class Detector { void setReceiverDataStreamingOutPort(int port, Positions pos = {}); Result getClientStreamingIP(Positions pos = {}) const; + // TODO these should probably be the same ?? same as what? void setClientDataStreamingInIP(const std::string &ip, Positions pos = {}); Result getReceiverStreamingIP(Positions pos = {}) const; + void setReceiverDataStreamingOutIP(const std::string &ip, Positions pos = {}); /** [Eiger, Jungfrau] */ Result getFlowControl10G(Positions pos = {}) const; + /** [Eiger, Jungfrau] */ void setFlowControl10G(bool enable, Positions pos = {}); /** [Eiger, Jungfrau] */ Result getTransmissionDelayFrame(Positions pos = {}) const; + /** * [Jungfrau: Sets the transmission delay of the first UDP packet being streamed out of the module * Options: 0 - 31, each value represenets 1 ms ] @@ -1019,6 +579,7 @@ class Detector { /** [Eiger] */ Result getTransmissionDelayRight(Positions pos = {}) const; + /** * [Eiger] * Sets the transmission delay of first packet streamed ut of the right UDP port @@ -1027,6 +588,7 @@ class Detector { /** [Moench] */ Result getAdditionalJsonHeader(Positions pos = {}) const; + /** [Moench] */ void setAdditionalJsonHeader(const std::string &jsonheader, Positions pos = {}); @@ -1049,34 +611,46 @@ class Detector { * For now limiting to all detectors working the same*/ /** [Moench: -1 if not found or cannot convert to int] */ Result getDetectorMinMaxEnergyThreshold(const bool isEmax, Positions pos = {}) const; + /** [Moench] */ void setDetectorMinMaxEnergyThreshold(const bool isEmax, const int value, Positions pos = {}); + /** [Moench: -1 if unknown mode] */ Result getFrameMode(Positions pos = {}) const; + /** [Moench] */ void setFrameMode(defs::frameModeType value, Positions pos = {}); + /** [Moench: -1 if unknown mode] */ Result getDetectorMode(Positions pos = {}) const; + /** [Moench] */ void setDetectorMode(defs::detectorModeType value, Positions pos = {}); /** [Gotthard] */ Result getDigitalTestBit(Positions pos = {}); + /** [Gotthard] */ Result setDigitalTestBit(const int value, Positions pos = {}); - /** [Gotthard, Jungfrau, CTB] */ + + /** [Gotthard][Jungfrau][CTB] */ Result executeFirmwareTest(Positions pos = {}); - /** [Gotthard, Jungfrau, CTB] */ + + /** [Gotthard][Jungfrau][CTB] */ Result executeBusTest(Positions pos = {}); + /** [Gotthard] subset modules not allowed */ void loadDarkImage(const std::string &fname, Positions pos = {}); + /** [Gotthard] subset modules not allowed */ void loadGainImage(const std::string &fname, Positions pos = {}); + /** * [Gotthard] subset modules not allowed * @param startACQ if start acq after reading counter */ void getCounterMemoryBlock(const std::string &fname, bool startACQ, Positions pos = {}); + /** * [Gotthard] * @param startACQ if start acq after resetting counter @@ -1086,11 +660,13 @@ class Detector { /** [Eiger] */ Result getCounterBit(Positions pos = {}) const; + /** [Eiger] If it is set, it resets chips completely (else partially) before an acquisition TODO: if it makes sense */ void setCounterBit(bool value, Positions pos = {}); /** [Gotthard, CTB]*/ Result> getROI(Positions pos = {}) const; + /** * [Gotthard Options: Only a single chip or all chips, only 1 ROI allowed] * [CTB: multiple ROIs allowed] @@ -1263,16 +839,19 @@ class Detector { /** [Eiger][Jungfrau] */ Result getStartingFrameNumber(Positions pos = {}) const; + /** [Eiger][Jungfrau] */ void setStartingFrameNumber(uint64_t value, Positions pos); /** [Eiger] */ Result getTenGigaEnabled(Positions pos = {}) const; + /** [Eiger] */ void setTenGigaEnabled(bool value, Positions pos = {}); /** [CTB] */ Result getLEDEnable(Positions pos = {}) const; + /** [CTB] */ void setLEDEnable(bool enable, Positions pos = {}); @@ -1291,24 +870,40 @@ class Detector { * * * ************************************************/ Result getFileFormat(Positions pos = {}) const; + /** default binary, Options: BINARY, HDF5 (library must be compiled with this option) */ void setFileFormat(defs::fileFormat f, Positions pos = {}); + Result getFilePath(Positions pos = {}) const; + void setFilePath(const std::string &fname, Positions pos = {}); + Result getFileNamePrefix(Positions pos = {}) const; + /** default run */ void setFileNamePrefix(const std::string &fname, Positions pos = {}); + Result getFileIndex(Positions pos = {}) const; + void setFileIndex(int i, Positions pos = {}); + Result getFileWrite(Positions pos = {}) const; + /** default writes */ + void setFileWrite(bool value, Positions pos = {}); + Result getMasterFileWrite(Positions pos = {}) const; + void setMasterFileWrite(bool value, Positions pos = {}); + Result getFileOverWrite(Positions pos = {}) const; + /** default overwites */ void setFileOverWrite(bool value, Positions pos = {}); + Result getFramesPerFile(Positions pos = {}) const; + void setFramesPerFile(int n, Positions pos = {}); @@ -1322,6 +917,11 @@ class Detector { Result printReceiverConfiguration(Positions pos = {}) const; + Result getReceiverPort(Positions pos = {}) const; + + /** Receiver TCP port (for client communication with Receiver) */ + void setReceiverPort(int value, Positions pos = {}); + Result getReceiverLock(Positions pos = {}); /** locks receiver server to client IP */ @@ -1334,6 +934,7 @@ class Detector { void execReceiverCommand(const std::string &cmd, Positions pos = {}); Result getReceiverStreamingFrequency(Positions pos = {}) const; + /** @param freq nth frame streamed out of receiver. * If 0, streaming timer is the timeout, * after which current frame sent out. Default is 0 at 200 ms. @@ -1342,6 +943,7 @@ class Detector { void setReceiverStreamingFrequency(int freq, Positions pos = {}); Result getReceiverStreamingTimer(Positions pos = {}) const; + /** * If receiver streaming frequency is 0 (default), then this timer between each * data stream is set. Default is 200 ms. @@ -1349,17 +951,24 @@ class Detector { void setReceiverStreamingTimer(int time_in_ms, Positions pos = {}); bool getDataStreamingToClient() const; + void setDataStreamingToClient(bool value); + Result getDataStreamingFromReceiver(Positions pos = {}) const; + void setDataStreamingFromReceiver(bool value, Positions pos = {}); Result getReceiverFifoDepth(Positions pos = {}) const; + void setReceiverFifoDepth(int nframes, Positions pos = {}); + Result getReceiverSilentMode(Positions pos = {}) const; + void setReceiverSilentMode(bool value, Positions pos = {}); - Result + Result getReceiverFrameDiscardPolicy(Positions pos = {}) const; + /** * default NO_DISCARD * Options: NO_DISCARD, DISCARD_EMPTY_FRAMES, DISCARD_PARTIAL_FRAMES @@ -1367,6 +976,7 @@ class Detector { void setReceiverFrameDiscardPolicy(defs::frameDiscardPolicy f, Positions pos = {}); Result getPartialFramesPadding(Positions pos = {}) const; + /** padding enabled */ void setPartialFramesPadding(bool value, Positions pos = {}); @@ -1378,7 +988,6 @@ class Detector { */ void setRxPadDeactivatedMod(bool pad, Positions pos = {}); - Result getReceiverUDPSocketBufferSize(Positions pos = {}) const; void setReceiverUDPSocketBufferSize(int64_t udpsockbufsize, @@ -1410,15 +1019,32 @@ class Detector { */ void setAcquiringFlag(bool value); + Result getRunStatus(Positions pos = {}); + + /** [Eiger] */ + void prepareAcquisition(); + + /** Start detector acquisition (Non blocking) */ + void startAcquisition(); + + void stopAcquisition(); + + /** [Eiger] Sends an internal software trigger to the detector */ + void sendSoftwareTrigger(Positions pos = {}); + /** Receiver starts listening to UDP packets from detector */ void startReceiver(Positions pos = {}); + /** Receiver stops listening to UDP packets from detector */ void stopReceiver(Positions pos = {}); + /** Read back the run status of the receiver */ Result getReceiverStatus(Positions pos = {}); Result getFramesCaughtByReceiver(Positions pos = {}) const; + Result getReceiverCurrentFrameIndex(Positions pos = {}) const; + void resetFramesCaught(Positions pos = {}); /************************************************** @@ -1442,45 +1068,31 @@ class Detector { /** [CTB] */ void setPatternClockControl(uint64_t word, Positions pos = {}); - /** - * [CTB] - * Caution: If word is -1 reads the addr (same as - * executing the pattern) - */ + /** [CTB] Caution: If word is -1 reads the addr (same as + * executing the pattern) */ void setPatternWord(int addr, uint64_t word, Positions pos = {}); - /** - * [CTB] - * Options: level: -1 (complete pattern) and 0-2 levels + /**[CTB] Options: level: -1 (complete pattern) and 0-2 levels * @returns array of start address, stop address and number of loops */ Result> getPatternLoops(int level, Positions pos = {}) const; - /** - * [CTB] - * Options: start, stop, n : 0-2 - * level: -1 (complete pattern) and 0-2 levels - */ + /** [CTB] Options: start, stop, n : 0-2 + * level: -1 (complete pattern) and 0-2 levels */ void setPatternLoops(int level, int start, int stop, int n, Positions pos = {}); /* [CTB] */ Result getPatternWaitAddr(int level, Positions pos = {}) const; - - /** - * [CTB] - * Options: level 0-2 - */ + + /** [CTB] Options: level 0-2 */ void setPatternWaitAddr(int level, int addr, Positions pos = {}); /** [CTB] */ Result getPatternWaitTime(int level, Positions pos = {}) const; - /** - * [CTB] - * Options: level 0-2 - */ + /** [CTB] Options: level 0-2 */ void setPatternWaitTime(int level, uint64_t t, Positions pos = {}); /** [CTB] */ @@ -1492,8 +1104,7 @@ class Detector { /** [CTB] */ Result getPatternBitMask(Positions pos = {}) const; - /** - * [CTB] Sets the bitmask that the mask will be applied to for every + /** [CTB] Sets the bitmask that the mask will be applied to for every * pattern */ void setPatternBitMask(uint64_t mask, Positions pos = {}); diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 77dedac81..611d93ae3 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -680,26 +680,6 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ void sendSoftwareTrigger(int detPos = -1);// - /** - * Start detector acquisition and read all data (Blocking until end of - * acquisition) - * @param detPos -1 for all detectors in list or specific detector position - */ - void startAndReadAll(int detPos = -1);// - - /** - * Start readout (without exposure or interrupting exposure) (Eiger store in - * ram) - * @param detPos -1 for all detectors in list or specific detector position - */ - void startReadOut(int detPos = -1);// - - /** - * Requests and receives all data from the detector (Eiger store in ram) - * @param detPos -1 for all detectors in list or specific detector position - */ - void readAll(int detPos = -1);// - /** * Configures in detector the destination for UDP packets * @param detPos -1 for all detectors in list or specific detector position @@ -2320,6 +2300,26 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ void startProcessingThread(); + /** + * Start detector acquisition and read all data (Blocking until end of + * acquisition) + * @param detPos -1 for all detectors in list or specific detector position + */ + void startAndReadAll(int detPos = -1);// + + /** + * Start readout (without exposure or interrupting exposure) (Eiger store in + * ram) + * @param detPos -1 for all detectors in list or specific detector position + */ + void startReadOut(int detPos = -1);// + + /** + * Requests and receives all data from the detector (Eiger store in ram) + * @param detPos -1 for all detectors in list or specific detector position + */ + void readAll(int detPos = -1);// + /** * Check if processing thread is ready to join main thread * @returns true if ready, else false diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index a8bd836e6..7a34f4621 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -60,7 +60,7 @@ Result Detector::getReceiverSoftwareVersion(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverSoftwareVersion, pos); } -std::string Detector::getUserDetails() const { return pimpl->getUserDetails(); } +std::string Detector::getUserDetailsFromSharedMemory() const { return pimpl->getUserDetails(); } defs::detectorType Detector::getDetectorType() const { return pimpl->getDetectorTypeAsEnum(); @@ -152,14 +152,6 @@ void Detector::setStopPort(int value, Positions pos) { pimpl->Parallel(&slsDetector::setStopPort, pos, value); } -Result Detector::getReceiverPort(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverPort, pos); -} - -void Detector::setReceiverPort(int value, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverPort, pos, value); -} - Result Detector::getLockServer(Positions pos) const { return pimpl->Parallel(&slsDetector::lockServer, pos, -1); } @@ -217,40 +209,6 @@ void Detector::saveSettingsFile(const std::string &value, Positions pos) { pimpl->Parallel(&slsDetector::saveSettingsFile, pos, value); } -Result Detector::getRunStatus(Positions pos) { - return pimpl->Parallel(&slsDetector::getRunStatus, pos); -} - -void Detector::prepareAcquisition() { - pimpl->Parallel(&slsDetector::prepareAcquisition, {}); -} - -void Detector::startAcquisition() { - if (getDetectorType() == defs::EIGER) { - prepareAcquisition(); - } - pimpl->Parallel(&slsDetector::startAcquisition, {}); -} - -void Detector::stopAcquisition() { pimpl->stopAcquisition(); } - -void Detector::sendSoftwareTrigger(Positions pos) { - pimpl->Parallel(&slsDetector::sendSoftwareTrigger, pos); -} - -void Detector::startAndReadAll() { - if (getDetectorType() == defs::EIGER) { - prepareAcquisition(); - } - pimpl->Parallel(&slsDetector::startAndReadAll, {}); -} - -void Detector::startReadOut() { - pimpl->Parallel(&slsDetector::startReadOut, {}); -} - -void Detector::readAll() { pimpl->Parallel(&slsDetector::readAll, {}); } - void Detector::configureMAC(Positions pos) { pimpl->Parallel(&slsDetector::configureMAC, pos); } @@ -271,7 +229,7 @@ void Detector::setNumberOfCycles(int64_t value) { pimpl->Parallel(&slsDetector::setTimer, {}, defs::CYCLES_NUMBER, value); } -Result Detector::getNumberOfStorageCells() const { +Result Detector::getNumberOfAdditionalStorageCells() const { return pimpl->Parallel(&slsDetector::setTimer, {}, defs::STORAGE_CELL_NUMBER, -1); } @@ -454,8 +412,8 @@ Result Detector::getADCClock(Positions pos) const { return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_CLOCK, -1, 0); } -void Detector::setADCClock(int value, Positions pos) { - pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_CLOCK, value, 0); +void Detector::setADCClock(int value_in_MHz, Positions pos) { + pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_CLOCK, value_in_MHz, 0); } Result Detector::getDBITClock(Positions pos) const { @@ -463,8 +421,8 @@ Result Detector::getDBITClock(Positions pos) const { 0); } -void Detector::setDBITClock(int value, Positions pos) { - pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_CLOCK, value, 0); +void Detector::setDBITClock(int value_in_MHz, Positions pos) { + pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_CLOCK, value_in_MHz, 0); } Result Detector::getRUNClock(Positions pos) const { @@ -472,8 +430,8 @@ Result Detector::getRUNClock(Positions pos) const { 0); } -void Detector::setRUNClock(int value, Positions pos) { - pimpl->Parallel(&slsDetector::setSpeed, pos, defs::CLOCK_DIVIDER, value, 0); +void Detector::setRUNClock(int value_in_MHz, Positions pos) { + pimpl->Parallel(&slsDetector::setSpeed, pos, defs::CLOCK_DIVIDER, value_in_MHz, 0); } Result Detector::getSYNCClock(Positions pos) const { @@ -1440,6 +1398,14 @@ Result Detector::printReceiverConfiguration(Positions pos) const { return pimpl->Parallel(&slsDetector::printReceiverConfiguration, pos); } +Result Detector::getReceiverPort(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverPort, pos); +} + +void Detector::setReceiverPort(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverPort, pos, value); +} + Result Detector::getReceiverLock(Positions pos) { return pimpl->Parallel(&slsDetector::lockReceiver, pos, -1); } @@ -1561,6 +1527,27 @@ bool Detector::getAcquiringFlag() const { return pimpl->getAcquiringFlag(); } void Detector::setAcquiringFlag(bool value) { pimpl->setAcquiringFlag(value); } +Result Detector::getRunStatus(Positions pos) { + return pimpl->Parallel(&slsDetector::getRunStatus, pos); +} + +void Detector::prepareAcquisition() { + pimpl->Parallel(&slsDetector::prepareAcquisition, {}); +} + +void Detector::startAcquisition() { + if (getDetectorType() == defs::EIGER) { + prepareAcquisition(); + } + pimpl->Parallel(&slsDetector::startAcquisition, {}); +} + +void Detector::stopAcquisition() { pimpl->stopAcquisition(); } + +void Detector::sendSoftwareTrigger(Positions pos) { + pimpl->Parallel(&slsDetector::sendSoftwareTrigger, pos); +} + void Detector::startReceiver(Positions pos) { pimpl->Parallel(&slsDetector::startReceiver, pos); } From c2f57f5ab05d6e67731f9f15ebdfa124b59183fb Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Mon, 12 Aug 2019 19:55:42 +0200 Subject: [PATCH 064/108] WIP --- slsDetectorSoftware/include/Detector.h | 46 -------------------------- 1 file changed, 46 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 969db6e87..824b11bb3 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -1109,52 +1109,6 @@ class Detector { */ void setPatternBitMask(uint64_t mask, Positions pos = {}); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - }; } // namespace sls \ No newline at end of file From 6f6ee199062b25453ce9b2f2b521145ef45de9f7 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Tue, 13 Aug 2019 09:16:29 +0200 Subject: [PATCH 065/108] WIP --- slsDetectorSoftware/include/Result.h | 10 +++++++--- slsSupportLib/include/TypeTraits.h | 13 +++++++++++++ slsSupportLib/tests/test-TypeTraits.cpp | 5 +++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/slsDetectorSoftware/include/Result.h b/slsDetectorSoftware/include/Result.h index 54d19b1a5..92a96aaaf 100644 --- a/slsDetectorSoftware/include/Result.h +++ b/slsDetectorSoftware/include/Result.h @@ -31,7 +31,6 @@ template > class Result { Result() = default; Result(std::initializer_list list) : vec(list){}; - /** Custom constructor from integer type to Result or Result */ template ::value && @@ -98,9 +97,14 @@ template > class Result { vec.push_back(std::forward(value)); } + /** Disable emplace_back if the underlying vector does not support it + * vector gcc 4.8 + */ template - auto emplace_back(Args &&... args) -> decltype(vec.emplace_back(args...)){ - vec.emplace_back(std::forward(args)...); + auto emplace_back(Args &&... args) -> + typename std::enable_if>::value, + decltype(vec.emplace_back(args...))>::type { + return vec.emplace_back(std::forward(args)...); } auto operator[](size_type pos) -> decltype(vec[pos]) { return vec[pos]; } diff --git a/slsSupportLib/include/TypeTraits.h b/slsSupportLib/include/TypeTraits.h index 71d37e9ad..39b9525c2 100644 --- a/slsSupportLib/include/TypeTraits.h +++ b/slsSupportLib/include/TypeTraits.h @@ -35,6 +35,19 @@ struct has_str().str())>, void>::type> : public std::true_type {}; +/** + * Has emplace_back method + */ +template struct has_emplace_back : std::false_type {}; + +template struct has_emplace_back_helper {}; + +template +struct has_emplace_back().emplace_back())>, + void>::type> : public std::true_type {}; + /** * Type trait to evaluate if template parameter is * complying with a standard container diff --git a/slsSupportLib/tests/test-TypeTraits.cpp b/slsSupportLib/tests/test-TypeTraits.cpp index 2234ca0ae..0df0ed186 100644 --- a/slsSupportLib/tests/test-TypeTraits.cpp +++ b/slsSupportLib/tests/test-TypeTraits.cpp @@ -43,4 +43,9 @@ TEST_CASE("sls::is_duration"){ TEST_CASE("initializer list"){ REQUIRE(sls::is_light_container>::value == true); +} + +TEST_CASE("Check for emplace back"){ + //we know vector should have this its the type trait that is tested + REQUIRE(sls::has_emplace_back>::value == true); } \ No newline at end of file From 2fe06c7163893dec0326d2dda2cf07cffb4d0ec7 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Tue, 13 Aug 2019 11:19:25 +0200 Subject: [PATCH 066/108] WIP --- slsDetectorSoftware/include/Result.h | 10 ---------- slsDetectorSoftware/src/Detector.cpp | 5 +++-- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/slsDetectorSoftware/include/Result.h b/slsDetectorSoftware/include/Result.h index 92a96aaaf..08386677c 100644 --- a/slsDetectorSoftware/include/Result.h +++ b/slsDetectorSoftware/include/Result.h @@ -97,16 +97,6 @@ template > class Result { vec.push_back(std::forward(value)); } - /** Disable emplace_back if the underlying vector does not support it - * vector gcc 4.8 - */ - template - auto emplace_back(Args &&... args) -> - typename std::enable_if>::value, - decltype(vec.emplace_back(args...))>::type { - return vec.emplace_back(std::forward(args)...); - } - auto operator[](size_type pos) -> decltype(vec[pos]) { return vec[pos]; } const_reference operator[](size_type pos) const { return vec[pos]; } diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 7a34f4621..81dc9792a 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -1072,7 +1072,7 @@ void Detector::setCounterBit(bool value, Positions pos) { } Result> Detector::getROI(Positions pos) const { - //vector holding module_id for the modules that should be read + //vector holding module_id for the modules that should be read const std::vector id_vec = [&]() { if (pos.empty() || (pos.size() == 1 && pos[0] == -1)){ std::vector tmp; @@ -1084,6 +1084,7 @@ Result> Detector::getROI(Positions pos) const { } }(); + //values to return Result> res; @@ -1091,7 +1092,7 @@ Result> Detector::getROI(Positions pos) const { for (const auto& i :id_vec){ int n = 0; auto ptr = pimpl->getROI(n, i); - res.emplace_back(ptr, ptr+n); + // res.emplace_back(ptr, ptr+n); } return res; } From 7b1cb517c041dc9b212f62aa9717f0565a6ac717 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Wed, 14 Aug 2019 09:08:23 +0200 Subject: [PATCH 067/108] removed emplace_back test --- slsDetectorSoftware/tests/test-Result.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/slsDetectorSoftware/tests/test-Result.cpp b/slsDetectorSoftware/tests/test-Result.cpp index ceb8f3d07..61a34efdc 100644 --- a/slsDetectorSoftware/tests/test-Result.cpp +++ b/slsDetectorSoftware/tests/test-Result.cpp @@ -142,15 +142,6 @@ TEST_CASE("Result of vectors"){ Result res{vecvec}; } -TEST_CASE("emplace back"){ - std::vector vec{1,2,3,4,5}; - Result> res; - res.emplace_back(vec.begin(), vec.end()); - REQUIRE(res.size() == 1); - REQUIRE(res[0].size() == 5); - REQUIRE(res[0] == vec); -} - TEST_CASE("Free function begin end"){ Result res{"ett", "nio", "sjutton"}; REQUIRE(begin(res) == res.begin()); From d4d8cbe9bc279186c3d08d1585fc43bb1026adaf Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Wed, 14 Aug 2019 09:20:50 +0200 Subject: [PATCH 068/108] gotthard fixed roi only xmin and xmax.remove updateoffsets --- slsDetectorGui/forms/form_tab_advanced.ui | 282 +++++---- slsDetectorGui/include/qTabAdvanced.h | 11 - slsDetectorGui/src/qTabAdvanced.cpp | 190 +----- .../bin/eigerDetectorServer_developer | Bin 302608 -> 302632 bytes .../bin/gotthardDetectorServer_developer | Bin 117024 -> 116980 bytes .../slsDetectorFunctionList.c | 119 ++-- .../slsDetectorServer_defs.h | 1 + .../slsDetectorFunctionList.h | 3 +- .../slsDetectorServer_funcs.c | 111 ++-- .../slsDetectorServer_funcs.h | 1 + slsDetectorSoftware/include/Detector.h | 21 +- .../include/multiSlsDetector.h | 112 +--- slsDetectorSoftware/include/slsDetector.h | 75 +-- .../include/slsDetectorUsers.h | 32 +- slsDetectorSoftware/src/Detector.cpp | 48 +- slsDetectorSoftware/src/multiSlsDetector.cpp | 588 +++--------------- slsDetectorSoftware/src/slsDetector.cpp | 185 ++---- .../src/slsDetectorCommand.cpp | 52 +- slsDetectorSoftware/src/slsDetectorUsers.cpp | 17 +- slsReceiverSoftware/include/DataStreamer.h | 4 +- slsReceiverSoftware/include/GeneralData.h | 35 +- .../include/slsReceiverImplementation.h | 10 +- slsReceiverSoftware/src/DataStreamer.cpp | 6 +- .../src/slsReceiverImplementation.cpp | 51 +- .../src/slsReceiverTCPIPInterface.cpp | 20 +- slsSupportLib/include/sls_detector_defs.h | 12 +- slsSupportLib/include/sls_detector_funcs.h | 2 + slsSupportLib/include/versionAPI.h | 4 +- 28 files changed, 573 insertions(+), 1419 deletions(-) diff --git a/slsDetectorGui/forms/form_tab_advanced.ui b/slsDetectorGui/forms/form_tab_advanced.ui index b6545fd4a..858567f9f 100755 --- a/slsDetectorGui/forms/form_tab_advanced.ui +++ b/slsDetectorGui/forms/form_tab_advanced.ui @@ -54,7 +54,7 @@ QTabWidget::North - 2 + 1 Qt::ElideLeft @@ -132,102 +132,20 @@ Region of Interest - - + + - + 0 0 - - - 130 - 0 - - - Add ROI Slot - - - - :/icons/images/add.png:/icons/images/add.png + X Min: - - - - - 0 - 0 - - - - - 130 - 0 - - - - Get ROI - - - - :/icons/images/download.png:/icons/images/download.png - - - - - - - Qt::Horizontal - - - - 20 - 20 - - - - - - - - Qt::Horizontal - - - - 20 - 20 - - - - - - - - - 0 - 0 - - - - - 130 - 0 - - - - Set ROI - - - - :/icons/images/upload.png:/icons/images/upload.png - - - - + @@ -237,12 +155,12 @@ - 130 - 0 + 0 + 35 - Clear ROI + Clear ROI @@ -250,45 +168,159 @@ - + + + + + 160 + 0 + + + + -1 + + + 1279 + + + -1 + + + + Qt::Horizontal - 20 + 40 20 - - - - QFrame::NoFrame + + + + + 0 + 0 + - - true + + X Max: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 160 + 0 + + + + -1 + + + 1279 + + + -1 + + + + + + + + 0 + 0 + + + + Readout: + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + + 0 + 35 + + + + Set ROI + + + + :/icons/images/refresh.png:/icons/images/refresh.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 160 + 0 + - - - - 0 - 0 - 735 - 235 - - - - - 1 - - - 15 - - - @@ -399,7 +431,7 @@ - Detector Control Port: + Readout Control Port: @@ -910,7 +942,7 @@ - Detector UDP MAC: + Readout UDP MAC: @@ -929,7 +961,7 @@ - Detector: + Readout: @@ -968,7 +1000,7 @@ - Detector UDP IP: + Readout UDP IP: @@ -981,7 +1013,7 @@ - Detector Stop Port: + Readout Stop Port: @@ -1402,11 +1434,11 @@ Exposure Time of a sub frame. Only for Eiger in 32 bit mode tabAdvancedSettings spinSetAllTrimbits - btnAddRoi + comboReadout + spinXmin + spinXmax btnSetRoi - btnGetRoi btnClearRoi - scrollArea comboDetector spinControlPort spinStopPort diff --git a/slsDetectorGui/include/qTabAdvanced.h b/slsDetectorGui/include/qTabAdvanced.h index 921232914..62986e7b9 100755 --- a/slsDetectorGui/include/qTabAdvanced.h +++ b/slsDetectorGui/include/qTabAdvanced.h @@ -29,7 +29,6 @@ private slots: void SetRxrUDPMAC(); void SetRxrZMQPort(int port); void SetRxrZMQIP(); - void AddROISlot(); void GetROI(); void ClearROI(); void SetROI(); @@ -56,22 +55,12 @@ private: void GetRxrUDPMAC(); void GetRxrZMQPort(); void GetRxrZMQIP(); - void ClearROIWidgets(); void GetAllTrimbits(); void GetNumStoragecells(); void GetSubExposureTime(); void GetSubDeadTime(); multiSlsDetector *myDet; - /** ROI */ - std::vector lblFromX; - std::vector spinFromX; - std::vector lblFromY; - std::vector spinFromY; - std::vector lblToX; - std::vector spinToX; - std::vector lblToY; - std::vector spinToY; }; diff --git a/slsDetectorGui/src/qTabAdvanced.cpp b/slsDetectorGui/src/qTabAdvanced.cpp index 72eb07e23..811fd8217 100755 --- a/slsDetectorGui/src/qTabAdvanced.cpp +++ b/slsDetectorGui/src/qTabAdvanced.cpp @@ -10,18 +10,7 @@ qTabAdvanced::qTabAdvanced(QWidget *parent, multiSlsDetector *detector) FILE_LOG(logDEBUG) << "Advanced ready"; } -qTabAdvanced::~qTabAdvanced() { - for (size_t i = 0; i < lblFromX.size(); ++i) { - delete lblFromX[i]; - delete lblFromY[i]; - delete lblToX[i]; - delete lblToY[i]; - delete spinFromX[i]; - delete spinFromY[i]; - delete spinToX[i]; - delete spinToY[i]; - } -} +qTabAdvanced::~qTabAdvanced() {} void qTabAdvanced::SetupWidgetWindow() { // enabling according to det type @@ -93,9 +82,8 @@ void qTabAdvanced::Initialization() { // roi if (tab_roi->isEnabled()) { - connect(btnAddRoi, SIGNAL(clicked()), this, SLOT(AddROISlot())); + connect(comboReadout, SIGNAL(currentIndexChanged(int)), this, SLOT(GetROI())); connect(btnSetRoi, SIGNAL(clicked()), this, SLOT(SetROI())); - connect(btnGetRoi, SIGNAL(clicked()), this, SLOT(GetROI())); connect(btnClearRoi, SIGNAL(clicked()), this, SLOT(ClearROI())); } @@ -122,14 +110,20 @@ void qTabAdvanced::PopulateDetectors() { FILE_LOG(logDEBUG) << "Populating detectors"; disconnect(comboDetector, SIGNAL(currentIndexChanged(int)), this, SLOT(SetDetector(int))); + disconnect(comboReadout, SIGNAL(currentIndexChanged(int)), this, SLOT(GetROI())); comboDetector->clear(); - for (unsigned int i = 0; i < myDet->size(); ++i) + comboReadout->clear(); + for (unsigned int i = 0; i < myDet->size(); ++i) { comboDetector->addItem(QString(myDet->getHostname(i).c_str())); + comboReadout->addItem(QString(myDet->getHostname(i).c_str())); + } comboDetector->setCurrentIndex(0); + comboReadout->setCurrentIndex(0); connect(comboDetector, SIGNAL(currentIndexChanged(int)), this, SLOT(SetDetector(int))); + connect(comboReadout, SIGNAL(currentIndexChanged(int)), this, SLOT(GetROI())); } void qTabAdvanced::GetControlPort() { @@ -462,173 +456,33 @@ void qTabAdvanced::SetRxrZMQIP() { &qTabAdvanced::GetRxrZMQIP) } -void qTabAdvanced::AddROISlot() { - FILE_LOG(logDEBUG) << "Add ROI Slot"; - - QLabel *lFromX = new QLabel("x min:"); - QLabel *lFromY = new QLabel("y min:"); - QLabel *lToX = new QLabel("x max:"); - QLabel *lToY = new QLabel("y max:"); - QSpinBox *sFromX = new QSpinBox(); - QSpinBox *sFromY = new QSpinBox(); - QSpinBox *sToX = new QSpinBox(); - QSpinBox *sToY = new QSpinBox(); - lFromX->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - lFromY->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - lToX->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - lToY->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - sFromX->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - sFromY->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - sToX->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - sToY->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - lFromX->setFixedWidth(50); - lFromY->setFixedWidth(50); - lToX->setFixedWidth(50); - lToY->setFixedWidth(50); - sFromX->setFixedWidth(80); - sFromY->setFixedWidth(80); - sToX->setFixedWidth(80); - sToY->setFixedWidth(80); - sFromX->setFixedHeight(19); - sFromY->setFixedHeight(19); - sToX->setFixedHeight(19); - sToY->setFixedHeight(19); - sFromX->setMaximum(myDet->getTotalNumberOfChannels(slsDetectorDefs::X) - 1); - sToX->setMaximum(myDet->getTotalNumberOfChannels(slsDetectorDefs::X) - 1); - sFromY->setMaximum(myDet->getTotalNumberOfChannels(slsDetectorDefs::Y) - 1); - sToY->setMaximum(myDet->getTotalNumberOfChannels(slsDetectorDefs::Y) - 1); - sFromX->setMinimum(-1); - sToX->setMinimum(-1); - sFromY->setMinimum(-1); - sToY->setMinimum(-1); - sFromX->setValue(-1); - sFromY->setValue(-1); - sToX->setValue(-1); - sToY->setValue(-1); - - lblFromX.push_back(lFromX); - lblFromY.push_back(lFromY); - lblToX.push_back(lToX); - lblToY.push_back(lToY); - spinFromX.push_back(sFromX); - spinFromY.push_back(sFromY); - spinToX.push_back(sToX); - spinToY.push_back(sToY); - - int nroi = (int)lblFromX.size(); - gridRoi->addWidget(lblFromX[nroi], nroi, 0, Qt::AlignTop); - gridRoi->addWidget(spinFromX[nroi], nroi, 1, Qt::AlignTop); - // FIXME: gridRoi->addItem(new - // QSpacerItem(40,20,QSizePolicy::Expanding,QSizePolicy::Fixed), - // nroi,2,Qt::AlignTop); - gridRoi->addWidget(lblToX[nroi], nroi, 3, Qt::AlignTop); - gridRoi->addWidget(spinToX[nroi], nroi, 4, Qt::AlignTop); - // FIXME: gridRoi->addItem(new - // QSpacerItem(40,20,QSizePolicy::Expanding,QSizePolicy::Fixed), - // nroi,5,Qt::AlignTop); - gridRoi->addWidget(lblFromY[nroi], nroi, 6, Qt::AlignTop); - gridRoi->addWidget(spinFromY[nroi], nroi, 7, Qt::AlignTop); - // FIXME: gridRoi->addItem(new - // QSpacerItem(40,20,QSizePolicy::Expanding,QSizePolicy::Fixed), - // nroi,8,Qt::AlignTop); - gridRoi->addWidget(lblToY[nroi], nroi, 9, Qt::AlignTop); - gridRoi->addWidget(spinToY[nroi], nroi, 10, Qt::AlignTop); - - lblFromX[nroi]->show(); - spinFromX[nroi]->show(); - lblToX[nroi]->show(); - spinToX[nroi]->show(); - lblFromY[nroi]->show(); - spinFromY[nroi]->show(); - lblToY[nroi]->show(); - spinToY[nroi]->show(); - - FILE_LOG(logDEBUG) << "ROI Inputs added"; -} - void qTabAdvanced::GetROI() { FILE_LOG(logDEBUG) << "Getting ROI"; - ClearROIWidgets(); - try { - int nroi = 0; - const slsDetectorDefs::ROI *roi = myDet->getROI(nroi); - if (roi != nullptr) { - for (int i = 0; i < nroi; ++i) { - AddROISlot(); - spinFromX[i]->setValue(roi[i].xmin); - spinFromY[i]->setValue(roi[i].ymin); - spinToX[i]->setValue(roi[i].xmax); - spinToY[i]->setValue(roi[i].ymax); - } - FILE_LOG(logDEBUG) << "ROIs populated: " << nroi; - } - + slsDetectorDefs::ROI roi = myDet->getROI(comboReadout->currentIndex()); + spinXmin->setValue(roi.xmin); + spinXmax->setValue(roi.xmax); } CATCH_DISPLAY ("Could not get ROI.", "qTabAdvanced::GetROI") } -void qTabAdvanced::ClearROIWidgets() { - FILE_LOG(logDEBUG) << "Clear ROI Widgets"; - - // hide widgets - QLayoutItem *item; - while ((item = gridRoi->takeAt(0))) { - if (item->widget()) { - item->widget()->hide(); - gridRoi->removeWidget(item->widget()); - } - } - - // delete widgets - for (size_t i = 0; i < lblFromX.size(); ++i) { - delete lblFromX[i]; - delete spinFromX[i]; - delete lblToX[i]; - delete spinToY[i]; - delete lblFromY[i]; - delete spinFromY[i]; - delete lblToY[i]; - delete spinToY[i]; - } - lblFromX.clear(); - spinFromX.clear(); - lblToX.clear(); - spinToY.clear(); - lblFromY.clear(); - spinFromY.clear(); - lblToY.clear(); - spinToY.clear(); -} - void qTabAdvanced::ClearROI() { FILE_LOG(logINFO) << "Clearing ROI"; - if (QMessageBox::warning( - this, "Clear ROI", - "Are you sure you want to clear all the ROI in detector?", - QMessageBox::Yes | QMessageBox::No, - QMessageBox::No) == QMessageBox::Yes) { - - ClearROIWidgets(); - SetROI(); - FILE_LOG(logDEBUG) << "ROIs cleared"; - } + spinXmin->setValue(-1); + spinXmax->setValue(-1); + SetROI(); + FILE_LOG(logDEBUG) << "ROIs cleared"; } void qTabAdvanced::SetROI() { - // get roi from widgets - int nroi = (int)lblFromX.size(); - slsDetectorDefs::ROI roi[nroi]; - for (int i = 0; i < nroi; ++i) { - roi[i].xmin = spinFromX[i]->value(); - roi[i].ymin = spinFromY[i]->value(); - roi[i].xmax = spinToX[i]->value(); - roi[i].ymax = spinToY[i]->value(); - } + + slsDetectorDefs::ROI roi; + roi.xmin = spinXmin->value(); + roi.xmax = spinXmax->value(); // set roi - FILE_LOG(logINFO) << "Setting ROI:" << nroi; + FILE_LOG(logINFO) << "Setting ROI: [" << roi.xmin << ", " << roi.xmax << "]"; try { - myDet->setROI(nroi, roi, -1); + myDet->setROI(roi, comboReadout->currentIndex()); } CATCH_DISPLAY ("Could not set these ROIs.", "qTabAdvanced::SetROI") diff --git a/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer b/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer index f79ce81f4e10757be6b2c605237aed6d07bc9d3f..58a992a6c86049b59c114161da0d46ad08fde533 100755 GIT binary patch delta 44635 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%0Aw?N63K)d%vfD&uyqC_52n_G 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 RrE=5G@@>914>;Du{y#I17b^e& delta 45927 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 PB^vcgv5RWbLVErmYT*%r delta 50976 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 diff --git a/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c index 6f7ce88b4..a0b0807d5 100755 --- a/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c @@ -37,8 +37,7 @@ int digitalTestBit = 0; // roi configuration int adcConfigured = -1; -ROI rois[MAX_ROIS]; -int nROI = 0; +ROI rois; int ipPacketSize = 0; int udpPacketSize = 0; @@ -397,7 +396,9 @@ void setupDetector() { bus_w(TEMP_SPI_OUT_REG, 0x0); // roi, gbit readout - setROIADC(-1); // set adcsyncreg, daqreg, chipofinterestreg, cleanfifos, + rois.xmin = -1; + rois.xmax = -1; + setROI(rois);// set adcsyncreg, daqreg, chipofinterestreg, cleanfifos, setGbitReadout(); // master, slave (25um) @@ -726,95 +727,49 @@ int setDynamicRange(int dr){ return DYNAMIC_RANGE; } -ROI* setROI(int n, ROI arg[], int *retvalsize, int *ret) { +int setROI(ROI arg) { - // set ROI - if(n >= 0){ - // print - if (!n) { - FILE_LOG(logINFO, ("Clearing ROI\n")); - } else { - FILE_LOG(logINFO, ("Setting ROI:\n")); - int i = 0; - for (i = 0; i < n; ++i) { - FILE_LOG(logINFO, ("\t(%d, %d)\n", arg[i].xmin, arg[i].xmax)); - } + int adc = -1; + if (arg.xmin == -1) { + FILE_LOG(logINFO, ("Clearing ROI\n")); + rois.xmin = -1; + rois.xmax = -1; + } else { + FILE_LOG(logINFO, ("Setting ROI:(%d, %d)\n", arg.xmin, arg.xmax)); + // validation + // xmin divisible by 256 and less than 1280 + if (((arg.xmin % NCHAN_PER_ADC) != 0) || (arg.xmin >= (NCHAN * NCHIP))) { + FILE_LOG(logERROR, ("Could not set roi. xmin is invalid\n")); + return FAIL; } - // only one ROI allowed per module - if (n > 1) { - FILE_LOG(logERROR, ("\tCannot set more than 1 ROI per module\n")); - *ret = FAIL; - *retvalsize = nROI; - return rois; + // xmax must be 255 more than xmin + if (arg.xmax != (arg.xmin + NCHAN_PER_ADC - 1)) { + FILE_LOG(logERROR, ("Could not set roi. xmax is invalid\n")); + return FAIL; } + rois.xmin = arg.xmin; + rois.xmax = arg.xmax; + adc = arg.xmin / NCHAN_PER_ADC; + } + FILE_LOG(logINFO, ("\tAdc to be configured: %d\n", adc)); + FILE_LOG(logINFO, ("\tROI to be configured: (%d, %d)\n", + (adc == -1) ? 0 : (rois.xmin), + (adc == -1) ? (NCHIP * NCHAN - 1) : (rois.xmax))); - //clear all rois - nROI = 0; + //set adc of interest + setROIADC(adc); + return OK; +} - // find adc number and recorrect channel limits - int adc = -1; - if (n) { - // all channels - if ((arg[0].xmin <= 0) && (arg[0].xmax >= NCHIP * NCHAN)) - adc = -1; - // single adc - else { - //adc = mid value/numchans - adc = ((((arg[0].xmax) + (arg[0].xmin))/2) / (NCHAN * NCHIPS_PER_ADC)); - // incorrect adc - if((adc < 0) || (adc > 4)) { - FILE_LOG(logERROR, ("\tadc value greater than 5. deleting roi\n")); - adc = -1; - } - // recorrect roi values - else { - rois[0].xmin = adc * (NCHAN * NCHIPS_PER_ADC); - rois[0].xmax = (adc + 1) * (NCHAN * NCHIPS_PER_ADC) - 1; - rois[0].ymin = -1; - rois[0].ymax = -1; - nROI = 1; - } - } - } - - if (adc == -1) - nROI = 0; - - FILE_LOG(logINFO, ("\tAdc to be configured: %d\n", adc)); - FILE_LOG(logINFO, ("\tROI to be configured: (%d, %d)\n", - (adc == -1) ? 0 : (rois[0].xmin), - (adc == -1) ? (NCHIP * NCHAN - 1) : (rois[0].xmax))); - - // could not set roi - if((n != 0) && ((arg[0].xmin != rois[0].xmin)|| - (arg[0].xmax != rois[0].xmax)|| - (arg[0].ymin != rois[0].ymin)|| - (arg[0].ymax != rois[0].ymax))) { - *ret = FAIL; - FILE_LOG(logERROR, ("\tCould not set given ROI\n")); - } - if(n != nROI) { - *ret = FAIL; - FILE_LOG(logERROR, ("\tCould not set or clear ROIs\n")); - } - - //set adc of interest - setROIADC(adc); - } else FILE_LOG(logINFO, ("Getting ROI:\n")); +ROI getROI() { + FILE_LOG(logINFO, ("Getting ROI:\n")); // print - if (!nROI) { + if (rois.xmin == -1) { FILE_LOG(logINFO, ("\tROI: None\n")); } else { - FILE_LOG(logINFO, ("ROI:\n")); - int i = 0; - for (i = 0; i < nROI; ++i) { - FILE_LOG(logINFO, ("\t(%d, %d)\n", rois[i].xmin, rois[i].xmax)); - - } + FILE_LOG(logINFO, ("ROI: (%d,%d)\n", rois.xmin, rois.xmax)); } - - *retvalsize = nROI; return rois; } diff --git a/slsDetectorServers/gotthardDetectorServer/slsDetectorServer_defs.h b/slsDetectorServers/gotthardDetectorServer/slsDetectorServer_defs.h index 6c037e852..16e1142cb 100755 --- a/slsDetectorServers/gotthardDetectorServer/slsDetectorServer_defs.h +++ b/slsDetectorServers/gotthardDetectorServer/slsDetectorServer_defs.h @@ -24,6 +24,7 @@ enum DACINDEX {VREF_DS, VCASCN_PB, VCASCP_PB, VOUT_CM, VCASC_OUT, VIN #define NCHIP (10) #define NDAC (8) #define NCHIPS_PER_ADC (2) +#define NCHAN_PER_ADC (256) #define DYNAMIC_RANGE (16) #define NUM_BITS_PER_PIXEL (DYNAMIC_RANGE / 8) #define DATA_BYTES (NCHIP * NCHAN * NUM_BITS_PER_PIXEL) diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h b/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h index fd4ca2898..7038b6135 100755 --- a/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h +++ b/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h @@ -114,7 +114,8 @@ void resetPeripheral(); // parameters - dr, roi int setDynamicRange(int dr); #ifdef GOTTHARDD -ROI* setROI(int n, ROI arg[], int *retvalsize, int *ret); +int setROI(ROI arg); +ROI getROI(); #endif #if defined(CHIPTESTBOARDD) || defined(MOENCHD) int setADCEnableMask(uint32_t mask); diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c index 4b98305cc..542af9d48 100755 --- a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c +++ b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c @@ -189,6 +189,7 @@ const char* getFunctionName(enum detFuncs func) { case F_SET_DYNAMIC_RANGE: return "F_SET_DYNAMIC_RANGE"; case F_SET_READOUT_FLAGS: return "F_SET_READOUT_FLAGS"; case F_SET_ROI: return "F_SET_ROI"; + case F_GET_ROI: return "F_GET_ROI"; case F_SET_SPEED: return "F_SET_SPEED"; case F_EXIT_SERVER: return "F_EXIT_SERVER"; case F_LOCK_SERVER: return "F_LOCK_SERVER"; @@ -279,6 +280,7 @@ void function_table() { flist[F_SET_DYNAMIC_RANGE] = &set_dynamic_range; flist[F_SET_READOUT_FLAGS] = &set_readout_flags; flist[F_SET_ROI] = &set_roi; + flist[F_GET_ROI] = &get_roi; flist[F_SET_SPEED] = &set_speed; flist[F_EXIT_SERVER] = &exit_server; flist[F_LOCK_SERVER] = &lock_server; @@ -1896,76 +1898,49 @@ int set_readout_flags(int file_des) { int set_roi(int file_des) { ret = OK; memset(mess, 0, sizeof(mess)); - int narg = -1; - ROI arg[MAX_ROIS]; - int nretval = -1; - ROI* retval = NULL; + ROI arg; - // receive number of ROIs - if (receiveData(file_des, &narg, sizeof(narg), INT32) < 0) + // receive ROI + if (receiveData(file_des, &arg.xmin, sizeof(int), INT32) < 0) return printSocketReadError(); - // receive ROIs - { - int iloop = 0; - for (iloop = 0; iloop < narg; ++iloop) { - if (receiveData(file_des, &arg[iloop].xmin, sizeof(int), INT32) < 0) - return printSocketReadError(); - if (receiveData(file_des, &arg[iloop].xmax, sizeof(int), INT32) < 0) - return printSocketReadError(); - if (receiveData(file_des, &arg[iloop].ymin, sizeof(int), INT32) < 0) - return printSocketReadError(); - if (receiveData(file_des, &arg[iloop].ymax, sizeof(int), INT32) < 0) - return printSocketReadError(); - } - } - FILE_LOG(logDEBUG1, ("Set ROI (narg:%d)\n", narg)); - { - int iloop = 0; - for (iloop = 0; iloop < narg; ++iloop) { - FILE_LOG(logDEBUG1, ("%d: %d\t%d\t%d\t%d\n", - arg[iloop].xmin, arg[iloop].xmax, arg[iloop].ymin, arg[iloop].ymax)); - } - } + if (receiveData(file_des, &arg.xmax, sizeof(int), INT32) < 0) + return printSocketReadError(); + FILE_LOG(logDEBUG1, ("Set ROI: [%d, %d]\n", arg.xmin, arg.xmax)); #ifndef GOTTHARDD functionNotImplemented(); #else - // set & get - if ((narg == GET_READOUT_FLAGS) || (Server_VerifyLock() == OK)) { - if (myDetectorType == GOTTHARD && narg > 1) { - ret = FAIL; - strcpy(mess,"Can not set more than one ROI per module.\n"); - FILE_LOG(logERROR,(mess)); - } else { - retval = setROI(narg, arg, &nretval, &ret); - if (ret == FAIL) { - if (nretval == -1) // chip test board - sprintf(mess,"Could not set ROI. Max ROI level (100) reached!\n"); - else if (nretval == -2) - sprintf(mess, "Could not set ROI. Could not allocate RAM\n"); - else - sprintf(mess,"Could not set all roi. " - "Set %d rois, but read %d rois\n", narg, nretval); - FILE_LOG(logERROR,(mess)); - } - FILE_LOG(logDEBUG1, ("nRois: %d\n", nretval)); - } + // only set + if (Server_VerifyLock() == OK) { + ret = setROI(arg); + if (ret == FAIL) { + sprintf(mess, "Could not set ROI. Invalid xmin or xmax\n"); + FILE_LOG(logERROR,(mess)); + } } #endif - Server_SendResult(file_des, INT32, UPDATE, NULL, 0); + return Server_SendResult(file_des, INT32, UPDATE, NULL, 0); +} + +int get_roi(int file_des) { + ret = OK; + memset(mess, 0, sizeof(mess)); + ROI retval; + +#ifndef GOTTHARDD + functionNotImplemented(); +#else + // only get + retval = getROI(); + FILE_LOG(logDEBUG1, ("nRois: (%d, %d)\n", retval.xmin, retval.xmax)); +#endif + + Server_SendResult(file_des, INT32, UPDATE, NULL, 0); if (ret != FAIL) { - //retvalsize could be swapped during sendData - int nretval1 = nretval; - sendData(file_des, &nretval1, sizeof(nretval1), INT32); - int iloop = 0; - for(iloop = 0; iloop < nretval; ++iloop) { - sendData(file_des, &retval[iloop].xmin, sizeof(int), INT32); - sendData(file_des, &retval[iloop].xmax, sizeof(int), INT32); - sendData(file_des, &retval[iloop].ymin, sizeof(int), INT32); - sendData(file_des, &retval[iloop].ymax, sizeof(int), INT32); - } + sendData(file_des, &retval.xmin, sizeof(int), INT32); + sendData(file_des, &retval.xmax, sizeof(int), INT32); } return ret; } @@ -1973,7 +1948,6 @@ int set_roi(int file_des) { - int set_speed(int file_des) { ret = OK; memset(mess, 0, sizeof(mess)); @@ -2284,20 +2258,9 @@ int send_update(int file_des) { // roi #if defined(GOTTHARDD) - ROI* retval = NULL; - ROI arg[1]; - int ret = OK, nretval = 0; - retval = setROI(-1, arg, &nretval, &ret); - //retvalsize could be swapped during sendData - int nretval1 = nretval; - sendData(file_des, &nretval1, sizeof(nretval1), INT32); - int iloop = 0; - for(iloop = 0; iloop < nretval; ++iloop) { - sendData(file_des, &retval[iloop].xmin, sizeof(int), INT32); - sendData(file_des, &retval[iloop].xmax, sizeof(int), INT32); - sendData(file_des, &retval[iloop].ymin, sizeof(int), INT32); - sendData(file_des, &retval[iloop].ymax, sizeof(int), INT32); - } + ROI retval = getROI(); + sendData(file_des, &retval.xmin, sizeof(int), INT32); + sendData(file_des, &retval.xmax, sizeof(int), INT32); #endif #if defined(CHIPTESTBOARDD) || defined(MOENCHD) diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.h b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.h index 66ed015c7..26c889650 100755 --- a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.h +++ b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.h @@ -49,6 +49,7 @@ int get_time_left(int); int set_dynamic_range(int); int set_readout_flags(int); int set_roi(int); +int get_roi(int); int set_speed(int); int exit_server(int); int lock_server(int); diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 824b11bb3..08eb14955 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -82,16 +82,10 @@ class Detector { /** * Sets the maximum number of channels of complete detector in both * dimensions. -1 means no limit in this dimension. This value is used to - * calculate row and column offsets for each module. + * calculate row and column channels for each module. */ void setMaxNumberOfChannels(const defs::coordinates value); - /** [Gotthard] */ - Result getDetectorOffsets(Positions pos = {}) const; - - /** [Gotthard] */ - void setDetectorOffsets(defs::coordinates value, Positions pos = {}); - /** [Eiger with specific quad hardware] */ Result getQuad(Positions pos = {}) const; @@ -664,15 +658,16 @@ class Detector { /** [Eiger] If it is set, it resets chips completely (else partially) before an acquisition TODO: if it makes sense */ void setCounterBit(bool value, Positions pos = {}); - /** [Gotthard, CTB]*/ - Result> getROI(Positions pos = {}) const; + /** [Gotthard]*/ + Result getROI(Positions pos = {}) const; /** - * [Gotthard Options: Only a single chip or all chips, only 1 ROI allowed] - * [CTB: multiple ROIs allowed] - * subset modules not allowed + * [Gotthard] + * Options: Only a single ROI per module + * Can set only a single ROI at a time + * @param module position index */ - void setROI(std::vector value, Positions pos = {}); + void setROI(defs::ROI value, int moduleId); /** [CTB]*/ Result getADCEnableMask(Positions pos = {}) const; diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 611d93ae3..c24a00cd9 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -65,16 +65,6 @@ struct sharedMultiSlsDetector { /** total number of channels including gap pixels in one dimension */ int numberOfChannelInclGapPixels[2]; - /** total number of channels for all detectors */ - int maxNumberOfChannels; - - /** max number of channels for all detectors in one dimension*/ - int maxNumberOfChannel[2]; - - /** max number of channels including gap pixels for all detectors in - * one dimension*/ - int maxNumberOfChannelInclGapPixels[2]; - /** max number of channels allowed for the complete set of detectors in * one dimension */ int maxNumberOfChannelsPerDetector[2]; @@ -432,8 +422,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { /** * Returns the maximum number of channels of all sls detectors in each - * dimension d from shared memory. multi detector shared memory variable to - * calculate offsets for each sls detector + * dimension d from shared memory. * @param d dimension d * @returns the maximum number of channels of all sls detectors in dimension * d @@ -442,8 +431,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { /** * Sets the maximum number of channels of all sls detectors in each - * dimension d from shared memory, multi detector shared memory variable to - * calculate offsets for each sls detector + * dimension d from shared memory * @param d dimension d * @param i maximum number of channels for multi structure in dimension d * @returns the maximum number of channels of all sls detectors in dimension @@ -453,37 +441,18 @@ class multiSlsDetector : public virtual slsDetectorDefs { /** * Returns maximum number of channels of all sls detectors in each - * dimension d from shared memory, multi detector shared memory variable to - * calculate offsets for each sls detector + * dimension d from shared memory * @returns maximum number of channels of all sls detectors */ slsDetectorDefs::coordinates getMaxNumberOfChannels() const; // /** * Sets maximum number of channels of all sls detectors in each - * dimension d from shared memory, multi detector shared memory variable to - * calculate offsets for each sls detector + * dimension d from shared memory * @param c maximum number of channels of all sls detectors */ void setMaxNumberOfChannels(const slsDetectorDefs::coordinates c); // - /** - * Get Detector offset from shared memory in dimension d - * @param d dimension d - * @param detPos -1 for all detectors in list or specific detector position - * @returns offset in dimension d, -1 if pos is not an actual position in - * list - */ - int getDetectorOffset(dimension d, int detPos = -1); // - - /** - * Set Detector offset in shared memory in dimension d - * @param d dimension d - * @param off offset for detector - * @param detPos -1 for all detectors in list or specific detector position - */ - void setDetectorOffset(dimension d, int off, int detPos = -1);// - /** * Get Quad Type (Only for Eiger Quad detector hardware) * @param detPos -1 for all detectors in list or specific detector position @@ -1376,22 +1345,27 @@ class multiSlsDetector : public virtual slsDetectorDefs { int setCounterBit(int i = -1, int detPos = -1); // /** - * Set ROI (Gotthard) - * At the moment only one set allowed - * @param n number of rois - * @param roiLimits array of roi + * Clear ROI (Gotthard) * @param detPos -1 for all detectors in list or specific detector position */ - void setROI(int n = -1, ROI roiLimits[] = nullptr, int detPos = -1); + void clearROI(int detPos = -1); /** - * Get ROI from each detector and convert it to the multi detector scale - * (Gotthard) - * @param n number of rois - * @param detPos -1 for all detectors in list or specific detector position - * @returns OK or FAIL + * Set ROI (Gotthard) + * At the moment only one set allowed per module + * Only allowed to set one ROI per module + * @param arg roi + * @param detPos specific detector position */ - const ROI *getROI(int &n, int detPos = -1); + void setROI(slsDetectorDefs::ROI arg, int detPos = -1); + + /** + * Get ROI (Gotthard) + * Only allowed to set one ROI per module + * @param detPos specific detector position + * @returns roi + */ + slsDetectorDefs::ROI getROI(int detPos) const; /** * Set ADC Enable Mask (CTB, Moench) @@ -2187,14 +2161,6 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ void initializeMembers(bool verify = true); - /** - * Appends detectors to the end of the list in shared memory - * Connects to them - * @param name concatenated hostname of the sls detectors to be appended to - * the list - */ - void addMultipleDetectors(const char *name);// - /** * Update user details in detector structure */ @@ -2206,23 +2172,6 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ bool isAcquireReady(); - /** - * Decodes which detector and the corresponding channel numbers for it - * Mainly useful in a multi detector setROI (Gotthard) - * @param offsetX channel number or total channel offset in x direction - * @param offsetY channel number or total channel offset in y direction - * @param channelX channel number from detector offset in x direction - * @param channelY channel number from detector offset in x direction - * @returns detector id or -1 if channel number out of range - */ - int decodeNChannel(int offsetX, int offsetY, int &channelX, int &channelY); - - /** - * Updates the channel offsets in X and Y dimension for all the sls - * detectors It is required for decodeNMod and setting ROI - */ - void updateOffsets(); - /** * Execute in command line and return result * @param cmd command @@ -2230,12 +2179,26 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ std::string exec(const char *cmd); + /** + * Appends detectors to the end of the list in shared memory + * Connects to them + * @param name concatenated hostname of the sls detectors to be appended to + * the list + */ + void addMultipleDetectors(const char *name);// + /** * Add sls detector * @param s hostname of the single detector */ void addSlsDetector(const std::string &hostname); + /** + * Updates the channel size in X and Y dimension for all the sls + * detectors + */ + void updateDetectorSize(); + /** * increments file index * @param detPos -1 for all detectors in list or specific detector position @@ -2243,13 +2206,6 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ int incrementFileIndex(int detPos = -1); - /** - * Ensures that min is less than max in both dimensions (Gotthard) - * @param n number of rois - * @param r array of rois - */ - void verifyMinMaxROI(int n, ROI r[]); - /** * add gap pixels to the image (only for Eiger in 4 bit mode) * @param image pointer to image without gap pixels diff --git a/slsDetectorSoftware/include/slsDetector.h b/slsDetectorSoftware/include/slsDetector.h index 269e8cdc7..de23d310d 100755 --- a/slsDetectorSoftware/include/slsDetector.h +++ b/slsDetectorSoftware/include/slsDetector.h @@ -13,7 +13,7 @@ class ServerInterface; #define SLS_SHMAPIVERSION 0x190726 -#define SLS_SHMVERSION 0x190726 +#define SLS_SHMVERSION 0x190813 /** * @short structure allocated in shared memory to store detector settings for @@ -35,10 +35,6 @@ struct sharedSlsDetector { /** END OF FIXED PATTERN -----------------------------------------------*/ - /** Detector offset in the X & Y direction in the multi detector structure - */ - int offset[2]; - /** Number of detectors in multi list in x dir and y dir */ int multiSize[2]; @@ -75,11 +71,8 @@ struct sharedSlsDetector { /** size of the data that are transfered from the detector */ int dataBytes; - /** number of rois defined */ - int nROI; - - /** list of rois */ - slsDetectorDefs::ROI roiLimits[MAX_ROIS]; + /** roi */ + slsDetectorDefs::ROI roi; /** adc enable mask */ uint32_t adcEnableMask; @@ -339,7 +332,7 @@ class slsDetector : public virtual slsDetectorDefs { /** * Update total number of channels (chiptestboard or moench) - * depending on the number of samples, roi, readout flags(ctb) + * depending on the number of samples, adenablemask, readout flags(ctb) */ void updateTotalNumberOfChannels(); @@ -423,32 +416,6 @@ class slsDetector : public virtual slsDetectorDefs { */ int getReadNLines(); - /** - * Get Detector offset from shared memory in dimension d - * @param d dimension d - * @returns offset in dimension d - */ - int getDetectorOffset(dimension d) const; - - /** - * Get Detector offset from shared memory in dimension d - * @returns offset - */ - slsDetectorDefs::coordinates getDetectorOffsets() const; - - /** - * Set Detector offset in shared memory in dimension d - * @param d dimension d - * @param off offset for detector - */ - void setDetectorOffset(dimension d, int off); - - /** - * Set Detector offset in shared memory - * @param value offset for detector - */ - void setDetectorOffsets(slsDetectorDefs::coordinates value); - /** * Set Detector offset in shared memory in dimension d * @param detx number of detectors in X dir in multi list @@ -1143,35 +1110,29 @@ class slsDetector : public virtual slsDetectorDefs { */ int setCounterBit(int cb = -1); + /** + * Clear ROI (Gotthard) + */ + void clearROI(); + /** * Set ROI (Gotthard) - * At the moment only one set allowed - * @param n number of rois - * @param roiLimits array of roi + * Also calls configuremac + * @param arg roi */ - void setROI(int n = -1, ROI roiLimits[] = nullptr); + void setROI(slsDetectorDefs::ROI arg); /** - * Get ROI from each detector and convert it to the multi detector scale - * (Gotthard) - * @param n number of rois - * @returns OK or FAIL + * Send ROI from shared memory to Receiver (Gotthard) */ - const slsDetectorDefs::ROI *getROI(int &n); + void sendROItoReceiver(); /** - * Returns number of rois - * @returns number of ROIs + * Get ROI (Gotthard) + * Update receiver if different from shm + * @returns roi */ - int getNRoi(); - - /** - * Send ROI to the detector after calculating - * from setROI - * @param n number of ROIs (-1 to get) - * @param roiLimits ROI - */ - void sendROI(int n = -1, ROI roiLimits[] = nullptr); + slsDetectorDefs::ROI getROI(); /** * Set ADC Enable Mask (CTB, Moench) diff --git a/slsDetectorSoftware/include/slsDetectorUsers.h b/slsDetectorSoftware/include/slsDetectorUsers.h index 734aabbc8..742d574cf 100755 --- a/slsDetectorSoftware/include/slsDetectorUsers.h +++ b/slsDetectorSoftware/include/slsDetectorUsers.h @@ -104,7 +104,7 @@ public: /** * Returns the maximum number of channels of all detectors * (provided by user in config file using detsizechan command) - * Offsets are calculated according to these dimensions + * number of channels in x and y are calculated according to these dimensions * @param nx number of channels in horizontal * @param ny number of channels in vertical * @returns the maximum number of channels of all detectors @@ -112,15 +112,13 @@ public: int getMaximumDetectorSize(int &nx, int &ny); /** - * Returns the size and offsets of detector/multi detector - * @param x horizontal position origin in channel number - * @param y vertical position origin in channel number + * Returns the size of detector/multi detector * @param nx number of channels in horiziontal * @param ny number of channels in vertical * @param detPos -1 for all detectors in list or specific detector position * @returns the total number of channels of all sls detectors */ - int getDetectorSize(int &x, int &y, int &nx, int &ny, int detPos = -1); + int getDetectorSize(int &nx, int &ny, int detPos); /** * Gets detector type @@ -496,22 +494,22 @@ public: int setFlowControl10G(int enable = -1, int detPos = -1); /** - * Set ROI (Gotthard) (>= 1 roi, but max 1 roi per module) - * At the moment only one set allowed - * @param n number of rois - * @param roiLimits array of roi - * @param detPos -1 for all detectors in list or specific detector position + * Set ROI (Gotthard) + * At the moment only one set allowed per module + * Only allowed to set one ROI per module + * @param arg roi + * @param detPos specific detector position */ - void setROI(int n=-1, slsDetectorDefs::ROI roiLimits[]=NULL, int detPos = -1); + void setROI(slsDetectorDefs::ROI arg, int detPos = -1); + /** - * Get ROI from each detector and convert it to the multi detector scale (Gotthard) - * >= 1 roi, but max 1 roi per module - * @param n number of rois - * @param detPos -1 for all detectors in list or specific detector position - * @returns pointer to array of ROI structure + * Get ROI (Gotthard) + * Only allowed to set one ROI per module + * @param detPos specific detector position + * @returns roi */ - const slsDetectorDefs::ROI* getROI(int &n, int detPos = -1); + slsDetectorDefs::ROI getROI(int detPos = -1); diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 81dc9792a..b35e7223a 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -110,16 +110,6 @@ void Detector::setMaxNumberOfChannels(const defs::coordinates value) { pimpl->setMaxNumberOfChannels(value); } -Result Detector::getDetectorOffsets(Positions pos) const { - return pimpl->Parallel(&slsDetector::getDetectorOffsets, pos); -} - -void Detector::setDetectorOffsets(defs::coordinates value, Positions pos) { - pimpl->Parallel(&slsDetector::setDetectorOffsets, pos, value); - // pimpl->Parallel(&slsDetector::setDetectorOffset, pos, - // value); -} - Result Detector::getQuad(Positions pos) const { return pimpl->Parallel(&slsDetector::getQuad, pos); } @@ -1071,41 +1061,15 @@ void Detector::setCounterBit(bool value, Positions pos) { pimpl->Parallel(&slsDetector::setCounterBit, pos, value); } -Result> Detector::getROI(Positions pos) const { - //vector holding module_id for the modules that should be read - const std::vector id_vec = [&]() { - if (pos.empty() || (pos.size() == 1 && pos[0] == -1)){ - std::vector tmp; - for(size_t i=0; i!= pimpl->size(); ++i) - tmp.push_back(i); - return tmp; - }else{ - return pos; - } - }(); - - - //values to return - Result> res; - - //for each detector id get the ROI - for (const auto& i :id_vec){ - int n = 0; - auto ptr = pimpl->getROI(n, i); - // res.emplace_back(ptr, ptr+n); - } - return res; +Result Detector::getROI(Positions pos) const { + return pimpl->Parallel(&slsDetector::getROI, pos); } -void Detector::setROI(std::vector value, Positions pos) { - if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) { - pimpl->setROI(static_cast(value.size()), value.data(), -1); - } else if (pos.size() > 1) { - throw RuntimeError("Cannot set roi to a subset of modules"); - } else { - pimpl->Parallel(&slsDetector::setROI, pos, - static_cast(value.size()), value.data()); +void Detector::setROI(defs::ROI value, int moduleId) { + if (moduleId < 0 && size() > 1) { + throw RuntimeError("Cannot set ROI for all modules simultaneously"); } + pimpl->Parallel(&slsDetector::setROI, {moduleId}, value); } Result Detector::getADCEnableMask(Positions pos) const { diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index ef1f9c1e1..1dd184d87 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -283,8 +283,8 @@ void multiSlsDetector::initializeDetectorStructure() { multi_shm()->numberOfChannel[Y] = 0; multi_shm()->numberOfChannelInclGapPixels[X] = 0; multi_shm()->numberOfChannelInclGapPixels[Y] = 0; - multi_shm()->maxNumberOfChannelsPerDetector[X] = 0; - multi_shm()->maxNumberOfChannelsPerDetector[Y] = 0; + multi_shm()->maxNumberOfChannelsPerDetector[X] = -1; + multi_shm()->maxNumberOfChannelsPerDetector[Y] = -1; multi_shm()->acquiringFlag = false; multi_shm()->receiver_upstream = false; } @@ -303,9 +303,6 @@ void multiSlsDetector::initializeMembers(bool verify) { throw; } } - - // depend on number of detectors - updateOffsets(); } void multiSlsDetector::updateUserdetails() { @@ -333,197 +330,6 @@ bool multiSlsDetector::isAcquireReady() { return OK != 0u; } -int multiSlsDetector::decodeNChannel(int offsetX, int offsetY, int &channelX, - int &channelY) { - channelX = -1; - channelY = -1; - // loop over - for (size_t i = 0; i < detectors.size(); ++i) { - int x = detectors[i]->getDetectorOffset(X); - int y = detectors[i]->getDetectorOffset(Y); - // check x offset range - if ((offsetX >= x) && - (offsetX < - (x + detectors[i]->getTotalNumberOfChannelsInclGapPixels(X)))) { - if (offsetY == -1) { - channelX = offsetX - x; - return i; - } else { - // check y offset range - if ((offsetY >= y) && - (offsetY < - (y + detectors[i]->getTotalNumberOfChannelsInclGapPixels( - Y)))) { - channelX = offsetX - x; - channelY = offsetY - y; - return i; - } - } - } - } - return -1; -} - -void multiSlsDetector::updateOffsets() { - FILE_LOG(logDEBUG1) << "Updating Multi-Detector Offsets"; - - int offsetX = 0, offsetY = 0, numX = 0, numY = 0; - int maxChanX = multi_shm()->maxNumberOfChannelsPerDetector[X]; - int maxChanY = multi_shm()->maxNumberOfChannelsPerDetector[Y]; - int prevChanX = 0; - int prevChanY = 0; - bool firstTime = true; - - multi_shm()->numberOfChannel[X] = 0; - multi_shm()->numberOfChannel[Y] = 0; - multi_shm()->numberOfDetector[X] = 0; - multi_shm()->numberOfDetector[Y] = 0; - - // gap pixels - int offsetX_gp = 0, offsetY_gp = 0, numX_gp = 0, numY_gp = 0; - int prevChanX_gp = 0, prevChanY_gp = 0; - multi_shm()->numberOfChannelInclGapPixels[X] = 0; - multi_shm()->numberOfChannelInclGapPixels[Y] = 0; - - for (size_t idet = 0; idet < detectors.size(); ++idet) { - FILE_LOG(logDEBUG1) - << "offsetX:" << offsetX << " prevChanX:" << prevChanX - << " offsetY:" << offsetY << " prevChanY:" << prevChanY - << " offsetX_gp:" << offsetX_gp << " prevChanX_gp:" << prevChanX_gp - << " offsetY_gp:" << offsetY_gp << " prevChanY_gp:" << prevChanY_gp; - - // incrementing in both direction - if (firstTime) { - // incrementing in both directions - firstTime = false; - if ((maxChanX > 0) && - ((offsetX + detectors[idet]->getTotalNumberOfChannels(X)) > - maxChanX)) { - FILE_LOG(logWARNING) - << "\nDetector[" << idet - << "] exceeds maximum channels " - "allowed for complete detector set in X dimension!"; - } - if ((maxChanY > 0) && - ((offsetY + detectors[idet]->getTotalNumberOfChannels(Y)) > - maxChanY)) { - FILE_LOG(logERROR) - << "\nDetector[" << idet - << "] exceeds maximum channels " - "allowed for complete detector set in Y dimension!"; - } - prevChanX = detectors[idet]->getTotalNumberOfChannels(X); - prevChanY = detectors[idet]->getTotalNumberOfChannels(Y); - prevChanX_gp = - detectors[idet]->getTotalNumberOfChannelsInclGapPixels(X); - prevChanY_gp = - detectors[idet]->getTotalNumberOfChannelsInclGapPixels(Y); - numX += detectors[idet]->getTotalNumberOfChannels(X); - numY += detectors[idet]->getTotalNumberOfChannels(Y); - numX_gp += - detectors[idet]->getTotalNumberOfChannelsInclGapPixels(X); - numY_gp += - detectors[idet]->getTotalNumberOfChannelsInclGapPixels(Y); - ++multi_shm()->numberOfDetector[X]; - ++multi_shm()->numberOfDetector[Y]; - FILE_LOG(logDEBUG1) << "incrementing in both direction"; - } - - // incrementing in y direction - else if ((maxChanY == -1) || - ((maxChanY > 0) && ((offsetY + prevChanY + - detectors[idet]->getTotalNumberOfChannels( - Y)) <= maxChanY))) { - offsetY += prevChanY; - offsetY_gp += prevChanY_gp; - prevChanY = detectors[idet]->getTotalNumberOfChannels(Y); - prevChanY_gp = - detectors[idet]->getTotalNumberOfChannelsInclGapPixels(Y); - numY += detectors[idet]->getTotalNumberOfChannels(Y); - numY_gp += - detectors[idet]->getTotalNumberOfChannelsInclGapPixels(Y); - // increment in y again only in the first column (else you double - // increment) - if (multi_shm()->numberOfDetector[X] == 1) - ++multi_shm()->numberOfDetector[Y]; - FILE_LOG(logDEBUG1) << "incrementing in y direction"; - } - - // incrementing in x direction - else { - if ((maxChanX > 0) && - ((offsetX + prevChanX + - detectors[idet]->getTotalNumberOfChannels(X)) > maxChanX)) { - FILE_LOG(logDEBUG1) - << "\nDetector[" << idet - << "] exceeds maximum channels " - "allowed for complete detector set in X dimension!"; - } - offsetY = 0; - offsetY_gp = 0; - prevChanY = detectors[idet]->getTotalNumberOfChannels(Y); - prevChanY_gp = - detectors[idet]->getTotalNumberOfChannelsInclGapPixels(Y); - numY = 0; // assuming symmetry with this statement. - // whats on 1st column should be on 2nd column - numY_gp = 0; - offsetX += prevChanX; - offsetX_gp += prevChanX_gp; - prevChanX = detectors[idet]->getTotalNumberOfChannels(X); - prevChanX_gp = - detectors[idet]->getTotalNumberOfChannelsInclGapPixels(X); - numX += detectors[idet]->getTotalNumberOfChannels(X); - numX_gp += - detectors[idet]->getTotalNumberOfChannelsInclGapPixels(X); - ++multi_shm()->numberOfDetector[X]; - FILE_LOG(logDEBUG1) << "incrementing in x direction"; - } - - double bytesperchannel = - (double)detectors[idet]->getDataBytes() / - (double)(detectors[idet]->getTotalNumberOfChannels(X) * - detectors[idet]->getTotalNumberOfChannels(Y)); - detectors[idet]->setDetectorOffset( - X, (bytesperchannel >= 1.0) ? offsetX_gp : offsetX); - detectors[idet]->setDetectorOffset( - Y, (bytesperchannel >= 1.0) ? offsetY_gp : offsetY); - - FILE_LOG(logDEBUG1) << "Detector[" << idet << "] has offsets (" - << detectors[idet]->getDetectorOffset(X) << ", " - << detectors[idet]->getDetectorOffset(Y) << ")"; - // offsetY has been reset sometimes and offsetX the first time, - // but remember the highest values - if (numX > multi_shm()->numberOfChannel[X]) { - multi_shm()->numberOfChannel[X] = numX; - } - if (numY > multi_shm()->numberOfChannel[Y]) { - multi_shm()->numberOfChannel[Y] = numY; - } - if (numX_gp > multi_shm()->numberOfChannelInclGapPixels[X]) { - multi_shm()->numberOfChannelInclGapPixels[X] = numX_gp; - } - if (numY_gp > multi_shm()->numberOfChannelInclGapPixels[Y]) { - multi_shm()->numberOfChannelInclGapPixels[Y] = numY_gp; - } - } - FILE_LOG(logDEBUG1) - << "\n\tNumber of Channels in X direction:" - << multi_shm()->numberOfChannel[X] - << "\n\tNumber of Channels in Y direction:" - << multi_shm()->numberOfChannel[Y] - << "\n\tNumber of Channels in X direction with Gap Pixels:" - << multi_shm()->numberOfChannelInclGapPixels[X] - << "\n\tNumber of Channels in Y direction with Gap Pixels:" - << multi_shm()->numberOfChannelInclGapPixels[Y]; - - multi_shm()->numberOfChannels = - multi_shm()->numberOfChannel[0] * multi_shm()->numberOfChannel[1]; - - for (auto &d : detectors) { - d->updateMultiSize(multi_shm()->numberOfDetector[0], - multi_shm()->numberOfDetector[1]); - } -} std::string multiSlsDetector::exec(const char *cmd) { int bufsize = 128; @@ -560,8 +366,6 @@ void multiSlsDetector::setHostname(const std::vector &name) { for (const auto &hostname : name) { addSlsDetector(hostname); } - - updateOffsets(); } void multiSlsDetector::setHostname(const char *name, int detPos) { @@ -598,8 +402,7 @@ void multiSlsDetector::addMultipleDetectors(const char *name) { for (const auto &hostname : sls::split(name, '+')) { addSlsDetector(hostname); } - - updateOffsets(); + updateDetectorSize(); } void multiSlsDetector::addSlsDetector(const std::string &hostname) { @@ -623,11 +426,63 @@ void multiSlsDetector::addSlsDetector(const std::string &hostname) { sls::make_unique(type, multiId, pos, false)); multi_shm()->numberOfDetectors = detectors.size(); multi_shm()->numberOfChannels += detectors[pos]->getTotalNumberOfChannels(); - detectors[pos]->setHostname(hostname); multi_shm()->multiDetectorType = getDetectorTypeAsEnum(-1);// -1 needed here } +void multiSlsDetector::updateDetectorSize() { + FILE_LOG(logDEBUG) << "Updating Multi-Detector Size: " << size(); + + int my = detectors[0]->getTotalNumberOfChannels(Y); + int mx = detectors[0]->getTotalNumberOfChannels(X); + int mgy = detectors[0]->getTotalNumberOfChannelsInclGapPixels(Y); + int mgx = detectors[0]->getTotalNumberOfChannelsInclGapPixels(X); + if (mgy == 0) { + mgy = my; + mgx = mx; + } + + int maxy = multi_shm()->maxNumberOfChannelsPerDetector[Y]; + if (maxy == -1) { + maxy = my * size(); + } + + int ndety = maxy / my; + int ndetx = size() / ndety; + if ((maxy % my) > 0) { + ++ndetx; + } + + multi_shm()->numberOfDetector[X] = ndetx; + multi_shm()->numberOfDetector[Y] = ndety; + multi_shm()->numberOfChannel[X] = mx * ndetx; + multi_shm()->numberOfChannel[Y] = my * ndety; + multi_shm()->numberOfChannelInclGapPixels[X] = mgx * ndetx; + multi_shm()->numberOfChannelInclGapPixels[Y] = mgy * ndety; + + FILE_LOG(logDEBUG) + << "\n\tNumber of Detectors in X direction:" + << multi_shm()->numberOfDetector[X] + << "\n\tNumber of Detectors in Y direction:" + << multi_shm()->numberOfDetector[Y] + << "\n\tNumber of Channels in X direction:" + << multi_shm()->numberOfChannel[X] + << "\n\tNumber of Channels in Y direction:" + << multi_shm()->numberOfChannel[Y] + << "\n\tNumber of Channels in X direction with Gap Pixels:" + << multi_shm()->numberOfChannelInclGapPixels[X] + << "\n\tNumber of Channels in Y direction with Gap Pixels:" + << multi_shm()->numberOfChannelInclGapPixels[Y]; + + multi_shm()->numberOfChannels = + multi_shm()->numberOfChannel[0] * multi_shm()->numberOfChannel[1]; + + for (auto &d : detectors) { + d->updateMultiSize(multi_shm()->numberOfDetector[0], + multi_shm()->numberOfDetector[1]); + } +} + slsDetectorDefs::detectorType multiSlsDetector::getDetectorTypeAsEnum() const { return multi_shm()->multiDetectorType; } @@ -732,14 +587,6 @@ void multiSlsDetector::setMaxNumberOfChannels(const slsDetectorDefs::coordinates multi_shm()->maxNumberOfChannelsPerDetector[Y] = c.y; } -int multiSlsDetector::getDetectorOffset(dimension d, int detPos) { - return detectors[detPos]->getDetectorOffset(d); -} - -void multiSlsDetector::setDetectorOffset(dimension d, int off, int detPos) { - detectors[detPos]->setDetectorOffset(d, off); -} - int multiSlsDetector::getQuad(int detPos) { int retval = detectors[0]->getQuad(); if (retval && size() > 1) { @@ -1272,8 +1119,6 @@ int multiSlsDetector::setDynamicRange(int dr, int detPos) { // change in dr if (dr != -1 && dr != prevValue) { - updateOffsets(); - // update speed, check ratecorrection if (getDetectorTypeAsEnum() == EIGER) { @@ -2172,318 +2017,40 @@ int multiSlsDetector::setCounterBit(int i, int detPos) { return sls::minusOneIfDifferent(r); } -void multiSlsDetector::verifyMinMaxROI(int n, ROI r[]) { - int temp; - for (int i = 0; i < n; ++i) { - if ((r[i].xmax) < (r[i].xmin)) { - temp = r[i].xmax; - r[i].xmax = r[i].xmin; - r[i].xmin = temp; - } - if ((r[i].ymax) < (r[i].ymin)) { - temp = r[i].ymax; - r[i].ymax = r[i].ymin; - r[i].ymin = temp; - } - } -} - -void multiSlsDetector::setROI(int n, ROI roiLimits[], int detPos) { +void multiSlsDetector::clearROI(int detPos) { // single if (detPos >= 0) { - detectors[detPos]->setROI(n, roiLimits); + detectors[detPos]->clearROI(); } // multi - int xmin = 0, xmax = 0, ymin = 0, ymax = 0, channelX = 0, channelY = 0, - idet = 0, lastChannelX = 0, lastChannelY = 0, index = 0, offsetX = 0, - offsetY = 0; - - bool invalidroi = false; - int ndet = detectors.size(); - ROI allroi[ndet][n]; - int nroi[ndet]; - for (int i = 0; i < ndet; ++i) { - nroi[i] = 0; - } - - if ((n < 0) || (roiLimits == nullptr)) { - throw RuntimeError("Cannot set ROI due to Invalid ROI"); - } - - // ensures min < max - verifyMinMaxROI(n, roiLimits); - FILE_LOG(logDEBUG1) << "Setting ROI for " << n << "rois:"; - for (int i = 0; i < n; ++i) { - FILE_LOG(logDEBUG1) - << i << ":" << roiLimits[i].xmin << "\t" << roiLimits[i].xmax - << "\t" << roiLimits[i].ymin << "\t" << roiLimits[i].ymax; - } - // for each roi - for (int i = 0; i < n; ++i) { - xmin = roiLimits[i].xmin; - xmax = roiLimits[i].xmax; - ymin = roiLimits[i].ymin; - ymax = roiLimits[i].ymax; - - if (size() > 1) { - // check roi max values - idet = decodeNChannel(xmax, ymax, channelX, channelY); - FILE_LOG(logDEBUG1) << "Decoded Channel max vals: " << std::endl - << "det:" << idet << "\t" << xmax << "\t" - << ymax << "\t" << channelX << "\t" << channelY; - if (idet == -1) { - FILE_LOG(logERROR) << "invalid roi"; - continue; - } - - // split in x dir - while (xmin <= xmax) { - invalidroi = false; - ymin = roiLimits[i].ymin; - // split in y dir - while (ymin <= ymax) { - // get offset for each detector - idet = decodeNChannel(xmin, ymin, channelX, channelY); - FILE_LOG(logDEBUG1) - << "Decoded Channel min vals: " << std::endl - << "det:" << idet << "\t" << xmin << "\t" << ymin - << "\t" << channelX << "\t" << channelY; - if (idet < 0 || idet >= (int)detectors.size()) { - FILE_LOG(logDEBUG1) << "invalid roi"; - invalidroi = true; - break; - } - // get last channel for each det in x and y dir - lastChannelX = - (detectors[idet]->getTotalNumberOfChannelsInclGapPixels( - X)) - - 1; - lastChannelY = - (detectors[idet]->getTotalNumberOfChannelsInclGapPixels( - Y)) - - 1; - - offsetX = detectors[idet]->getDetectorOffset(X); - offsetY = detectors[idet]->getDetectorOffset(Y); - // at the end in x dir - if ((offsetX + lastChannelX) >= xmax) { - lastChannelX = xmax - offsetX; - } - // at the end in y dir - if ((offsetY + lastChannelY) >= ymax) { - lastChannelY = ymax - offsetY; - } - - FILE_LOG(logDEBUG1) - << "lastChannelX:" << lastChannelX << "\t" - << "lastChannelY:" << lastChannelY; - - // creating the list of roi for corresponding detector - index = nroi[idet]; - allroi[idet][index].xmin = channelX; - allroi[idet][index].xmax = lastChannelX; - allroi[idet][index].ymin = channelY; - allroi[idet][index].ymax = lastChannelY; - nroi[idet] = nroi[idet] + 1; - - ymin = lastChannelY + offsetY + 1; - if ((lastChannelY + offsetY) == ymax) { - ymin = ymax + 1; - } - - FILE_LOG(logDEBUG1) - << "nroi[idet]:" << nroi[idet] << "\tymin:" << ymin; - } - if (invalidroi) { - break; - } - - xmin = lastChannelX + offsetX + 1; - if ((lastChannelX + offsetX) == xmax) { - xmin = xmax + 1; - } - } - } else { // FIXME: check if xmax is greater? or reduce logic above? - idet = 0; - nroi[idet] = n; - index = 0; - allroi[idet][index].xmin = xmin; - allroi[idet][index].xmax = xmax; - allroi[idet][index].ymin = ymin; - allroi[idet][index].ymax = ymax; - // nroi[idet] = nroi[idet] + 1; - } - } - - FILE_LOG(logDEBUG1) << "Setting ROI :"; - for (size_t i = 0; i < detectors.size(); ++i) { - FILE_LOG(logDEBUG1) << "detector " << i; - for (int j = 0; j < nroi[i]; ++j) { - FILE_LOG(logDEBUG1) - << allroi[i][j].xmin << "\t" << allroi[i][j].xmax << "\t" - << allroi[i][j].ymin << "\t" << allroi[i][j].ymax; - } - } - - // settings the rois for each detector - for (size_t i = 0; i != detectors.size(); ++i) { - detectors[i]->setROI(nroi[i], allroi[i]); - } + parallelCall(&slsDetector::clearROI); } -const slsDetectorDefs::ROI *multiSlsDetector::getROI(int &n, int detPos) { +void multiSlsDetector::setROI(slsDetectorDefs::ROI arg, int detPos) { // single if (detPos >= 0) { - return detectors[detPos]->getROI(n); + detectors[detPos]->setROI(arg); } // multi - n = 0; - int num = 0; - int ndet = detectors.size(); - int maxroi = ndet * MAX_ROIS; - ROI temproi; - ROI roiLimits[maxroi]; - ROI *retval = new ROI[maxroi]; - const ROI *temp = nullptr; - int index = 0; + if (detPos < 0 && size() > 1) { + throw RuntimeError("Cannot set ROI for all modules simultaneously"); + } + detectors[0]->setROI(arg); +} - // get each detector's roi array - for (size_t idet = 0; idet < detectors.size(); ++idet) { - temp = detectors[idet]->getROI(index); - if (temp != nullptr) { - if (index != 0) { - FILE_LOG(logINFO) << "detector " << idet << ":"; - } - for (int j = 0; j < index; ++j) { - FILE_LOG(logINFO) - << temp[j].xmin << "\t" << temp[j].xmax << "\t" - << temp[j].ymin << "\t" << temp[j].ymax; - int x = detectors[idet]->getDetectorOffset(X); - int y = detectors[idet]->getDetectorOffset(Y); - roiLimits[n].xmin = temp[j].xmin + x; - roiLimits[n].xmax = temp[j].xmax + x; - roiLimits[n].ymin = temp[j].ymin + y; - roiLimits[n].ymax = temp[j].ymin + y; - ++n; - } - } +slsDetectorDefs::ROI multiSlsDetector::getROI(int detPos) const { + // single + if (detPos >= 0) { + return detectors[detPos]->getROI(); } - // empty roi - if (n == 0) { - return nullptr; + // multi + if (detPos < 0 && size() > 1) { + throw RuntimeError("Cannot get ROI for all modules simultaneously"); } - - FILE_LOG(logDEBUG1) << "ROI :" << std::endl; - for (int j = 0; j < n; ++j) { - FILE_LOG(logDEBUG1) - << roiLimits[j].xmin << "\t" << roiLimits[j].xmax << "\t" - << roiLimits[j].ymin << "\t" << roiLimits[j].ymax; - } - - // combine all the adjacent rois in x direction - for (int i = 0; i < n; ++i) { - // since the ones combined are replaced by -1 - if ((roiLimits[i].xmin) == -1) { - continue; - } - for (int j = i + 1; j < n; ++j) { - // since the ones combined are replaced by -1 - if ((roiLimits[j].xmin) == -1) { - continue; - } - // if y values are same - if (((roiLimits[i].ymin) == (roiLimits[j].ymin)) && - ((roiLimits[i].ymax) == (roiLimits[j].ymax))) { - // if adjacent, increase [i] range and replace all [j] with -1 - if ((roiLimits[i].xmax) + 1 == roiLimits[j].xmin) { - roiLimits[i].xmax = roiLimits[j].xmax; - roiLimits[j].xmin = -1; - roiLimits[j].xmax = -1; - roiLimits[j].ymin = -1; - roiLimits[j].ymax = -1; - } - // if adjacent, increase [i] range and replace all [j] with -1 - else if ((roiLimits[i].xmin) - 1 == roiLimits[j].xmax) { - roiLimits[i].xmin = roiLimits[j].xmin; - roiLimits[j].xmin = -1; - roiLimits[j].xmax = -1; - roiLimits[j].ymin = -1; - roiLimits[j].ymax = -1; - } - } - } - } - - FILE_LOG(logDEBUG1) << "Combined along x axis Getting ROI :\ndetector " - << n; - for (int j = 0; j < n; ++j) { - FILE_LOG(logDEBUG1) - << roiLimits[j].xmin << "\t" << roiLimits[j].xmax << "\t" - << roiLimits[j].ymin << "\t" << roiLimits[j].ymax; - } - - // combine all the adjacent rois in y direction - for (int i = 0; i < n; ++i) { - // since the ones combined are replaced by -1 - if ((roiLimits[i].ymin) == -1) { - continue; - } - for (int j = i + 1; j < n; ++j) { - // since the ones combined are replaced by -1 - if ((roiLimits[j].ymin) == -1) { - continue; - } - // if x values are same - if (((roiLimits[i].xmin) == (roiLimits[j].xmin)) && - ((roiLimits[i].xmax) == (roiLimits[j].xmax))) { - // if adjacent, increase [i] range and replace all [j] with -1 - if ((roiLimits[i].ymax) + 1 == roiLimits[j].ymin) { - roiLimits[i].ymax = roiLimits[j].ymax; - roiLimits[j].xmin = -1; - roiLimits[j].xmax = -1; - roiLimits[j].ymin = -1; - roiLimits[j].ymax = -1; - } - // if adjacent, increase [i] range and replace all [j] with -1 - else if ((roiLimits[i].ymin) - 1 == roiLimits[j].ymax) { - roiLimits[i].ymin = roiLimits[j].ymin; - roiLimits[j].xmin = -1; - roiLimits[j].xmax = -1; - roiLimits[j].ymin = -1; - roiLimits[j].ymax = -1; - } - } - } - } - - // get rid of -1s - for (int i = 0; i < n; ++i) { - if ((roiLimits[i].xmin) != -1) { - retval[num] = roiLimits[i]; - ++num; - } - } - // sort final roi - for (int i = 0; i < num; ++i) { - for (int j = i + 1; j < num; ++j) { - if (retval[j].xmin < retval[i].xmin) { - temproi = retval[i]; - retval[i] = retval[j]; - retval[j] = temproi; - } - } - } - n = num; - - FILE_LOG(logDEBUG1) << "\nxmin\txmax\tymin\tymax"; - for (int i = 0; i < n; ++i) { - FILE_LOG(logDEBUG1) << retval[i].xmin << "\t" << retval[i].xmax << "\t" - << retval[i].ymin << "\t" << retval[i].ymax; - } - return retval; + return detectors[0]->getROI(); } void multiSlsDetector::setADCEnableMask(uint32_t mask, int detPos) { @@ -2688,15 +2255,16 @@ int multiSlsDetector::enableGapPixels(int val, int detPos) { int ret = sls::minusOneIfDifferent(r); if (val != -1) { - updateOffsets(); + multi_shm()->numberOfChannelInclGapPixels[X] = sls::sum(parallelCall(&slsDetector::getTotalNumberOfChannelsInclGapPixels, X)); + multi_shm()->numberOfChannelInclGapPixels[Y] = sls::sum(parallelCall(&slsDetector::getTotalNumberOfChannelsInclGapPixels, Y)); } return ret; } void multiSlsDetector::setGapPixelsEnable(bool enable, Positions pos){ Parallel(&slsDetector::enableGapPixels, pos, static_cast(enable)); - - updateOffsets(); + multi_shm()->numberOfChannelInclGapPixels[X] = sls::sum(parallelCall(&slsDetector::getTotalNumberOfChannelsInclGapPixels, X)); + multi_shm()->numberOfChannelInclGapPixels[Y] = sls::sum(parallelCall(&slsDetector::getTotalNumberOfChannelsInclGapPixels, Y)); } int multiSlsDetector::setTrimEn(std::vector energies, int detPos) { diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index a8e373ad9..c2fc2416f 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -308,15 +308,13 @@ void slsDetector::initializeDetectorStructure(detectorType type) { shm()->controlPort = DEFAULT_PORTNO; sls::strcpy_safe(shm()->hostname, DEFAULT_HOSTNAME); shm()->myDetectorType = type; - shm()->offset[X] = 0; - shm()->offset[Y] = 0; shm()->multiSize[X] = 0; shm()->multiSize[Y] = 0; - + shm()->controlPort = DEFAULT_PORTNO; shm()->stopPort = DEFAULT_PORTNO + 1; sls::strcpy_safe(shm()->settingsDir, getenv("HOME")); - shm()->nROI = 0; - memset(shm()->roiLimits, 0, MAX_ROIS * sizeof(ROI)); + shm()->roi.xmin = -1; + shm()->roi.xmax = -1; shm()->adcEnableMask = BIT32_MASK; shm()->roFlags = NORMAL_READOUT; shm()->currentSettings = UNINITIALIZED; @@ -688,28 +686,6 @@ int slsDetector::getReadNLines() { return retval; } -int slsDetector::getDetectorOffset(dimension d) const { - return shm()->offset[d]; -} - -slsDetectorDefs::coordinates slsDetector::getDetectorOffsets() const { - slsDetectorDefs::coordinates coord; - coord.x = shm()->offset[X]; - coord.y = shm()->offset[Y]; - return coord; -} - -void slsDetector::setDetectorOffset(dimension d, int off) { - if (off >= 0) { - shm()->offset[d] = off; - } -} - -void slsDetector::setDetectorOffsets(slsDetectorDefs::coordinates value) { - shm()->offset[X] = value.x; - shm()->offset[Y] = value.y; -} - void slsDetector::updateMultiSize(int detx, int dety) { shm()->multiSize[0] = detx; shm()->multiSize[1] = dety; @@ -878,17 +854,9 @@ void slsDetector::updateCachedDetectorVariables() { // roi if (shm()->myDetectorType == GOTTHARD) { n += client.Receive(&i32, sizeof(i32)); - shm()->nROI = i32; - for (int i = 0; i < shm()->nROI; ++i) { - n += client.Receive(&i32, sizeof(i32)); - shm()->roiLimits[i].xmin = i32; - n += client.Receive(&i32, sizeof(i32)); - shm()->roiLimits[i].xmax = i32; - n += client.Receive(&i32, sizeof(i32)); - shm()->roiLimits[i].ymin = i32; - n += client.Receive(&i32, sizeof(i32)); - shm()->roiLimits[i].xmax = i32; - } + shm()->roi.xmin = i32; + n += client.Receive(&i32, sizeof(i32)); + shm()->roi.xmax = i32; } if (shm()->myDetectorType == CHIPTESTBOARD || @@ -1849,7 +1817,7 @@ std::string slsDetector::setReceiverHostname(const std::string &receiverIP) { break; case GOTTHARD: - sendROI(-1, nullptr); + sendROItoReceiver(); break; default: @@ -2344,44 +2312,27 @@ int slsDetector::setCounterBit(int cb) { return retval; } -void slsDetector::setROI(int n, ROI roiLimits[]) { - std::sort(roiLimits, roiLimits + n, - [](ROI a, ROI b) { return a.xmin < b.xmin; }); - - sendROI(n, roiLimits); +void slsDetector::clearROI() { + FILE_LOG(logDEBUG1) << "Clearing ROI"; + slsDetectorDefs::ROI arg; + arg.xmin = -1; + arg.xmax = -1; + setROI(arg); } -const slsDetectorDefs::ROI *slsDetector::getROI(int &n) { - sendROI(-1, nullptr); - n = shm()->nROI; - return shm()->roiLimits; -} - -int slsDetector::getNRoi() { return shm()->nROI; } - -void slsDetector::sendROI(int n, ROI roiLimits[]) { +void slsDetector::setROI(slsDetectorDefs::ROI arg) { int fnum = F_SET_ROI; int ret = FAIL; - int narg = n; - // send roiLimits if given, else from shm - ROI *arg = (roiLimits != nullptr) ? roiLimits : shm()->roiLimits; - int nretval = 0; - ROI retval[MAX_ROIS]; - FILE_LOG(logDEBUG1) << "Sending ROI to detector" << narg; - + if (arg.xmin < 0 || arg.xmax >= getTotalNumberOfChannels()) { + arg.xmin = -1; + arg.xmax = -1; + } + FILE_LOG(logDEBUG) << "Sending ROI to detector [" << arg.xmin << ", " << arg.xmax << "]"; auto client = DetectorSocket(shm()->hostname, shm()->controlPort); client.Send(&fnum, sizeof(fnum)); - client.Send(&narg, sizeof(narg)); - if (narg != -1) { - for (int i = 0; i < narg; ++i) { - client.Send(&arg[i].xmin, sizeof(int)); - client.Send(&arg[i].xmax, sizeof(int)); - client.Send(&arg[i].ymin, sizeof(int)); - client.Send(&arg[i].ymax, sizeof(int)); - } - } + client.Send(&arg.xmin, sizeof(int)); + client.Send(&arg.xmax, sizeof(int)); client.Receive(&ret, sizeof(ret)); - // handle ret if (ret == FAIL) { char mess[MAX_STR_LENGTH]{}; @@ -2389,65 +2340,63 @@ void slsDetector::sendROI(int n, ROI roiLimits[]) { throw RuntimeError("Detector " + std::to_string(detId) + " returned error: " + std::string(mess)); } else { - client.Receive(&nretval, sizeof(nretval)); - int nrec = 0; - for (int i = 0; i < nretval; ++i) { - nrec += client.Receive(&retval[i].xmin, sizeof(int)); - nrec += client.Receive(&retval[i].xmax, sizeof(int)); - nrec += client.Receive(&retval[i].ymin, sizeof(int)); - nrec += client.Receive(&retval[i].ymax, sizeof(int)); - } - shm()->nROI = nretval; - FILE_LOG(logDEBUG1) << "nRoi: " << nretval; - for (int i = 0; i < nretval; ++i) { - shm()->roiLimits[i] = retval[i]; - FILE_LOG(logDEBUG1) - << "ROI [" << i << "] (" << shm()->roiLimits[i].xmin << "," - << shm()->roiLimits[i].xmax << "," << shm()->roiLimits[i].ymin - << "," << shm()->roiLimits[i].ymax << ")"; + memcpy(&shm()->roi, &arg, sizeof(ROI)); + if (ret == FORCE_UPDATE) { + updateCachedDetectorVariables(); } } - if (ret == FORCE_UPDATE) { - updateCachedDetectorVariables(); - } + // old firmware requires configuremac after setting roi - if (shm()->myDetectorType == GOTTHARD && n != -1) { + if (shm()->myDetectorType == GOTTHARD) { configureMAC(); } + sendROItoReceiver(); +} + +void slsDetector::sendROItoReceiver() { // update roi in receiver if (shm()->useReceiverFlag) { - fnum = F_RECEIVER_SET_ROI; - ret = FAIL; - narg = shm()->nROI; - arg = shm()->roiLimits; - FILE_LOG(logDEBUG1) << "Sending ROI to receiver: " << shm()->nROI; - - auto receiver = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort); - receiver.Send(&fnum, sizeof(fnum)); - receiver.Send(&narg, sizeof(narg)); - if (narg != -1) { - for (int i = 0; i < narg; ++i) { - receiver.Send(&arg[i].xmin, sizeof(int)); - receiver.Send(&arg[i].xmax, sizeof(int)); - receiver.Send(&arg[i].ymin, sizeof(int)); - receiver.Send(&arg[i].ymax, sizeof(int)); - } - } - receiver.Receive(&ret, sizeof(ret)); - - if (ret == FAIL) { - char mess[MAX_STR_LENGTH]{}; - receiver.Receive(mess, MAX_STR_LENGTH); - throw ReceiverError("Receiver " + std::to_string(detId) + - " returned error: " + std::string(mess)); - } - if (ret == FORCE_UPDATE) { - updateCachedReceiverVariables(); - } + FILE_LOG(logDEBUG1) << "Sending ROI to receiver"; + sendToReceiver(F_RECEIVER_SET_ROI, shm()->roi, nullptr); } } +slsDetectorDefs::ROI slsDetector::getROI() { + int fnum = F_GET_ROI; + int ret = FAIL; + FILE_LOG(logDEBUG1) << "Getting ROI from detector"; + auto client = DetectorSocket(shm()->hostname, shm()->controlPort); + client.Send(&fnum, sizeof(fnum)); + client.Receive(&ret, sizeof(ret)); + // handle ret + if (ret == FAIL) { + char mess[MAX_STR_LENGTH]{}; + client.Receive(mess, MAX_STR_LENGTH); + throw RuntimeError("Detector " + std::to_string(detId) + + " returned error: " + std::string(mess)); + } else { + ROI retval; + client.Receive(&retval.xmin, sizeof(int)); + client.Receive(&retval.xmax, sizeof(int)); + FILE_LOG(logDEBUG1) + << "ROI retval [" << retval.xmin << "," + << retval.xmax << "]"; + if (ret == FORCE_UPDATE) { + updateCachedDetectorVariables(); + } + // if different from shm, update and send to receiver + if (shm()->roi.xmin != retval.xmin || shm()->roi.xmax != retval.xmax) { + memcpy(&shm()->roi, &retval, sizeof(ROI)); + sendROItoReceiver(); + } + } + + return shm()->roi; +} + + + void slsDetector::setADCEnableMask(uint32_t mask) { uint32_t arg = mask; FILE_LOG(logDEBUG1) << "Setting ADC Enable mask to 0x" << std::hex << arg diff --git a/slsDetectorSoftware/src/slsDetectorCommand.cpp b/slsDetectorSoftware/src/slsDetectorCommand.cpp index 3989a1d3a..3c3a7c36a 100755 --- a/slsDetectorSoftware/src/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp @@ -308,7 +308,14 @@ slsDetectorCommand::slsDetectorCommand(multiSlsDetector *det) { ++i; /*! \page config - - roi [i] [xmin] [xmax] [ymin] [ymax] sets region of interest of the detector, where i is number of rois;i=0 to clear rois. Used for GOTTHARD only. \c Returns \c (int) + - clearroi resets region of interest of the detector. Used for GOTTHARD only. \c Returns \c (string) + */ + descrToFuncMap[i].m_pFuncName = "clearroi"; + descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdDetectorSize; + ++i; + + /*! \page config + - roi [xmin] [xmax] sets region of interest of the detector. Used for GOTTHARD only. \c Returns \c (int) */ descrToFuncMap[i].m_pFuncName = "roi"; descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdDetectorSize; @@ -3252,28 +3259,28 @@ std::string slsDetectorCommand::cmdDetectorSize(int narg, const char * const arg if (action == HELP_ACTION) return helpDetectorSize(action); - int ret, val = -1, pos = -1, i; + int ret, val = -1; char ans[1000]; if (action == PUT_ACTION) { - if (!sscanf(args[1], "%d", &val)) + if (cmd != "roi" && !sscanf(args[1], "%d", &val)) return std::string("could not scan ") + std::string(args[0]) + std::string(" ") + std::string(args[1]); + if (cmd == "clearroi") { + myDet->clearROI(detPos); + } + if (cmd == "roi") { //debug number of arguments - if ((val < 0) || (narg != ((val * 4) + 2))) + if (narg != 3) return helpDetectorSize(action); - ROI allroi[val]; - pos = 2; - for (i = 0; i < val; ++i) { - if ((!sscanf(args[pos++], "%d", &allroi[i].xmin)) || - (!sscanf(args[pos++], "%d", &allroi[i].xmax)) || - (!sscanf(args[pos++], "%d", &allroi[i].ymin)) || - (!sscanf(args[pos++], "%d", &allroi[i].ymax))) - return std::string("cannot parse arguments for roi"); - } - myDet->setROI(val, allroi, detPos); + ROI roi; + if (!sscanf(args[1], "%d", &roi.xmin)) + return std::string("cannot parse arguments for roi xmin"); + if (!sscanf(args[2], "%d", &roi.xmax)) + return std::string("cannot parse arguments for roi xmax"); + myDet->setROI(roi, detPos); } if (cmd == "detsizechan") { @@ -3308,17 +3315,21 @@ std::string slsDetectorCommand::cmdDetectorSize(int narg, const char * const arg if ((!sscanf(args[1], "%d", &val)) || (val != 0 && val != 1)) return std::string("cannot scan gappixels mode: must be 0 or 1"); - if (detPos < 0) // only in multi detector level to update offsets etc. + if (detPos < 0) // only in multi detector level to update number of channels etc. myDet->enableGapPixels(val, detPos); } } if (cmd == "dr") { ret = myDet->setDynamicRange(val, detPos); + } else if (cmd == "clearroi") { + if (action == GET_ACTION) { + return std::string("Cannot get"); + } + return std::string("successful"); } else if (cmd == "roi") { - const ROI* r = myDet->getROI(ret, detPos); - - delete [] r; + ROI roi = myDet->getROI(detPos); + return (std::string("[") + std::to_string(roi.xmin) + std::string(",") + std::to_string(roi.xmax) + std::string("]")); } else if (cmd == "detsizechan") { sprintf(ans, "%d %d", myDet->getMaxNumberOfChannelsPerDetector(X), myDet->getMaxNumberOfChannelsPerDetector(Y)); return std::string(ans); @@ -3330,7 +3341,7 @@ std::string slsDetectorCommand::cmdDetectorSize(int narg, const char * const arg return std::string("Not required for this detector\n"); ret = myDet->getFlippedData(Y, detPos); } else if (cmd == "gappixels") { - if (detPos >= 0) // only in multi detector level to update offsets etc. + if (detPos >= 0) // only in multi detector level to update number of channels etc. return std::string("Cannot execute this command from slsDetector level. Please use multiSlsDetector level.\n"); ret = myDet->enableGapPixels(-1, detPos); } @@ -3349,7 +3360,8 @@ std::string slsDetectorCommand::helpDetectorSize(int action) { std::ostringstream os; if (action == PUT_ACTION || action == HELP_ACTION) { os << "dr i \n sets the dynamic range of the detector" << std::endl; - os << "roi i xmin xmax ymin ymax \n sets region of interest where i is number of rois;i=0 to clear rois" << std::endl; + os << "clearroi \n resets region of interest" << std::endl; + os << "roi xmin xmax \n sets region of interest " << std::endl; os << "detsizechan x y \n sets the maximum number of channels for complete detector set in both directions; -1 is no limit" << std::endl; os << "quad i \n if i = 1, sets the detector size to a quad (Specific to an EIGER quad hardware). 0 by default."<< std::endl; os << "flippeddatax x \n sets if the data should be flipped on the x axis" << std::endl; diff --git a/slsDetectorSoftware/src/slsDetectorUsers.cpp b/slsDetectorSoftware/src/slsDetectorUsers.cpp index f4b83b178..8e89ca408 100755 --- a/slsDetectorSoftware/src/slsDetectorUsers.cpp +++ b/slsDetectorSoftware/src/slsDetectorUsers.cpp @@ -14,14 +14,7 @@ int slsDetectorUsers::getMaximumDetectorSize(int &nx, int &ny){ return nx*ny; } -int slsDetectorUsers::getDetectorSize(int &x, int &y, int &nx, int &ny, int detPos){ - if (detPos < 0) { - x = 0; - y = 0; - } else { - x = detector.getDetectorOffset(slsDetectorDefs::X, detPos); - y = detector.getDetectorOffset(slsDetectorDefs::Y, detPos); - } +int slsDetectorUsers::getDetectorSize(int &nx, int &ny, int detPos){ nx=detector.getTotalNumberOfChannels(slsDetectorDefs::X, detPos); ny=detector.getTotalNumberOfChannels(slsDetectorDefs::Y, detPos); return nx*ny; @@ -226,12 +219,12 @@ int slsDetectorUsers::setFlowControl10G(int i, int detPos) { return detector.setFlowControl10G(i, detPos); } -void slsDetectorUsers::setROI(int n, slsDetectorDefs::ROI roiLimits[], int detPos) { - detector.setROI(n, roiLimits, detPos); +void slsDetectorUsers::setROI(slsDetectorDefs::ROI arg, int detPos) { + detector.setROI(arg, detPos); } -const slsDetectorDefs::ROI* slsDetectorUsers::getROI(int &n, int detPos) { - return detector.getROI(n, detPos); +slsDetectorDefs::ROI slsDetectorUsers::getROI(int detPos) { + return detector.getROI(detPos); } /************************************************************************ diff --git a/slsReceiverSoftware/include/DataStreamer.h b/slsReceiverSoftware/include/DataStreamer.h index b3e62d48d..152d006c0 100755 --- a/slsReceiverSoftware/include/DataStreamer.h +++ b/slsReceiverSoftware/include/DataStreamer.h @@ -32,7 +32,7 @@ class DataStreamer : private virtual slsDetectorDefs, public ThreadObject { * @param nd pointer to number of detectors in each dimension * @param gpEnable pointer to gap pixels enable */ - DataStreamer(int ind, Fifo* f, uint32_t* dr, std::vector* r, + DataStreamer(int ind, Fifo* f, uint32_t* dr, ROI* r, uint64_t* fi, int fd, char* ajh, int* nd, bool* gpEnable); /** @@ -188,7 +188,7 @@ class DataStreamer : private virtual slsDetectorDefs, public ThreadObject { uint32_t* dynamicRange; /** ROI */ - std::vector* roi; + ROI* roi; /** adc Configured */ int adcConfigured; diff --git a/slsReceiverSoftware/include/GeneralData.h b/slsReceiverSoftware/include/GeneralData.h index 87ad410d0..99beeeddd 100755 --- a/slsReceiverSoftware/include/GeneralData.h +++ b/slsReceiverSoftware/include/GeneralData.h @@ -142,17 +142,17 @@ public: * Set ROI * @param i ROI */ - virtual void SetROI(std::vector i) { + virtual void SetROI(slsDetectorDefs::ROI i) { FILE_LOG(logERROR) << "SetROI is a generic function that should be overloaded by a derived class"; }; /** * Get Adc configured * @param index thread index for debugging purposes - * @param i pointer to a vector of ROI pointers + * @param ROI * @returns adc configured */ - virtual int GetAdcConfigured(int index, std::vector* i) const{ + virtual int GetAdcConfigured(int index, slsDetectorDefs::ROI i) const{ FILE_LOG(logERROR) << "GetAdcConfigured is a generic function that should be overloaded by a derived class"; return 0; }; @@ -311,9 +311,9 @@ private: * Set ROI * @param i ROI */ - void SetROI(std::vector i) { + void SetROI(slsDetectorDefs::ROI i) { // all adcs - if(!i.size()) { + if(i.xmin == -1) { nPixelsX = 1280; dataSize = 1280; packetSize = GOTTHARD_PACKET_SIZE; @@ -352,28 +352,21 @@ private: /** * Get Adc configured * @param index thread index for debugging purposes - * @param i pointer to a vector of ROI + * @param i ROI * @returns adc configured */ - int GetAdcConfigured(int index, std::vector* i) const{ + int GetAdcConfigured(int index, slsDetectorDefs::ROI i) const{ int adc = -1; // single adc - if(i->size()) { + if(i.xmin != -1) { // gotthard can have only one adc per detector enabled (or all) - // so just looking at the first roi is enough (more not possible at the moment) - - //if its for 1 adc or general - if ((i->at(0).xmin == 0) && (i->at(0).xmax == nChip * nChan)) + //adc = mid value/numchans also for only 1 roi + adc = ((((i.xmax) + (i.xmin))/2)/ + (nChan * nChipsPerAdc)); + if((adc < 0) || (adc > 4)) { + FILE_LOG(logWARNING) << index << ": Deleting ROI. " + "Adc value should be between 0 and 4"; adc = -1; - else { - //adc = mid value/numchans also for only 1 roi - adc = ((((i->at(0).xmax) + (i->at(0).xmin))/2)/ - (nChan * nChipsPerAdc)); - if((adc < 0) || (adc > 4)) { - FILE_LOG(logWARNING) << index << ": Deleting ROI. " - "Adc value should be between 0 and 4"; - adc = -1; - } } } FILE_LOG(logINFO) << "Adc Configured: " << adc; diff --git a/slsReceiverSoftware/include/slsReceiverImplementation.h b/slsReceiverSoftware/include/slsReceiverImplementation.h index aacab85cb..f579bc94d 100755 --- a/slsReceiverSoftware/include/slsReceiverImplementation.h +++ b/slsReceiverSoftware/include/slsReceiverImplementation.h @@ -207,9 +207,9 @@ class slsReceiverImplementation : private virtual slsDetectorDefs { //***acquisition parameters*** /** * Get ROI - * @return index of adc enabled, else -1 if all enabled + * @return roi */ - std::vector getROI() const; + ROI getROI() const; /** * Get ADC Enable Mask @@ -529,10 +529,10 @@ class slsReceiverImplementation : private virtual slsDetectorDefs { //***acquisition parameters*** /** * Set ROI - * @param i ROI + * @param arg ROI * @return OK or FAIL */ - int setROI(const std::vector new_roi); + int setROI(ROI arg); /** * Set ADC Enable Mask @@ -961,7 +961,7 @@ class slsReceiverImplementation : private virtual slsDetectorDefs { //***acquisition parameters*** /* ROI */ - std::vector roi; + ROI roi; /** ADC Enable Mask */ uint32_t adcEnableMask; /** streaming frequency */ diff --git a/slsReceiverSoftware/src/DataStreamer.cpp b/slsReceiverSoftware/src/DataStreamer.cpp index c11d383df..3d5db32b9 100755 --- a/slsReceiverSoftware/src/DataStreamer.cpp +++ b/slsReceiverSoftware/src/DataStreamer.cpp @@ -16,7 +16,7 @@ const std::string DataStreamer::TypeName = "DataStreamer"; -DataStreamer::DataStreamer(int ind, Fifo* f, uint32_t* dr, std::vector* r, +DataStreamer::DataStreamer(int ind, Fifo* f, uint32_t* dr, ROI* r, uint64_t* fi, int fd, char* ajh, int* nd, bool* gpEnable) : ThreadObject(ind), runningFlag(0), @@ -93,9 +93,9 @@ void DataStreamer::ResetParametersforNewMeasurement(const std::string& fname){ delete[] completeBuffer; completeBuffer = nullptr; } - if (roi->size()) { + if (roi->xmin != -1) { if (generalData->myDetectorType == GOTTHARD) { - adcConfigured = generalData->GetAdcConfigured(index, roi); + adcConfigured = generalData->GetAdcConfigured(index, *roi); } completeBuffer = new char[generalData->imageSizeComplete]; memset(completeBuffer, 0, generalData->imageSizeComplete); diff --git a/slsReceiverSoftware/src/slsReceiverImplementation.cpp b/slsReceiverSoftware/src/slsReceiverImplementation.cpp index 1634f8c83..28b3f100e 100755 --- a/slsReceiverSoftware/src/slsReceiverImplementation.cpp +++ b/slsReceiverSoftware/src/slsReceiverImplementation.cpp @@ -104,7 +104,8 @@ void slsReceiverImplementation::InitializeMembers() { overwriteEnable = true; //***acquisition parameters*** - roi.clear(); + roi.xmin = -1; + roi.xmax = -1; adcEnableMask = BIT32_MASK; streamingFrequency = 0; streamingTimerInMs = DEFAULT_STREAMING_TIMER_IN_MS; @@ -305,7 +306,7 @@ int slsReceiverImplementation::getNumberofUDPInterfaces() const { } /***acquisition parameters***/ -std::vector slsReceiverImplementation::getROI() const { +slsDetectorDefs::ROI slsReceiverImplementation::getROI() const { FILE_LOG(logDEBUG3) << __SHORT_AT__ << " called"; return roi; } @@ -858,51 +859,21 @@ int slsReceiverImplementation::setUDPSocketBufferSize(const int64_t s) { } /***acquisition parameters***/ -int slsReceiverImplementation::setROI( - const std::vector new_roi) { - bool change = false; - if (roi.size() != new_roi.size()) - change = true; - else { - for (size_t i = 0; i != new_roi.size(); ++i) { - if ((roi[i].xmin != new_roi[i].xmin) || - (roi[i].xmax != new_roi[i].xmax) || - (roi[i].ymin != new_roi[i].ymin) || - (roi[i].xmax != new_roi[i].xmax)) { - change = true; - break; - } - } - } +int slsReceiverImplementation::setROI(slsDetectorDefs::ROI arg) { + if (roi.xmin != arg.xmin || roi.xmax != arg.xmax) { + roi.xmin = arg.xmin; + roi.xmax = arg.xmax; - if (change) { - roi = new_roi; - switch (myDetectorType) { - case GOTTHARD: - generalData->SetROI(new_roi); - framesPerFile = generalData->maxFramesPerFile; - break; - default: - break; - } + // only for gotthard + generalData->SetROI(arg); + framesPerFile = generalData->maxFramesPerFile; for (const auto &it : dataProcessor) it->SetPixelDimension(); if (SetupFifoStructure() == FAIL) return FAIL; } - std::stringstream sstm; - sstm << "ROI: "; - if (!roi.size()) - sstm << "0"; - else { - for (size_t i = 0; i < roi.size(); ++i) { - sstm << "( " << roi[i].xmin << ", " << roi[i].xmax << ", " - << roi[i].ymin << ", " << roi[i].ymax << " )"; - } - } - std::string message = sstm.str(); - FILE_LOG(logINFO) << message; + FILE_LOG(logINFO) << "ROI: [" << roi.xmin << ", " << roi.xmax << "]";; FILE_LOG(logINFO) << "Packets per Frame: " << (generalData->packetsPerFrame); return OK; diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp index ba99be5ae..7aacb2eb8 100755 --- a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp +++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp @@ -510,22 +510,12 @@ int slsReceiverTCPIPInterface::set_detector_hostname(Interface &socket) { } int slsReceiverTCPIPInterface::set_roi(Interface &socket) { - static_assert(sizeof(ROI) == 4 * sizeof(int), "ROI not packed"); - auto narg = socket.Receive(); - std::vector arg; - for (int iloop = 0; iloop < narg; ++iloop) { - ROI temp{}; - socket.Receive(temp); - arg.push_back(temp); - } - FILE_LOG(logDEBUG1) << "Set ROI narg: " << narg; - for (int iloop = 0; iloop < narg; ++iloop) { - FILE_LOG(logDEBUG1) - << "(" << arg[iloop].xmin << ", " << arg[iloop].xmax << ", " - << arg[iloop].ymin << ", " << arg[iloop].ymax << ")"; - } + static_assert(sizeof(ROI) == 2 * sizeof(int), "ROI not packed"); + ROI arg; + socket.Receive(arg); + FILE_LOG(logDEBUG1) << "Set ROI: [" << arg.xmin << ", " << arg.xmax << "]"; - if (myDetectorType == EIGER || myDetectorType == JUNGFRAU) + if (myDetectorType != GOTTHARD) functionNotImplemented(); VerifyIdle(socket); diff --git a/slsSupportLib/include/sls_detector_defs.h b/slsSupportLib/include/sls_detector_defs.h index e224a319f..816836d9e 100755 --- a/slsSupportLib/include/sls_detector_defs.h +++ b/slsSupportLib/include/sls_detector_defs.h @@ -220,12 +220,18 @@ format @short structure for a region of interest xmin,xmax,ymin,ymax define the limits of the region */ + + #ifdef __cplusplus + struct ROI { + int xmin{-1}; /**< is the roi xmin (in channel number) */ + int xmax{-1}; /**< is the roi xmax (in channel number)*/ + }; + #else typedef struct { int xmin; /**< is the roi xmin (in channel number) */ int xmax; /**< is the roi xmax (in channel number)*/ - int ymin; /**< is the roi ymin (in channel number)*/ - int ymax; /**< is the roi ymax (in channel number)*/ - } ROI; + } ROI; + #endif /** network parameters diff --git a/slsSupportLib/include/sls_detector_funcs.h b/slsSupportLib/include/sls_detector_funcs.h index cbc2caedd..3aa838a93 100755 --- a/slsSupportLib/include/sls_detector_funcs.h +++ b/slsSupportLib/include/sls_detector_funcs.h @@ -35,6 +35,7 @@ enum detFuncs{ F_SET_DYNAMIC_RANGE, /**< set/get detector dynamic range */ F_SET_READOUT_FLAGS, /**< set/get readout flags */ F_SET_ROI, /**< set/get region of interest */ + F_GET_ROI, F_SET_SPEED, /**< set/get readout speed parameters */ F_EXIT_SERVER, /**< turn off detector server */ F_LOCK_SERVER, /**< Locks/Unlocks server communication to the given client */ @@ -185,6 +186,7 @@ static const char* getFunctionNameFromEnum(enum detFuncs func) { case F_SET_DYNAMIC_RANGE: return "F_SET_DYNAMIC_RANGE"; case F_SET_READOUT_FLAGS: return "F_SET_READOUT_FLAGS"; case F_SET_ROI: return "F_SET_ROI"; + case F_GET_ROI: return "F_GET_ROI"; case F_SET_SPEED: return "F_SET_SPEED"; case F_EXIT_SERVER: return "F_EXIT_SERVER"; case F_LOCK_SERVER: return "F_LOCK_SERVER"; diff --git a/slsSupportLib/include/versionAPI.h b/slsSupportLib/include/versionAPI.h index 1392d0ae8..85bcbd662 100644 --- a/slsSupportLib/include/versionAPI.h +++ b/slsSupportLib/include/versionAPI.h @@ -2,9 +2,9 @@ #define GITBRANCH "developer" #define APIMOENCH 0x181108 #define APICTB 0x190604 -#define APIGOTTHARD 0x190715 #define APILIB 0x190723 #define APIRECEIVER 0x190722 #define APIGUI 0x190723 #define APIJUNGFRAU 0x190730 -#define APIEIGER 0x190809 +#define APIGOTTHARD 0x190813 +#define APIEIGER 0x190814 From 97192c53428a18738e23f761dbef331b0a62efe2 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Wed, 14 Aug 2019 09:31:42 +0200 Subject: [PATCH 069/108] removed prepare acq --- slsDetectorSoftware/include/Detector.h | 3 --- slsDetectorSoftware/src/Detector.cpp | 9 +-------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 824b11bb3..ccd4a3c5e 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -1021,9 +1021,6 @@ class Detector { Result getRunStatus(Positions pos = {}); - /** [Eiger] */ - void prepareAcquisition(); - /** Start detector acquisition (Non blocking) */ void startAcquisition(); diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 81dc9792a..f31e8b4bd 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -1532,15 +1532,8 @@ Result Detector::getRunStatus(Positions pos) { return pimpl->Parallel(&slsDetector::getRunStatus, pos); } -void Detector::prepareAcquisition() { - pimpl->Parallel(&slsDetector::prepareAcquisition, {}); -} - void Detector::startAcquisition() { - if (getDetectorType() == defs::EIGER) { - prepareAcquisition(); - } - pimpl->Parallel(&slsDetector::startAcquisition, {}); + pimpl->startAcquisition(); } void Detector::stopAcquisition() { pimpl->stopAcquisition(); } From 7f5640dd4ebb9073260708091700c28b940e045e Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Wed, 14 Aug 2019 10:32:56 +0200 Subject: [PATCH 070/108] updated multi shm --- slsDetectorSoftware/include/multiSlsDetector.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index c24a00cd9..698c0e7ea 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -17,7 +17,7 @@ class detectorData; #include #define MULTI_SHMAPIVERSION 0x190809 -#define MULTI_SHMVERSION 0x190807 +#define MULTI_SHMVERSION 0x190814 #define SHORT_STRING_LENGTH 50 #define DATE_LENGTH 30 From a23a3f4467c14cc65cda89314a94f4ce3e0a341d Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Wed, 14 Aug 2019 10:36:19 +0200 Subject: [PATCH 071/108] prepare private --- slsDetectorSoftware/include/multiSlsDetector.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index c24a00cd9..8861f5068 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -625,11 +625,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ runStatus getRunStatus(int detPos = -1);// - /** - * Prepares detector for acquisition (Eiger) - * @param detPos -1 for all detectors in list or specific detector position - */ - void prepareAcquisition(int detPos = -1);// + /** * Start detector acquisition (Non blocking) @@ -2166,6 +2162,12 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ void updateUserdetails(); + /** + * Prepares detector for acquisition (Eiger) + * @param detPos -1 for all detectors in list or specific detector position + */ + void prepareAcquisition(int detPos = -1);// + /** * Check if acquiring flag is set, set error if set * @returns FAIL if not ready, OK if ready From 8e2b89d488c3affa4a1ed9c83fd80a31abf47de2 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Wed, 14 Aug 2019 11:54:03 +0200 Subject: [PATCH 072/108] fixed python --- python/sls_detector/experimental.py | 4 +- python/src/experimental.cpp | 4 +- slsDetectorSoftware/include/Detector.h | 323 +++++++++++++------------ slsDetectorSoftware/src/Detector.cpp | 8 +- 4 files changed, 174 insertions(+), 165 deletions(-) diff --git a/python/sls_detector/experimental.py b/python/sls_detector/experimental.py index 1f9c749e1..82a591219 100755 --- a/python/sls_detector/experimental.py +++ b/python/sls_detector/experimental.py @@ -120,11 +120,11 @@ class ExperimentalDetector(multiDetectorApi): # File @property def fname(self): - return element_if_equal(self.getFileName()) + return element_if_equal(self.getFileNamePrefix()) @fname.setter def fname(self, file_name): - self.setFileName(file_name) + self.setFileNamePrefix(file_name) @property def fpath(self): diff --git a/python/src/experimental.cpp b/python/src/experimental.cpp index c7cb0db91..22355f8be 100644 --- a/python/src/experimental.cpp +++ b/python/src/experimental.cpp @@ -44,8 +44,8 @@ void init_experimental(py::module &m) { py::arg(), py::arg() = Positions{}) // File - .def("getFileName", &Detector::getFileName) - .def("setFileName", &Detector::setFileName, py::arg(),py::arg() = Positions{}) + .def("getFileNamePrefix", &Detector::getFileNamePrefix) + .def("setFileNamePrefix", &Detector::setFileNamePrefix, py::arg(),py::arg() = Positions{}) .def("getFilePath", &Detector::getFilePath) .def("setFilePath", &Detector::setFilePath, py::arg(),py::arg() = Positions{}) .def("setFileWrite", &Detector::setFileWrite, py::arg(), diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 12082f3d6..cb4f60bab 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -24,22 +24,22 @@ class Detector { Detector(int multi_id = 0); ~Detector(); - /************************************************** * * * CONFIGURATIOn * * * * ************************************************/ - /** - * Frees the shared memory of this detector and all modules - * belonging to it. - */ + + /* Free the shared memory of this detector and all modules + * belonging to it.*/ void freeSharedMemory(); + void setConfig(const std::string &fname); + Result getHostname(Positions pos = {}) const; - /** - * Frees shared memory and adds detectors to the list - * Also updates local detector cache */ + + /* Frees shared memory, adds detectors to the list + * and updates local detector cache */ void setHostname(const std::vector &value); int getMultiId() const; @@ -58,23 +58,20 @@ class Detector { Result getReceiverSoftwareVersion(Positions pos = {}) const; - /** Get user details of shared memory */ std::string getUserDetailsFromSharedMemory() const; - defs::detectorType getDetectorType() const; - - Result getDetectorTypeAsEnum(Positions pos = {}) const; + Result getDetectorType(Positions pos = {}) const; Result getDetectorTypeAsString(Positions pos = {}) const; - /** @returns the total number of detectors in the multidetector structure */ + /** @returns the total number of detectors */ int size() const; defs::coordinates getNumberOfDetectors() const; Result getNumberOfChannels(Positions pos = {}) const; - Result + Result getNumberOfChannelsInclGapPixels(Positions pos = {}) const; defs::coordinates getMaxNumberOfChannels() const; @@ -86,22 +83,22 @@ class Detector { */ void setMaxNumberOfChannels(const defs::coordinates value); - /** [Eiger with specific quad hardware] */ + /** [Eiger] with specific quad hardware */ Result getQuad(Positions pos = {}) const; - /** [Eiger with specific quad hardware] */ + /** [Eiger] with specific quad hardware */ void setQuad(const bool enable, Positions pos = {}); /** [Eiger] */ Result getReadNLines(Positions pos = {}) const; - /** [Eiger] Number of lines to read out per half module - * Options: 0 - 256. Depending on dynamic range and - * 10 GbE enabled, only specific values are accepted - */ + /** [Eiger] Number of lines to read out per half module + * Options: 0 - 256. Depending on dynamic range and + * 10 GbE enabled, only specific values are accepted + */ void setReadNLines(const int value, Positions pos = {}); - Result getControlPort(Positions pos = {}) const; + Result getControlPort(Positions pos = {}) const; /** Detector Control TCP port (for client communication with Detector * control server) */ @@ -159,12 +156,15 @@ class Detector { /** [Not CTB] Sets the detector trimbit/settings directory */ void setSettingsDir(const std::string &value, Positions pos = {}); - /** [Not CTB] Loads the modules settings/trimbits reading from a specific file - * file name extension is automatically generated from detector serial number */ + /** [Not CTB] Loads the modules settings/trimbits reading from a specific + * file + * file name extension is automatically generated from detector serial + * number */ void loadSettingsFile(const std::string &value, Positions pos = {}); /** [Not CTB] Saves the modules settings/trimbits to a specific file - * file name extension is automatically generated from detector serial number */ + * file name extension is automatically generated from detector serial + * number */ void saveSettingsFile(const std::string &value, Positions pos = {}); /** Configures in detector the destination for UDP packets */ @@ -188,8 +188,8 @@ class Detector { Result getStorageCellStart(Positions pos = {}) const; /** - * [Jungfrau] Sets the storage cell storing the first acquisition of the series - * Options: 0-15 + * [Jungfrau] Sets the storage cell storing the first acquisition of the + * series Options: 0-15 */ void setStoragecellStart(int cell, Positions pos = {}); @@ -212,23 +212,23 @@ class Detector { Result getPeriod(Positions pos = {}) const; void setPeriod(ns t, Positions pos = {}); - + /** [Gotthard][Jungfrau] */ Result getDelayAfterTrigger(Positions pos = {}) const; /** [Gotthard][Jungfrau] */ void setDelayAfterTrigger(ns value, Positions pos = {}); - /** [Eiger in 32 bit mode] */ + /** [Eiger] in 32 bit mode */ Result getSubExptime(Positions pos = {}) const; - /** [Eiger in 32 bit mode] */ + /** [Eiger] in 32 bit mode */ void setSubExptime(ns t, Positions pos = {}); - /** [Eiger in 32 bit mode] */ + /** [Eiger] in 32 bit mode */ Result getSubDeadTime(Positions pos = {}) const; - /** [Eiger in 32 bit mode] */ + /** [Eiger] in 32 bit mode */ void setSubDeadTime(ns value, Positions pos = {}); /** [Jungfrau] */ @@ -243,7 +243,7 @@ class Detector { /** [Gotthard][Jungfrau][CTB] */ Result getNumberOfCyclesLeft(Positions pos = {}) const; - + /** [Gotthard] */ Result getExptimeLeft(Positions pos = {}) const; @@ -259,7 +259,7 @@ class Detector { /** [Jungfrau][CTB] Get time from detector start */ Result getActualTime(Positions pos = {}) const; - /** [Jungfrau][CTB] Get timestamp at a frame start */ + /** [Jungfrau][CTB] Get timestamp at a frame start */ Result getMeasurementTime(Positions pos = {}) const; /** [Eiger] Get measured period between previous two frames */ @@ -271,7 +271,7 @@ class Detector { /** [Eiger][Jungfrau] */ Result getSpeed(Positions pos = {}) const; - /** [Eiger][Jungfrau] + /** [Eiger][Jungfrau] * @param value speed (0 full speed, 1 half speed, 2 quarter speed) */ void setSpeed(int value, Positions pos = {}); @@ -371,14 +371,14 @@ class Detector { Result getVoltage(defs::dacIndex index, Positions pos = {}) const; /** - * [CTB] mV + * [CTB] mV * Options: V_LIMIT, V_POWER_A, V_POWER_B, V_POWER_C, * V_POWER_D, V_POWER_IO, V_POWER_CHIP */ void setVoltage(int value, defs::dacIndex index, Positions pos = {}); /** - * [CTB] mV + * [CTB] mV * Options: V_POWER_A, V_POWER_B, V_POWER_C, V_POWER_D, V_POWER_IO, * V_POWER_CHIP */ @@ -386,7 +386,7 @@ class Detector { Positions pos = {}) const; /** - * [CTB] mA + * [CTB] mA * Options: I_POWER_A, I_POWER_B, I_POWER_C, I_POWER_D, I_POWER_IO */ Result getMeasuredCurrent(defs::dacIndex index, @@ -399,19 +399,23 @@ class Detector { void setDAC(int value, defs::dacIndex index, bool mV, Positions pos = {}); - Result getTimingMode(Positions pos = {}) const; + Result + getTimingMode(Positions pos = {}) const; /** * [Gotthard, Jungfrau, CTB Options: AUTO_TIMING, TRIGGER_EXPOSURE] * [Eiger Options: AUTO_TIMING, TRIGGER_EXPOSURE, GATED, BURST_TRIGGER] */ - void setTimingMode(defs::externalCommunicationMode value, Positions pos = {}); + void setTimingMode(defs::externalCommunicationMode value, + Positions pos = {}); /** [Gotthard] */ - Result getExternalSignalFlags(Positions pos = {}) const; + Result + getExternalSignalFlags(Positions pos = {}) const; /** [Gotthard] Options: TRIGGER_IN_RISING_EDGE, TRIGGER_IN_FALLING_EDGE */ - void setExternalSignalFlags(defs::externalSignalFlag value, Positions pos = {}); + void setExternalSignalFlags(defs::externalSignalFlag value, + Positions pos = {}); /** [Eiger] */ Result getParallelMode(Positions pos = {}) const; @@ -428,7 +432,8 @@ class Detector { /** [CTB] */ Result getSignalType(Positions pos = {}) const; - /** [CTB] Options: NORMAL_READOUT = 0, DIGITAL_ONLY = 1, ANALOG_AND_DIGITAL = 2 */ + /** [CTB] Options: NORMAL_READOUT = 0, DIGITAL_ONLY = 1, ANALOG_AND_DIGITAL + * = 2 */ void setSignalType(int value, Positions pos = {}); /** [Eiger] */ @@ -471,7 +476,7 @@ class Detector { * Validates and sets the receiver. * Updates local receiver cache parameters * Configures the detector to the receiver as UDP destination - * @param receiver receiver hostname or IP address + * @param receiver receiver hostname or IP address */ void setReceiverHostname(const std::string &receiver, Positions pos = {}); @@ -496,7 +501,7 @@ class Detector { void setReceiverUDPMAC2(const std::string &udpmac, Positions pos = {}); Result getReceiverUDPPort(Positions pos = {}) const; - + void setReceiverUDPPort(int udpport, Positions pos = {}); /** [Eiger right port][Jungfrau bottom half] */ @@ -507,30 +512,30 @@ class Detector { /** [Jungfrau] */ Result getNumberofUDPInterfaces(Positions pos = {}) const; - + /** [Jungfrau] Also restarts client and receiver sockets */ void setNumberofUDPInterfaces(int n, Positions pos = {}); /** [Jungfrau] */ Result getSelectedUDPInterface(Positions pos = {}) const; - - /** + + /** * [Jungfrau: * Effective only when number of interfaces is 1. - * Options: 0 (outer, default), 1(inner)] + * Options: 0 (outer, default), 1(inner)] */ void selectUDPInterface(int interface, Positions pos = {}); Result getClientStreamingPort(Positions pos = {}) const; - /** + /** * pos can be for a single module or all modules, not a subset * If pos for all modules, ports for each module is calculated (increments) * Restarts client zmq sockets */ void setClientDataStreamingInPort(int port, Positions pos = {}); - + Result getReceiverStreamingPort(Positions pos = {}) const; - /** + /** * pos can be for a single module or all modules, not a subset * If pos for all modules, ports for each module is calculated (increments) * Restarts receiver zmq sockets @@ -538,51 +543,54 @@ class Detector { void setReceiverDataStreamingOutPort(int port, Positions pos = {}); Result getClientStreamingIP(Positions pos = {}) const; - + // TODO these should probably be the same ?? same as what? void setClientDataStreamingInIP(const std::string &ip, Positions pos = {}); Result getReceiverStreamingIP(Positions pos = {}) const; - + void setReceiverDataStreamingOutIP(const std::string &ip, Positions pos = {}); /** [Eiger, Jungfrau] */ Result getFlowControl10G(Positions pos = {}) const; - + /** [Eiger, Jungfrau] */ void setFlowControl10G(bool enable, Positions pos = {}); /** [Eiger, Jungfrau] */ Result getTransmissionDelayFrame(Positions pos = {}) const; - - /** - * [Jungfrau: Sets the transmission delay of the first UDP packet being streamed out of the module - * Options: 0 - 31, each value represenets 1 ms ] - * [Eiger: Sets the transmission delay of entire frame streamed out for both left and right UDP ports] + + /** + * [Jungfrau: Sets the transmission delay of the first UDP packet being + * streamed out of the module Options: 0 - 31, each value represenets 1 ms ] + * [Eiger: Sets the transmission delay of entire frame streamed out for both + * left and right UDP ports] */ void setTransmissionDelayFrame(int value, Positions pos = {}); /** [Eiger] */ Result getTransmissionDelayLeft(Positions pos = {}) const; - /** + /** * [Eiger] - * Sets the transmission delay of first packet streamed ut of the left UDP port + * Sets the transmission delay of first packet streamed ut of the left UDP + * port */ void setTransmissionDelayLeft(int value, Positions pos = {}); /** [Eiger] */ Result getTransmissionDelayRight(Positions pos = {}) const; - - /** + + /** * [Eiger] - * Sets the transmission delay of first packet streamed ut of the right UDP port + * Sets the transmission delay of first packet streamed ut of the right UDP + * port */ void setTransmissionDelayRight(int value, Positions pos = {}); - + /** [Moench] */ Result getAdditionalJsonHeader(Positions pos = {}) const; - + /** [Moench] */ void setAdditionalJsonHeader(const std::string &jsonheader, Positions pos = {}); @@ -590,10 +598,10 @@ class Detector { /** [Moench] */ Result getAdditionalJsonParameter(const std::string &key, Positions pos = {}) const; - /** + /** * [Moench] - * Sets the value for additional json header parameter if found, - * else appends the parameter key and value + * Sets the value for additional json header parameter if found, + * else appends the parameter key and value * The value cannot be empty */ void setAdditionalJsonParameter(const std::string &key, @@ -604,49 +612,52 @@ class Detector { * else? Use a generic zmq message passing system... * For now limiting to all detectors working the same*/ /** [Moench: -1 if not found or cannot convert to int] */ - Result getDetectorMinMaxEnergyThreshold(const bool isEmax, Positions pos = {}) const; - + Result getDetectorMinMaxEnergyThreshold(const bool isEmax, + Positions pos = {}) const; + /** [Moench] */ - void setDetectorMinMaxEnergyThreshold(const bool isEmax, const int value, Positions pos = {}); - + void setDetectorMinMaxEnergyThreshold(const bool isEmax, const int value, + Positions pos = {}); + /** [Moench: -1 if unknown mode] */ Result getFrameMode(Positions pos = {}) const; - - /** [Moench] */ + + /** [Moench] */ void setFrameMode(defs::frameModeType value, Positions pos = {}); - + /** [Moench: -1 if unknown mode] */ - Result getDetectorMode(Positions pos = {}) const; - + Result getDetectorMode(Positions pos = {}) const; + /** [Moench] */ void setDetectorMode(defs::detectorModeType value, Positions pos = {}); /** [Gotthard] */ Result getDigitalTestBit(Positions pos = {}); - + /** [Gotthard] */ Result setDigitalTestBit(const int value, Positions pos = {}); - + /** [Gotthard][Jungfrau][CTB] */ Result executeFirmwareTest(Positions pos = {}); - + /** [Gotthard][Jungfrau][CTB] */ Result executeBusTest(Positions pos = {}); - + /** [Gotthard] subset modules not allowed */ void loadDarkImage(const std::string &fname, Positions pos = {}); - + /** [Gotthard] subset modules not allowed */ void loadGainImage(const std::string &fname, Positions pos = {}); - + /** - * [Gotthard] subset modules not allowed + * [Gotthard] subset modules not allowed * @param startACQ if start acq after reading counter */ - void getCounterMemoryBlock(const std::string &fname, bool startACQ, Positions pos = {}); - + void getCounterMemoryBlock(const std::string &fname, bool startACQ, + Positions pos = {}); + /** - * [Gotthard] + * [Gotthard] * @param startACQ if start acq after resetting counter * TODO! does it make sense to call one detector? */ @@ -654,18 +665,19 @@ class Detector { /** [Eiger] */ Result getCounterBit(Positions pos = {}) const; - - /** [Eiger] If it is set, it resets chips completely (else partially) before an acquisition TODO: if it makes sense */ + + /** [Eiger] If it is set, it resets chips completely (else partially) before + * an acquisition TODO: if it makes sense */ void setCounterBit(bool value, Positions pos = {}); /** [Gotthard]*/ Result getROI(Positions pos = {}) const; - - /** - * [Gotthard] + + /** + * [Gotthard] * Options: Only a single ROI per module * Can set only a single ROI at a time - * @param module position index + * @param module position index */ void setROI(defs::ROI value, int moduleId); @@ -718,11 +730,11 @@ class Detector { Result getBottom(Positions pos = {}) const; /** [Eiger] for gui purposes */ - void setBottom(bool value, Positions pos = {}); + void setBottom(bool value, Positions pos = {}); - /** [Eiger] + /** [Eiger] * @returns -1 if they are all different - */ + */ Result getAllTrimbits(Positions pos = {}) const; /**[Eiger] */ @@ -732,7 +744,7 @@ class Detector { Result getGapPixelsEnable(Positions pos = {}) const; /** - * [Eiger] + * [Eiger] * 4 bit mode not implemented in Receiver, but in client data call back * Fills in gap pixels in data */ @@ -749,7 +761,8 @@ class Detector { */ void pulsePixel(int n, int x, int y, Positions pos = {}); - /** [Eiger] Pulse Pixel n times and move by a relative value of x and y coordinates */ + /** [Eiger] Pulse Pixel n times and move by a relative value of x and y + * coordinates */ void pulsePixelNMove(int n, int x, int y, Positions pos = {}); /** [Eiger] Pulse chip n times */ @@ -761,10 +774,10 @@ class Detector { /** * [Jungfrau]Set threshold temperature * If temperature crosses threshold temperature - * and temperature control is enabled, - * power to chip will be switched off and + * and temperature control is enabled, + * power to chip will be switched off and * temperature event will be set - * @param val value in millidegrees TODO! Verify + * @param val value in millidegrees TODO! Verify */ void setThresholdTemperature(int temp, Positions pos = {}); @@ -786,10 +799,10 @@ class Detector { /** [Jungfrau][CTB] */ void resetFPGA(Positions pos = {}); - /** - * Copy detector server fname from tftp folder of hostname to detector + /** + * Copy detector server fname from tftp folder of hostname to detector * Also changes respawn server, which is effective after a reboot. - */ + */ void copyDetectorServer(const std::string &fname, const std::string &hostname, Positions pos = {}); @@ -799,8 +812,9 @@ class Detector { /** * [Jungfrau][Gotthard][CTB] * Updates the firmware, detector server and then reboots detector - * controller blackfin. - * @param sname name of detector server binary found on tftp folder of host pc + * controller blackfin. + * @param sname name of detector server binary found on tftp folder of host + * pc * @param hostname name of pc to tftp from * @param fname programming file name * @param pos detector positions @@ -813,7 +827,7 @@ class Detector { Result getPowerChip(Positions pos = {}) const; /** [Jungfrau] */ - void setPowerChip(bool on, Positions pos = {}); + void setPowerChip(bool on, Positions pos = {}); /** [Jungfrau] */ Result getAutoCompDisable(Positions pos = {}) const; @@ -834,19 +848,19 @@ class Detector { /** [Eiger][Jungfrau] */ Result getStartingFrameNumber(Positions pos = {}) const; - + /** [Eiger][Jungfrau] */ void setStartingFrameNumber(uint64_t value, Positions pos); /** [Eiger] */ Result getTenGigaEnabled(Positions pos = {}) const; - + /** [Eiger] */ void setTenGigaEnabled(bool value, Positions pos = {}); /** [CTB] */ Result getLEDEnable(Positions pos = {}) const; - + /** [CTB] */ void setLEDEnable(bool enable, Positions pos = {}); @@ -865,42 +879,42 @@ class Detector { * * * ************************************************/ Result getFileFormat(Positions pos = {}) const; - - /** default binary, Options: BINARY, HDF5 (library must be compiled with this option) */ + + /** default binary, Options: BINARY, HDF5 (library must be compiled with + * this option) */ void setFileFormat(defs::fileFormat f, Positions pos = {}); - + Result getFilePath(Positions pos = {}) const; - + void setFilePath(const std::string &fname, Positions pos = {}); - + Result getFileNamePrefix(Positions pos = {}) const; - + /** default run */ void setFileNamePrefix(const std::string &fname, Positions pos = {}); Result getFileIndex(Positions pos = {}) const; - + void setFileIndex(int i, Positions pos = {}); - + Result getFileWrite(Positions pos = {}) const; - - /** default writes */ - + + /** default writes */ + void setFileWrite(bool value, Positions pos = {}); - + Result getMasterFileWrite(Positions pos = {}) const; - + void setMasterFileWrite(bool value, Positions pos = {}); - + Result getFileOverWrite(Positions pos = {}) const; - + /** default overwites */ void setFileOverWrite(bool value, Positions pos = {}); - - Result getFramesPerFile(Positions pos = {}) const; - - void setFramesPerFile(int n, Positions pos = {}); + Result getFramesPerFile(Positions pos = {}) const; + + void setFramesPerFile(int n, Positions pos = {}); /************************************************** * * @@ -929,8 +943,8 @@ class Detector { void execReceiverCommand(const std::string &cmd, Positions pos = {}); Result getReceiverStreamingFrequency(Positions pos = {}) const; - - /** @param freq nth frame streamed out of receiver. + + /** @param freq nth frame streamed out of receiver. * If 0, streaming timer is the timeout, * after which current frame sent out. Default is 0 at 200 ms. * For every frame, set freq to 1. @@ -938,40 +952,40 @@ class Detector { void setReceiverStreamingFrequency(int freq, Positions pos = {}); Result getReceiverStreamingTimer(Positions pos = {}) const; - + /** - * If receiver streaming frequency is 0 (default), then this timer between each - * data stream is set. Default is 200 ms. + * If receiver streaming frequency is 0 (default), then this timer between + * each data stream is set. Default is 200 ms. */ void setReceiverStreamingTimer(int time_in_ms, Positions pos = {}); bool getDataStreamingToClient() const; - + void setDataStreamingToClient(bool value); - + Result getDataStreamingFromReceiver(Positions pos = {}) const; - + void setDataStreamingFromReceiver(bool value, Positions pos = {}); Result getReceiverFifoDepth(Positions pos = {}) const; - + void setReceiverFifoDepth(int nframes, Positions pos = {}); - + Result getReceiverSilentMode(Positions pos = {}) const; - + void setReceiverSilentMode(bool value, Positions pos = {}); Result getReceiverFrameDiscardPolicy(Positions pos = {}) const; - - /** - * default NO_DISCARD + + /** + * default NO_DISCARD * Options: NO_DISCARD, DISCARD_EMPTY_FRAMES, DISCARD_PARTIAL_FRAMES */ void setReceiverFrameDiscardPolicy(defs::frameDiscardPolicy f, Positions pos = {}); Result getPartialFramesPadding(Positions pos = {}) const; - + /** padding enabled */ void setPartialFramesPadding(bool value, Positions pos = {}); @@ -996,8 +1010,8 @@ class Detector { * * * ************************************************/ /** - * Blocking call, starts the receiver and detector. - * Increments file index if file write enabled. + * Blocking call, starts the receiver and detector. + * Increments file index if file write enabled. * Acquired the number of frames set. */ void acquire(); @@ -1016,7 +1030,7 @@ class Detector { Result getRunStatus(Positions pos = {}); - /** Start detector acquisition (Non blocking) */ + /** Non blocking */ void startAcquisition(); void stopAcquisition(); @@ -1026,17 +1040,17 @@ class Detector { /** Receiver starts listening to UDP packets from detector */ void startReceiver(Positions pos = {}); - + /** Receiver stops listening to UDP packets from detector */ void stopReceiver(Positions pos = {}); - + /** Read back the run status of the receiver */ Result getReceiverStatus(Positions pos = {}); Result getFramesCaughtByReceiver(Positions pos = {}) const; - + Result getReceiverCurrentFrameIndex(Positions pos = {}) const; - + void resetFramesCaught(Positions pos = {}); /************************************************** @@ -1044,7 +1058,7 @@ class Detector { * PATTERN * * * * ************************************************/ - + /** [CTB] */ void setPattern(const std::string &fname, Positions pos = {}); @@ -1077,7 +1091,7 @@ class Detector { /* [CTB] */ Result getPatternWaitAddr(int level, Positions pos = {}) const; - + /** [CTB] Options: level 0-2 */ void setPatternWaitAddr(int level, int addr, Positions pos = {}); @@ -1100,7 +1114,6 @@ class Detector { * pattern */ void setPatternBitMask(uint64_t mask, Positions pos = {}); - }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 6268498c9..f4280bb8a 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -62,12 +62,8 @@ Result Detector::getReceiverSoftwareVersion(Positions pos) const { std::string Detector::getUserDetailsFromSharedMemory() const { return pimpl->getUserDetails(); } -defs::detectorType Detector::getDetectorType() const { - return pimpl->getDetectorTypeAsEnum(); -} - Result -Detector::getDetectorTypeAsEnum(Positions pos) const { +Detector::getDetectorType(Positions pos) const { return pimpl->Parallel(&slsDetector::getDetectorTypeAsEnum, pos); } @@ -487,7 +483,7 @@ Result Detector::getTemp(defs::dacIndex index, Positions pos) const { throw RuntimeError("Unknown Temperature Index"); } auto res = pimpl->Parallel(&slsDetector::getADC, pos, index); - switch (getDetectorType()) { + switch (getDetectorType().squash()) { case defs::EIGER: case defs::JUNGFRAU: for (auto &it : res) { From d14fdc3a3fddce98dd5bb96203b7c8796ce12402 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Wed, 14 Aug 2019 17:40:30 +0200 Subject: [PATCH 073/108] WIP --- slsDetectorSoftware/include/Detector.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index cb4f60bab..167a114a5 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -900,7 +900,6 @@ class Detector { Result getFileWrite(Positions pos = {}) const; /** default writes */ - void setFileWrite(bool value, Positions pos = {}); Result getMasterFileWrite(Positions pos = {}) const; @@ -984,6 +983,7 @@ class Detector { */ void setReceiverFrameDiscardPolicy(defs::frameDiscardPolicy f, Positions pos = {}); + Result getPartialFramesPadding(Positions pos = {}) const; /** padding enabled */ From ba0c6ff286d371b9ba34f65ff8242afaea8009dc Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Wed, 14 Aug 2019 17:49:09 +0200 Subject: [PATCH 074/108] eiger bug fix: quad gap pixels --- slsDetectorGui/src/qDrawPlot.cpp | 7 ++- .../include/multiSlsDetector.h | 3 +- slsDetectorSoftware/src/multiSlsDetector.cpp | 60 ++++++++++++++----- slsDetectorSoftware/src/slsDetector.cpp | 7 +-- slsReceiverSoftware/include/DataStreamer.h | 6 +- slsReceiverSoftware/src/DataStreamer.cpp | 7 ++- .../src/slsReceiverImplementation.cpp | 6 +- slsSupportLib/include/ZmqSocket.h | 8 ++- 8 files changed, 72 insertions(+), 32 deletions(-) diff --git a/slsDetectorGui/src/qDrawPlot.cpp b/slsDetectorGui/src/qDrawPlot.cpp index 2784f9e0a..b242c8711 100755 --- a/slsDetectorGui/src/qDrawPlot.cpp +++ b/slsDetectorGui/src/qDrawPlot.cpp @@ -90,8 +90,11 @@ void qDrawPlot::SetupPlots() { break; case slsDetectorDefs::EIGER: if (myDet->getQuad()) { - nPixelsX = (myDet->getTotalNumberOfChannelsInclGapPixels(slsDetectorDefs::X) / 2) - 1; - nPixelsY = myDet->getTotalNumberOfChannelsInclGapPixels(slsDetectorDefs::Y) * 2; + nPixelsX /= 2; + nPixelsY *= 2; + if (nPixelsX != nPixelsY) { + --nPixelsX; + } } break; default: diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index c55266144..367013933 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -2213,9 +2213,10 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param image pointer to image without gap pixels * @param gpImage poiner to image with gap pixels, if NULL, allocated * inside function + * quadEnable quad enabled * @returns number of data bytes of image with gap pixels */ - int processImageWithGapPixels(char *image, char *&gpImage); + int processImageWithGapPixels(char *image, char *&gpImage, bool quadEnable); /** * Create Receiving Data Sockets diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index 1dd184d87..c3251b052 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -2839,6 +2839,7 @@ void multiSlsDetector::readFrameFromReceiver() { int nDetPixelsX = 0; int nDetPixelsY = 0; bool gappixelsenable = false; + bool quadEnable = false; bool eiger = false; bool numInterfaces = getNumberofUDPInterfaces(); // cannot pick up from zmq @@ -2932,10 +2933,9 @@ void multiSlsDetector::readFrameFromReceiver() { ? true : false; // to be changed to EIGER when firmware // updates its header data - // gap pixels enable gappixelsenable = (doc["gappixels"].GetUint() == 0) ? false : true; - + quadEnable = (doc["quad"].GetUint() == 0) ? false : true; FILE_LOG(logDEBUG1) << "One Time Header Info:" "\n\tsize: " @@ -2945,7 +2945,8 @@ void multiSlsDetector::readFrameFromReceiver() { << "\n\tnPixelsX: " << nPixelsX << "\n\tnPixelsY: " << nPixelsY << "\n\tnX: " << nX << "\n\tnY: " << nY << "\n\teiger: " << eiger - << "\n\tgappixelsenable: " << gappixelsenable; + << "\n\tgappixelsenable: " << gappixelsenable + << "\n\tquadEnable: " << quadEnable; } // each time, parse rest of header currentFileName = doc["fname"].GetString(); @@ -3011,13 +3012,31 @@ void multiSlsDetector::readFrameFromReceiver() { } } } + FILE_LOG(logINFOBLUE) + << "Call Back Info:" + << "\n\t nDetPixelsX: " << nDetPixelsX + << "\n\t nDetPixelsY: " << nDetPixelsY + << "\n\t databytes: " << multisize + << "\n\t dynamicRange: " << dynamicRange; // send data to callback if (data) { setCurrentProgress(currentAcquisitionIndex + 1); // 4bit gap pixels if (dynamicRange == 4 && gappixelsenable) { - int n = processImageWithGapPixels(multiframe, multigappixels); + if (quadEnable) { + nDetPixelsX += 2; + nDetPixelsY += 2; + } else { + nDetPixelsX = nX * (nPixelsX + 3); + nDetPixelsY = nY * (nPixelsY + 1); + } + int n = processImageWithGapPixels(multiframe, multigappixels, quadEnable); + FILE_LOG(logINFORED) + << "Call Back Info Recalculated:" + << "\n\t nDetPixelsX: " << nDetPixelsX + << "\n\t nDetPixelsY: " << nDetPixelsY + << "\n\t databytes: " << n; thisData = new detectorData( getCurrentProgress(), currentFileName.c_str(), nDetPixelsX, nDetPixelsY, multigappixels, n, dynamicRange, @@ -3073,14 +3092,23 @@ void multiSlsDetector::readFrameFromReceiver() { delete[] multigappixels; } -int multiSlsDetector::processImageWithGapPixels(char *image, char *&gpImage) { - // eiger 4 bit mode - int nxb = multi_shm()->numberOfDetector[X] * (512 + 3); +int multiSlsDetector::processImageWithGapPixels(char *image, char *&gpImage, bool quadEnable) { + // eiger 4 bit mode + int nxb = multi_shm()->numberOfDetector[X] * (512 + 3); //(divided by 2 already) int nyb = multi_shm()->numberOfDetector[Y] * (256 + 1); - int gapdatabytes = nxb * nyb; - + int nchipInRow = 4; int nxchip = multi_shm()->numberOfDetector[X] * 4; int nychip = multi_shm()->numberOfDetector[Y] * 1; + if (quadEnable) { + nxb = multi_shm()->numberOfDetector[X] * (256 + 1); //(divided by 2 already) + nyb = multi_shm()->numberOfDetector[Y] * (512 + 2); + nxchip /= 2; + nychip *= 2; + nchipInRow /= 2; + } + int gapdatabytes = nxb * nyb; + + // allocate if (gpImage == nullptr) { @@ -3097,14 +3125,14 @@ int multiSlsDetector::processImageWithGapPixels(char *image, char *&gpImage) { // copying line by line src = image; dst = gpImage; - for (int row = 0; row < nychip; ++row) { // for each chip in a row + for (int row = 0; row < nychip; ++row) { // for each chip row for (int ichipy = 0; ichipy < b1chipy; ++ichipy) { // for each row in a chip - for (int col = 0; col < nxchip; ++col) { + for (int col = 0; col < nxchip; ++col) {// for each chip in a row memcpy(dst, src, b1chipx); src += b1chipx; dst += b1chipx; - if (((col + 1) % 4) != 0) { + if (((col + 1) % nchipInRow) != 0) { // skip gap pixels ++dst; } } @@ -3118,12 +3146,12 @@ int multiSlsDetector::processImageWithGapPixels(char *image, char *&gpImage) { uint8_t temp, g1, g2; int mod; dst = gpImage; - for (int row = 0; row < nychip; ++row) { // for each chip in a row + for (int row = 0; row < nychip; ++row) { // for each chip row for (int ichipy = 0; ichipy < b1chipy; ++ichipy) { // for each row in a chip - for (int col = 0; col < nxchip; ++col) { + for (int col = 0; col < nxchip; ++col) {// for each chip in a row dst += b1chipx; - mod = (col + 1) % 4; + mod = (col + 1) % nchipInRow; // get gap pixels // copy gap pixel(chip 0, 1, 2) if (mod != 0) { // neighbouring gap pixels to left @@ -3155,7 +3183,7 @@ int multiSlsDetector::processImageWithGapPixels(char *image, char *&gpImage) { uint8_t temp, g1, g2; char *dst_prevline = nullptr; dst = gpImage; - for (int row = 0; row < nychip; ++row) { // for each chip in a row + for (int row = 0; row < nychip; ++row) { // for each chip row dst += (b1chipy * nxb); // horizontal copying of gap pixels from neighboring past line // (bottom parts) diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index c2fc2416f..faa8eb011 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -657,6 +657,7 @@ bool slsDetector::getQuad() { sendToDetector(F_GET_QUAD, nullptr, retval); FILE_LOG(logDEBUG1) << "Quad Type :" << retval; return (retval == 0 ? false : true); + } void slsDetector::setQuad(const bool enable) { @@ -1798,6 +1799,7 @@ std::string slsDetector::setReceiverHostname(const std::string &receiverIP) { enableGapPixels(shm()->gappixels); enableTenGigabitEthernet(shm()->tenGigaEnable); setReadOutFlags(GET_READOUT_FLAGS); + setQuad(getQuad()); break; case CHIPTESTBOARD: @@ -1807,6 +1809,7 @@ std::string slsDetector::setReceiverHostname(const std::string &receiverIP) { setReadOutFlags(GET_READOUT_FLAGS); setADCEnableMask(shm()->adcEnableMask); setReceiverDbitOffset(shm()->rxDbitOffset); + setReceiverDbitList(shm()->rxDbitList); break; case MOENCH: @@ -1824,10 +1827,6 @@ std::string slsDetector::setReceiverHostname(const std::string &receiverIP) { break; } - if (shm()->myDetectorType == CHIPTESTBOARD) { - setReceiverDbitList(shm()->rxDbitList); - } - setReceiverSilentMode(static_cast(shm()->rxSilentMode)); // data streaming setReceiverStreamingFrequency(shm()->rxReadFreq); diff --git a/slsReceiverSoftware/include/DataStreamer.h b/slsReceiverSoftware/include/DataStreamer.h index 152d006c0..567cf364a 100755 --- a/slsReceiverSoftware/include/DataStreamer.h +++ b/slsReceiverSoftware/include/DataStreamer.h @@ -31,9 +31,10 @@ class DataStreamer : private virtual slsDetectorDefs, public ThreadObject { * @param ajh additional json header * @param nd pointer to number of detectors in each dimension * @param gpEnable pointer to gap pixels enable + * @param qe pointer to quad Enable */ DataStreamer(int ind, Fifo* f, uint32_t* dr, ROI* r, - uint64_t* fi, int fd, char* ajh, int* nd, bool* gpEnable); + uint64_t* fi, int fd, char* ajh, int* nd, bool* gpEnable, bool* qe); /** * Destructor @@ -226,5 +227,8 @@ class DataStreamer : private virtual slsDetectorDefs, public ThreadObject { /** Gap Pixels Enable */ bool* gapPixelsEnable; + /** Quad Enable */ + bool* quadEnable; + }; diff --git a/slsReceiverSoftware/src/DataStreamer.cpp b/slsReceiverSoftware/src/DataStreamer.cpp index 3d5db32b9..2f16b7078 100755 --- a/slsReceiverSoftware/src/DataStreamer.cpp +++ b/slsReceiverSoftware/src/DataStreamer.cpp @@ -17,7 +17,7 @@ const std::string DataStreamer::TypeName = "DataStreamer"; DataStreamer::DataStreamer(int ind, Fifo* f, uint32_t* dr, ROI* r, - uint64_t* fi, int fd, char* ajh, int* nd, bool* gpEnable) : + uint64_t* fi, int fd, char* ajh, int* nd, bool* gpEnable, bool* qe) : ThreadObject(ind), runningFlag(0), generalData(nullptr), @@ -34,7 +34,8 @@ DataStreamer::DataStreamer(int ind, Fifo* f, uint32_t* dr, ROI* r, firstAcquisitionIndex(0), firstMeasurementIndex(0), completeBuffer(nullptr), - gapPixelsEnable(gpEnable) + gapPixelsEnable(gpEnable), + quadEnable(qe) { numDet[0] = nd[0]; numDet[1] = nd[1]; @@ -263,7 +264,7 @@ int DataStreamer::SendHeader(sls_receiver_header* rheader, uint32_t size, uint32 header.modId, header.row, header.column, header.reserved, header.debug, header.roundRNumber, header.detType, header.version, - *gapPixelsEnable ? 1 : 0, flippedDataX, + *gapPixelsEnable ? 1 : 0, flippedDataX, *quadEnable, additionJsonHeader ); } diff --git a/slsReceiverSoftware/src/slsReceiverImplementation.cpp b/slsReceiverSoftware/src/slsReceiverImplementation.cpp index 28b3f100e..a77b40da8 100755 --- a/slsReceiverSoftware/src/slsReceiverImplementation.cpp +++ b/slsReceiverSoftware/src/slsReceiverImplementation.cpp @@ -793,7 +793,7 @@ int slsReceiverImplementation::setNumberofUDPInterfaces(const int n) { } dataStreamer.push_back(sls::make_unique( i, fifo[i].get(), &dynamicRange, &roi, &fileIndex, - fd, additionalJsonHeader, (int*)nd, &gapPixelsEnable)); + fd, additionalJsonHeader, (int*)nd, &gapPixelsEnable, &quadEnable)); dataStreamer[i]->SetGeneralData(generalData); dataStreamer[i]->CreateZmqSockets( &numThreads, streamingPort, streamingSrcIP); @@ -945,7 +945,7 @@ int slsReceiverImplementation::setDataStreamEnable(const bool enable) { } dataStreamer.push_back(sls::make_unique( i, fifo[i].get(), &dynamicRange, &roi, &fileIndex, - fd, additionalJsonHeader, (int*)nd, &gapPixelsEnable)); + fd, additionalJsonHeader, (int*)nd, &gapPixelsEnable, &quadEnable)); dataStreamer[i]->SetGeneralData(generalData); dataStreamer[i]->CreateZmqSockets( &numThreads, streamingPort, streamingSrcIP); @@ -1370,7 +1370,7 @@ void slsReceiverImplementation::stopReceiver() { dataProcessor[0]->EndofAcquisition(anycaught, maxIndexCaught); } - // wait for the processes (DataStreamer) to be done + // wait for the processes (dataStreamer) to be done running = true; while (running) { running = false; diff --git a/slsSupportLib/include/ZmqSocket.h b/slsSupportLib/include/ZmqSocket.h index 033205914..9506a1804 100755 --- a/slsSupportLib/include/ZmqSocket.h +++ b/slsSupportLib/include/ZmqSocket.h @@ -265,6 +265,7 @@ public: * @param version detector header version * @param gapPixelsEnable gap pixels enable (exception: if gap pixels enable for 4 bit mode, data is not yet gap pixel enabled in receiver) * @param flippedDataX if it is flipped across x axis + * @param quadEnable if quad is enabled * @param additionalJsonHeader additional json header * @returns 0 if error, else 1 */ @@ -276,6 +277,7 @@ public: uint16_t modId = 0, uint16_t row = 0, uint16_t column = 0, uint16_t reserved = 0, uint32_t debug = 0, uint16_t roundRNumber = 0, uint8_t detType = 0, uint8_t version = 0, int gapPixelsEnable = 0, int flippedDataX = 0, + uint32_t quadEnable = 0, char* additionalJsonHeader = 0) { @@ -310,7 +312,8 @@ public: //additional stuff "\"gappixels\":%u, " - "\"flippedDataX\":%u" + "\"flippedDataX\":%u, " + "\"quad\":%u" ;//"}\n"; char buf[MAX_STR_LENGTH] = ""; @@ -324,7 +327,8 @@ public: //additional stuff gapPixelsEnable, - flippedDataX + flippedDataX, + quadEnable ); if (additionalJsonHeader && strlen(additionalJsonHeader)) { From ce14435c686ea90ae3e17931b65ca29ea05464cd Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Wed, 14 Aug 2019 17:49:32 +0200 Subject: [PATCH 075/108] WIP --- slsDetectorSoftware/src/multiSlsDetector.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index c3251b052..90d9f1413 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -3012,7 +3012,7 @@ void multiSlsDetector::readFrameFromReceiver() { } } } - FILE_LOG(logINFOBLUE) + FILE_LOG(logDEBUG) << "Call Back Info:" << "\n\t nDetPixelsX: " << nDetPixelsX << "\n\t nDetPixelsY: " << nDetPixelsY @@ -3032,7 +3032,7 @@ void multiSlsDetector::readFrameFromReceiver() { nDetPixelsY = nY * (nPixelsY + 1); } int n = processImageWithGapPixels(multiframe, multigappixels, quadEnable); - FILE_LOG(logINFORED) + FILE_LOG(logDEBUG) << "Call Back Info Recalculated:" << "\n\t nDetPixelsX: " << nDetPixelsX << "\n\t nDetPixelsY: " << nDetPixelsY From e635ff035ca2d74e84d9d692248df86da3f3954a Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Wed, 14 Aug 2019 21:14:06 +0200 Subject: [PATCH 076/108] receiver master file includes quad, gap pixels enable, version updated for binary and hdf5, parallel, analog, digital, adc, dbitofset, dbitlist --- slsReceiverSoftware/include/BinaryFile.h | 13 +-- .../include/BinaryFileStatic.h | 67 ++++++++------- slsReceiverSoftware/include/DataProcessor.h | 11 +-- slsReceiverSoftware/include/File.h | 14 +--- slsReceiverSoftware/include/HDF5File.h | 13 +-- slsReceiverSoftware/include/HDF5FileStatic.h | 83 ++++++++++++------- slsReceiverSoftware/include/receiver_defs.h | 27 +++++- slsReceiverSoftware/src/BinaryFile.cpp | 9 +- slsReceiverSoftware/src/DataProcessor.cpp | 7 +- slsReceiverSoftware/src/HDF5File.cpp | 10 +-- .../src/slsReceiverImplementation.cpp | 28 ++++++- 11 files changed, 157 insertions(+), 125 deletions(-) diff --git a/slsReceiverSoftware/include/BinaryFile.h b/slsReceiverSoftware/include/BinaryFile.h index 1ac9ff8ab..6178d728c 100755 --- a/slsReceiverSoftware/include/BinaryFile.h +++ b/slsReceiverSoftware/include/BinaryFile.h @@ -58,19 +58,10 @@ class BinaryFile : private virtual slsDetectorDefs, public File, public BinaryFi /** * Create master file * @param mfwenable master file write enable - * @param en ten giga enable - * @param size image size - * @param nx number of pixels in x direction - * @param ny number of pixels in y direction - * @param at acquisition time - * @param st sub exposure time - * @param sp sub period - * @param ap acquisition period + * @param attr master file attributes * @returns OK or FAIL */ - int CreateMasterFile(bool mfwenable, bool en, uint32_t size, - uint32_t nx, uint32_t ny, uint64_t at, uint64_t st, uint64_t sp, - uint64_t ap) override; + int CreateMasterFile(bool mfwenable, masterAttributes& attr) override; /** * Close Current File diff --git a/slsReceiverSoftware/include/BinaryFileStatic.h b/slsReceiverSoftware/include/BinaryFileStatic.h index 3fbd8c25a..132eb203d 100755 --- a/slsReceiverSoftware/include/BinaryFileStatic.h +++ b/slsReceiverSoftware/include/BinaryFileStatic.h @@ -97,26 +97,11 @@ class BinaryFileStatic { * @param fd pointer to file handle * @param fname master file name * @param owenable overwrite enable - * @param dr dynamic range - * @param tenE ten giga enable - * @param size image size - * @param nPixelsX number of pixels in x direction - * @param nPixelsY number of pixels in y direction - * @param nf number of images - * @param maxf maximum frames per file - * @param acquisitionTime acquisition time - * @param acquisitionPeriod acquisition period - * @param subexposuretime sub exposure time - * @param subperiod sub period - * @param version version of software for binary writing + * @param attr master file attributes * @returns 0 for success and 1 for fail */ static int CreateMasterDataFile(FILE*& fd, std::string fname, bool owenable, - uint32_t dr, bool tenE, uint32_t size, - uint32_t nPixelsX, uint32_t nPixelsY, uint64_t nf, - uint32_t maxf, - uint64_t acquisitionTime, uint64_t subexposuretime, - uint64_t subperiod, uint64_t acquisitionPeriod, double version) + masterAttributes& attr) { if(!owenable){ if (NULL == (fd = fopen((const char *) fname.c_str(), "wx"))){ @@ -135,17 +120,26 @@ class BinaryFileStatic { char message[MAX_MASTER_FILE_LENGTH]; sprintf(message, "Version : %.1f\n" + "Detector Type : %d\n" "Dynamic Range : %d\n" "Ten Giga : %d\n" "Image Size : %d bytes\n" - "row : %d pixels\n" - "col : %d pixels\n" - "Max. Frames Per File : %u\n" + "nPixelsX : %d pixels\n" + "nPixelsY : %d pixels\n" + "Max Frames Per File : %u\n" "Total Frames : %lld\n" "Exptime (ns) : %lld\n" "SubExptime (ns) : %lld\n" "SubPeriod(ns) : %lld\n" "Period (ns) : %lld\n" + "Gap Pixels Enable : %d\n" + "Quad Enable : %d\n" + "Parallel Flag : %d\n" + "Analog Flag : %d\n" + "Digital Flag : %d\n" + "ADC Mask : %d\n" + "Dbit Offset : %d\n" + "Dbit Bitset : %lld\n" "Timestamp : %s\n\n" "#Frame Header\n" @@ -164,18 +158,27 @@ class BinaryFileStatic { "Header Version : 1 byte\n" "Packets Caught Mask : 64 bytes\n" , - version, - dr, - tenE, - size, - nPixelsX, - nPixelsY, - maxf, - (long long int)nf, - (long long int)acquisitionTime, - (long long int)subexposuretime, - (long long int)subperiod, - (long long int)acquisitionPeriod, + attr.version, + attr.detectorType, + attr.dynamicRange, + attr.tenGiga, + attr.imageSize, + attr.nPixelsX, + attr.nPixelsY, + attr.maxFramesPerFile, + (long long int)attr.totalFrames, + (long long int)attr.exptimeNs, + (long long int)attr.subExptimeNs, + (long long int)attr.subPeriodNs, + (long long int)attr.periodNs, + attr.gapPixelsEnable, + attr.quadEnable, + attr.parallelFlag, + attr.analogFlag, + attr.digitalFlag, + attr.adcmask, + attr.dbitoffset, + (long long int)attr.dbitlist, ctime(&t)); if (strlen(message) > MAX_MASTER_FILE_LENGTH) { FILE_LOG(logERROR) << "Master File Size " << strlen(message) << diff --git a/slsReceiverSoftware/include/DataProcessor.h b/slsReceiverSoftware/include/DataProcessor.h index 9c5febfdb..d4fc0ef71 100755 --- a/slsReceiverSoftware/include/DataProcessor.h +++ b/slsReceiverSoftware/include/DataProcessor.h @@ -10,6 +10,7 @@ */ #include "ThreadObject.h" +#include "receiver_defs.h" class GeneralData; class Fifo; @@ -175,16 +176,10 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { /** * Create New File - * @param en ten giga enable - * @param nf number of frames - * @param at acquisition time - * @param st sub exposure time - * @param sp sub period - * @param ap acquisition period + * @param attr master file attributes * @returns OK or FAIL */ - int CreateNewFile(bool en, uint64_t nf, uint64_t at, uint64_t st, - uint64_t sp, uint64_t ap); + int CreateNewFile(masterAttributes& attr); /** * Closes files diff --git a/slsReceiverSoftware/include/File.h b/slsReceiverSoftware/include/File.h index 2a0dfb761..02a43c8e0 100755 --- a/slsReceiverSoftware/include/File.h +++ b/slsReceiverSoftware/include/File.h @@ -10,6 +10,7 @@ #include "sls_detector_defs.h" #include "logger.h" +#include "receiver_defs.h" #include @@ -109,19 +110,10 @@ class File : private virtual slsDetectorDefs { /** * Create master file * @param mfwenable master file write enable - * @param en ten giga enable - * @param size image size - * @param nx number of pixels in x direction - * @param ny number of pixels in y direction - * @param at acquisition time - * @param st sub exposure time - * @param sp sub period - * @param ap acquisition period + * @param attr master file attributes * @returns OK or FAIL */ - virtual int CreateMasterFile(bool mfwenable, bool en, uint32_t size, - uint32_t nx, uint32_t ny, uint64_t at, uint64_t st, - uint64_t sp, uint64_t ap) = 0; + virtual int CreateMasterFile(bool mfwenable, masterAttributes& attr) = 0; // HDf5 specific /** diff --git a/slsReceiverSoftware/include/HDF5File.h b/slsReceiverSoftware/include/HDF5File.h index 0a93ed712..c3727109e 100755 --- a/slsReceiverSoftware/include/HDF5File.h +++ b/slsReceiverSoftware/include/HDF5File.h @@ -94,19 +94,10 @@ class HDF5File : private virtual slsDetectorDefs, public File, public HDF5FileSt /** * Create master file * @param mfwenable master file write enable - * @param en ten giga enable - * @param size image size - * @param nx number of pixels in x direction - * @param ny number of pixels in y direction - * @param at acquisition time - * @param st sub exposure time - * @param sp sub period - * @param ap acquisition period + * @param attr master file attributes * @returns OK or FAIL */ - int CreateMasterFile(bool mfwenable, bool en, uint32_t size, - uint32_t nx, uint32_t ny, uint64_t at, uint64_t st, uint64_t sp, - uint64_t ap); + int CreateMasterFile(bool mfwenable, masterAttributes& attr); /** * End of Acquisition diff --git a/slsReceiverSoftware/include/HDF5FileStatic.h b/slsReceiverSoftware/include/HDF5FileStatic.h index fc771ab99..d7f0ca915 100755 --- a/slsReceiverSoftware/include/HDF5FileStatic.h +++ b/slsReceiverSoftware/include/HDF5FileStatic.h @@ -291,26 +291,11 @@ public: * Create master file * @param fname master file name * @param owenable overwrite enable - * @param dr dynamic range - * @param tenE ten giga enable - * @param size image size - * @param nx number of pixels in x direction - * @param ny number of pixels in y direction - * @param nf number of images - * @param maxf maximum frames per file - * @param acquisitionTime acquisition time - * @param subexposuretime sub exposure time - * @param subperiod sub period - * @param acquisitionPeriod acquisition period - * @param version version of software for hdf5 writing + * @param attr master file attributes * @returns 0 for success and 1 for fail */ static int CreateMasterDataFile(H5File*& fd, std::string fname, bool owenable, - uint32_t dr, bool tenE, uint32_t size, - uint32_t nPixelsx, uint32_t nPixelsy, uint64_t nf, - uint32_t maxf, - uint64_t acquisitionTime, uint64_t subexposuretime, - uint64_t subperiod, uint64_t acquisitionPeriod, double version) + masterAttributes& attr) { try { Exception::dontPrint(); //to handle errors @@ -337,7 +322,7 @@ public: //create attributes //version - dValue=version; + dValue = attr.version; attribute = fd->createAttribute("version",PredType::NATIVE_DOUBLE, dataspace); attribute.write(PredType::NATIVE_DOUBLE, &dValue); @@ -351,61 +336,101 @@ public: //Dynamic Range dataset = group5.createDataSet ( "dynamic range", PredType::NATIVE_INT, dataspace ); - dataset.write ( &dr, PredType::NATIVE_INT); + dataset.write ( &(attr.dynamicRange), PredType::NATIVE_INT); attribute = dataset.createAttribute("unit",strdatatype, dataspace); attribute.write(strdatatype, std::string("bits")); //Ten Giga - iValue = tenE; + iValue = attr.tenGiga; dataset = group5.createDataSet ( "ten giga enable", PredType::NATIVE_INT, dataspace ); dataset.write ( &iValue, PredType::NATIVE_INT); //Image Size dataset = group5.createDataSet ( "image size", PredType::NATIVE_INT, dataspace ); - dataset.write ( &size, PredType::NATIVE_INT); + dataset.write ( &(attr.imageSize), PredType::NATIVE_INT); attribute = dataset.createAttribute("unit",strdatatype, dataspace); attribute.write(strdatatype, std::string("bytes")); //x dataset = group5.createDataSet ( "number of pixels in x axis", PredType::NATIVE_INT, dataspace ); - dataset.write ( &nPixelsx, PredType::NATIVE_INT); + dataset.write ( &(attr.nPixelsX), PredType::NATIVE_INT); //y dataset = group5.createDataSet ( "number of pixels in y axis", PredType::NATIVE_INT, dataspace ); - dataset.write ( &nPixelsy, PredType::NATIVE_INT); + dataset.write ( &(attr.nPixelsY), PredType::NATIVE_INT); //Maximum frames per file dataset = group5.createDataSet ( "maximum frames per file", PredType::NATIVE_INT, dataspace ); - dataset.write ( &maxf, PredType::NATIVE_INT); + dataset.write ( &(attr.maxFramesPerFile), PredType::NATIVE_INT); //Total Frames dataset = group5.createDataSet ( "total frames", PredType::STD_U64LE, dataspace ); - dataset.write ( &nf, PredType::STD_U64LE); + dataset.write ( &(attr.totalFrames), PredType::STD_U64LE); //Exptime dataset = group5.createDataSet ( "exposure time", PredType::STD_U64LE, dataspace ); - dataset.write ( &acquisitionTime, PredType::STD_U64LE); + dataset.write ( &(attr.exptimeNs), PredType::STD_U64LE); attribute = dataset.createAttribute("unit",strdatatype, dataspace); attribute.write(strdatatype, std::string("ns")); //SubExptime dataset = group5.createDataSet ( "sub exposure time", PredType::STD_U64LE, dataspace ); - dataset.write ( &subexposuretime, PredType::STD_U64LE); + dataset.write ( &(attr.subExptimeNs), PredType::STD_U64LE); attribute = dataset.createAttribute("unit",strdatatype, dataspace); attribute.write(strdatatype, std::string("ns")); //SubPeriod dataset = group5.createDataSet ( "sub period", PredType::STD_U64LE, dataspace ); - dataset.write ( &subperiod, PredType::STD_U64LE); + dataset.write ( &(attr.subPeriodNs), PredType::STD_U64LE); attribute = dataset.createAttribute("unit",strdatatype, dataspace); attribute.write(strdatatype, std::string("ns")); //Period dataset = group5.createDataSet ( "acquisition period", PredType::STD_U64LE, dataspace ); - dataset.write ( &acquisitionPeriod, PredType::STD_U64LE); + dataset.write ( &(attr.periodNs), PredType::STD_U64LE); attribute = dataset.createAttribute("unit",strdatatype, dataspace); attribute.write(strdatatype, std::string("ns")); + //Gap Pixels Enable + dataset = group5.createDataSet ( "gap pixels enable", PredType::NATIVE_INT, dataspace ); + dataset.write ( &(attr.gapPixelsEnable), PredType::NATIVE_INT); + + //Quad Enable + dataset = group5.createDataSet ( "quad enable", PredType::NATIVE_INT, dataspace ); + dataset.write ( &(attr.quadEnable), PredType::NATIVE_INT); + + //Gap Pixels Enable + dataset = group5.createDataSet ( "gap pixels enable", PredType::NATIVE_INT, dataspace ); + dataset.write ( &(attr.gapPixelsEnable), PredType::NATIVE_INT); + + //Quad Enable + dataset = group5.createDataSet ( "quad enable", PredType::NATIVE_INT, dataspace ); + dataset.write ( &(attr.quadEnable), PredType::NATIVE_INT); + + //Parallel Flag + dataset = group5.createDataSet ( "parallel flag", PredType::NATIVE_INT, dataspace ); + dataset.write ( &(attr.gapPixelsEnable), PredType::NATIVE_INT); + + //Analog Flag + dataset = group5.createDataSet ( "analog flag", PredType::NATIVE_INT, dataspace ); + dataset.write ( &(attr.quadEnable), PredType::NATIVE_INT); + + //Digital Flag + dataset = group5.createDataSet ( "digital flag", PredType::NATIVE_INT, dataspace ); + dataset.write ( &(attr.gapPixelsEnable), PredType::NATIVE_INT); + + //ADC Mask + dataset = group5.createDataSet ( "adc mask", PredType::NATIVE_INT, dataspace ); + dataset.write ( &(attr.quadEnable), PredType::NATIVE_INT); + + //Dbit Offset + dataset = group5.createDataSet ( "dbit offset", PredType::NATIVE_INT, dataspace ); + dataset.write ( &(attr.gapPixelsEnable), PredType::NATIVE_INT); + + // Dbit List + dataset = group5.createDataSet ( "dbit bitset list", PredType::STD_U64LE, dataspace ); + dataset.write ( &(attr.periodNs), PredType::STD_U64LE); + //Timestamp time_t t = time(0); dataset = group5.createDataSet ( "timestamp", strdatatype, dataspace ); diff --git a/slsReceiverSoftware/include/receiver_defs.h b/slsReceiverSoftware/include/receiver_defs.h index d1d004f87..2122ac88e 100755 --- a/slsReceiverSoftware/include/receiver_defs.h +++ b/slsReceiverSoftware/include/receiver_defs.h @@ -30,8 +30,8 @@ #define MAX_CHUNKED_IMAGES (1) //versions -#define HDF5_WRITER_VERSION (3.0) //1 decimal places -#define BINARY_WRITER_VERSION (3.0) //1 decimal places +#define HDF5_WRITER_VERSION (5.0) //1 decimal places +#define BINARY_WRITER_VERSION (5.0) //1 decimal places //parameters to calculate fifo depth @@ -49,3 +49,26 @@ #define STREAMER_PRIORITY (10) #define TCP_PRIORITY (10) +struct masterAttributes { + double version; + uint32_t detectorType; + uint32_t dynamicRange; + uint32_t tenGiga; + uint32_t imageSize; + uint32_t nPixelsX; + uint32_t nPixelsY; + uint32_t maxFramesPerFile; + uint64_t totalFrames; + uint64_t exptimeNs; + uint64_t subExptimeNs; + uint64_t subPeriodNs; + uint64_t periodNs; + uint32_t gapPixelsEnable; + uint32_t quadEnable; + uint32_t parallelFlag; + uint32_t analogFlag; + uint32_t digitalFlag; + uint32_t adcmask; + uint32_t dbitoffset; + uint64_t dbitlist; + }; \ No newline at end of file diff --git a/slsReceiverSoftware/src/BinaryFile.cpp b/slsReceiverSoftware/src/BinaryFile.cpp index 24923a9e9..78caee98f 100755 --- a/slsReceiverSoftware/src/BinaryFile.cpp +++ b/slsReceiverSoftware/src/BinaryFile.cpp @@ -114,9 +114,7 @@ int BinaryFile::WriteToFile(char* buffer, int buffersize, uint64_t fnum, uint32_ } -int BinaryFile::CreateMasterFile(bool mfwenable, bool en, uint32_t size, - uint32_t nx, uint32_t ny, uint64_t at, uint64_t st, uint64_t sp, - uint64_t ap) { +int BinaryFile::CreateMasterFile(bool mfwenable, masterAttributes& attr) { //beginning of every acquisition numFramesInFile = 0; numActualPacketsInFile = 0; @@ -127,10 +125,9 @@ int BinaryFile::CreateMasterFile(bool mfwenable, bool en, uint32_t size, if(!(*silentMode)) { FILE_LOG(logINFO) << "Master File: " << masterFileName; } + attr.version = BINARY_WRITER_VERSION; return BinaryFileStatic::CreateMasterDataFile(masterfd, masterFileName, - *overWriteEnable, - *dynamicRange, en, size, nx, ny, *numImages, *maxFramesPerFile, - at, st, sp, ap, BINARY_WRITER_VERSION); + *overWriteEnable, attr); } return OK; } diff --git a/slsReceiverSoftware/src/DataProcessor.cpp b/slsReceiverSoftware/src/DataProcessor.cpp index 766a3d72e..d9cd81f13 100755 --- a/slsReceiverSoftware/src/DataProcessor.cpp +++ b/slsReceiverSoftware/src/DataProcessor.cpp @@ -248,15 +248,12 @@ void DataProcessor::SetupFileWriter(bool fwe, int* nd, uint32_t* maxf, } // only the first file -int DataProcessor::CreateNewFile(bool en, uint64_t nf, uint64_t at, uint64_t st, - uint64_t sp, uint64_t ap) { +int DataProcessor::CreateNewFile(masterAttributes& attr) { if (file == nullptr) return FAIL; file->CloseAllFiles(); file->resetSubFileIndex(); - if (file->CreateMasterFile(*masterFileWriteEnable, en, generalData->imageSize, - generalData->nPixelsX, generalData->nPixelsY, - at, st, sp, ap) == FAIL) + if (file->CreateMasterFile(*masterFileWriteEnable, attr) == FAIL) return FAIL; if (file->CreateFile() == FAIL) return FAIL; diff --git a/slsReceiverSoftware/src/HDF5File.cpp b/slsReceiverSoftware/src/HDF5File.cpp index c462a8520..ec1b07982 100755 --- a/slsReceiverSoftware/src/HDF5File.cpp +++ b/slsReceiverSoftware/src/HDF5File.cpp @@ -240,9 +240,7 @@ int HDF5File::WriteToFile(char* buffer, int buffersize, uint64_t fnum, uint32_t } -int HDF5File::CreateMasterFile(bool mfwenable, bool en, uint32_t size, - uint32_t nx, uint32_t ny, uint64_t at, uint64_t st, uint64_t sp, - uint64_t ap) { +int HDF5File::CreateMasterFile(bool mfwenable, masterAttributes& attr) { //beginning of every acquisition numFramesInFile = 0; @@ -257,11 +255,9 @@ int HDF5File::CreateMasterFile(bool mfwenable, bool en, uint32_t size, FILE_LOG(logINFO) << "Master File: " << masterFileName; } pthread_mutex_lock(&Mutex); + attr.version = HDF5_WRITER_VERSION; int ret = HDF5FileStatic::CreateMasterDataFile(masterfd, masterFileName, - *overWriteEnable, - *dynamicRange, en, size, nx, ny, *numImages, *maxFramesPerFile, - at, st, sp, ap, - HDF5_WRITER_VERSION); + *overWriteEnable, attr); pthread_mutex_unlock(&Mutex); return ret; } diff --git a/slsReceiverSoftware/src/slsReceiverImplementation.cpp b/slsReceiverSoftware/src/slsReceiverImplementation.cpp index a77b40da8..65bd9c989 100755 --- a/slsReceiverSoftware/src/slsReceiverImplementation.cpp +++ b/slsReceiverSoftware/src/slsReceiverImplementation.cpp @@ -1647,10 +1647,32 @@ int slsReceiverImplementation::CreateUDPSockets() { int slsReceiverImplementation::SetupWriter() { FILE_LOG(logDEBUG3) << __SHORT_AT__ << " called"; bool error = false; + masterAttributes attr; + attr.detectorType = myDetectorType; + attr.dynamicRange = dynamicRange; + attr.tenGiga = tengigaEnable; + attr.imageSize = generalData->imageSize; + attr.nPixelsX = generalData->nPixelsX; + attr.nPixelsY = generalData->nPixelsY; + attr.maxFramesPerFile = framesPerFile; + attr.totalFrames = numberOfFrames; + attr.exptimeNs = acquisitionTime; + attr.subExptimeNs = subExpTime; + attr.subPeriodNs = subPeriod; + attr.periodNs = acquisitionPeriod; + attr.gapPixelsEnable = gapPixelsEnable; + attr.quadEnable = quadEnable; + attr.parallelFlag = (readoutFlags & PARALLEL) ? 1 : 0; + attr.analogFlag = (readoutFlags == NORMAL_READOUT || readoutFlags & ANALOG_AND_DIGITAL) ? 1 : 0; + attr.digitalFlag = (readoutFlags & DIGITAL_ONLY || readoutFlags & ANALOG_AND_DIGITAL) ? 1 : 0; + attr.adcmask = adcEnableMask; + attr.dbitoffset = ctbDbitOffset; + attr.dbitlist = 0; + for (auto &i : ctbDbitList) { + attr.dbitlist |= (1 << i); + } for (unsigned int i = 0; i < dataProcessor.size(); ++i) - if (dataProcessor[i]->CreateNewFile( - tengigaEnable, numberOfFrames, acquisitionTime, subExpTime, - subPeriod, acquisitionPeriod) == FAIL) { + if (dataProcessor[i]->CreateNewFile(attr) == FAIL) { error = true; break; } From 947252c852b826ecd5071091be90d6af78fe3625 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Fri, 16 Aug 2019 09:45:49 +0200 Subject: [PATCH 077/108] WIP --- slsDetectorGui/src/qDrawPlot.cpp | 5 +- .../slsDetectorServer_funcs.c | 5 - slsDetectorSoftware/include/Detector.h | 1495 +++++++++-------- .../include/multiSlsDetector.h | 86 +- slsDetectorSoftware/include/slsDetector.h | 82 +- slsDetectorSoftware/src/Detector.cpp | 148 +- slsDetectorSoftware/src/multiSlsDetector.cpp | 154 +- slsDetectorSoftware/src/slsDetector.cpp | 127 +- .../src/slsDetectorCommand.cpp | 21 +- slsDetectorSoftware/src/slsDetectorUsers.cpp | 10 +- slsSupportLib/include/sls_detector_defs.h | 2 +- 11 files changed, 934 insertions(+), 1201 deletions(-) diff --git a/slsDetectorGui/src/qDrawPlot.cpp b/slsDetectorGui/src/qDrawPlot.cpp index b242c8711..61972327c 100755 --- a/slsDetectorGui/src/qDrawPlot.cpp +++ b/slsDetectorGui/src/qDrawPlot.cpp @@ -80,8 +80,9 @@ void qDrawPlot::SetupPlots() { setFont(QFont("Sans Serif", qDefs::Q_FONT_SIZE, QFont::Normal)); // default image size - nPixelsX = myDet->getTotalNumberOfChannelsInclGapPixels(slsDetectorDefs::X); - nPixelsY = myDet->getTotalNumberOfChannelsInclGapPixels(slsDetectorDefs::Y); + slsDetectorDefs::xy res = myDet->getNumberOfChannels(); + nPixelsX = res.x; + nPixelsY = res.y; switch(detType) { case slsDetectorDefs::MOENCH: npixelsy_jctb = (myDet->setTimer(slsDetectorDefs::ANALOG_SAMPLES, -1) * 2)/25;// for moench 03 diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c index 542af9d48..16aacb94e 100755 --- a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c +++ b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c @@ -2181,11 +2181,6 @@ int send_update(int file_des) { n = sendData(file_des,&i32,sizeof(i32),INT32); if (n < 0) return printSocketReadError(); - // databytes - i32 = calculateDataBytes(); - n = sendData(file_des,&i32,sizeof(i32),INT32); - if (n < 0) return printSocketReadError(); - // settings #if defined(EIGERD) || defined(JUNGFRAUD) || defined(GOTTHARDD) i32 = (int)getSettings(); diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 167a114a5..0972d85a6 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -19,14 +19,17 @@ class Detector { public: /** - * @param multi_id multi detector shared memory id + * @param shm_id detector shared memory id + * Default value is 0. Can be set to more values for + * multiple detectors.It is important only if you + * are controlling multiple detectors from the same pc. */ - Detector(int multi_id = 0); + Detector(int shm_id = 0); ~Detector(); /************************************************** * * - * CONFIGURATIOn * + * CONFIGURATION * * * * ************************************************/ @@ -34,176 +37,66 @@ class Detector { * belonging to it.*/ void freeSharedMemory(); - void setConfig(const std::string &fname); + void loadConfig(const std::string &fname); Result getHostname(Positions pos = {}) const; /* Frees shared memory, adds detectors to the list * and updates local detector cache */ - void setHostname(const std::vector &value); + void setHostname(const std::vector &hostname); - int getMultiId() const; + /** Gets shared memory ID */ + int getShmId() const; - void checkDetectorVersionCompatibility(Positions pos = {}) const; - - void checkReceiverVersionCompatibility(Positions pos = {}) const; - - Result getDetectorFirmwareVersion(Positions pos = {}) const; + Result getFirmwareVersion(Positions pos = {}) const; Result getDetectorServerVersion(Positions pos = {}) const; - Result getDetectorSerialNumber(Positions pos = {}) const; + Result getSerialNumber(Positions pos = {}) const; - int64_t getClientSoftwareVersion() const; + int64_t getClientVersion() const; - Result getReceiverSoftwareVersion(Positions pos = {}) const; - - std::string getUserDetailsFromSharedMemory() const; + Result getReceiverVersion(Positions pos = {}) const; Result getDetectorType(Positions pos = {}) const; - Result getDetectorTypeAsString(Positions pos = {}) const; - - /** @returns the total number of detectors */ + /** Gets the total number of detectors */ int size() const; - defs::coordinates getNumberOfDetectors() const; + defs::xy getModuleGeometry() const; - Result getNumberOfChannels(Positions pos = {}) const; + Result getModuleSize(Positions pos = {}) const; - Result - getNumberOfChannelsInclGapPixels(Positions pos = {}) const; - - defs::coordinates getMaxNumberOfChannels() const; + /** Gets the actual full detector size. It is the same even if ROI changes */ + defs::xy getDetectorSize() const; /** - * Sets the maximum number of channels of complete detector in both - * dimensions. -1 means no limit in this dimension. This value is used to - * calculate row and column channels for each module. + * Sets the detector size in both dimensions. + * This value is used to calculate row and column positions for each module. */ - void setMaxNumberOfChannels(const defs::coordinates value); + void setDetectorSize(const defs::xy value); - /** [Eiger] with specific quad hardware */ - Result getQuad(Positions pos = {}) const; - - /** [Eiger] with specific quad hardware */ - void setQuad(const bool enable, Positions pos = {}); - - /** [Eiger] */ - Result getReadNLines(Positions pos = {}) const; - - /** [Eiger] Number of lines to read out per half module - * Options: 0 - 256. Depending on dynamic range and - * 10 GbE enabled, only specific values are accepted - */ - void setReadNLines(const int value, Positions pos = {}); - - Result getControlPort(Positions pos = {}) const; - - /** Detector Control TCP port (for client communication with Detector - * control server) */ - void setControlPort(int value, Positions pos = {}); - - Result getStopPort(Positions pos = {}) const; - - /** Detector Stop TCP port (for client communication with Detector Stop - * server) */ - void setStopPort(int value, Positions pos = {}); - - Result getLockServer(Positions pos = {}) const; - - /** Lock for detector control server to this client IP */ - void setLockServer(bool value, Positions pos = {}); - - /** Get last client IP saved on detector server */ - Result getLastClientIP(Positions pos = {}) const; - - void exitServer(Positions pos = {}); - - /** Execute a command on the detector server */ - void execCommand(const std::string &value, Positions pos = {}); - - void writeConfigurationFile(const std::string &value); - - /** [Not CTB] */ + /** [Jungfrau][Gotthard] */ Result getSettings(Positions pos = {}) const; - /** - * [Not CTB] - * Load detector settings from the settings file picked from the - * trimdir/settingsdir - * Eiger only stores in shared memory ( a get will - * overwrite this) For Eiger, one must use setThresholdEnergy - */ + /** [Jungfrau][Gotthard] */ void setSettings(defs::detectorSettings value, Positions pos = {}); - /** [Eiger] */ - Result getThresholdEnergy(Positions pos = {}) const; - /** - * [Eiger] - * Set threshold energy - * @param value threshold in eV - * @param sett ev. change settings - * @param tb 1 to include trimbits, 0 to exclude - */ - void setThresholdEnergy(int value, - defs::detectorSettings sett = defs::GET_SETTINGS, - int tb = 1, Positions pos = {}); - Result getSettingsDir(Positions pos = {}) const; - - /** [Not CTB] Sets the detector trimbit/settings directory */ - void setSettingsDir(const std::string &value, Positions pos = {}); - - /** [Not CTB] Loads the modules settings/trimbits reading from a specific - * file - * file name extension is automatically generated from detector serial - * number */ - void loadSettingsFile(const std::string &value, Positions pos = {}); - - /** [Not CTB] Saves the modules settings/trimbits to a specific file - * file name extension is automatically generated from detector serial - * number */ - void saveSettingsFile(const std::string &value, Positions pos = {}); - - /** Configures in detector the destination for UDP packets */ - void configureMAC(Positions pos = {}); + /************************************************** + * * + * Acquisition Parameters * + * * + * ************************************************/ Result getNumberOfFrames() const; void setNumberOfFrames(int64_t value); - Result getNumberOfCycles() const; + Result getNumberOfTriggers() const; - void setNumberOfCycles(int64_t value); - - /** [Jungfrau] */ - Result getNumberOfAdditionalStorageCells() const; - - /** [Jungfrau] */ - void setNumberOfStorageCells(int64_t value); - - /** [Jungfrau] */ - Result getStorageCellStart(Positions pos = {}) const; - - /** - * [Jungfrau] Sets the storage cell storing the first acquisition of the - * series Options: 0-15 - */ - void setStoragecellStart(int cell, Positions pos = {}); - - /** [CTB] */ - Result getNumberOfAnalogSamples(Positions pos = {}) const; - - /** [CTB] */ - void setNumberOfAnalogSamples(int64_t value, Positions pos = {}); - - /** [CTB] */ - Result getNumberOfDigitalSamples(Positions pos = {}) const; - - /** [CTB] */ - void setNumberOfDigitalSamples(int64_t value, Positions pos = {}); + void setNumberOfTriggers(int64_t value); Result getExptime(Positions pos = {}) const; @@ -219,60 +112,20 @@ class Detector { /** [Gotthard][Jungfrau] */ void setDelayAfterTrigger(ns value, Positions pos = {}); - /** [Eiger] in 32 bit mode */ - Result getSubExptime(Positions pos = {}) const; - - /** [Eiger] in 32 bit mode */ - void setSubExptime(ns t, Positions pos = {}); - - /** [Eiger] in 32 bit mode */ - Result getSubDeadTime(Positions pos = {}) const; - - /** [Eiger] in 32 bit mode */ - void setSubDeadTime(ns value, Positions pos = {}); - - /** [Jungfrau] */ - Result getStorageCellDelay(Positions pos = {}) const; - - /** [Jungfrau] - * Options: (0-1638375 ns (resolution of 25ns) */ - void setStorageCellDelay(ns value, Positions pos = {}); - /** [Gotthard][Jungfrau][CTB] */ Result getNumberOfFramesLeft(Positions pos = {}) const; /** [Gotthard][Jungfrau][CTB] */ Result getNumberOfCyclesLeft(Positions pos = {}) const; - /** [Gotthard] */ - Result getExptimeLeft(Positions pos = {}) const; - - /** [Gotthard] */ - Result getPeriodLeft(Positions pos = {}) const; - /** [Gotthard][Jungfrau][CTB] */ Result getDelayAfterTriggerLeft(Positions pos = {}) const; - /** [Gotthard][Jungfrau][CTB] */ - Result getNumberOfFramesFromStart(Positions pos = {}) const; - - /** [Jungfrau][CTB] Get time from detector start */ - Result getActualTime(Positions pos = {}) const; - - /** [Jungfrau][CTB] Get timestamp at a frame start */ - Result getMeasurementTime(Positions pos = {}) const; - - /** [Eiger] Get measured period between previous two frames */ - Result getMeasuredPeriod(Positions pos = {}) const; - - /** [Eiger] Get measured sub frame period between previous two frames */ - Result getMeasuredSubFramePeriod(Positions pos = {}) const; - /** [Eiger][Jungfrau] */ Result getSpeed(Positions pos = {}) const; - /** [Eiger][Jungfrau] - * @param value speed (0 full speed, 1 half speed, 2 quarter speed) + /** [Eiger][Jungfrau] // TODO: create enum for speed + * Options: (0 full speed, 1 half speed, 2 quarter speed) */ void setSpeed(int value, Positions pos = {}); @@ -285,57 +138,6 @@ class Detector { /** [Jungfrau][CTB] */ Result getMaxADCPhaseShift(Positions pos = {}) const; - /** [CTB] */ - Result getDBITPhase(bool inDeg, Positions pos = {}) const; - - /** [CTB] */ - void setDBITPhase(int value, bool inDeg, Positions pos = {}); - - /** [CTB] */ - Result getMaxDBITPhaseShift(Positions pos = {}) const; - - /** [CTB] */ - Result getADCClock(Positions pos = {}) const; - - /** [CTB] */ - void setADCClock(int value_in_MHz, Positions pos = {}); - - /** [CTB] */ - Result getDBITClock(Positions pos = {}) const; - - /** [CTB] */ - void setDBITClock(int value_in_MHz, Positions pos = {}); - - /** [CTB] */ - Result getRUNClock(Positions pos = {}) const; - - /** [CTB] */ - void setRUNClock(int value_in_MHz, Positions pos = {}); - - /** [CTB] */ - Result getSYNCClock(Positions pos = {}) const; - - /** [CTB] */ - Result getADCPipeline(Positions pos = {}) const; - - /** [CTB] */ - void setADCPipeline(int value, Positions pos = {}); - - /** [CTB] */ - Result getDBITPipeline(Positions pos = {}) const; - - /** [CTB] */ - void setDBITPipeline(int value, Positions pos = {}); - - Result getDynamicRange(Positions pos = {}) const; - - /** - * [Eiger] - * Options: 4, 8, 16, 32 - * If i is 32, also sets clkdivider to 2, if 16, sets clkdivider to 1 - */ - void setDynamicRange(int value); - Result getHighVoltage(Positions pos = {}) const; /** @@ -345,60 +147,22 @@ class Detector { */ void setHighVoltage(int value, Positions pos = {}); - /** [Eiger] */ - Result getIODelay(Positions pos = {}) const; - - /** [Eiger] */ - void setIODelay(int value, Positions pos = {}); - /** * (Degrees) - * [Gotthard Options: TEMPERATURE_ADC, TEMPERATURE_FPGA] - * [Jungfrau Options: TEMPERATURE_ADC, TEMPERATURE_FPGA] - * [Eiger Options: TEMPERATURE_FPGA, TEMPERATURE_FPGAEXT, TEMPERATURE_10GE, + * [Gotthard] Options: TEMPERATURE_ADC, TEMPERATURE_FPGA + * [Jungfrau] Options: TEMPERATURE_ADC, TEMPERATURE_FPGA + * [Eiger] Options: TEMPERATURE_FPGA, TEMPERATURE_FPGAEXT, TEMPERATURE_10GE, * TEMPERATURE_DCDC, TEMPERATURE_SODL, TEMPERATURE_SODR, TEMPERATURE_FPGA2, - * TEMPERATURE_FPGA3) (CTB Options: SLOW_ADC_TEMP] + * TEMPERATURE_FPGA3 + * [CTB] Options: SLOW_ADC_TEMP */ Result getTemp(defs::dacIndex index, Positions pos = {}) const; - /** [CTB] */ - Result getVrefVoltage(bool mV, Positions pos = {}) const; - - /** [CTB] */ - void setVrefVoltage(int value, bool mV, Positions pos = {}); - - /** [CTB] */ - Result getVoltage(defs::dacIndex index, Positions pos = {}) const; - - /** - * [CTB] mV - * Options: V_LIMIT, V_POWER_A, V_POWER_B, V_POWER_C, - * V_POWER_D, V_POWER_IO, V_POWER_CHIP - */ - void setVoltage(int value, defs::dacIndex index, Positions pos = {}); - - /** - * [CTB] mV - * Options: V_POWER_A, V_POWER_B, V_POWER_C, V_POWER_D, V_POWER_IO, - * V_POWER_CHIP - */ - Result getMeasuredVoltage(defs::dacIndex index, - Positions pos = {}) const; - - /** - * [CTB] mA - * Options: I_POWER_A, I_POWER_B, I_POWER_C, I_POWER_D, I_POWER_IO - */ - Result getMeasuredCurrent(defs::dacIndex index, - Positions pos = {}) const; - - /** [CTB] Options: SLOW_ADC0 - SLOW_ADC7 */ - Result getSlowADC(defs::dacIndex index, Positions pos = {}) const; - Result getDAC(defs::dacIndex index, bool mV, Positions pos = {}) const; void setDAC(int value, defs::dacIndex index, bool mV, Positions pos = {}); + //TODO: rename externalCommunicationMode: timingMode Result getTimingMode(Positions pos = {}) const; @@ -409,96 +173,91 @@ class Detector { void setTimingMode(defs::externalCommunicationMode value, Positions pos = {}); - /** [Gotthard] */ - Result - getExternalSignalFlags(Positions pos = {}) const; - /** [Gotthard] Options: TRIGGER_IN_RISING_EDGE, TRIGGER_IN_FALLING_EDGE */ - void setExternalSignalFlags(defs::externalSignalFlag value, - Positions pos = {}); + /************************************************** + * * + * ACQUISITION * + * * + * ************************************************/ + /** + * Blocking call, starts the receiver and detector. + * Increments file index if file write enabled. + * Acquired the number of frames set. + */ + void acquire(); - /** [Eiger] */ - Result getParallelMode(Positions pos = {}) const; - - /** [Eiger] */ - void setParallelMode(bool value, Positions pos = {}); - - /** [Eiger] */ - Result getOverFlowMode(Positions pos = {}) const; - - /** [Eiger] */ - void setOverFlowMode(bool value, Positions pos = {}); - - /** [CTB] */ - Result getSignalType(Positions pos = {}) const; - - /** [CTB] Options: NORMAL_READOUT = 0, DIGITAL_ONLY = 1, ANALOG_AND_DIGITAL - * = 2 */ - void setSignalType(int value, Positions pos = {}); - - /** [Eiger] */ - Result getInterruptSubframe(Positions pos = {}) const; - - /** [Eiger] when set, the last subframe is interrupted at end of acq */ - void setInterruptSubframe(const bool enable, Positions pos = {}); - - Result readRegister(uint32_t addr, Positions pos = {}) const; - - void writeRegister(uint32_t addr, uint32_t val, Positions pos = {}); - - void setBit(uint32_t addr, int bitnr, Positions pos = {}); - - void clearBit(uint32_t addr, int bitnr, Positions pos = {}); - - Result getDetectorMAC(Positions pos = {}) const; - - void setDetectorMAC(const std::string &detectorMAC, Positions pos = {}); - - /** [Jungfrau] bottom half */ - Result getDetectorMAC2(Positions pos = {}) const; - - /** [Jungfrau] bottom half */ - void setDetectorMAC2(const std::string &detectorMAC, Positions pos = {}); - - Result getDetectorIP(Positions pos = {}) const; - - void setDetectorIP(const std::string &detectorIP, Positions pos = {}); - - /** [Jungfrau] bottom half */ - Result getDetectorIP2(Positions pos = {}) const; - - /** [Jungfrau] bottom half */ - void setDetectorIP2(const std::string &detectorIP, Positions pos = {}); - - Result getReceiverHostname(Positions pos = {}) const; + /** Non blocking + * Starts the reciever (if enabled) and then the detector + * You have to check detector status until it is idle before you call stopACquisition + * + */ + void startAcquisition(); /** - * Validates and sets the receiver. - * Updates local receiver cache parameters - * Configures the detector to the receiver as UDP destination - * @param receiver receiver hostname or IP address + * Stops detector acquisition and then receiver (if enabled) + * If no receiver enabled, you can skip this for normal acquisition (no abort) */ - void setReceiverHostname(const std::string &receiver, Positions pos = {}); + void stopAcquisition();//TODO: cannot do this. for acquire, to stop acquisition, must not also do stop receiver(mutex) - Result getReceiverUDPIP(Positions pos = {}) const; + /** + * Clears the acquiring flag. This has to be done manually + * after an acquisition was aborted. + */ + void clearAcquiringFlag(); - void setReceiverUDPIP(const std::string &udpip, Positions pos = {}); + Result getDetectorStatus(Positions pos = {}) const; - /** [Jungfrau bottom half] */ - Result getReceiverUDPIP2(Positions pos = {}) const; + Result getReceiverStatus(Positions pos = {}) const; - /** [Jungfrau bottom half] */ - void setReceiverUDPIP2(const std::string &udpip, Positions pos = {}); + Result getFramesCaught(Positions pos = {}) const; - Result getReceiverUDPMAC(Positions pos = {}) const; + /** [Eiger][Jungfrau] */ + Result getStartingFrameNumber(Positions pos = {}) const; - void setReceiverUDPMAC(const std::string &udpmac, Positions pos = {}); + /** [Eiger][Jungfrau] */ + void setStartingFrameNumber(uint64_t value, Positions pos); - /** [Jungfrau bottom half] */ - Result getReceiverUDPMAC2(Positions pos = {}) const; +//TODO: remove resetframescaught in receiver + + + /************************************************** + * * + * Network Configuration (Detector<->Receiver) * + * * + * ************************************************/ + + /** Configures the destination for UDP packets in the detector */ + void configureMAC(Positions pos = {});//TODO: find a reasonable name + + Result getSourceUDPMAC(Positions pos = {}) const; + + /* For Eiger 1G, the detector will replace with its own DHCP MAC + * For Eiger 10G, the detector will replace with its own DHCP MAC + 1 + * Others can be anything (beware of certain bits) + */ + + void setSourceUDPMAC(const std::string &detectorMAC, Positions pos = {}); + + Result getSourceUDPIP(Positions pos = {}) const; + + /* For Eiger 1G, the detector will replace with its own DHCP IP + * 10G Eiger and other detectors, the source UDP IP must be in the + * same subnet of the destination UDP IP + */ + void setSourceUDPIP(const std::string &detectorIP, Positions pos = {}); + + Result getDestinationUDPIP(Positions pos = {}) const; + + /** IP of the interface in receiver that the detector sends data to */ + void setDestinationUDPIP(const std::string &udpip, Positions pos = {}); + + Result getDestinationUDPMAC(Positions pos = {}) const; + + /** MAC of the interface in receiver that the detector sends data to + * Only needed if you use a custom receiver (not slsReceiver) + */ + void setDestinationUDPMAC(const std::string &udpmac, Positions pos = {}); - /** [Jungfrau bottom half] */ - void setReceiverUDPMAC2(const std::string &udpmac, Positions pos = {}); Result getReceiverUDPPort(Positions pos = {}) const; @@ -510,6 +269,25 @@ class Detector { /** [Eiger right port][Jungfrau bottom half] */ void setReceiverUDPPort2(int udpport, Positions pos = {}); + Result printReceiverConfiguration(Positions pos = {}) const; + + /** [Eiger, Jungfrau] */ + Result getFlowControl10G(Positions pos = {}) const; + + /** [Eiger, Jungfrau] */ + void setFlowControl10G(bool enable, Positions pos = {}); + + /** [Eiger, Jungfrau] */ + Result getTransmissionDelayFrame(Positions pos = {}) const; + + /** + * [Jungfrau]: Sets the transmission delay of the first UDP packet being + * streamed out of the module Options: 0 - 31, each value represenets 1 ms + * [Eiger]: Sets the transmission delay of entire frame streamed out for both + * left and right UDP ports + */ + void setTransmissionDelayFrame(int value, Positions pos = {}); + /** [Jungfrau] */ Result getNumberofUDPInterfaces(Positions pos = {}) const; @@ -526,54 +304,35 @@ class Detector { */ void selectUDPInterface(int interface, Positions pos = {}); - Result getClientStreamingPort(Positions pos = {}) const; - /** - * pos can be for a single module or all modules, not a subset - * If pos for all modules, ports for each module is calculated (increments) - * Restarts client zmq sockets - */ - void setClientDataStreamingInPort(int port, Positions pos = {}); + /** [Jungfrau] bottom half */ + Result getDetectorMAC2(Positions pos = {}) const; - Result getReceiverStreamingPort(Positions pos = {}) const; - /** - * pos can be for a single module or all modules, not a subset - * If pos for all modules, ports for each module is calculated (increments) - * Restarts receiver zmq sockets - */ - void setReceiverDataStreamingOutPort(int port, Positions pos = {}); + /** [Jungfrau] bottom half */ + void setDetectorMAC2(const std::string &detectorMAC, Positions pos = {}); - Result getClientStreamingIP(Positions pos = {}) const; + /** [Jungfrau] bottom half */ + Result getDetectorIP2(Positions pos = {}) const; - // TODO these should probably be the same ?? same as what? - void setClientDataStreamingInIP(const std::string &ip, Positions pos = {}); + /** [Jungfrau] bottom half */ + void setDetectorIP2(const std::string &detectorIP, Positions pos = {}); - Result getReceiverStreamingIP(Positions pos = {}) const; + /** [Jungfrau bottom half] */ + Result getReceiverUDPIP2(Positions pos = {}) const; - void setReceiverDataStreamingOutIP(const std::string &ip, - Positions pos = {}); + /** [Jungfrau bottom half] */ + void setReceiverUDPIP2(const std::string &udpip, Positions pos = {}); + + /** [Jungfrau bottom half] */ + Result getReceiverUDPMAC2(Positions pos = {}) const; - /** [Eiger, Jungfrau] */ - Result getFlowControl10G(Positions pos = {}) const; - - /** [Eiger, Jungfrau] */ - void setFlowControl10G(bool enable, Positions pos = {}); - - /** [Eiger, Jungfrau] */ - Result getTransmissionDelayFrame(Positions pos = {}) const; - - /** - * [Jungfrau: Sets the transmission delay of the first UDP packet being - * streamed out of the module Options: 0 - 31, each value represenets 1 ms ] - * [Eiger: Sets the transmission delay of entire frame streamed out for both - * left and right UDP ports] - */ - void setTransmissionDelayFrame(int value, Positions pos = {}); + /** [Jungfrau bottom half] */ + void setReceiverUDPMAC2(const std::string &udpmac, Positions pos = {}); /** [Eiger] */ Result getTransmissionDelayLeft(Positions pos = {}) const; /** * [Eiger] - * Sets the transmission delay of first packet streamed ut of the left UDP + * Sets the transmission delay of first packet streamed out of the left UDP * port */ void setTransmissionDelayLeft(int value, Positions pos = {}); @@ -588,289 +347,68 @@ class Detector { */ void setTransmissionDelayRight(int value, Positions pos = {}); - /** [Moench] */ - Result getAdditionalJsonHeader(Positions pos = {}) const; - /** [Moench] */ - void setAdditionalJsonHeader(const std::string &jsonheader, - Positions pos = {}); - /** [Moench] */ - Result getAdditionalJsonParameter(const std::string &key, - Positions pos = {}) const; - /** - * [Moench] - * Sets the value for additional json header parameter if found, - * else appends the parameter key and value - * The value cannot be empty - */ - void setAdditionalJsonParameter(const std::string &key, - const std::string &value, - Positions pos = {}); + /************************************************** + * * + * RECEIVER CONFIG * + * * + * ************************************************/ - /** [Moench] TODO! How do we do this best??? Can be refactored to something - * else? Use a generic zmq message passing system... - * For now limiting to all detectors working the same*/ - /** [Moench: -1 if not found or cannot convert to int] */ - Result getDetectorMinMaxEnergyThreshold(const bool isEmax, - Positions pos = {}) const; + /** true when slsReceiver is used */ + Result getUseReceiverFlag(Positions pos = {}) const; - /** [Moench] */ - void setDetectorMinMaxEnergyThreshold(const bool isEmax, const int value, - Positions pos = {}); - - /** [Moench: -1 if unknown mode] */ - Result getFrameMode(Positions pos = {}) const; - - /** [Moench] */ - void setFrameMode(defs::frameModeType value, Positions pos = {}); - - /** [Moench: -1 if unknown mode] */ - Result getDetectorMode(Positions pos = {}) const; - - /** [Moench] */ - void setDetectorMode(defs::detectorModeType value, Positions pos = {}); - - /** [Gotthard] */ - Result getDigitalTestBit(Positions pos = {}); - - /** [Gotthard] */ - Result setDigitalTestBit(const int value, Positions pos = {}); - - /** [Gotthard][Jungfrau][CTB] */ - Result executeFirmwareTest(Positions pos = {}); - - /** [Gotthard][Jungfrau][CTB] */ - Result executeBusTest(Positions pos = {}); - - /** [Gotthard] subset modules not allowed */ - void loadDarkImage(const std::string &fname, Positions pos = {}); - - /** [Gotthard] subset modules not allowed */ - void loadGainImage(const std::string &fname, Positions pos = {}); + Result getReceiverHostname(Positions pos = {}) const; /** - * [Gotthard] subset modules not allowed - * @param startACQ if start acq after reading counter + * Validates and sets the receiver. + * Updates local receiver cache parameters + * Configures the detector to the receiver as UDP destination + * @param receiver receiver hostname or IP address */ - void getCounterMemoryBlock(const std::string &fname, bool startACQ, - Positions pos = {}); + void setReceiverHostname(const std::string &receiver, Positions pos = {}); + + Result getReceiverPort(Positions pos = {}) const; + + /** Receiver TCP port (for client communication with Receiver) */ + void setReceiverPort(int value, Positions pos = {}); + + Result getReceiverFifoDepth(Positions pos = {}) const; + + void setReceiverFifoDepth(int nframes, Positions pos = {}); + + Result getReceiverSilentMode(Positions pos = {}) const; + + void setReceiverSilentMode(bool value, Positions pos = {}); + + Result + getReceiverFrameDiscardPolicy(Positions pos = {}) const; /** - * [Gotthard] - * @param startACQ if start acq after resetting counter - * TODO! does it make sense to call one detector? + * default NO_DISCARD + * Options: NO_DISCARD, DISCARD_EMPTY_FRAMES, DISCARD_PARTIAL_FRAMES */ - void resetCounterBlock(bool startACQ, Positions pos = {}); + void setReceiverFrameDiscardPolicy(defs::frameDiscardPolicy f, + Positions pos = {}); + + Result getPartialFramesPadding(Positions pos = {}) const; - /** [Eiger] */ - Result getCounterBit(Positions pos = {}) const; + /** padding enabled */ + void setPartialFramesPadding(bool value, Positions pos = {}); - /** [Eiger] If it is set, it resets chips completely (else partially) before - * an acquisition TODO: if it makes sense */ - void setCounterBit(bool value, Positions pos = {}); + Result getReceiverUDPSocketBufferSize(Positions pos = {}) const; - /** [Gotthard]*/ - Result getROI(Positions pos = {}) const; + void setReceiverUDPSocketBufferSize(int64_t udpsockbufsize, + Positions pos = {}); + Result + getReceiverRealUDPSocketBufferSize(Positions pos = {}) const; - /** - * [Gotthard] - * Options: Only a single ROI per module - * Can set only a single ROI at a time - * @param module position index - */ - void setROI(defs::ROI value, int moduleId); + Result getReceiverLock(Positions pos = {}); - /** [CTB]*/ - Result getADCEnableMask(Positions pos = {}) const; + /** locks receiver server to client IP */ + void setReceiverLock(bool value, Positions pos = {}); - /** [CTB]*/ - void setADCEnableMask(uint32_t mask, Positions pos = {}); - - /** [CTB] */ - Result getADCInvert(Positions pos = {}) const; - - /** [CTB]*/ - void setADCInvert(uint32_t value, Positions pos = {}); - - /** [CTB] */ - Result getExternalSamplingSource(Positions pos = {}) const; - - /** [CTB] Value between 0-63 */ - void setExternalSamplingSource(int value, Positions pos = {}); - - /** [CTB] */ - Result getExternalSampling(Positions pos = {}) const; - - /** [CTB] */ - void setExternalSampling(bool value, Positions pos = {}); - - /** [CTB] */ - Result> getReceiverDbitList(Positions pos = {}) const; - - /** [CTB] list contains the set of bits (0-63) to save */ - void setReceiverDbitList(std::vector list, Positions pos = {}); - - /** [CTB] */ - Result getReceiverDbitOffset(Positions pos = {}) const; - - /** [CTB] Set number of bytes of digital data to skip in the Receiver */ - void setReceiverDbitOffset(int value, Positions pos = {}); - - /** [Gotthard][Jungfrau][CTB] not possible to read back*/ - void writeAdcRegister(uint32_t addr, uint32_t value, Positions pos = {}); - - /** [Eiger] */ - Result getActive(Positions pos = {}) const; - - /** [Eiger] */ - void setActive(bool active, Positions pos = {}); - - /** [Eiger] */ - Result getBottom(Positions pos = {}) const; - - /** [Eiger] for gui purposes */ - void setBottom(bool value, Positions pos = {}); - - /** [Eiger] - * @returns -1 if they are all different - */ - Result getAllTrimbits(Positions pos = {}) const; - - /**[Eiger] */ - void setAllTrimbits(int value, Positions pos = {}); - - /**[Eiger] */ - Result getGapPixelsEnable(Positions pos = {}) const; - - /** - * [Eiger] - * 4 bit mode not implemented in Receiver, but in client data call back - * Fills in gap pixels in data - */ - void setGapPixelsEnable(bool enable); - - /**[Eiger] Returns energies in eV where the module is trimmed */ - Result> getTrimEnergies(Positions pos = {}) const; - - /** [Eiger] Set the energies where the detector is trimmed */ - void setTrimEnergies(std::vector energies, Positions pos = {}); - - /** - * [Eiger] Pulse Pixel n times at x and y coordinates - */ - void pulsePixel(int n, int x, int y, Positions pos = {}); - - /** [Eiger] Pulse Pixel n times and move by a relative value of x and y - * coordinates */ - void pulsePixelNMove(int n, int x, int y, Positions pos = {}); - - /** [Eiger] Pulse chip n times */ - void pulseChip(int n, Positions pos = {}); - - /** [Jungfrau] */ - Result getThresholdTemperature(Positions pos = {}) const; - - /** - * [Jungfrau]Set threshold temperature - * If temperature crosses threshold temperature - * and temperature control is enabled, - * power to chip will be switched off and - * temperature event will be set - * @param val value in millidegrees TODO! Verify - */ - void setThresholdTemperature(int temp, Positions pos = {}); - - /** [Jungfrau] */ - Result getTemperatureControl(Positions pos = {}) const; - - /** [Jungfrau] */ - void setTemperatureControl(bool enable, Positions pos = {}); - - /** [Jungfrau] */ - Result getTemperatureEvent(Positions pos = {}) const; - - /** [Jungfrau] */ - void ResetTemperatureEvent(Positions pos = {}); - - /** [Jungfrau][CTB] */ - void programFPGA(const std::string &fname, Positions pos = {}); - - /** [Jungfrau][CTB] */ - void resetFPGA(Positions pos = {}); - - /** - * Copy detector server fname from tftp folder of hostname to detector - * Also changes respawn server, which is effective after a reboot. - */ - void copyDetectorServer(const std::string &fname, - const std::string &hostname, Positions pos = {}); - - /** [Jungfrau][Gotthard][CTB] */ - void rebootController(Positions pos = {}); - - /** - * [Jungfrau][Gotthard][CTB] - * Updates the firmware, detector server and then reboots detector - * controller blackfin. - * @param sname name of detector server binary found on tftp folder of host - * pc - * @param hostname name of pc to tftp from - * @param fname programming file name - * @param pos detector positions - */ - void updateFirmwareAndServer(const std::string &sname, - const std::string &hostname, - const std::string &fname, Positions pos = {}); - - /** [Jungfrau] */ - Result getPowerChip(Positions pos = {}) const; - - /** [Jungfrau] */ - void setPowerChip(bool on, Positions pos = {}); - - /** [Jungfrau] */ - Result getAutoCompDisable(Positions pos = {}) const; - - /** [Jungfrau] TODO??? fix docs ? */ - void setAutoCompDisable(bool value, Positions pos = {}); - - /** [Eiger] - * @returns deadtime in ns, 0 = disabled - */ - Result getRateCorrection(Positions pos = {}) const; - - /** - * [Eiger] Set Rate correction - * 0 disable correction, <0 set to default, >0 deadtime in ns - */ - void setRateCorrection(int64_t dead_time_ns, Positions pos = {}); - - /** [Eiger][Jungfrau] */ - Result getStartingFrameNumber(Positions pos = {}) const; - - /** [Eiger][Jungfrau] */ - void setStartingFrameNumber(uint64_t value, Positions pos); - - /** [Eiger] */ - Result getTenGigaEnabled(Positions pos = {}) const; - - /** [Eiger] */ - void setTenGigaEnabled(bool value, Positions pos = {}); - - /** [CTB] */ - Result getLEDEnable(Positions pos = {}) const; - - /** [CTB] */ - void setLEDEnable(bool enable, Positions pos = {}); - - /** - * [CTB] Set Digital IO Delay - * cannot get - * @param digital IO mask to select the pins - * @param delay delay in ps(1 bit=25ps, max of 775 ps) - */ - void setDigitalIODelay(uint64_t pinMask, int delay, Positions pos = {}); + Result getReceiverLastClientIP(Positions pos = {}) const; /************************************************** * * @@ -915,31 +453,20 @@ class Detector { void setFramesPerFile(int n, Positions pos = {}); + /************************************************** * * - * RECEIVER CONFIG * + * ZMQ Streaming Parameters * * * * ************************************************/ - /** true when slsReceiver is used */ - Result getUseReceiverFlag(Positions pos = {}) const; - Result printReceiverConfiguration(Positions pos = {}) const; + Result getDataStreamingFromReceiver(Positions pos = {}) const; - Result getReceiverPort(Positions pos = {}) const; + void setDataStreamingFromReceiver(bool value, Positions pos = {}); - /** Receiver TCP port (for client communication with Receiver) */ - void setReceiverPort(int value, Positions pos = {}); + bool getDataStreamingToClient() const; - Result getReceiverLock(Positions pos = {}); - - /** locks receiver server to client IP */ - void setReceiverLock(bool value, Positions pos = {}); - - Result getReceiverLastClientIP(Positions pos = {}) const; - - void exitReceiver(Positions pos = {}); - - void execReceiverCommand(const std::string &cmd, Positions pos = {}); + void setDataStreamingToClient(bool value); Result getReceiverStreamingFrequency(Positions pos = {}) const; @@ -958,36 +485,227 @@ class Detector { */ void setReceiverStreamingTimer(int time_in_ms, Positions pos = {}); - bool getDataStreamingToClient() const; + Result getClientStreamingPort(Positions pos = {}) const; + /** + * pos can be for a single module or all modules, not a subset + * If pos for all modules, ports for each module is calculated (increments) + * Restarts client zmq sockets + */ + void setClientDataStreamingInPort(int port, Positions pos = {}); - void setDataStreamingToClient(bool value); + Result getReceiverStreamingPort(Positions pos = {}) const; + /** + * pos can be for a single module or all modules, not a subset + * If pos for all modules, ports for each module is calculated (increments) + * Restarts receiver zmq sockets + */ + void setReceiverDataStreamingOutPort(int port, Positions pos = {}); - Result getDataStreamingFromReceiver(Positions pos = {}) const; + Result getClientStreamingIP(Positions pos = {}) const; - void setDataStreamingFromReceiver(bool value, Positions pos = {}); + // TODO these should probably be the same ?? same as what? + void setClientDataStreamingInIP(const std::string &ip, Positions pos = {}); - Result getReceiverFifoDepth(Positions pos = {}) const; + Result getReceiverStreamingIP(Positions pos = {}) const; - void setReceiverFifoDepth(int nframes, Positions pos = {}); + void setReceiverDataStreamingOutIP(const std::string &ip, + Positions pos = {}); - Result getReceiverSilentMode(Positions pos = {}) const; + /** [Moench] */ + Result getAdditionalJsonHeader(Positions pos = {}) const; - void setReceiverSilentMode(bool value, Positions pos = {}); + /** [Moench] */ + void setAdditionalJsonHeader(const std::string &jsonheader, + Positions pos = {}); - Result - getReceiverFrameDiscardPolicy(Positions pos = {}) const; + /** [Moench] */ + Result getAdditionalJsonParameter(const std::string &key, + Positions pos = {}) const; + /** + * [Moench] + * Sets the value for additional json header parameter if found, + * else appends the parameter key and value + * The value cannot be empty + */ + void setAdditionalJsonParameter(const std::string &key, + const std::string &value, + Positions pos = {}); + + /** [Moench] TODO! How do we do this best??? Can be refactored to something + * else? Use a generic zmq message passing system... + * For now limiting to all detectors working the same*/ + /** [Moench: -1 if not found or cannot convert to int] */ + Result getDetectorMinMaxEnergyThreshold(const bool isEmax, + Positions pos = {}) const; + + /** [Moench] */ + void setDetectorMinMaxEnergyThreshold(const bool isEmax, const int value, + Positions pos = {}); + + /** [Moench: -1 if unknown mode] */ + Result getFrameMode(Positions pos = {}) const; + + /** [Moench] */ + void setFrameMode(defs::frameModeType value, Positions pos = {}); + + /** [Moench: -1 if unknown mode] */ + Result getDetectorMode(Positions pos = {}) const; + + /** [Moench] */ + void setDetectorMode(defs::detectorModeType value, Positions pos = {}); + + + /************************************************** + * * + * Eiger Specific * + * * + * ************************************************/ + + Result getDynamicRange(Positions pos = {}) const; + + /** [Eiger] */ + Result getTenGigaEnabled(Positions pos = {}) const; + + /** [Eiger] */ + void setTenGigaEnabled(bool value, Positions pos = {}); /** - * default NO_DISCARD - * Options: NO_DISCARD, DISCARD_EMPTY_FRAMES, DISCARD_PARTIAL_FRAMES + * [Eiger] + * Options: 4, 8, 16, 32 + * If i is 32, also sets clkdivider to 2, if 16, sets clkdivider to 1 */ - void setReceiverFrameDiscardPolicy(defs::frameDiscardPolicy f, - Positions pos = {}); - - Result getPartialFramesPadding(Positions pos = {}) const; + void setDynamicRange(int value); - /** padding enabled */ - void setPartialFramesPadding(bool value, Positions pos = {}); + /** [Eiger] in 32 bit mode */ + Result getSubExptime(Positions pos = {}) const; + + /** [Eiger] in 32 bit mode */ + void setSubExptime(ns t, Positions pos = {}); + + /** [Eiger] in 32 bit mode */ + Result getSubDeadTime(Positions pos = {}) const; + + /** [Eiger] in 32 bit mode */ + void setSubDeadTime(ns value, Positions pos = {}); + + /** [Eiger] */ + Result getThresholdEnergy(Positions pos = {}) const; + + /** [Eiger] */ + void setThresholdEnergy(int threshold_ev, + defs::detectorSettings settings = defs::STANDARD, + bool trimbits = true, Positions pos = {}); + + /** [Eiger] */ + Result getSettingsDir(Positions pos = {}) const; + + /** [Eiger] */ + void setSettingsDir(const std::string &value, Positions pos = {}); + + /** [Eiger] */ + void loadTrimbits(const std::string &fname, Positions pos = {}); + + /**[Eiger] */ + Result getGapPixelsEnable(Positions pos = {}) const; + + /** + * [Eiger] + * 4 bit mode not implemented in Receiver, but in client data call back + * Fills in gap pixels in data + */ + void setGapPixelsEnable(bool enable); + + /** [Eiger] */ + Result getParallelMode(Positions pos = {}) const; + + /** [Eiger] */ + void setParallelMode(bool value, Positions pos = {}); + + /** [Eiger] */ + Result getOverFlowMode(Positions pos = {}) const; + + /** [Eiger] */ + void setOverFlowMode(bool value, Positions pos = {}); + + /** [Eiger] */ + Result getBottom(Positions pos = {}) const; + + /** [Eiger] for gui purposes */ + void setBottom(bool value, Positions pos = {}); + + /** [Eiger] + * @returns -1 if they are all different + */ + Result getAllTrimbits(Positions pos = {}) const; + + /**[Eiger] */ + void setAllTrimbits(int value, Positions pos = {}); + + /**[Eiger] Returns energies in eV where the module is trimmed */ + Result> getTrimEnergies(Positions pos = {}) const; + + /** [Eiger] Set the energies where the detector is trimmed */ + void setTrimEnergies(std::vector energies, Positions pos = {}); + + /** [Eiger] + * @returns deadtime in ns, 0 = disabled + */ + Result getRateCorrection(Positions pos = {}) const; + + /** + * [Eiger] Set Rate correction + * 0 disable correction, <0 set to default, >0 deadtime in ns + */ + void setRateCorrection(int64_t dead_time_ns, Positions pos = {}); + + /** [Eiger] Sends an internal software trigger to the detector */ + void sendSoftwareTrigger(Positions pos = {}); + + /** [Eiger] */ + Result getPartialReadout(Positions pos = {}) const; + + /** [Eiger] Number of lines to read out per half module + * Options: 0 - 256. Depending on dynamic range and + * 10 GbE enabled, only specific values are accepted. + */ + void setPartialReadout(const int lines, Positions pos = {}); + + /** [Eiger] */ + Result getIODelay(Positions pos = {}) const; + + /** [Eiger] */ + void setIODelay(int value, Positions pos = {}); + + /** [Eiger] */ + Result getInterruptSubframe(Positions pos = {}) const; + + /** [Eiger] when set, the last subframe is interrupted at end of acq */ + void setInterruptSubframe(const bool enable, Positions pos = {}); + + /** [Eiger] */ + Result getCounterBit(Positions pos = {}) const; + + /** [Eiger] If it is set, it resets chips completely (else partially) before + * an acquisition TODO: if it makes sense */ + void setCounterBit(bool value, Positions pos = {}); + + /** + * [Eiger] Pulse Pixel n times at x and y coordinates + */ + void pulsePixel(int n, int x, int y, Positions pos = {}); + + /** [Eiger] Pulse Pixel n times and move by a relative value of x and y + * coordinates */ + void pulsePixelNMove(int n, int x, int y, Positions pos = {}); + + /** [Eiger] Pulse chip n times */ + void pulseChip(int n, Positions pos = {}); + + /** [Eiger] */ + Result getActive(Positions pos = {}) const; + + /** [Eiger] */ + void setActive(bool active, Positions pos = {}); /** [Eiger] */ Result getRxPadDeactivatedMod(Positions pos = {}) const; @@ -997,61 +715,291 @@ class Detector { */ void setRxPadDeactivatedMod(bool pad, Positions pos = {}); - Result getReceiverUDPSocketBufferSize(Positions pos = {}) const; + /** [Eiger] with specific quad hardware */ + Result getQuad(Positions pos = {}) const; - void setReceiverUDPSocketBufferSize(int64_t udpsockbufsize, - Positions pos = {}); - Result - getReceiverRealUDPSocketBufferSize(Positions pos = {}) const; + /** [Eiger] with specific quad hardware */ + void setQuad(const bool enable); + + /** [Eiger] minimum two frames */ + Result getMeasuredPeriod(Positions pos = {}) const; + + /** [Eiger] */ + Result getMeasuredSubFramePeriod(Positions pos = {}) const; /************************************************** * * - * ACQUISITION * + * Jungfrau Specific * * * * ************************************************/ - /** - * Blocking call, starts the receiver and detector. - * Increments file index if file write enabled. - * Acquired the number of frames set. - */ - void acquire(); + + /** [Jungfrau] */ + Result getThresholdTemperature(Positions pos = {}) const; /** - * Get the acquiring flag. When true the detector blocks - * any attempt to start a new acquisition. + * [Jungfrau]Set threshold temperature + * If temperature crosses threshold temperature + * and temperature control is enabled, + * power to chip will be switched off and + * temperature event will be set + * @param val value in millidegrees TODO! Verify */ - bool getAcquiringFlag() const; + void setThresholdTemperature(int temp, Positions pos = {}); + + /** [Jungfrau] */ + Result getTemperatureControl(Positions pos = {}) const; + + /** [Jungfrau] */ + void setTemperatureControl(bool enable, Positions pos = {}); + + /** [Jungfrau] */ + Result getTemperatureEvent(Positions pos = {}) const; + + /** [Jungfrau] */ + void ResetTemperatureEvent(Positions pos = {}); + + /** [Jungfrau] */ + Result getPowerChip(Positions pos = {}) const; + + /** [Jungfrau] */ + void setPowerChip(bool on, Positions pos = {}); + + /** [Jungfrau] */ + Result getAutoCompDisable(Positions pos = {}) const; + + /** [Jungfrau] TODO??? fix docs ? */ + void setAutoCompDisable(bool value, Positions pos = {}); + + /** [Jungfrau] Advanced */ + Result getNumberOfAdditionalStorageCells() const; + + /** [Jungfrau] Advanced */ + void setNumberOfAdditionalStorageCells(int64_t value); + + /** [Jungfrau] Advanced */ + Result getStorageCellStart(Positions pos = {}) const; + + /** [Jungfrau] Advanced. Sets the storage cell storing the first acquisition of the + * series. Options: 0-15 + */ + void setStoragecellStart(int cell, Positions pos = {}); + + /** [Jungfrau] Advanced*/ + Result getStorageCellDelay(Positions pos = {}) const; + + /** [Jungfrau] Advanced + * Options: (0-1638375 ns (resolution of 25ns) */ + void setStorageCellDelay(ns value, Positions pos = {}); + + + /************************************************** + * * + * Gotthard Specific * + * * + * ************************************************/ + + /** [Gotthard]*/ + Result getROI(Positions pos = {}) const; /** - * Set the acquiring flag. This might have to done manually - * after an acquisition was aborted. + * [Gotthard] + * Options: Only a single ROI per module + * Can set only a single ROI at a time + * @param module position index */ - void setAcquiringFlag(bool value); + void setROI(defs::ROI value, int moduleId); - Result getRunStatus(Positions pos = {}); + /** [Gotthard] */ + Result getExptimeLeft(Positions pos = {}) const; - /** Non blocking */ - void startAcquisition(); + /** [Gotthard] */ + Result getPeriodLeft(Positions pos = {}) const; - void stopAcquisition(); + /** [Gotthard] */ + Result + getExternalSignalFlags(Positions pos = {}) const; - /** [Eiger] Sends an internal software trigger to the detector */ - void sendSoftwareTrigger(Positions pos = {}); + /** [Gotthard] Options: TRIGGER_IN_RISING_EDGE, TRIGGER_IN_FALLING_EDGE */ + void setExternalSignalFlags(defs::externalSignalFlag value, + Positions pos = {}); - /** Receiver starts listening to UDP packets from detector */ - void startReceiver(Positions pos = {}); + /** [Gotthard] subset modules not allowed */ + void loadDarkImage(const std::string &fname, Positions pos = {}); - /** Receiver stops listening to UDP packets from detector */ - void stopReceiver(Positions pos = {}); + /** [Gotthard] subset modules not allowed */ + void loadGainImage(const std::string &fname, Positions pos = {}); - /** Read back the run status of the receiver */ - Result getReceiverStatus(Positions pos = {}); + /** + * [Gotthard] subset modules not allowed + * @param startACQ if start acq after reading counter + */ + void getCounterMemoryBlock(const std::string &fname, bool startACQ, + Positions pos = {}); - Result getFramesCaughtByReceiver(Positions pos = {}) const; + /** + * [Gotthard] + * @param startACQ if start acq after resetting counter + * TODO! does it make sense to call one detector? + */ + void resetCounterBlock(bool startACQ, Positions pos = {}); - Result getReceiverCurrentFrameIndex(Positions pos = {}) const; + /** [Gotthard] */ + Result getDigitalTestBit(Positions pos = {}); + + /** [Gotthard] */ + Result setDigitalTestBit(const int value, Positions pos = {}); + + /************************************************** + * * + * CTB Specific * + * * + * ************************************************/ + + /** [CTB] */ + Result getNumberOfAnalogSamples(Positions pos = {}) const; + + /** [CTB] */ + void setNumberOfAnalogSamples(int64_t value, Positions pos = {}); + + /** [CTB] */ + Result getNumberOfDigitalSamples(Positions pos = {}) const; + + /** [CTB] */ + void setNumberOfDigitalSamples(int64_t value, Positions pos = {}); + + /** [CTB] */ + Result getSignalType(Positions pos = {}) const; + + /** [CTB] Options: NORMAL_READOUT = 0, DIGITAL_ONLY = 1, ANALOG_AND_DIGITAL + * = 2 */ + void setSignalType(int value, Positions pos = {}); + + /** [CTB] */ + Result getDBITPhase(bool inDeg, Positions pos = {}) const; + + /** [CTB] */ + void setDBITPhase(int value, bool inDeg, Positions pos = {}); + + /** [CTB] */ + Result getMaxDBITPhaseShift(Positions pos = {}) const; + + /** [CTB] */ + Result getADCClock(Positions pos = {}) const; + + /** [CTB] */ + void setADCClock(int value_in_MHz, Positions pos = {}); + + /** [CTB] */ + Result getDBITClock(Positions pos = {}) const; + + /** [CTB] */ + void setDBITClock(int value_in_MHz, Positions pos = {}); + + /** [CTB] */ + Result getRUNClock(Positions pos = {}) const; + + /** [CTB] */ + void setRUNClock(int value_in_MHz, Positions pos = {}); + + /** [CTB] */ + Result getSYNCClock(Positions pos = {}) const; + + /** [CTB] */ + Result getADCPipeline(Positions pos = {}) const; + + /** [CTB] */ + void setADCPipeline(int value, Positions pos = {}); + + /** [CTB] */ + Result getDBITPipeline(Positions pos = {}) const; + + /** [CTB] */ + void setDBITPipeline(int value, Positions pos = {}); + + /** [CTB] */ + Result getVrefVoltage(bool mV, Positions pos = {}) const; + + /** [CTB] */ + void setVrefVoltage(int value, bool mV, Positions pos = {}); + + /** [CTB] */ + Result getVoltage(defs::dacIndex index, Positions pos = {}) const; + + /** + * [CTB] mV + * Options: V_LIMIT, V_POWER_A, V_POWER_B, V_POWER_C, + * V_POWER_D, V_POWER_IO, V_POWER_CHIP + */ + void setVoltage(int value, defs::dacIndex index, Positions pos = {}); + + /** + * [CTB] mV + * Options: V_POWER_A, V_POWER_B, V_POWER_C, V_POWER_D, V_POWER_IO, + * V_POWER_CHIP + */ + Result getMeasuredVoltage(defs::dacIndex index, + Positions pos = {}) const; + + /** + * [CTB] mA + * Options: I_POWER_A, I_POWER_B, I_POWER_C, I_POWER_D, I_POWER_IO + */ + Result getMeasuredCurrent(defs::dacIndex index, + Positions pos = {}) const; + + /** [CTB] Options: SLOW_ADC0 - SLOW_ADC7 */ + Result getSlowADC(defs::dacIndex index, Positions pos = {}) const; + + /** [CTB]*/ + Result getADCEnableMask(Positions pos = {}) const; + + /** [CTB]*/ + void setADCEnableMask(uint32_t mask, Positions pos = {}); + + /** [CTB] */ + Result getADCInvert(Positions pos = {}) const; + + /** [CTB]*/ + void setADCInvert(uint32_t value, Positions pos = {}); + + /** [CTB] */ + Result getExternalSamplingSource(Positions pos = {}) const; + + /** [CTB] Value between 0-63 */ + void setExternalSamplingSource(int value, Positions pos = {}); + + /** [CTB] */ + Result getExternalSampling(Positions pos = {}) const; + + /** [CTB] */ + void setExternalSampling(bool value, Positions pos = {}); + + /** [CTB] */ + Result> getReceiverDbitList(Positions pos = {}) const; + + /** [CTB] list contains the set of bits (0-63) to save */ + void setReceiverDbitList(std::vector list, Positions pos = {}); + + /** [CTB] */ + Result getReceiverDbitOffset(Positions pos = {}) const; + + /** [CTB] Set number of bytes of digital data to skip in the Receiver */ + void setReceiverDbitOffset(int value, Positions pos = {}); + + /** + * [CTB] Set Digital IO Delay + * cannot get + * @param digital IO mask to select the pins + * @param delay delay in ps(1 bit=25ps, max of 775 ps) + */ + void setDigitalIODelay(uint64_t pinMask, int delay, Positions pos = {}); + + /** [CTB] */ + Result getLEDEnable(Positions pos = {}) const; + + /** [CTB] */ + void setLEDEnable(bool enable, Positions pos = {}); - void resetFramesCaught(Positions pos = {}); /************************************************** * * @@ -1114,6 +1062,105 @@ class Detector { * pattern */ void setPatternBitMask(uint64_t mask, Positions pos = {}); + + /************************************************** + * * + * Advanced * + * * + * ************************************************/ + + /** [Jungfrau][CTB] */ + void programFPGA(const std::string &fname, Positions pos = {}); + + /** [Jungfrau][CTB] */ + void resetFPGA(Positions pos = {}); + + /** [Jungfrau][Gotthard][CTB] + * Copy detector server fname from tftp folder of hostname to detector + * Also changes respawn server, which is effective after a reboot. + */ + void copyDetectorServer(const std::string &fname, + const std::string &hostname, Positions pos = {}); + + /** [Jungfrau][Gotthard][CTB] */ + void rebootController(Positions pos = {}); + + /** + * [Jungfrau][Gotthard][CTB] + * Updates the firmware, detector server and then reboots detector + * controller blackfin. + * @param sname name of detector server binary found on tftp folder of host + * pc + * @param hostname name of pc to tftp from + * @param fname programming file name + * @param pos detector positions + */ + void updateFirmwareAndServer(const std::string &sname, + const std::string &hostname, + const std::string &fname, Positions pos = {}); + + Result readRegister(uint32_t addr, Positions pos = {}) const; + + void writeRegister(uint32_t addr, uint32_t val, Positions pos = {}); + + void setBit(uint32_t addr, int bitnr, Positions pos = {}); + + void clearBit(uint32_t addr, int bitnr, Positions pos = {}); + + /** [Gotthard][Jungfrau][CTB] */ + Result executeFirmwareTest(Positions pos = {}); + + /** [Gotthard][Jungfrau][CTB] */ + Result executeBusTest(Positions pos = {}); + + /** [Gotthard][Jungfrau][CTB] not possible to read back*/ + void writeAdcRegister(uint32_t addr, uint32_t value, Positions pos = {}); + + + /************************************************** + * * + * Insignificant * + * * + * ************************************************/ + + + + Result getControlPort(Positions pos = {}) const; + + /** Detector Control TCP port (for client communication with Detector + * control server) */ + void setControlPort(int value, Positions pos = {}); + + Result getStopPort(Positions pos = {}) const; + + /** Detector Stop TCP port (for client communication with Detector Stop + * server) */ + void setStopPort(int value, Positions pos = {}); + + Result getDetectorLock(Positions pos = {}) const; + + void setDetectorLock(bool lock, Positions pos = {}); + + /** Get last client IP saved on detector server */ + Result getLastClientIP(Positions pos = {}) const; + + /** Execute a command on the detector server */ + void execCommand(const std::string &value, Positions pos = {}); + + /** [Gotthard][Jungfrau][CTB] */ + Result getNumberOfFramesFromStart(Positions pos = {}) const; + + /** [Jungfrau][CTB] Get time from detector start */ + Result getActualTime(Positions pos = {}) const; + + /** [Jungfrau][CTB] Get timestamp at a frame start */ + Result getMeasurementTime(Positions pos = {}) const; + + std::string getUserDetails() const; + + Result getReceiverCurrentFrameIndex(Positions pos = {}) const; + + }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 367013933..d3250d016 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -57,17 +57,10 @@ struct sharedMultiSlsDetector { int numberOfDetector[2]; /** total number of channels for all detectors */ - int numberOfChannels; + int numberOfChannels[2]; - /** total number of channels for all detectors in one dimension*/ - int numberOfChannel[2]; - - /** total number of channels including gap pixels in one dimension */ - int numberOfChannelInclGapPixels[2]; - - /** max number of channels allowed for the complete set of detectors in - * one dimension */ - int maxNumberOfChannelsPerDetector[2]; + /** max number of channels for complete detector*/ + int maxNumberOfChannels[2]; /** flag for acquiring */ bool acquiringFlag; @@ -367,91 +360,32 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ size_t size() const;// - /** - * Returns number of detectors in dimension d - * @param d dimension d - * @returns number of detectors in dimension d - */ - int getNumberOfDetectors(dimension d) const;// - /** * Returns the number of detectors in each direction - @param nx number of detectors in x direction - @param ny number of detectors in y direction */ - void getNumberOfDetectors(int &nx, int &ny) const;// + slsDetectorDefs::xy getNumberOfDetectors() const;// /** - * Returns the total number of channels of all sls detectors from shared - * memory - * @param detPos -1 for all detectors in list or specific detector position - * @returns the total number of channels of all sls detectors - */ - int getTotalNumberOfChannels(int detPos = -1);// - - /** - * Returns the total number of channels of all sls detectors in dimension d - * from shared memory + * Returns the total number of channels of all sls detectors including gap pixels * @param d dimension d * @param detPos -1 for all detectors in list or specific detector position - * @returns the total number of channels of all sls detectors in dimension d + * @returns the total number of channels of all sls detectors including gap pixels */ - int getTotalNumberOfChannels(dimension d, int detPos = -1);// + slsDetectorDefs::xy getNumberOfChannels(int detPos = -1);// - /** - * Returns the total number of channels from shared memory in each dimension - * @returns the total number of channels in each dimension - */ - slsDetectorDefs::coordinates getNumberOfChannels() const; // - - /** - * Returns the total number of channels of all sls detectors in dimension d - * including gap pixels from shared memory - * @param d dimension d - * @param detPos -1 for all detectors in list or specific detector position - * @returns the total number of channels of all sls detectors in dimension d - * including gap pixels - */ - int getTotalNumberOfChannelsInclGapPixels(dimension d, int detPos = -1);// - - /** - * Returns the total number of channels including gap pixels - * @returns the total number of channels including gap pixels - */ - slsDetectorDefs::coordinates getTotalNumberOfChannelsInclGapPixels() const; // - - /** - * Returns the maximum number of channels of all sls detectors in each - * dimension d from shared memory. - * @param d dimension d - * @returns the maximum number of channels of all sls detectors in dimension - * d - */ - int getMaxNumberOfChannelsPerDetector(dimension d);// - - /** - * Sets the maximum number of channels of all sls detectors in each - * dimension d from shared memory - * @param d dimension d - * @param i maximum number of channels for multi structure in dimension d - * @returns the maximum number of channels of all sls detectors in dimension - * d - */ - int setMaxNumberOfChannelsPerDetector(dimension d, int i);// - /** * Returns maximum number of channels of all sls detectors in each * dimension d from shared memory * @returns maximum number of channels of all sls detectors */ - slsDetectorDefs::coordinates getMaxNumberOfChannels() const; // + slsDetectorDefs::xy getMaxNumberOfChannels() const; // /** * Sets maximum number of channels of all sls detectors in each * dimension d from shared memory * @param c maximum number of channels of all sls detectors */ - void setMaxNumberOfChannels(const slsDetectorDefs::coordinates c); // + void setMaxNumberOfChannels(const slsDetectorDefs::xy c); // /** * Get Quad Type (Only for Eiger Quad detector hardware) @@ -935,6 +869,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { std::string getDetectorMAC2(int detPos = -1); // /** + * //TODO: custom ip (eiger 10G and other detectors), use 0.0.0.0 and test * Validates the format of the detector IP address and sets it * @param detectorIP detector IP address * @param detPos -1 for all detectors in list or specific detector position @@ -985,6 +920,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { std::string getReceiverHostname(int detPos = -1) const; // /** + * TODO: replace this with setEthernetInterface * Validates the format of the receiver UDP IP address and sets it * @param udpip receiver UDP IP address * @param detPos -1 for all detectors in list or specific detector position diff --git a/slsDetectorSoftware/include/slsDetector.h b/slsDetectorSoftware/include/slsDetector.h index de23d310d..d6160f385 100755 --- a/slsDetectorSoftware/include/slsDetector.h +++ b/slsDetectorSoftware/include/slsDetector.h @@ -13,7 +13,7 @@ class ServerInterface; #define SLS_SHMAPIVERSION 0x190726 -#define SLS_SHMVERSION 0x190813 +#define SLS_SHMVERSION 0x190815 /** * @short structure allocated in shared memory to store detector settings for @@ -68,9 +68,6 @@ struct sharedSlsDetector { /** dynamic range of the detector data */ int dynamicRange; - /** size of the data that are transfered from the detector */ - int dataBytes; - /** roi */ slsDetectorDefs::ROI roi; @@ -171,9 +168,6 @@ struct sharedSlsDetector { /** gap pixels in each direction */ int nGappixels[2]; - /** data bytes including gap pixels */ - int dataBytesInclGapPixels; - /** additional json header */ char rxAdditionalJsonHeader[MAX_STR_LENGTH]; @@ -324,73 +318,17 @@ class slsDetector : public virtual slsDetectorDefs { */ int setDetectorType(detectorType type = GET_DETECTOR_TYPE); - /** - * Returns the total number of channels from shared memory - * @returns the total number of channels - */ - int getTotalNumberOfChannels() const; - /** * Update total number of channels (chiptestboard or moench) * depending on the number of samples, adenablemask, readout flags(ctb) */ - void updateTotalNumberOfChannels(); - - /** - * Returns the total number of channels in dimension d from shared memory - * @param d dimension d - * @returns the total number of channels in dimension d - */ - int getTotalNumberOfChannels(dimension d) const; - - /** - * Returns the total number of channels from shared memory in each dimension - * @returns the total number of channels in each dimension - */ - slsDetectorDefs::coordinates getNumberOfChannels() const; - - /** - * Returns the total number of channels of in dimension d including gap - * pixels from shared memory - * @param d dimension d - * @returns the total number of channels including gap pixels in dimension d - * including gap pixels - */ - int getTotalNumberOfChannelsInclGapPixels(dimension d) const; + void updateNumberOfChannels(); /** * Returns the total number of channels including gap pixels * @returns the total number of channels including gap pixels */ - slsDetectorDefs::coordinates getNumberOfChannelsInclGapPixels() const; - - /** - * returns the number of channels per chip from shared memory (Mythen) - * @returns number of channels per chip - */ - int getNChans() const; - - /** - * returns the number of channels per chip in dimension d from shared memory - * (Mythen) - * @param d dimension d - * @returns number of channels per chip in dimension d - */ - int getNChans(dimension d) const; - - /** - * returns the number of chips per module from shared memory (Mythen) - * @returns number of chips per module - */ - int getNChips() const; - - /** - * returns the number of chips per module in dimension d from shared memory - * (Mythen) - * @param d dimension d - * @returns number of chips per module in dimension d - */ - int getNChips(dimension d) const; + slsDetectorDefs::xy getNumberOfChannels() const; /** * Get Quad Type (Only for Eiger Quad detector hardware) @@ -654,7 +592,7 @@ class slsDetector : public virtual slsDetectorDefs { int setSpeed(speedVariable sp, int value = -1, int mode = 0); /** - * Set/get dynamic range and updates the number of dataBytes + * Set/get dynamic range * (Eiger: If i is 32, also sets clkdivider to 2, if 16, sets clkdivider to * 1) * @param i dynamic range (-1 get) @@ -665,18 +603,6 @@ class slsDetector : public virtual slsDetectorDefs { int getDynamicRangeFromShm(); - /** - * Recalculated number of data bytes - * @returns tota number of data bytes - */ - int getDataBytes(); - - /** - * Recalculated number of data bytes including gap pixels - * @returns tota number of data bytes including gap pixels - */ - int getDataBytesInclGapPixels(); - /** * Set/get dacs value * @param val value (in V) diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index f4280bb8a..8e6699f6c 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -8,14 +8,14 @@ namespace sls { using defs = slsDetectorDefs; -Detector::Detector(int multi_id) - : pimpl(sls::make_unique(multi_id)) {} +Detector::Detector(int shm_id) + : pimpl(sls::make_unique(shm_id)) {} Detector::~Detector() = default; // Configuration void Detector::freeSharedMemory() { pimpl->freeSharedMemory(); } -void Detector::setConfig(const std::string &fname) { +void Detector::loadConfig(const std::string &fname) { pimpl->readConfigurationFile(fname); } @@ -27,17 +27,9 @@ void Detector::setHostname(const std::vector &value) { pimpl->setHostname(value); } -int Detector::getMultiId() const { return pimpl->getMultiId(); } +int Detector::getShmId() const { return pimpl->getMultiId(); } -void Detector::checkDetectorVersionCompatibility(Positions pos) const { - pimpl->Parallel(&slsDetector::checkDetectorVersionCompatibility, pos); -} - -void Detector::checkReceiverVersionCompatibility(Positions pos) const { - pimpl->Parallel(&slsDetector::checkReceiverVersionCompatibility, pos); -} - -Result Detector::getDetectorFirmwareVersion(Positions pos) const { +Result Detector::getFirmwareVersion(Positions pos) const { return pimpl->Parallel(&slsDetector::getId, pos, defs::DETECTOR_FIRMWARE_VERSION); } @@ -47,40 +39,33 @@ Result Detector::getDetectorServerVersion(Positions pos) const { defs::DETECTOR_SOFTWARE_VERSION); } -Result Detector::getDetectorSerialNumber(Positions pos) const { +Result Detector::getSerialNumber(Positions pos) const { return pimpl->Parallel(&slsDetector::getId, pos, defs::DETECTOR_SERIAL_NUMBER); } -int64_t Detector::getClientSoftwareVersion() const { +int64_t Detector::getClientVersion() const { return pimpl->getClientSoftwareVersion(); } -Result Detector::getReceiverSoftwareVersion(Positions pos) const { +Result Detector::getReceiverVersion(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverSoftwareVersion, pos); } -std::string Detector::getUserDetailsFromSharedMemory() const { return pimpl->getUserDetails(); } +std::string Detector::getUserDetails() const { return pimpl->getUserDetails(); } Result Detector::getDetectorType(Positions pos) const { return pimpl->Parallel(&slsDetector::getDetectorTypeAsEnum, pos); } -Result Detector::getDetectorTypeAsString(Positions pos) const { - return pimpl->Parallel(&slsDetector::getDetectorTypeAsString, pos); -} - int Detector::size() const { return pimpl->size(); } -defs::coordinates Detector::getNumberOfDetectors() const { - defs::coordinates coord; - coord.x = pimpl->getNumberOfDetectors(defs::X); - coord.y = pimpl->getNumberOfDetectors(defs::Y); - return coord; +defs::xy Detector::getModuleGeometry() const { + return pimpl->getNumberOfDetectors(); } -Result Detector::getNumberOfChannels(Positions pos) const { +Result Detector::getModuleSize(Positions pos) const { if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) { // TODO: also check condition that pos.size == @@ -90,19 +75,11 @@ Result Detector::getNumberOfChannels(Positions pos) const { return pimpl->Parallel(&slsDetector::getNumberOfChannels, pos); } -Result -Detector::getNumberOfChannelsInclGapPixels(Positions pos) const { - if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) { - return {pimpl->getTotalNumberOfChannelsInclGapPixels()}; - } - return pimpl->Parallel(&slsDetector::getNumberOfChannelsInclGapPixels, pos); -} - -defs::coordinates Detector::getMaxNumberOfChannels() const { +defs::xy Detector::getDetectorSize() const { return pimpl->getMaxNumberOfChannels(); } -void Detector::setMaxNumberOfChannels(const defs::coordinates value) { +void Detector::setDetectorSize(const defs::xy value) { pimpl->setMaxNumberOfChannels(value); } @@ -110,16 +87,16 @@ Result Detector::getQuad(Positions pos) const { return pimpl->Parallel(&slsDetector::getQuad, pos); } -void Detector::setQuad(const bool value, Positions pos) { - pimpl->setQuad(value, 0); +void Detector::setQuad(const bool value) { + pimpl->setQuad(value); } -Result Detector::getReadNLines(Positions pos) const { +Result Detector::getPartialReadout(Positions pos) const { return pimpl->Parallel(&slsDetector::getReadNLines, pos); } -void Detector::setReadNLines(const int value, Positions pos) { - pimpl->Parallel(&slsDetector::setReadNLines, pos, value); +void Detector::setPartialReadout(const int lines, Positions pos) { + pimpl->Parallel(&slsDetector::setReadNLines, pos, lines); } Result Detector::getControlPort(Positions pos) const { @@ -138,30 +115,22 @@ void Detector::setStopPort(int value, Positions pos) { pimpl->Parallel(&slsDetector::setStopPort, pos, value); } -Result Detector::getLockServer(Positions pos) const { +Result Detector::getDetectorLock(Positions pos) const { return pimpl->Parallel(&slsDetector::lockServer, pos, -1); } -void Detector::setLockServer(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::lockServer, pos, static_cast(value)); +void Detector::setDetectorLock(bool lock, Positions pos) { + pimpl->Parallel(&slsDetector::lockServer, pos, static_cast(lock)); } Result Detector::getLastClientIP(Positions pos) const { return pimpl->Parallel(&slsDetector::getLastClientIP, pos); } -void Detector::exitServer(Positions pos) { - pimpl->Parallel(&slsDetector::exitServer, pos); -} - void Detector::execCommand(const std::string &value, Positions pos) { pimpl->Parallel(&slsDetector::execCommand, pos, value); } -void Detector::writeConfigurationFile(const std::string &value) { - pimpl->writeConfigurationFile(value); -} - Result Detector::getSettings(Positions pos) const { return pimpl->Parallel(&slsDetector::getSettings, pos); } @@ -174,9 +143,9 @@ Result Detector::getThresholdEnergy(Positions pos) const { return pimpl->Parallel(&slsDetector::getThresholdEnergy, pos); } -void Detector::setThresholdEnergy(int value, defs::detectorSettings sett, - int tb, Positions pos) { - pimpl->Parallel(&slsDetector::setThresholdEnergy, pos, value, sett, tb); +void Detector::setThresholdEnergy(int threshold_ev, defs::detectorSettings settings, + bool trimbits, Positions pos) { + pimpl->Parallel(&slsDetector::setThresholdEnergy, pos, threshold_ev, settings, static_cast(trimbits)); } Result Detector::getSettingsDir(Positions pos) const { @@ -187,14 +156,10 @@ void Detector::setSettingsDir(const std::string &value, Positions pos) { pimpl->Parallel(&slsDetector::setSettingsDir, pos, value); } -void Detector::loadSettingsFile(const std::string &value, Positions pos) { +void Detector::loadTrimbits(const std::string &value, Positions pos) { pimpl->Parallel(&slsDetector::loadSettingsFile, pos, value); } -void Detector::saveSettingsFile(const std::string &value, Positions pos) { - pimpl->Parallel(&slsDetector::saveSettingsFile, pos, value); -} - void Detector::configureMAC(Positions pos) { pimpl->Parallel(&slsDetector::configureMAC, pos); } @@ -207,11 +172,11 @@ void Detector::setNumberOfFrames(int64_t value) { pimpl->Parallel(&slsDetector::setTimer, {}, defs::FRAME_NUMBER, value); } -Result Detector::getNumberOfCycles() const { +Result Detector::getNumberOfTriggers() const { return pimpl->Parallel(&slsDetector::setTimer, {}, defs::CYCLES_NUMBER, -1); } -void Detector::setNumberOfCycles(int64_t value) { +void Detector::setNumberOfTriggers(int64_t value) { pimpl->Parallel(&slsDetector::setTimer, {}, defs::CYCLES_NUMBER, value); } @@ -220,7 +185,7 @@ Result Detector::getNumberOfAdditionalStorageCells() const { defs::STORAGE_CELL_NUMBER, -1); } -void Detector::setNumberOfStorageCells(int64_t value) { +void Detector::setNumberOfAdditionalStorageCells(int64_t value) { pimpl->Parallel(&slsDetector::setTimer, {}, defs::STORAGE_CELL_NUMBER, value); } @@ -695,10 +660,10 @@ void Detector::clearBit(uint32_t addr, int bitnr, Positions pos) { pimpl->Parallel(&slsDetector::clearBit, pos, addr, bitnr); } -Result Detector::getDetectorMAC(Positions pos) const { +Result Detector::getSourceUDPMAC(Positions pos) const { return pimpl->Parallel(&slsDetector::getDetectorMAC, pos); } -void Detector::setDetectorMAC(const std::string &detectorMAC, Positions pos) { +void Detector::setSourceUDPMAC(const std::string &detectorMAC, Positions pos) { pimpl->Parallel(&slsDetector::setDetectorMAC, pos, detectorMAC); } @@ -709,11 +674,11 @@ void Detector::setDetectorMAC2(const std::string &detectorMAC, Positions pos) { pimpl->Parallel(&slsDetector::setDetectorMAC2, pos, detectorMAC); } -Result Detector::getDetectorIP(Positions pos) const { +Result Detector::getSourceUDPIP(Positions pos) const { return pimpl->Parallel(&slsDetector::getDetectorIP, pos); } -void Detector::setDetectorIP(const std::string &detectorIP, Positions pos) { +void Detector::setSourceUDPIP(const std::string &detectorIP, Positions pos) { pimpl->Parallel(&slsDetector::setDetectorIP, pos, detectorIP); } @@ -733,11 +698,11 @@ void Detector::setReceiverHostname(const std::string &receiver, Positions pos) { pimpl->Parallel(&slsDetector::setReceiverHostname, pos, receiver); } -Result Detector::getReceiverUDPIP(Positions pos) const { +Result Detector::getDestinationUDPIP(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverUDPIP, pos); } -void Detector::setReceiverUDPIP(const std::string &udpip, Positions pos) { +void Detector::setDestinationUDPIP(const std::string &udpip, Positions pos) { pimpl->Parallel(&slsDetector::setReceiverUDPIP, pos, udpip); } @@ -749,11 +714,11 @@ void Detector::setReceiverUDPIP2(const std::string &udpip, Positions pos) { pimpl->Parallel(&slsDetector::setReceiverUDPIP2, pos, udpip); } -Result Detector::getReceiverUDPMAC(Positions pos) const { +Result Detector::getDestinationUDPMAC(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverUDPMAC, pos); } -void Detector::setReceiverUDPMAC(const std::string &udpmac, Positions pos) { +void Detector::setDestinationUDPMAC(const std::string &udpmac, Positions pos) { pimpl->Parallel(&slsDetector::setReceiverUDPMAC, pos, udpmac); } @@ -1379,14 +1344,6 @@ Result Detector::getReceiverLastClientIP(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverLastClientIP, pos); } -void Detector::exitReceiver(Positions pos) { - pimpl->Parallel(&slsDetector::exitReceiver, pos); -} - -void Detector::execReceiverCommand(const std::string &cmd, Positions pos) { - pimpl->Parallel(&slsDetector::execReceiverCommand, pos, cmd); -} - Result Detector::getReceiverStreamingFrequency(Positions pos) const { return pimpl->Parallel(&slsDetector::setReceiverStreamingTimer, pos, -1); } @@ -1484,36 +1441,33 @@ Detector::getReceiverRealUDPSocketBufferSize(Positions pos) const { // Acquisition void Detector::acquire() { pimpl->acquire(); } -bool Detector::getAcquiringFlag() const { return pimpl->getAcquiringFlag(); } +void Detector::clearAcquiringFlag() { pimpl->setAcquiringFlag(0); } -void Detector::setAcquiringFlag(bool value) { pimpl->setAcquiringFlag(value); } - -Result Detector::getRunStatus(Positions pos) { +Result Detector::getDetectorStatus(Positions pos) const{ return pimpl->Parallel(&slsDetector::getRunStatus, pos); } void Detector::startAcquisition() { - pimpl->startAcquisition(); + if (getUseReceiverFlag({}).squash()) + pimpl->Parallel(&slsDetector::startReceiver, {}); + pimpl->Parallel(&slsDetector::startAcquisition, {}); } -void Detector::stopAcquisition() { pimpl->stopAcquisition(); } +void Detector::stopAcquisition() { + pimpl->Parallel(&slsDetector::stopAcquisition, {}); + if (getUseReceiverFlag({}).squash()) //TODO: problem for acquire() + pimpl->Parallel(&slsDetector::stopReceiver, {}); +} void Detector::sendSoftwareTrigger(Positions pos) { pimpl->Parallel(&slsDetector::sendSoftwareTrigger, pos); } -void Detector::startReceiver(Positions pos) { - pimpl->Parallel(&slsDetector::startReceiver, pos); -} -void Detector::stopReceiver(Positions pos) { - pimpl->Parallel(&slsDetector::stopReceiver, pos); -} - -Result Detector::getReceiverStatus(Positions pos) { +Result Detector::getReceiverStatus(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverStatus, pos); } -Result Detector::getFramesCaughtByReceiver(Positions pos) const { +Result Detector::getFramesCaught(Positions pos) const { return pimpl->Parallel(&slsDetector::getFramesCaughtByReceiver, pos); } @@ -1521,10 +1475,6 @@ Result Detector::getReceiverCurrentFrameIndex(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverCurrentFrameIndex, pos); } -void Detector::resetFramesCaught(Positions pos) { - pimpl->Parallel(&slsDetector::resetFramesCaught, pos); -} - // pattern void Detector::setPattern(const std::string &fname, Positions pos) { diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index 90d9f1413..4424bc84d 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -278,13 +278,10 @@ void multiSlsDetector::initializeDetectorStructure() { multi_shm()->multiDetectorType = GENERIC; multi_shm()->numberOfDetector[X] = 0; multi_shm()->numberOfDetector[Y] = 0; - multi_shm()->numberOfChannels = 0; - multi_shm()->numberOfChannel[X] = 0; - multi_shm()->numberOfChannel[Y] = 0; - multi_shm()->numberOfChannelInclGapPixels[X] = 0; - multi_shm()->numberOfChannelInclGapPixels[Y] = 0; - multi_shm()->maxNumberOfChannelsPerDetector[X] = -1; - multi_shm()->maxNumberOfChannelsPerDetector[Y] = -1; + multi_shm()->numberOfChannels[X] = 0; + multi_shm()->numberOfChannels[Y] = 0; + multi_shm()->maxNumberOfChannels[X] = 0; + multi_shm()->maxNumberOfChannels[Y] = 0; multi_shm()->acquiringFlag = false; multi_shm()->receiver_upstream = false; } @@ -425,7 +422,6 @@ void multiSlsDetector::addSlsDetector(const std::string &hostname) { detectors.push_back( sls::make_unique(type, multiId, pos, false)); multi_shm()->numberOfDetectors = detectors.size(); - multi_shm()->numberOfChannels += detectors[pos]->getTotalNumberOfChannels(); detectors[pos]->setHostname(hostname); multi_shm()->multiDetectorType = getDetectorTypeAsEnum(-1);// -1 needed here } @@ -433,17 +429,12 @@ void multiSlsDetector::addSlsDetector(const std::string &hostname) { void multiSlsDetector::updateDetectorSize() { FILE_LOG(logDEBUG) << "Updating Multi-Detector Size: " << size(); - int my = detectors[0]->getTotalNumberOfChannels(Y); - int mx = detectors[0]->getTotalNumberOfChannels(X); - int mgy = detectors[0]->getTotalNumberOfChannelsInclGapPixels(Y); - int mgx = detectors[0]->getTotalNumberOfChannelsInclGapPixels(X); - if (mgy == 0) { - mgy = my; - mgx = mx; - } + slsDetectorDefs::xy res = detectors[0]->getNumberOfChannels(); + int my = res.x; + int mx = res.y; - int maxy = multi_shm()->maxNumberOfChannelsPerDetector[Y]; - if (maxy == -1) { + int maxy = multi_shm()->maxNumberOfChannels[Y]; + if (maxy == 0) { maxy = my * size(); } @@ -455,10 +446,8 @@ void multiSlsDetector::updateDetectorSize() { multi_shm()->numberOfDetector[X] = ndetx; multi_shm()->numberOfDetector[Y] = ndety; - multi_shm()->numberOfChannel[X] = mx * ndetx; - multi_shm()->numberOfChannel[Y] = my * ndety; - multi_shm()->numberOfChannelInclGapPixels[X] = mgx * ndetx; - multi_shm()->numberOfChannelInclGapPixels[Y] = mgy * ndety; + multi_shm()->numberOfChannels[X] = mx * ndetx; + multi_shm()->numberOfChannels[Y] = my * ndety; FILE_LOG(logDEBUG) << "\n\tNumber of Detectors in X direction:" @@ -466,22 +455,19 @@ void multiSlsDetector::updateDetectorSize() { << "\n\tNumber of Detectors in Y direction:" << multi_shm()->numberOfDetector[Y] << "\n\tNumber of Channels in X direction:" - << multi_shm()->numberOfChannel[X] + << multi_shm()->numberOfChannels[X] << "\n\tNumber of Channels in Y direction:" - << multi_shm()->numberOfChannel[Y] - << "\n\tNumber of Channels in X direction with Gap Pixels:" - << multi_shm()->numberOfChannelInclGapPixels[X] - << "\n\tNumber of Channels in Y direction with Gap Pixels:" - << multi_shm()->numberOfChannelInclGapPixels[Y]; + << multi_shm()->numberOfChannels[Y]; - multi_shm()->numberOfChannels = - multi_shm()->numberOfChannel[0] * multi_shm()->numberOfChannel[1]; for (auto &d : detectors) { d->updateMultiSize(multi_shm()->numberOfDetector[0], multi_shm()->numberOfDetector[1]); } -} + + multi_shm()->maxNumberOfChannels[X] = multi_shm()->numberOfChannels[X]; + multi_shm()->maxNumberOfChannels[Y] = multi_shm()->numberOfChannels[Y]; + } slsDetectorDefs::detectorType multiSlsDetector::getDetectorTypeAsEnum() const { return multi_shm()->multiDetectorType; @@ -512,86 +498,43 @@ std::string multiSlsDetector::getDetectorTypeAsString(int detPos) { size_t multiSlsDetector::size() const { return detectors.size(); } -int multiSlsDetector::getNumberOfDetectors(dimension d) const { - return multi_shm()->numberOfDetector[d]; +slsDetectorDefs::xy multiSlsDetector::getNumberOfDetectors() const { + slsDetectorDefs::xy res; + res.x = multi_shm()->numberOfDetector[X]; + res.y = multi_shm()->numberOfDetector[Y]; + return res; } -void multiSlsDetector::getNumberOfDetectors(int &nx, int &ny) const { - nx = multi_shm()->numberOfDetector[X]; - ny = multi_shm()->numberOfDetector[Y]; -} - -int multiSlsDetector::getTotalNumberOfChannels(int detPos) { +slsDetectorDefs::xy multiSlsDetector::getNumberOfChannels(int detPos) { // single if (detPos >= 0) { - return detectors[detPos]->getTotalNumberOfChannels(); + return detectors[detPos]->getNumberOfChannels(); } // multi - return multi_shm()->numberOfChannels; -} - -int multiSlsDetector::getTotalNumberOfChannels(dimension d, int detPos) { - // single - if (detPos >= 0) { - return detectors[detPos]->getTotalNumberOfChannels(d); - } - - // multi - return multi_shm()->numberOfChannel[d]; -} - -slsDetectorDefs::coordinates multiSlsDetector::getNumberOfChannels() const { - slsDetectorDefs::coordinates coord; - coord.x = multi_shm()->numberOfChannel[X]; - coord.y = multi_shm()->numberOfChannel[Y]; + slsDetectorDefs::xy coord; + coord.x = multi_shm()->numberOfChannels[X]; + coord.y = multi_shm()->numberOfChannels[Y]; return coord; } -int multiSlsDetector::getTotalNumberOfChannelsInclGapPixels(dimension d, - int detPos) { - // single - if (detPos >= 0) { - return detectors[detPos]->getTotalNumberOfChannelsInclGapPixels(d); - } - - // multi - return multi_shm()->numberOfChannelInclGapPixels[d]; -} - -slsDetectorDefs::coordinates multiSlsDetector::getTotalNumberOfChannelsInclGapPixels() const { - slsDetectorDefs::coordinates coord; - coord.x = multi_shm()->numberOfChannelInclGapPixels[X]; - coord.y = multi_shm()->numberOfChannelInclGapPixels[Y]; +slsDetectorDefs::xy multiSlsDetector::getMaxNumberOfChannels() const { + slsDetectorDefs::xy coord; + coord.x = multi_shm()->maxNumberOfChannels[X]; + coord.y = multi_shm()->maxNumberOfChannels[Y]; return coord; } -int multiSlsDetector::getMaxNumberOfChannelsPerDetector(dimension d) { - return multi_shm()->maxNumberOfChannelsPerDetector[d]; -} - -int multiSlsDetector::setMaxNumberOfChannelsPerDetector(dimension d, int i) { - multi_shm()->maxNumberOfChannelsPerDetector[d] = i; - return multi_shm()->maxNumberOfChannelsPerDetector[d]; -} - -slsDetectorDefs::coordinates multiSlsDetector::getMaxNumberOfChannels() const { - slsDetectorDefs::coordinates coord; - coord.x = multi_shm()->maxNumberOfChannelsPerDetector[X]; - coord.y = multi_shm()->maxNumberOfChannelsPerDetector[Y]; - return coord; -} - -void multiSlsDetector::setMaxNumberOfChannels(const slsDetectorDefs::coordinates c) { - multi_shm()->maxNumberOfChannelsPerDetector[X] = c.x; - multi_shm()->maxNumberOfChannelsPerDetector[Y] = c.y; +void multiSlsDetector::setMaxNumberOfChannels(const slsDetectorDefs::xy c) { + multi_shm()->maxNumberOfChannels[X] = c.x; + multi_shm()->maxNumberOfChannels[Y] = c.y; } int multiSlsDetector::getQuad(int detPos) { int retval = detectors[0]->getQuad(); if (retval && size() > 1) { throw RuntimeError("Quad type is available only for 1 Eiger Quad Half " - "module, but it Quad is enabled for 1st readout"); + "module, but Quad is enabled for 1st readout"); } return retval; } @@ -1959,7 +1902,7 @@ void multiSlsDetector::loadImageToDetector(imageType index, // multi // read image for all - int nch = multi_shm()->numberOfChannels; + int nch = getNumberOfChannels().x; short int imageVals[nch]; if (readDataFile(fname, imageVals, nch) < nch * (int)sizeof(short int)) { throw RuntimeError("Could not open file or not enough data in file to " @@ -1968,7 +1911,7 @@ void multiSlsDetector::loadImageToDetector(imageType index, // send image to all for (size_t idet = 0; idet < detectors.size(); ++idet) { - detectors[idet]->sendImageToDetector(index, imageVals + idet * detectors[idet]->getTotalNumberOfChannels()); + detectors[idet]->sendImageToDetector(index, imageVals + idet * detectors[idet]->getNumberOfChannels().x); } } @@ -1980,11 +1923,11 @@ void multiSlsDetector::writeCounterBlockFile(const std::string &fname, } // multi - int nch = multi_shm()->numberOfChannels; + int nch = getNumberOfChannels().x; short int imageVals[nch]; for (size_t idet = 0; idet < detectors.size(); ++idet) { detectors[idet]->getCounterBlock( - imageVals + idet * detectors[idet]->getTotalNumberOfChannels(), + imageVals + idet * detectors[idet]->getNumberOfChannels().x, startACQ); } @@ -2255,16 +2198,27 @@ int multiSlsDetector::enableGapPixels(int val, int detPos) { int ret = sls::minusOneIfDifferent(r); if (val != -1) { - multi_shm()->numberOfChannelInclGapPixels[X] = sls::sum(parallelCall(&slsDetector::getTotalNumberOfChannelsInclGapPixels, X)); - multi_shm()->numberOfChannelInclGapPixels[Y] = sls::sum(parallelCall(&slsDetector::getTotalNumberOfChannelsInclGapPixels, Y)); + Parallel(&slsDetector::enableGapPixels, {}, val); + Result res = Parallel(&slsDetector::getNumberOfChannels, {}); + multi_shm()->numberOfChannels[X] = 0; + multi_shm()->numberOfChannels[Y] = 0; + for (auto &it : res) { + multi_shm()->numberOfChannels[X] += it.x; + multi_shm()->numberOfChannels[Y] += it.y; + } } return ret; } void multiSlsDetector::setGapPixelsEnable(bool enable, Positions pos){ Parallel(&slsDetector::enableGapPixels, pos, static_cast(enable)); - multi_shm()->numberOfChannelInclGapPixels[X] = sls::sum(parallelCall(&slsDetector::getTotalNumberOfChannelsInclGapPixels, X)); - multi_shm()->numberOfChannelInclGapPixels[Y] = sls::sum(parallelCall(&slsDetector::getTotalNumberOfChannelsInclGapPixels, Y)); + Result res = Parallel(&slsDetector::getNumberOfChannels, {}); + multi_shm()->numberOfChannels[X] = 0; + multi_shm()->numberOfChannels[Y] = 0; + for (auto &it : res) { + multi_shm()->numberOfChannels[X] += it.x; + multi_shm()->numberOfChannels[Y] += it.y; + } } int multiSlsDetector::setTrimEn(std::vector energies, int detPos) { diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index faa8eb011..aa523aa7d 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -414,17 +414,9 @@ void slsDetector::initializeDetectorStructure(detectorType type) { shm()->nChans = shm()->nChan[X] * shm()->nChan[Y]; shm()->nChips = shm()->nChip[X] * shm()->nChip[Y]; - // calculating databytes - shm()->dataBytes = shm()->nChips * shm()->nChans * shm()->dynamicRange / 8; - shm()->dataBytesInclGapPixels = (shm()->nChip[X] * shm()->nChan[X] + - shm()->gappixels * shm()->nGappixels[X]) * - (shm()->nChip[Y] * shm()->nChan[Y] + - shm()->gappixels * shm()->nGappixels[Y]) * - shm()->dynamicRange / 8; - - // update #nchans and databytes, as it depends on #samples, adcmask, + // update #nchans, as it depends on #samples, adcmask, // readoutflags (ctb only) - updateTotalNumberOfChannels(); + updateNumberOfChannels(); } int slsDetector::sendModule(sls_detector_module *myMod, @@ -574,16 +566,11 @@ std::string slsDetector::getDetectorTypeAsString() const { return slsDetectorDefs::detectorTypeToString(getDetectorTypeAsEnum()); } -int slsDetector::getTotalNumberOfChannels() const { - return shm()->nChans * shm()->nChips; -} - -void slsDetector::updateTotalNumberOfChannels() { +void slsDetector::updateNumberOfChannels() { if (shm()->myDetectorType == CHIPTESTBOARD || shm()->myDetectorType == MOENCH) { int nachans = 0, ndchans = 0; - int adatabytes = 0, ddatabytes = 0; // analog channels (normal, analog/digital readout) if (shm()->roFlags == slsDetectorDefs::NORMAL_READOUT || ((shm()->roFlags & slsDetectorDefs::ANALOG_AND_DIGITAL) != 0)) { @@ -596,10 +583,7 @@ void slsDetector::updateTotalNumberOfChannels() { ++nachans; } } - adatabytes = nachans * (shm()->dynamicRange / 8) * - shm()->timerValue[ANALOG_SAMPLES]; - FILE_LOG(logDEBUG1) << "#Analog Channels:" << nachans - << " Databytes: " << adatabytes; + FILE_LOG(logDEBUG1) << "#Analog Channels:" << nachans; } // digital channels (ctb only, digital, analog/digital readout) @@ -607,50 +591,20 @@ void slsDetector::updateTotalNumberOfChannels() { (((shm()->roFlags & DIGITAL_ONLY) != 0) || ((shm()->roFlags & ANALOG_AND_DIGITAL) != 0))) { ndchans = 64; - ddatabytes = - (sizeof(uint64_t) * shm()->timerValue[DIGITAL_SAMPLES]); - FILE_LOG(logDEBUG1) << "#Digital Channels:" << ndchans - << " Databytes: " << ddatabytes; + FILE_LOG(logDEBUG1) << "#Digital Channels:" << ndchans; } shm()->nChans = nachans + ndchans; - shm()->dataBytes = adatabytes + ddatabytes; - FILE_LOG(logDEBUG1) << "# Total #Channels:" << shm()->nChans - << " Databytes: " << shm()->dataBytes; + FILE_LOG(logDEBUG1) << "# Total #Channels:" << shm()->nChans; } } -int slsDetector::getTotalNumberOfChannels(dimension d) const { - return shm()->nChan[d] * shm()->nChip[d]; -} - -slsDetectorDefs::coordinates slsDetector::getNumberOfChannels() const { - slsDetectorDefs::coordinates coord; - coord.x = shm()->nChan[X] * shm()->nChip[X]; - coord.y = shm()->nChan[Y] * shm()->nChip[Y]; - return coord; -} - -int slsDetector::getTotalNumberOfChannelsInclGapPixels(dimension d) const { - return (shm()->nChan[d] * shm()->nChip[d] + - shm()->gappixels * shm()->nGappixels[d]); -} - -slsDetectorDefs::coordinates slsDetector::getNumberOfChannelsInclGapPixels() const { - slsDetectorDefs::coordinates coord; +slsDetectorDefs::xy slsDetector::getNumberOfChannels() const { + slsDetectorDefs::xy coord; coord.x = (shm()->nChan[X] * shm()->nChip[X] + shm()->gappixels * shm()->nGappixels[X]); coord.y = (shm()->nChan[Y] * shm()->nChip[Y] + shm()->gappixels * shm()->nGappixels[Y]); return coord; } - -int slsDetector::getNChans() const { return shm()->nChans; } - -int slsDetector::getNChans(dimension d) const { return shm()->nChan[d]; } - -int slsDetector::getNChips() const { return shm()->nChips; } - -int slsDetector::getNChips(dimension d) const { return shm()->nChip[d]; } - bool slsDetector::getQuad() { int retval = -1; FILE_LOG(logDEBUG1) << "Getting Quad Type"; @@ -785,11 +739,7 @@ void slsDetector::updateCachedDetectorVariables() { // dr n += client.Receive(&i32, sizeof(i32)); - shm()->dynamicRange = i32; - - // databytes - n += client.Receive(&i32, sizeof(i32)); - shm()->dataBytes = i32; + shm()->dynamicRange = i32; // settings if ((shm()->myDetectorType != CHIPTESTBOARD) && @@ -881,9 +831,9 @@ void slsDetector::updateCachedDetectorVariables() { if (shm()->myDetectorType == MOENCH) setAdditionalJsonParameter("adcmask", std::to_string(u32)); - // update #nchans and databytes, as it depends on #samples, adcmask, + // update #nchans, as it depends on #samples, adcmask, // readoutflags - updateTotalNumberOfChannels(); + updateNumberOfChannels(); } if (n == 0) { @@ -1390,10 +1340,10 @@ int64_t slsDetector::setTimer(timerIndex index, int64_t t) { sendToDetector(F_SET_TIMER, args, retval); FILE_LOG(logDEBUG1) << getTimerType(index) << ": " << retval; shm()->timerValue[index] = retval; - // update #nchans and databytes, as it depends on #samples, adcmask, + // update #nchans, as it depends on #samples, adcmask, // readoutflags if (index == ANALOG_SAMPLES || index == DIGITAL_SAMPLES) { - updateTotalNumberOfChannels(); + updateNumberOfChannels(); } // setting timers consequences (eiger (ratecorr) ) @@ -1477,27 +1427,10 @@ int slsDetector::setDynamicRange(int n) { // TODO! Properly handle fail int retval = -1; FILE_LOG(logDEBUG1) << "Setting dynamic range to " << n; - int olddr = shm()->dynamicRange; sendToDetector(F_SET_DYNAMIC_RANGE, n, retval); FILE_LOG(logDEBUG1) << "Dynamic Range: " << retval; shm()->dynamicRange = retval; - // only for eiger - // setting dr consequences on databytes shm - // (a get can also change timer value, hence check difference) - if (olddr != shm()->dynamicRange) { - shm()->dataBytes = shm()->nChips * shm()->nChans * retval / 8; - shm()->dataBytesInclGapPixels = - (shm()->nChip[X] * shm()->nChan[X] + - shm()->gappixels * shm()->nGappixels[X]) * - (shm()->nChip[Y] * shm()->nChan[Y] + - shm()->gappixels * shm()->nGappixels[Y]) * - retval / 8; - FILE_LOG(logDEBUG1) << "Data bytes " << shm()->dataBytes; - FILE_LOG(logDEBUG1) << "Data bytes including gap pixels" - << shm()->dataBytesInclGapPixels; - } - if (shm()->useReceiverFlag) { n = shm()->dynamicRange; retval = -1; @@ -1512,12 +1445,6 @@ int slsDetector::getDynamicRangeFromShm() { return shm()->dynamicRange; } -int slsDetector::getDataBytes() { return shm()->dataBytes; } - -int slsDetector::getDataBytesInclGapPixels() { - return shm()->dataBytesInclGapPixels; -} - int slsDetector::setDAC(int val, dacIndex index, int mV) { int args[]{static_cast(index), mV, val}; int retval = -1; @@ -1565,10 +1492,10 @@ int slsDetector::setReadOutFlags(readOutFlags flag) { sendToDetector(F_SET_READOUT_FLAGS, arg, retval); FILE_LOG(logDEBUG1) << "Readout flag: " << retval; shm()->roFlags = retval; - // update #nchans and databytes, as it depends on #samples, adcmask, + // update #nchans, as it depends on #samples, adcmask, // readoutflags if (shm()->myDetectorType == CHIPTESTBOARD) { - updateTotalNumberOfChannels(); + updateNumberOfChannels(); } FILE_LOG(logDEBUG1) << "Setting receiver readout flags to " << arg; if (shm()->useReceiverFlag) { @@ -2246,7 +2173,7 @@ int slsDetector::digitalTest(digitalTestMode mode, int ival) { void slsDetector::loadImageToDetector(imageType index, const std::string &fname) { - int nChan = getTotalNumberOfChannels(); + int nChan = getNumberOfChannels().x; int16_t args[nChan]; FILE_LOG(logDEBUG1) << "Loading " << (index == 0u ? "Dark" : "Gain") << "image from file " << fname; @@ -2261,7 +2188,7 @@ void slsDetector::loadImageToDetector(imageType index, void slsDetector::sendImageToDetector(imageType index, int16_t imageVals[]) { int fnum = F_LOAD_IMAGE; - int nChan = getTotalNumberOfChannels(); + int nChan = getNumberOfChannels().x; int args[]{static_cast(index), nChan}; FILE_LOG(logDEBUG1) << "Sending image to detector"; auto client = DetectorSocket(shm()->hostname, shm()->controlPort); @@ -2281,7 +2208,7 @@ void slsDetector::sendImageToDetector(imageType index, int16_t imageVals[]) { void slsDetector::writeCounterBlockFile(const std::string &fname, int startACQ) { - int nChan = getTotalNumberOfChannels(); + int nChan = getNumberOfChannels().x; int16_t retvals[nChan]; FILE_LOG(logDEBUG1) << "Reading Counter to " << fname << (startACQ != 0 ? " and Restarting Acquisition" @@ -2292,7 +2219,7 @@ void slsDetector::writeCounterBlockFile(const std::string &fname, void slsDetector::getCounterBlock(int16_t image[], int startACQ) { int fnum = F_READ_COUNTER_BLOCK; - int nChan = getTotalNumberOfChannels(); + int nChan = getNumberOfChannels().x; int args[] = {startACQ, nChan}; FILE_LOG(logDEBUG1) << "Reading Counter block with startacq: " << startACQ; sendToDetector(fnum, args, sizeof(args), image, nChan * sizeof(int16_t)); @@ -2322,7 +2249,7 @@ void slsDetector::clearROI() { void slsDetector::setROI(slsDetectorDefs::ROI arg) { int fnum = F_SET_ROI; int ret = FAIL; - if (arg.xmin < 0 || arg.xmax >= getTotalNumberOfChannels()) { + if (arg.xmin < 0 || arg.xmax >= getNumberOfChannels().x) { arg.xmin = -1; arg.xmax = -1; } @@ -2403,9 +2330,9 @@ void slsDetector::setADCEnableMask(uint32_t mask) { sendToDetector(F_SET_ADC_ENABLE_MASK, &arg, sizeof(arg), nullptr, 0); shm()->adcEnableMask = mask; - // update #nchans and databytes, as it depends on #samples, adcmask, + // update #nchans, as it depends on #samples, adcmask, // readoutflags - updateTotalNumberOfChannels(); + updateNumberOfChannels(); // send to processor if (shm()->myDetectorType == MOENCH) @@ -2592,16 +2519,6 @@ int slsDetector::enableGapPixels(int val) { sendToReceiver(fnum, &val, sizeof(val), &retval, sizeof(retval)); FILE_LOG(logDEBUG1) << "Gap pixels enable to receiver:" << retval; shm()->gappixels = retval; - // update databytes - shm()->dataBytesInclGapPixels = 0; - if (shm()->dynamicRange != 4) { - shm()->dataBytesInclGapPixels = - (shm()->nChip[X] * shm()->nChan[X] + - shm()->gappixels * shm()->nGappixels[X]) * - (shm()->nChip[Y] * shm()->nChan[Y] + - shm()->gappixels * shm()->nGappixels[Y]) * - shm()->dynamicRange / 8; - } } } return shm()->gappixels; diff --git a/slsDetectorSoftware/src/slsDetectorCommand.cpp b/slsDetectorSoftware/src/slsDetectorCommand.cpp index 3c3a7c36a..1a72cec51 100755 --- a/slsDetectorSoftware/src/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp @@ -322,7 +322,7 @@ slsDetectorCommand::slsDetectorCommand(multiSlsDetector *det) { ++i; /*! \page config - - detsizechan [xmax] [ymax] sets the maximum number of channels in each dimension for complete detector set; -1 is no limit. Use for multi-detector system as first command in config file. \c Returns \c ("int int") + - detsizechan [xmax] [ymax] sets the maximum number of channels in each dimension for complete detector set; 0 is no limit. Use for multi-detector system as first command in config file. \c Returns \c ("int int") */ descrToFuncMap[i].m_pFuncName = "detsizechan"; descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdDetectorSize; @@ -3284,10 +3284,14 @@ std::string slsDetectorCommand::cmdDetectorSize(int narg, const char * const arg } if (cmd == "detsizechan") { - if ((sscanf(args[1], "%d", &val)) && (val > 0)) - myDet->setMaxNumberOfChannelsPerDetector(X, val); - if ((narg > 2) && (sscanf(args[2], "%d", &val)) && (val > 0)) - myDet->setMaxNumberOfChannelsPerDetector(Y, val); + int val2 = 0; + if ((!sscanf(args[1], "%d", &val)) || (narg <= 2) || (!sscanf(args[2], "%d", &val2))) { + return std::string("Could not scan det size chan values"); + } + slsDetectorDefs::xy res; + res.x = val; + res.y = val2; + myDet->setMaxNumberOfChannels(res); } if(cmd=="quad"){ @@ -3331,7 +3335,8 @@ std::string slsDetectorCommand::cmdDetectorSize(int narg, const char * const arg ROI roi = myDet->getROI(detPos); return (std::string("[") + std::to_string(roi.xmin) + std::string(",") + std::to_string(roi.xmax) + std::string("]")); } else if (cmd == "detsizechan") { - sprintf(ans, "%d %d", myDet->getMaxNumberOfChannelsPerDetector(X), myDet->getMaxNumberOfChannelsPerDetector(Y)); + slsDetectorDefs::xy res = myDet->getMaxNumberOfChannels(); + sprintf(ans, "%d %d", res.x, res.y); return std::string(ans); } else if (cmd=="quad") { return std::to_string(myDet->getQuad()); @@ -3362,7 +3367,7 @@ std::string slsDetectorCommand::helpDetectorSize(int action) { os << "dr i \n sets the dynamic range of the detector" << std::endl; os << "clearroi \n resets region of interest" << std::endl; os << "roi xmin xmax \n sets region of interest " << std::endl; - os << "detsizechan x y \n sets the maximum number of channels for complete detector set in both directions; -1 is no limit" << std::endl; + os << "detsizechan x y \n sets the maximum number of channels for complete detector set in both directions; 0 is no limit" << std::endl; os << "quad i \n if i = 1, sets the detector size to a quad (Specific to an EIGER quad hardware). 0 by default."<< std::endl; os << "flippeddatax x \n sets if the data should be flipped on the x axis" << std::endl; os << "flippeddatay y \n sets if the data should be flipped on the y axis" << std::endl; @@ -3371,7 +3376,7 @@ std::string slsDetectorCommand::helpDetectorSize(int action) { if (action == GET_ACTION || action == HELP_ACTION) { os << "dr \n gets the dynamic range of the detector" << std::endl; os << "roi \n gets region of interest" << std::endl; - os << "detsizechan \n gets the maximum number of channels for complete detector set in both directions; -1 is no limit" << std::endl; + os << "detsizechan \n gets the maximum number of channels for complete detector set in both directions; 0 is no limit" << std::endl; os << "quad \n returns 1 if the detector size is a quad (Specific to an EIGER quad hardware). 0 by default."<< std::endl; os << "flippeddatax\n gets if the data will be flipped on the x axis" << std::endl; os << "flippeddatay\n gets if the data will be flipped on the y axis" << std::endl; diff --git a/slsDetectorSoftware/src/slsDetectorUsers.cpp b/slsDetectorSoftware/src/slsDetectorUsers.cpp index 8e89ca408..ec24f7dd4 100755 --- a/slsDetectorSoftware/src/slsDetectorUsers.cpp +++ b/slsDetectorSoftware/src/slsDetectorUsers.cpp @@ -9,14 +9,16 @@ int slsDetectorUsers::size() const { } int slsDetectorUsers::getMaximumDetectorSize(int &nx, int &ny){ - nx=detector.getMaxNumberOfChannelsPerDetector(slsDetectorDefs::X); - ny=detector.getMaxNumberOfChannelsPerDetector(slsDetectorDefs::Y); + slsDetectorDefs::xy res = detector.getMaxNumberOfChannels(); + nx=res.x; + ny=res.y; return nx*ny; } int slsDetectorUsers::getDetectorSize(int &nx, int &ny, int detPos){ - nx=detector.getTotalNumberOfChannels(slsDetectorDefs::X, detPos); - ny=detector.getTotalNumberOfChannels(slsDetectorDefs::Y, detPos); + slsDetectorDefs::xy res = detector.getNumberOfChannels(); + nx=res.x; + ny=res.y; return nx*ny; } diff --git a/slsSupportLib/include/sls_detector_defs.h b/slsSupportLib/include/sls_detector_defs.h index 816836d9e..f9d2f9b00 100755 --- a/slsSupportLib/include/sls_detector_defs.h +++ b/slsSupportLib/include/sls_detector_defs.h @@ -292,7 +292,7 @@ format }; #ifdef __cplusplus - struct coordinates { + struct xy { int x{0}; int y{0}; }; From 336f8ceb50b258c93420d98e21b8c536b60e0ffc Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Fri, 16 Aug 2019 10:46:42 +0200 Subject: [PATCH 078/108] WIP --- python/src/DetectorPythonInterface.h | 22 ++------------------ python/src/experimental.cpp | 7 ++----- python/src/main.cpp | 10 +++------ slsDetectorSoftware/src/multiSlsDetector.cpp | 16 +++++++------- 4 files changed, 14 insertions(+), 41 deletions(-) diff --git a/python/src/DetectorPythonInterface.h b/python/src/DetectorPythonInterface.h index 9f8b3efc0..58993377d 100755 --- a/python/src/DetectorPythonInterface.h +++ b/python/src/DetectorPythonInterface.h @@ -20,22 +20,8 @@ class DetectorPythonInterface { int getMultiDetectorId() { return multi_detector_id; } - // get image size as [nrow, ncols] return as a pair of ints - std::pair getImageSize() { - std::pair image_size{0, 0}; - image_size.first = det.getMaxNumberOfChannelsPerDetector( - slsDetectorDefs::dimension::Y); - image_size.second = det.getMaxNumberOfChannelsPerDetector( - slsDetectorDefs::dimension::X); - return image_size; - } - void setImageSize(const int rows, const int cols) { - det.setMaxNumberOfChannelsPerDetector(slsDetectorDefs::dimension::Y, - rows); - det.setMaxNumberOfChannelsPerDetector(slsDetectorDefs::dimension::X, - cols); - } + // blocking command, acquire set number of frames void acquire() { det.acquire(); } @@ -150,11 +136,7 @@ class DetectorPythonInterface { slsDetectorDefs::dacIndex dacNameToEnum(std::string dac_name); - std::pair getDetectorGeometry() { - std::pair g; - det.getNumberOfDetectors(g.first, g.second); - return g; - } + int getNumberOfDetectors() { return det.size(); } diff --git a/python/src/experimental.cpp b/python/src/experimental.cpp index 22355f8be..7f7168876 100644 --- a/python/src/experimental.cpp +++ b/python/src/experimental.cpp @@ -18,16 +18,13 @@ void init_experimental(py::module &m) { // Acq related .def("acquire", &Detector::acquire) - .def("startReceiver", &Detector::startReceiver, py::arg() = Positions{}) - .def("stopReceiver", &Detector::stopReceiver, py::arg() = Positions{}) - .def("getAcquiringFlag", &Detector::getAcquiringFlag) - .def("setAcquiringFlag", &Detector::setAcquiringFlag) + .def("clearAcquiringFlag", &Detector::clearAcquiringFlag) .def("getReceiverStatus", &Detector::getReceiverStatus, py::arg() = Positions{}) // Configuration .def("free", &Detector::freeSharedMemory) - .def("setConfig", &Detector::setConfig) + .def("loadConfig", &Detector::loadConfig) .def("getHostname", &Detector::getHostname, py::arg() = Positions{}) // Bits and registers diff --git a/python/src/main.cpp b/python/src/main.cpp index 90cb37e8d..bf0ca5d39 100755 --- a/python/src/main.cpp +++ b/python/src/main.cpp @@ -332,14 +332,10 @@ PYBIND11_MODULE(_sls_detector, m) { py::arg("level"), py::arg("duration"), py::arg("det_id") = -1) .def("getPatternWaitTime", &DetectorPythonInterface::getPatternWaitTime, - py::arg("level"), py::arg("det_id") = -1) + py::arg("level"), py::arg("det_id") = -1); + + - .def("getImageSize", &DetectorPythonInterface::getImageSize) - .def("setImageSize", &DetectorPythonInterface::setImageSize) - .def("getNumberOfDetectors", - &DetectorPythonInterface::getNumberOfDetectors) - .def("getDetectorGeometry", - &DetectorPythonInterface::getDetectorGeometry); diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index 4424bc84d..0be45641c 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -429,25 +429,23 @@ void multiSlsDetector::addSlsDetector(const std::string &hostname) { void multiSlsDetector::updateDetectorSize() { FILE_LOG(logDEBUG) << "Updating Multi-Detector Size: " << size(); - slsDetectorDefs::xy res = detectors[0]->getNumberOfChannels(); - int my = res.x; - int mx = res.y; - + const slsDetectorDefs::xy det_size = detectors[0]->getNumberOfChannels(); + int maxy = multi_shm()->maxNumberOfChannels[Y]; if (maxy == 0) { - maxy = my * size(); + maxy = det_size.y * size(); } - int ndety = maxy / my; + int ndety = maxy / det_size.y; int ndetx = size() / ndety; - if ((maxy % my) > 0) { + if ((maxy % det_size.y) > 0) { ++ndetx; } multi_shm()->numberOfDetector[X] = ndetx; multi_shm()->numberOfDetector[Y] = ndety; - multi_shm()->numberOfChannels[X] = mx * ndetx; - multi_shm()->numberOfChannels[Y] = my * ndety; + multi_shm()->numberOfChannels[X] = det_size.x * ndetx; + multi_shm()->numberOfChannels[Y] = det_size.y * ndety; FILE_LOG(logDEBUG) << "\n\tNumber of Detectors in X direction:" From 10ce82fc5f28a2670a635886afc3afefa46cfc31 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Fri, 16 Aug 2019 17:07:30 +0200 Subject: [PATCH 079/108] WIP --- .../include/multiSlsDetector.h | 16 ++-- slsDetectorSoftware/include/slsDetector.h | 35 +++---- slsDetectorSoftware/src/Detector.cpp | 4 +- slsDetectorSoftware/src/multiSlsDetector.cpp | 95 ++++++++----------- slsDetectorSoftware/src/slsDetector.cpp | 80 +++++++--------- .../src/slsDetectorCommand.cpp | 24 +---- .../include/slsReceiverImplementation.h | 12 +-- .../src/slsReceiverImplementation.cpp | 15 +-- .../src/slsReceiverTCPIPInterface.cpp | 13 ++- slsSupportLib/include/versionAPI.h | 2 +- 10 files changed, 115 insertions(+), 181 deletions(-) diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index d3250d016..96f99e2a5 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -54,13 +54,13 @@ struct sharedMultiSlsDetector { * -----------------------------------------------*/ /** Number of detectors operated at once */ - int numberOfDetector[2]; + slsDetectorDefs::xy numberOfDetector; /** total number of channels for all detectors */ - int numberOfChannels[2]; + slsDetectorDefs::xy numberOfChannels; /** max number of channels for complete detector*/ - int maxNumberOfChannels[2]; + slsDetectorDefs::xy maxNumberOfChannels; /** flag for acquiring */ bool acquiringFlag; @@ -1413,22 +1413,20 @@ class multiSlsDetector : public virtual slsDetectorDefs { int setDeactivatedRxrPaddingMode(int padding = -1, int detPos = -1); /** - * Returns the enable if data will be flipped across x or y axis (Eiger) - * @param d axis across which data is flipped + * Returns the enable if data will be flipped across x axis (Eiger) * @param detPos -1 for all detectors in list or specific detector position * @returns 1 for flipped, else 0 */ - int getFlippedData(dimension d = X, int detPos = -1); // + int getFlippedDataX(int detPos = -1); // /** * Sets the enable which determines if - * data will be flipped across x or y axis (Eiger) - * @param d axis across which data is flipped + * data will be flipped across x axis (Eiger) * @param value 0 or 1 to reset/set or -1 to get value * @param detPos -1 for all detectors in list or specific detector position * @returns enable flipped data across x or y axis */ - int setFlippedData(dimension d = X, int value = -1, int detPos = -1); // + int setFlippedDataX(int value = -1, int detPos = -1); // /** * Sets all the trimbits to a particular value (Eiger) diff --git a/slsDetectorSoftware/include/slsDetector.h b/slsDetectorSoftware/include/slsDetector.h index d6160f385..5eec4a878 100755 --- a/slsDetectorSoftware/include/slsDetector.h +++ b/slsDetectorSoftware/include/slsDetector.h @@ -13,7 +13,7 @@ class ServerInterface; #define SLS_SHMAPIVERSION 0x190726 -#define SLS_SHMVERSION 0x190815 +#define SLS_SHMVERSION 0x190816 /** * @short structure allocated in shared memory to store detector settings for @@ -36,7 +36,7 @@ struct sharedSlsDetector { /** END OF FIXED PATTERN -----------------------------------------------*/ /** Number of detectors in multi list in x dir and y dir */ - int multiSize[2]; + slsDetectorDefs::xy multiSize; /** is the port used for control functions */ int controlPort; @@ -50,17 +50,11 @@ struct sharedSlsDetector { /** list of the energies at which the detector has been trimmed */ sls::FixedCapacityContainer trimEnergies; - /** number of channels per chip */ - int nChans; - /** number of channels per chip in one direction */ - int nChan[2]; - - /** number of chips per module*/ - int nChips; + slsDetectorDefs::xy nChan; /** number of chips per module in one direction */ - int nChip[2]; + slsDetectorDefs::xy nChip; /** number of dacs per module*/ int nDacs; @@ -142,7 +136,7 @@ struct sharedSlsDetector { int tenGigaEnable; /** flipped data across x or y axis */ - int flippedData[2]; + int flippedDataX; /** tcp port from gui/different process to receiver (only data) */ int zmqport; @@ -166,7 +160,7 @@ struct sharedSlsDetector { int gappixels; /** gap pixels in each direction */ - int nGappixels[2]; + slsDetectorDefs::xy nGappixels; /** additional json header */ char rxAdditionalJsonHeader[MAX_STR_LENGTH]; @@ -356,10 +350,9 @@ class slsDetector : public virtual slsDetectorDefs { /** * Set Detector offset in shared memory in dimension d - * @param detx number of detectors in X dir in multi list - * @param dety number of detectors in Y dir in multi list + * @param det detector size */ - void updateMultiSize(int detx, int dety); + void updateMultiSize(slsDetectorDefs::xy det); int setControlPort(int port_number); @@ -1168,20 +1161,18 @@ class slsDetector : public virtual slsDetectorDefs { bool setDeactivatedRxrPaddingMode(int padding = -1); /** - * Returns the enable if data will be flipped across x or y axis (Eiger) - * @param d axis across which data is flipped + * Returns the enable if data will be flipped across x axis (Eiger) * @returns 1 for flipped, else 0 */ - int getFlippedData(dimension d = X) const; + int getFlippedDataX() const; /** * Sets the enable which determines if - * data will be flipped across x or y axis (Eiger) - * @param d axis across which data is flipped + * data will be flipped across x axis (Eiger) * @param value 0 or 1 to reset/set or -1 to get value - * @returns enable flipped data across x or y axis + * @returns enable flipped data across x axis */ - int setFlippedData(dimension d = X, int value = -1); + int setFlippedDataX(int value = -1); /** * Sets all the trimbits to a particular value (Eiger) diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 8e6699f6c..8727c1658 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -1094,11 +1094,11 @@ void Detector::setActive(bool active, Positions pos) { } Result Detector::getBottom(Positions pos) const { - return pimpl->Parallel(&slsDetector::getFlippedData, pos, defs::X); + return pimpl->Parallel(&slsDetector::getFlippedDataX, pos); } void Detector::setBottom(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setFlippedData, pos, defs::X, static_cast(value)); + pimpl->Parallel(&slsDetector::setFlippedDataX, pos, static_cast(value)); } Result Detector::getAllTrimbits(Positions pos) const { diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index 0be45641c..0ecd1243e 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -276,12 +276,12 @@ void multiSlsDetector::initializeDetectorStructure() { multi_shm()->shmversion = MULTI_SHMVERSION; multi_shm()->numberOfDetectors = 0; multi_shm()->multiDetectorType = GENERIC; - multi_shm()->numberOfDetector[X] = 0; - multi_shm()->numberOfDetector[Y] = 0; - multi_shm()->numberOfChannels[X] = 0; - multi_shm()->numberOfChannels[Y] = 0; - multi_shm()->maxNumberOfChannels[X] = 0; - multi_shm()->maxNumberOfChannels[Y] = 0; + multi_shm()->numberOfDetector.x = 0; + multi_shm()->numberOfDetector.y = 0; + multi_shm()->numberOfChannels.x = 0; + multi_shm()->numberOfChannels.y = 0; + multi_shm()->maxNumberOfChannels.x = 0; + multi_shm()->maxNumberOfChannels.y = 0; multi_shm()->acquiringFlag = false; multi_shm()->receiver_upstream = false; } @@ -431,7 +431,7 @@ void multiSlsDetector::updateDetectorSize() { const slsDetectorDefs::xy det_size = detectors[0]->getNumberOfChannels(); - int maxy = multi_shm()->maxNumberOfChannels[Y]; + int maxy = multi_shm()->maxNumberOfChannels.y; if (maxy == 0) { maxy = det_size.y * size(); } @@ -442,29 +442,26 @@ void multiSlsDetector::updateDetectorSize() { ++ndetx; } - multi_shm()->numberOfDetector[X] = ndetx; - multi_shm()->numberOfDetector[Y] = ndety; - multi_shm()->numberOfChannels[X] = det_size.x * ndetx; - multi_shm()->numberOfChannels[Y] = det_size.y * ndety; + multi_shm()->numberOfDetector.x = ndetx; + multi_shm()->numberOfDetector.y = ndety; + multi_shm()->numberOfChannels.x = det_size.x * ndetx; + multi_shm()->numberOfChannels.y = det_size.y * ndety; FILE_LOG(logDEBUG) << "\n\tNumber of Detectors in X direction:" - << multi_shm()->numberOfDetector[X] + << multi_shm()->numberOfDetector.x << "\n\tNumber of Detectors in Y direction:" - << multi_shm()->numberOfDetector[Y] + << multi_shm()->numberOfDetector.y << "\n\tNumber of Channels in X direction:" - << multi_shm()->numberOfChannels[X] + << multi_shm()->numberOfChannels.x << "\n\tNumber of Channels in Y direction:" - << multi_shm()->numberOfChannels[Y]; + << multi_shm()->numberOfChannels.y; for (auto &d : detectors) { - d->updateMultiSize(multi_shm()->numberOfDetector[0], - multi_shm()->numberOfDetector[1]); + d->updateMultiSize(multi_shm()->numberOfDetector); } - - multi_shm()->maxNumberOfChannels[X] = multi_shm()->numberOfChannels[X]; - multi_shm()->maxNumberOfChannels[Y] = multi_shm()->numberOfChannels[Y]; + multi_shm()->maxNumberOfChannels = multi_shm()->numberOfChannels; } slsDetectorDefs::detectorType multiSlsDetector::getDetectorTypeAsEnum() const { @@ -497,10 +494,7 @@ std::string multiSlsDetector::getDetectorTypeAsString(int detPos) { size_t multiSlsDetector::size() const { return detectors.size(); } slsDetectorDefs::xy multiSlsDetector::getNumberOfDetectors() const { - slsDetectorDefs::xy res; - res.x = multi_shm()->numberOfDetector[X]; - res.y = multi_shm()->numberOfDetector[Y]; - return res; + return multi_shm()->numberOfDetector; } slsDetectorDefs::xy multiSlsDetector::getNumberOfChannels(int detPos) { @@ -510,22 +504,15 @@ slsDetectorDefs::xy multiSlsDetector::getNumberOfChannels(int detPos) { } // multi - slsDetectorDefs::xy coord; - coord.x = multi_shm()->numberOfChannels[X]; - coord.y = multi_shm()->numberOfChannels[Y]; - return coord; + return multi_shm()->numberOfChannels; } slsDetectorDefs::xy multiSlsDetector::getMaxNumberOfChannels() const { - slsDetectorDefs::xy coord; - coord.x = multi_shm()->maxNumberOfChannels[X]; - coord.y = multi_shm()->maxNumberOfChannels[Y]; - return coord; + return multi_shm()->maxNumberOfChannels; } void multiSlsDetector::setMaxNumberOfChannels(const slsDetectorDefs::xy c) { - multi_shm()->maxNumberOfChannels[X] = c.x; - multi_shm()->maxNumberOfChannels[Y] = c.y; + multi_shm()->maxNumberOfChannels = c; } int multiSlsDetector::getQuad(int detPos) { @@ -2140,25 +2127,25 @@ int multiSlsDetector::setDeactivatedRxrPaddingMode(int padding, int detPos) { return sls::minusOneIfDifferent(r); } -int multiSlsDetector::getFlippedData(dimension d, int detPos) { +int multiSlsDetector::getFlippedDataX(int detPos) { // single if (detPos >= 0) { - return detectors[detPos]->getFlippedData(d); + return detectors[detPos]->getFlippedDataX(); } // multi - auto r = serialCall(&slsDetector::getFlippedData, d); + auto r = serialCall(&slsDetector::getFlippedDataX); return sls::minusOneIfDifferent(r); } -int multiSlsDetector::setFlippedData(dimension d, int value, int detPos) { +int multiSlsDetector::setFlippedDataX(int value, int detPos) { // single if (detPos >= 0) { - return detectors[detPos]->setFlippedData(d, value); + return detectors[detPos]->setFlippedDataX(value); } // multi - auto r = parallelCall(&slsDetector::setFlippedData, d, value); + auto r = parallelCall(&slsDetector::setFlippedDataX, value); return sls::minusOneIfDifferent(r); } @@ -2198,11 +2185,11 @@ int multiSlsDetector::enableGapPixels(int val, int detPos) { if (val != -1) { Parallel(&slsDetector::enableGapPixels, {}, val); Result res = Parallel(&slsDetector::getNumberOfChannels, {}); - multi_shm()->numberOfChannels[X] = 0; - multi_shm()->numberOfChannels[Y] = 0; + multi_shm()->numberOfChannels.x = 0; + multi_shm()->numberOfChannels.y = 0; for (auto &it : res) { - multi_shm()->numberOfChannels[X] += it.x; - multi_shm()->numberOfChannels[Y] += it.y; + multi_shm()->numberOfChannels.x += it.x; + multi_shm()->numberOfChannels.y += it.y; } } return ret; @@ -2211,11 +2198,11 @@ int multiSlsDetector::enableGapPixels(int val, int detPos) { void multiSlsDetector::setGapPixelsEnable(bool enable, Positions pos){ Parallel(&slsDetector::enableGapPixels, pos, static_cast(enable)); Result res = Parallel(&slsDetector::getNumberOfChannels, {}); - multi_shm()->numberOfChannels[X] = 0; - multi_shm()->numberOfChannels[Y] = 0; + multi_shm()->numberOfChannels.x = 0; + multi_shm()->numberOfChannels.y = 0; for (auto &it : res) { - multi_shm()->numberOfChannels[X] += it.x; - multi_shm()->numberOfChannels[Y] += it.y; + multi_shm()->numberOfChannels.x += it.x; + multi_shm()->numberOfChannels.y += it.y; } } @@ -3046,14 +3033,14 @@ void multiSlsDetector::readFrameFromReceiver() { int multiSlsDetector::processImageWithGapPixels(char *image, char *&gpImage, bool quadEnable) { // eiger 4 bit mode - int nxb = multi_shm()->numberOfDetector[X] * (512 + 3); //(divided by 2 already) - int nyb = multi_shm()->numberOfDetector[Y] * (256 + 1); + int nxb = multi_shm()->numberOfDetector.x * (512 + 3); //(divided by 2 already) + int nyb = multi_shm()->numberOfDetector.y * (256 + 1); int nchipInRow = 4; - int nxchip = multi_shm()->numberOfDetector[X] * 4; - int nychip = multi_shm()->numberOfDetector[Y] * 1; + int nxchip = multi_shm()->numberOfDetector.x * 4; + int nychip = multi_shm()->numberOfDetector.y * 1; if (quadEnable) { - nxb = multi_shm()->numberOfDetector[X] * (256 + 1); //(divided by 2 already) - nyb = multi_shm()->numberOfDetector[Y] * (512 + 2); + nxb = multi_shm()->numberOfDetector.x * (256 + 1); //(divided by 2 already) + nyb = multi_shm()->numberOfDetector.y * (512 + 2); nxchip /= 2; nychip *= 2; nchipInRow /= 2; diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index aa523aa7d..b694b12e1 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -308,8 +308,8 @@ void slsDetector::initializeDetectorStructure(detectorType type) { shm()->controlPort = DEFAULT_PORTNO; sls::strcpy_safe(shm()->hostname, DEFAULT_HOSTNAME); shm()->myDetectorType = type; - shm()->multiSize[X] = 0; - shm()->multiSize[Y] = 0; + shm()->multiSize.x = 0; + shm()->multiSize.y = 0; shm()->controlPort = DEFAULT_PORTNO; shm()->stopPort = DEFAULT_PORTNO + 1; sls::strcpy_safe(shm()->settingsDir, getenv("HOME")); @@ -354,8 +354,7 @@ void slsDetector::initializeDetectorStructure(detectorType type) { shm()->selectedUDPInterface = 0; shm()->useReceiverFlag = false; shm()->tenGigaEnable = 0; - shm()->flippedData[X] = 0; - shm()->flippedData[Y] = 0; + shm()->flippedDataX = 0; shm()->zmqport = DEFAULT_ZMQ_CL_PORTNO + (detId * ((shm()->myDetectorType == EIGER) ? 2 : 1)); shm()->rxZmqport = DEFAULT_ZMQ_RX_PORTNO + @@ -401,20 +400,16 @@ void slsDetector::initializeDetectorStructure(detectorType type) { // get the detector parameters based on type detParameters parameters{type}; - shm()->nChan[X] = parameters.nChanX; - shm()->nChan[Y] = parameters.nChanY; - shm()->nChip[X] = parameters.nChipX; - shm()->nChip[Y] = parameters.nChipY; + shm()->nChan.x = parameters.nChanX; + shm()->nChan.y = parameters.nChanY; + shm()->nChip.x = parameters.nChipX; + shm()->nChip.y = parameters.nChipY; shm()->nDacs = parameters.nDacs; shm()->dynamicRange = parameters.dynamicRange; - shm()->nGappixels[X] = parameters.nGappixelsX; - shm()->nGappixels[Y] = parameters.nGappixelsY; + shm()->nGappixels.x = parameters.nGappixelsX; + shm()->nGappixels.y = parameters.nGappixelsY; - // derived parameters - shm()->nChans = shm()->nChan[X] * shm()->nChan[Y]; - shm()->nChips = shm()->nChip[X] * shm()->nChip[Y]; - - // update #nchans, as it depends on #samples, adcmask, + // update #nchan, as it depends on #samples, adcmask, // readoutflags (ctb only) updateNumberOfChannels(); } @@ -491,8 +486,7 @@ int slsDetector::receiveModule(sls_detector_module *myMod, if (shm()->myDetectorType == EIGER) { ts += client.Receive(myMod->chanregs, sizeof(int) * (myMod->nchan)); FILE_LOG(logDEBUG1) - << "nchans= " << shm()->nChans << " nchips= " << shm()->nChips - << "mod - nchans= " << myMod->nchan << " nchips= " << myMod->nchip + << " nchan= " << myMod->nchan << " nchip= " << myMod->nchip << "received chans of size " << ts; } FILE_LOG(logDEBUG1) << "received module of size " << ts << " register " @@ -593,15 +587,15 @@ void slsDetector::updateNumberOfChannels() { ndchans = 64; FILE_LOG(logDEBUG1) << "#Digital Channels:" << ndchans; } - shm()->nChans = nachans + ndchans; - FILE_LOG(logDEBUG1) << "# Total #Channels:" << shm()->nChans; + shm()->nChan.x = nachans + ndchans; + FILE_LOG(logDEBUG1) << "# Total #Channels:" << shm()->nChan.x; } } slsDetectorDefs::xy slsDetector::getNumberOfChannels() const { slsDetectorDefs::xy coord; - coord.x = (shm()->nChan[X] * shm()->nChip[X] + shm()->gappixels * shm()->nGappixels[X]); - coord.y = (shm()->nChan[Y] * shm()->nChip[Y] + shm()->gappixels * shm()->nGappixels[Y]); + coord.x = (shm()->nChan.x * shm()->nChip.x + shm()->gappixels * shm()->nGappixels.x); + coord.y = (shm()->nChan.y * shm()->nChip.y + shm()->gappixels * shm()->nGappixels.y); return coord; } @@ -641,9 +635,8 @@ int slsDetector::getReadNLines() { return retval; } -void slsDetector::updateMultiSize(int detx, int dety) { - shm()->multiSize[0] = detx; - shm()->multiSize[1] = dety; +void slsDetector::updateMultiSize(slsDetectorDefs::xy det) { + shm()->multiSize = det; } @@ -831,7 +824,7 @@ void slsDetector::updateCachedDetectorVariables() { if (shm()->myDetectorType == MOENCH) setAdditionalJsonParameter("adcmask", std::to_string(u32)); - // update #nchans, as it depends on #samples, adcmask, + // update #nchan, as it depends on #samples, adcmask, // readoutflags updateNumberOfChannels(); } @@ -1259,7 +1252,7 @@ void slsDetector::configureMAC() { // 2d positions to detector to put into udp header { int pos[2] = {0, 0}; - int max = shm()->multiSize[Y] * (shm()->numUDPInterfaces); + int max = shm()->multiSize.y * (shm()->numUDPInterfaces); // row pos[0] = (detId % max); // col for horiz. udp ports @@ -1340,7 +1333,7 @@ int64_t slsDetector::setTimer(timerIndex index, int64_t t) { sendToDetector(F_SET_TIMER, args, retval); FILE_LOG(logDEBUG1) << getTimerType(index) << ": " << retval; shm()->timerValue[index] = retval; - // update #nchans, as it depends on #samples, adcmask, + // update #nchan, as it depends on #samples, adcmask, // readoutflags if (index == ANALOG_SAMPLES || index == DIGITAL_SAMPLES) { updateNumberOfChannels(); @@ -1492,7 +1485,7 @@ int slsDetector::setReadOutFlags(readOutFlags flag) { sendToDetector(F_SET_READOUT_FLAGS, arg, retval); FILE_LOG(logDEBUG1) << "Readout flag: " << retval; shm()->roFlags = retval; - // update #nchans, as it depends on #samples, adcmask, + // update #nchan, as it depends on #samples, adcmask, // readoutflags if (shm()->myDetectorType == CHIPTESTBOARD) { updateNumberOfChannels(); @@ -1677,7 +1670,7 @@ std::string slsDetector::setReceiverHostname(const std::string &receiverIP) { << "\nasamples:" << (shm()->timerValue[ANALOG_SAMPLES]) << "\ndsamples:" << (shm()->timerValue[DIGITAL_SAMPLES]) << "\ndynamic range:" << shm()->dynamicRange - << "\nflippeddatax:" << (shm()->flippedData[X]) + << "\nflippeddatax:" << (shm()->flippedDataX) << "\nactivated: " << shm()->activated << "\nreceiver deactivated padding: " << shm()->rxPadDeactivatedModules << "\nsilent Mode:" << shm()->rxSilentMode @@ -1719,7 +1712,7 @@ std::string slsDetector::setReceiverHostname(const std::string &receiverIP) { shm()->timerValue[SUBFRAME_ACQUISITION_TIME]); setTimer(SUBFRAME_DEADTIME, shm()->timerValue[SUBFRAME_DEADTIME]); setDynamicRange(shm()->dynamicRange); - setFlippedData(X, -1); + setFlippedDataX(-1); activate(-1); setDeactivatedRxrPaddingMode( static_cast(shm()->rxPadDeactivatedModules)); @@ -2330,7 +2323,7 @@ void slsDetector::setADCEnableMask(uint32_t mask) { sendToDetector(F_SET_ADC_ENABLE_MASK, &arg, sizeof(arg), nullptr, 0); shm()->adcEnableMask = mask; - // update #nchans, as it depends on #samples, adcmask, + // update #nchan, as it depends on #samples, adcmask, // readoutflags updateNumberOfChannels(); @@ -2477,29 +2470,24 @@ bool slsDetector::setDeactivatedRxrPaddingMode(int padding) { return shm()->rxPadDeactivatedModules; } -int slsDetector::getFlippedData(dimension d) const { - return shm()->flippedData[d]; +int slsDetector::getFlippedDataX() const { + return shm()->flippedDataX; } -int slsDetector::setFlippedData(dimension d, int value) { - if (d == Y) { - throw RuntimeError("Flipped across Y axis is not implemented"); - } +int slsDetector::setFlippedDataX(int value) { // replace get with shm value (write to shm right away as it is a det value, // not rx value) if (value > -1) { - shm()->flippedData[d] = (value > 0) ? 1 : 0; + shm()->flippedDataX = (value > 0) ? 1 : 0; } - int args[]{static_cast(d), value}; int retval = -1; - args[1] = shm()->flippedData[d]; - FILE_LOG(logDEBUG1) << "Setting flipped data across axis " << d - << " with value: " << value; + int arg = shm()->flippedDataX; + FILE_LOG(logDEBUG1) << "Setting flipped data across x axis with value: " << arg; if (shm()->useReceiverFlag) { - sendToReceiver(F_SET_FLIPPED_DATA_RECEIVER, args, retval); + sendToReceiver(F_SET_FLIPPED_DATA_RECEIVER, arg, retval); FILE_LOG(logDEBUG1) << "Flipped data:" << retval; } - return shm()->flippedData[d]; + return shm()->flippedDataX; } int slsDetector::setAllTrimbits(int val) { @@ -2978,10 +2966,10 @@ void slsDetector::updateCachedReceiverVariables() const { } void slsDetector::sendMultiDetectorSize() { - int args[]{shm()->multiSize[0], shm()->multiSize[1]}; + int args[]{shm()->multiSize.x, shm()->multiSize.y}; int retval = -1; FILE_LOG(logDEBUG1) << "Sending multi detector size to receiver: (" - << shm()->multiSize[0] << "," << shm()->multiSize[1] + << shm()->multiSize.x << "," << shm()->multiSize.y << ")"; if (shm()->useReceiverFlag) { sendToReceiver(F_SEND_RECEIVER_MULTIDETSIZE, args, retval); diff --git a/slsDetectorSoftware/src/slsDetectorCommand.cpp b/slsDetectorSoftware/src/slsDetectorCommand.cpp index 1a72cec51..07134b020 100755 --- a/slsDetectorSoftware/src/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp @@ -122,13 +122,6 @@ slsDetectorCommand::slsDetectorCommand(multiSlsDetector *det) { descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdExitServer; ++i; - /*! \page test - - flippeddatay [i] enables/disables data being flipped across y axis. 1 enables, 0 disables. Not implemented. - */ - descrToFuncMap[i].m_pFuncName = "flippeddatay"; - descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdDetectorSize; - ++i; - /* digital test and debugging */ /*! \page test @@ -3304,15 +3297,7 @@ std::string slsDetectorCommand::cmdDetectorSize(int narg, const char * const arg if ((!sscanf(args[1], "%d", &val)) || (val != 0 && val != 1)) return std::string("cannot scan flippeddata x mode: must be 0 or 1"); - myDet->setFlippedData(X, val, detPos); - } - - if (cmd == "flippeddatay") { - return std::string("Not required for this detector\n"); - if ((!sscanf(args[1], "%d", &val)) || (val != 0 && val != 1)) - return std::string("cannot scan flippeddata y mode: must be 0 or 1"); - - myDet->setFlippedData(Y, val, detPos); + myDet->setFlippedDataX(val, detPos); } if (cmd == "gappixels") { @@ -3341,10 +3326,7 @@ std::string slsDetectorCommand::cmdDetectorSize(int narg, const char * const arg } else if (cmd=="quad") { return std::to_string(myDet->getQuad()); } else if (cmd == "flippeddatax") { - ret = myDet->getFlippedData(X, detPos); - } else if (cmd == "flippeddatay") { - return std::string("Not required for this detector\n"); - ret = myDet->getFlippedData(Y, detPos); + ret = myDet->getFlippedDataX(detPos); } else if (cmd == "gappixels") { if (detPos >= 0) // only in multi detector level to update number of channels etc. return std::string("Cannot execute this command from slsDetector level. Please use multiSlsDetector level.\n"); @@ -3370,7 +3352,6 @@ std::string slsDetectorCommand::helpDetectorSize(int action) { os << "detsizechan x y \n sets the maximum number of channels for complete detector set in both directions; 0 is no limit" << std::endl; os << "quad i \n if i = 1, sets the detector size to a quad (Specific to an EIGER quad hardware). 0 by default."<< std::endl; os << "flippeddatax x \n sets if the data should be flipped on the x axis" << std::endl; - os << "flippeddatay y \n sets if the data should be flipped on the y axis" << std::endl; os << "gappixels i \n enables/disables gap pixels in system (detector & receiver). 1 sets, 0 unsets. Used in EIGER only and multidetector level." << std::endl; } if (action == GET_ACTION || action == HELP_ACTION) { @@ -3379,7 +3360,6 @@ std::string slsDetectorCommand::helpDetectorSize(int action) { os << "detsizechan \n gets the maximum number of channels for complete detector set in both directions; 0 is no limit" << std::endl; os << "quad \n returns 1 if the detector size is a quad (Specific to an EIGER quad hardware). 0 by default."<< std::endl; os << "flippeddatax\n gets if the data will be flipped on the x axis" << std::endl; - os << "flippeddatay\n gets if the data will be flipped on the y axis" << std::endl; os << "gappixels\n gets if gap pixels is enabled in system. Used in EIGER only and multidetector level." << std::endl; } return os.str(); diff --git a/slsReceiverSoftware/include/slsReceiverImplementation.h b/slsReceiverSoftware/include/slsReceiverImplementation.h index f579bc94d..1e5dc2e88 100755 --- a/slsReceiverSoftware/include/slsReceiverImplementation.h +++ b/slsReceiverSoftware/include/slsReceiverImplementation.h @@ -63,10 +63,10 @@ class slsReceiverImplementation : private virtual slsDetectorDefs { std::string getDetectorHostname() const; /* - * Get flipped data across 'axis' - * @return if data is flipped across 'axis' + * Get flipped data across x axis + * @return if data is flipped across x axis */ - int getFlippedData(int axis = 0) const; + int getFlippedDataX() const; /** * Get Gap Pixels Enable (eiger specific) @@ -390,10 +390,10 @@ class slsReceiverImplementation : private virtual slsDetectorDefs { void setMultiDetectorSize(const int *size); /* - * Get flipped data across 'axis' - * @return if data is flipped across 'axis' + * Get flipped data across x axis + * @return if data is flipped across x axis */ - void setFlippedData(int axis = 0, int enable = -1); + void setFlippedDataX(int enable = -1); /** * Set Gap Pixels Enable (eiger specific) diff --git a/slsReceiverSoftware/src/slsReceiverImplementation.cpp b/slsReceiverSoftware/src/slsReceiverImplementation.cpp index 65bd9c989..f4788a177 100755 --- a/slsReceiverSoftware/src/slsReceiverImplementation.cpp +++ b/slsReceiverSoftware/src/slsReceiverImplementation.cpp @@ -148,16 +148,9 @@ std::string slsReceiverImplementation::getDetectorHostname() const { return std::string(detHostname); } -int slsReceiverImplementation::getFlippedData(int axis) const { +int slsReceiverImplementation::getFlippedDataX() const { FILE_LOG(logDEBUG3) << __SHORT_AT__ << " called"; - switch(axis) { - case 0: - return flippedDataX; - case 1: - return 0; - default: - return -1; - } + return flippedDataX; } bool slsReceiverImplementation::getGapPixelsEnable() const { @@ -482,10 +475,8 @@ void slsReceiverImplementation::setMultiDetectorSize(const int *size) { FILE_LOG(logINFO) << log_message; } -void slsReceiverImplementation::setFlippedData(int axis, int enable) { +void slsReceiverImplementation::setFlippedDataX(int enable) { FILE_LOG(logDEBUG3) << __SHORT_AT__ << " called"; - if (axis != 0) - return; flippedDataX = (enable == 0) ? 0 : 1; if (!quadEnable) { diff --git a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp index 7aacb2eb8..aa86b5b42 100755 --- a/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp +++ b/slsReceiverSoftware/src/slsReceiverTCPIPInterface.cpp @@ -976,19 +976,18 @@ int slsReceiverTCPIPInterface::set_streaming_timer(Interface &socket) { int slsReceiverTCPIPInterface::set_flipped_data(Interface &socket) { // TODO! Why 2 args? memset(mess, 0, sizeof(mess)); - int args[2]{0, -1}; - socket.Receive(args); + auto arg = socket.Receive(); if (myDetectorType != EIGER) functionNotImplemented(); - if (args[1] >= 0) { + if (arg >= 0) { VerifyIdle(socket); - FILE_LOG(logDEBUG1) << "Setting flipped data:" << args[1]; - impl()->setFlippedData(args[0], args[1]); + FILE_LOG(logDEBUG1) << "Setting flipped data:" << arg; + impl()->setFlippedDataX(arg); } - int retval = impl()->getFlippedData(args[0]); - validate(args[1], retval, std::string("set flipped data"), DEC); + int retval = impl()->getFlippedDataX(); + validate(arg, retval, std::string("set flipped data"), DEC); FILE_LOG(logDEBUG1) << "Flipped Data:" << retval; return socket.sendResult(retval); } diff --git a/slsSupportLib/include/versionAPI.h b/slsSupportLib/include/versionAPI.h index 85bcbd662..a6749e060 100644 --- a/slsSupportLib/include/versionAPI.h +++ b/slsSupportLib/include/versionAPI.h @@ -7,4 +7,4 @@ #define APIGUI 0x190723 #define APIJUNGFRAU 0x190730 #define APIGOTTHARD 0x190813 -#define APIEIGER 0x190814 +#define APIEIGER 0x190816 From d3e60eba80ff7f1c11c3f7ebcc33e1c615be15c6 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Fri, 16 Aug 2019 17:08:11 +0200 Subject: [PATCH 080/108] eiger binary --- .../bin/eigerDetectorServer_developer | Bin 302632 -> 302632 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer b/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer index 58a992a6c86049b59c114161da0d46ad08fde533..4e842b523fce5549bb1d6c2b5c76409461dc0537 100755 GIT binary patch delta 32560 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 Rz62S_gAtbWCA!*({}0zt1q}cI From a0bdfcdae3f5e2f0bda89e38a68364c1185a22fa Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Fri, 16 Aug 2019 17:38:41 +0200 Subject: [PATCH 081/108] WIP --- slsDetectorGui/src/qTabMeasurement.cpp | 6 +++--- .../bin/ctbDetectorServer_developer | Bin 154820 -> 155444 bytes .../slsDetectorFunctionList.c | 6 +++--- .../slsDetectorFunctionList.c | 10 +++++----- .../bin/gotthardDetectorServer_developer | Bin 116980 -> 116932 bytes .../slsDetectorFunctionList.c | 8 ++++---- .../bin/jungfrauDetectorServer_developer | Bin 123348 -> 123844 bytes .../slsDetectorFunctionList.c | 6 +++--- .../slsDetectorFunctionList.c | 6 +++--- .../slsDetectorFunctionList.h | 4 ++-- .../slsDetectorServer_funcs.c | 12 ++++++------ .../slsDetectorServer_funcs.h | 2 +- slsDetectorSoftware/include/Detector.h | 6 ++---- .../include/multiSlsDetector.h | 4 +--- slsDetectorSoftware/include/slsDetector.h | 3 +-- .../include/slsDetectorUsers.h | 2 +- slsDetectorSoftware/src/Detector.cpp | 12 +++++------- slsDetectorSoftware/src/multiSlsDetector.cpp | 8 +++----- slsDetectorSoftware/src/slsDetector.cpp | 7 +++---- .../src/slsDetectorCommand.cpp | 6 +++--- slsDetectorSoftware/src/slsDetectorUsers.cpp | 2 +- slsSupportLib/include/sls_detector_defs.h | 16 +++++++--------- slsSupportLib/include/sls_detector_funcs.h | 4 ++-- slsSupportLib/include/versionAPI.h | 6 +++--- 24 files changed, 62 insertions(+), 74 deletions(-) diff --git a/slsDetectorGui/src/qTabMeasurement.cpp b/slsDetectorGui/src/qTabMeasurement.cpp index 7efad7761..679fc1d2d 100755 --- a/slsDetectorGui/src/qTabMeasurement.cpp +++ b/slsDetectorGui/src/qTabMeasurement.cpp @@ -201,9 +201,9 @@ void qTabMeasurement::GetTimingMode() { try { auto oldMode = comboTimingMode->currentIndex(); - auto retval = myDet->setExternalCommunicationMode(); + auto retval = myDet->setTimingMode(); switch(retval) { - case slsDetectorDefs::GET_EXTERNAL_COMMUNICATION_MODE: + case slsDetectorDefs::GET_TIMING_MODE: qDefs::Message(qDefs::WARNING, "Timing Mode is inconsistent for all detectors.", "qTabMeasurement::GetTimingMode"); break; case slsDetectorDefs::AUTO_TIMING: @@ -229,7 +229,7 @@ void qTabMeasurement::SetTimingMode(int val) { FILE_LOG(logINFO) << "Setting timing mode:" << comboTimingMode->currentText().toAscii().data(); try { - myDet->setExternalCommunicationMode(static_cast(val)); + myDet->setTimingMode(static_cast(val)); EnableWidgetsforTimingMode(); } CATCH_HANDLE("Could not set timing mode.", "qTabMeasurement::SetTimingMode", this, &qTabMeasurement::GetTimingMode) } diff --git a/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer b/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer index 8dea4330e48f09fc99ce9ab0265737d9e4b7149b..42f66de081da4eaff165aad7bcc626395ca5ea9d 100755 GIT binary patch delta 60988 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 delta 60240 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 NwE=DDM**wY{U6JJ<@Nvo diff --git a/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c index a0b0807d5..c8b277102 100755 --- a/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c @@ -1226,10 +1226,10 @@ int setHighVoltage(int val){ /* parameters - timing, extsig */ -void setTiming( enum externalCommunicationMode arg){ +void setTiming( enum timingMode arg){ u_int32_t addr = EXT_SIGNAL_REG; - if (arg != GET_EXTERNAL_COMMUNICATION_MODE){ + if (arg != GET_TIMING_MODE){ switch((int)arg){ case AUTO_TIMING: FILE_LOG(logINFO, ("Set Timing: Auto\n")); @@ -1251,7 +1251,7 @@ void setTiming( enum externalCommunicationMode arg){ } } -enum externalCommunicationMode getTiming() { +enum timingMode getTiming() { u_int32_t regval = bus_r(EXT_SIGNAL_REG); switch (regval) { case EXT_SIGNAL_TRGGR_IN_RSNG_VAL: @@ -1456,7 +1456,7 @@ int configureMAC(uint32_t destip, uint64_t destmac, uint64_t sourcemac, uint32_t */ FILE_LOG(logINFOBLUE, ("Sending an image to counter the packet numbers\n")); // remember old parameters - enum externalCommunicationMode oldtiming = getTiming(); + enum timingMode oldtiming = getTiming(); uint64_t oldframes = setTimer(FRAME_NUMBER, -1); uint64_t oldcycles = setTimer(CYCLES_NUMBER, -1); uint64_t oldPeriod = setTimer(FRAME_PERIOD, -1); diff --git a/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer b/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer index bed4cebbf728d5b5cada2838ea5c983e09940ca3..9cbf3a8b0539258f9048a40150b86a036d3683bc 100755 GIT binary patch delta 49097 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%0AM8f@ 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 delta 48837 zcmce<4_s7L`agaz;B~+eFN!!K=|H4JXd{x1hB_cBk_r+kn(2tBq@-wQYUYeYib@6^ zR;YDzBy_1<7yoR|IBZL;Th>~kQJIm;b%@9%Lo*u&5Gg&B^BdsIfAI2V@K8Kc=gYF~=b25#FPzLZss;8TPKPz|6MwMvs9G)-bD=oou< zZGzAW3IIyKFF~-r$pR9E_DMc~_8L|fp!2aYj^i5);4>5)(X7S3*TxtbM=EPEA#zUf zfN!58OH0ok*Bu5tSzxUhzwuc#;9k)_{Mz!0BZbxyg|^zi2654 zly8hl4_oWsqctx!C4)vd+({(De?v90yMY;Ao?{$D)OuPNESmrpU9dYBxeSQN*+P5{? zC+UpY_4az3V54;yF0}d{w=j;v=iBY=@Ci=SZVMN__f`2*H{6iS0?2Z|!6xfuc-CZE z()7}F#vs%tGl1)OH0JqCtwCr2-5}DD&!>TI2i-2xVb3Rn_QUgjlWF?k=MA7Wpfw_` zeqIkc26T)_`#rA%Z2)Z$>5lbLTEkQ!1B?ujado{G335Q^h;-X}4d@M^H;8oedLDEM z=n|1`T(1IM1-eS48`cwJx51;W)hJQ5T#pfgnPD8oFByaih7ruWjK>*c-f_A1_)?Y5 zKRXfWeE_7cTd-;Vx~AhzR!03x|0b(hJ(_16@2ulv`O6q4jD+@ zK)+JPu}gfOaRh8Zlb?(xKbh9haBDxE%W?Hq`|-T zvF`Yr;dR!iY3LiO(Kl3+T>6qH@}J*(`xb>j;%JPF_72AZBNsy|+jB8&*SlhTGx zN*g>%hd^m9l%~puxs@;3oFJ%DSU{qnPw@dczcj2X!R`~ zg3Mc0;RYcWvAKv%xTUp+i?NGuX%V|}>vi}*K4S9`8+%JV!Pck+82ni z(YK6>ey?L_)v8t^lh_xctir9~CN?pFoap|T7vDb?>A@&4fPayXAO{r&g zIsS9A2C)~5Rw1??v8H-NzkL&Zq$s-nW*wrxDO!l=vxq*6*xfhl?We`q_iolB_Eb>@ zVw(`#gxHsFHrWL+_VCRn#Qwc#0%BVc+lttYH>Hlq<#^*}J7NzOjnqa97FYS46kRx4 zRHJE+kI=ZsY;3RLjf|sob3Ghcqm!GZ?7ycy{(JkbSL$SgO6#rNPpBAAvn6#_Rd!vM zW?W}w{Zo6_TeZivR<@OV>K`)9zQ$^~UA8t$=Vl}I`J{J1go&)VQ*&wR)Mq!@(HBiY zUo=Iqxg1R$)ErUpyl$d7_@e(y#)`ov!ZT<&mncUYC*~1OI*)KXbmWVGfBTsJxw^() zgPwiJ9VZ!vPWl?4Zx!^dnvwv02mdBJ#^b+H$C$au;1ZMI5|dQA z>5vE)0M%*|NrTV`k&RP!+NMKj#|_z^!hfUw6tlU+rpl(1lF3Gu|ByR&p2kj!8lhxA=x&s1_f(hT$?FC?W24nzzHUHP z+Y8C&pu_<+h_0C$4tC7-G$f!VoqjzH3FZ<<(5L~8h;J0*eXbi3Pt7yrx)JfQ}}Y*B&1SQjwNjRU>+8iY7R#-#?~;lKRa4&j#(I`eBg z9{#p~x3wQ{N3S3*Bp9aE4}FPu`i|cAP4u>JCJ1v=SwJEx)`wQGqxZ9NoXb%Fsgj5M z`PcSQ5PP`5E6^7LrMjlm%>ej82K*pHoP7FfT#l12IYW}$H`L^9Uwx5O(gY)=I?&@l zR7`ho9Nfv9uF0ONdvA#feXG?H0gwIjZ{9c+owMLy3d$1zNPCqT&!~H1)+a46H1w&* zED@L>x*Xeoi-eDQl~Jxy>N~Z{dbG-X7&t$b7(#+I_ZO_&dwj3cLN#zXjGp{SZb%sW z7}**!zkgk-k5HHTOHJINRewKpsQr+2Z-6dDhs6V7`wfV^ydhP$AX^$9=tT8RliQY9 zqFEsnKDUw>`e{u~sF9{r#xZ##qaMIBMgtV-kExulI}No#rMA=rL7m0|5>Y9OSUQYH zp?BEErh$H8lUA^F=dnD~0(ABqtdsCJptD z+(NKshzw6-gh(((vvh=~V&}7Y5SzY9w%blkNNhYFi$|(UFEHx9cq|D|0URML9r)=} zkFjPvH4IPX!Y^|7kz`FoT*?Mn2(9g8jif17rFh(!7K8`BXXxC33Q)5ppj~G2x+bh| zA@VCsix!L+Z`*4Ubm==rYz zh|4>g$-kHyWMVaABEj;ux|1})>r-uUow;5!n#>RNXWt;F2lNli&AZ(~DtJ081Wy+iQfcYv zJk!1N*$iZsF9MmBNs8fbe#-oCfRqG3c!leYK2ZX`(#JBna7&8LSYQu?pV#k9FQz zMjW_t8PVV#1y`Pr#Dg235ex2{>*NuK?mWn~(j9%NJT%Z52?n@*7~uAi9ruNq=Av28 z#QgYpa7tzf>O=E zs(J>cCV~nB1pqY;lqm`%0HhvdJSYID;h-`=0YF8A$_51hMJ<&N3IK{)sst1O6tz?p zC;%vGDJv)dC~B!wpa7smOZm}#SMt-Kex~}Fj8H$*V;CW7CKQ`V6H=}9pa7t#)=8iM zps3Pmpa7t#(ne4KP*mw$PykR=>9wE$ps3PCpa7tt^!>takN}WW>!Y9mps3b$pz3B4 zLwGQ$)v8T~S?B>~d3ALn8i2%917;RW0Tk6h1quL)YQTd6fT9{`K>`W9plTuDl8c+aGmqA5= z0)V;*N)HME$^j}F6aZ8sC?hBUs4qa}g93p1G~9&x0|@~6AtEb40YKG(Isgg)$_DBL zC;+I#pz1*ZK)nsB5flJa6{t2)08oDd#mq)c&Zg8ZP{E)8pk4__!_|TWfGk2}3@8Ao zO`zgI0YI$>H3bv^)U%+nK>5f7kAZT60)UDG6+8!}m_wo+P_%o`00jU=yZ5=E0HA31o(Bp5igxdXpiKA!lJ@TvAOWCgPgw&B0E+gM zCqV%~(Vnsq6aW9M&nI@5>9aT0+ z03vBel?Ms{s`E&gf^j+kfU$l!#`@uOvM+O(SWF~i(=d^cIa9!y5?i9+)PhqRTkqkR z3_{)r2EZTkKE}sk<`$Qx;8cNA6<4C*w2#F3!pM3B$MPul6dvUdd*y7d$JQ%2Y2z@{ zAIG=wn5xJYDFLqpydXEvL```X%(GzjRwOJkVA^lsTly$?P2e?w7p&mLO~hu#M82i3 zg4YUOD|jIao&}q6mPvd|KLt;n%$NjqGT)+6Fjd&NRi*GP{S~}CY~JNf;afr#yi?$v z0&jqV*M^;^wyAten1ZLnR*h~N-*TUV=frBTc_x_O45k^(2V^FA zSHZgq-e3hUXFe7L^ZAw`3SKjK&EQ2Tc-cmr0~`642Nk>q@EX92R`AjmVD~+30pIeF zf@uZQ3SNwY=a+>IyDYwCsDhUZUM_gU6g(?!}v1$glaUQsSu zQ!d{!M#0lQ!w6c_GknWf1=9+q6})i@UfOcBjUJKUFR)V z?=sQlSb2ljc^AMZ=V45oha-t4GSB7MDQ>;egS}(ohVHdBZmC$tb;C05dY4tM)#ScR z(J{|Q=$J?MDd|Ba-DrGBA$EyJY_TZz-?G?NP82#C!;ri;%czsEO4O?pG}kRw3#%IA z*_)*c>$Q7T>R=wz5_i5&#?1E-V&*@#*NUv27M*xb+6OyuZHxP07?zV|AXUa~QhmMH zTlT&lB}a=&t|JM<`f`$5WbUv?#WfUbrAn>g*Y36Ly|MSP%1OwkJ7A))c0LDqp|ZVZ z_@PyYjvVT)3)J<6GCLOc)BZkn6;fB-CiQa)rH)*acLL6G*XUM2Kho`CyXn7qP77f6vk0-VCT0?q0wn^*BI9*TEb1QpmH`$z) zoshqBrP;RA#zNj}d1jnvRD$>YGmQFt9}7Yk7uDEr9FR81qcqt0RQJ)Sj5XLBy$X%5 z&c6 z{zE?6Vhv+5>JC{g{c$S&2NTD@<8qjM@b zudRq4EGCjno1&9WJpTG4F2nFH$JbZ&Ej@1CuXQ=9$@bX$(X~9(wE| z%i;$3SGP%JIYVBFyMOk;N9yf@-JgyX==d2-jhF>4$ApeaIt%P(5bYLZ41gN1w$oE? z*)Q&u*F@6ekpYiqy7MadxyBx@t+!#v!;$7Luqu!fi(4I6XO{}BM(%3l{@ZVpbY?}Z z(cDwX%18PpNnP#jYW=rooC}S1=fXUI8IVTLT3&yE*HMUKv zXkPYnI<7H}8Q|lB)SI{<_2ziNyuddVf6B#-h9C0L_0aXhK(bnq$)PK9kNM>l+GF-z z)k9l{GSI&F-(%}=Xv{c#$EDfjY)I6jgWYAKHXfptBWV89QFJ-)lM8%>lM6oVlJyWp z)(fx5{b11*>eL^ughwrwTB6h9FM8BNKN;)>(WCU;#DmgSc-6SOHtsKT8Fbdph4o#I zT`yjgoI3alQR{~-Y)AFBqk4;O$R(iFD>biOW9!i?Q16y|1?pd?FL}LtZ8xS>%{cF> z$P468`T?d_+}YYLm)OVS#zsB*g(mp;OP6R((i?z`!xlkr4K?9b1if}4c`&u-UWGk7 zV9$;PUm+Ep7sypcWs&P=PN-Z3=-U4iWkdLBJiIr=P@BSXxTUZq(lW@^p*z2U+xb?ywc_vnO9E)#F) znvA%$fB_y?00Cw@rV@|yI9m?N1K+Xyai(XahPH?BPHjN82ljxnum_a&F~*zq%VaLD zy|l}BX~Hkpp-9F&U$m+`kAqV$n2Z)S@^KT6p&buA&fu^9ajiXCsKxoM)sljXfcyVT zyH&F~h_-vRADxXj;`697epDsL$UK+hXnWJ~H_)M>e+amfig{2mFDpVwWEe-3Ldmz< z(JCj1bA->@n;L*CThKqQn55HoX(uic z9^XgNN61-v<^xL^V?AoL$z8j3Fz}odTC=|{2j7vALTk4Ef2vvIQdzpoap5P~|GT%h zn_#qwD|})9nod<4h^h@sNkcY0QVjSzFvUnO<1WS_=qPa-=AH)724B|ZF%OL1LxVdI zi|GXl>kl42LFJ&%X%+QaK~?sniaY#Q;PSD&7V(b0J?`Q7+NHGHaxSbx*R@x1VbmCrRAc`miX;s{54Dk9W1>v*L`HSThHw^Mb~fwq0>)u|+H0=SKgm7+{GX`)uP;|= zPorh?*q7iJ!pDF07J*TZM^}Y3qv~)4;C;A=cA+l-7BhK##M3{+gAQ1ORLa*YQ5)Q;?@F8}?gZ#wi}Z@0{dOF=o4+f4%I zJ?&gbrx@yAJ5T#)eHZ`NTUGa(LXLjg<(TtdMjd5>L(Q8cXW9AMg|dXXC}Hlxi|CDh z&5_HEPSaDu*Dui$e)~*UCrrGDQYHpQl$%z2j?2MQt)Nue|DaSclqz0$0ZRQvq13}3 zr7}dN$nTVLUi4VXBrfUY^54$n`=Qj#YhBCrl`P_(Rkk^Y_I8-yPU<>Wr$?Swd zcj*rUpjI^0>Vfufb`Lh8_sBCvTx6QmRocVu;^uWrVwu)BX02z}<90=ET;g1K9W&hp zNiWBV~VTRtBx!7TAGocB?(W&8t^ywexi%@c%b_*wPBRcPL)726U| zw8=y9+O|48e{9)Ayb>bGV#&|rA5cu5y|T_i*4c%l7cvgvNtx?%+}9>gmJ{1(Pqk?o z?~(QI;W~Q)77(R2xtuP?Cft;gJ7|?UseiPP4GWC^z5(yXjQ*~{#S{EBxgv7Au>ODL znEt=cepGXVD=3yPrzPy2OUpcK4$jfDagLrX*+#mB_Q;cBjmHJpczWBOf9_&481+hCD})u@!< z9Ltp>;=H)KIA4Klj8LhEcA6K`6f~`OpH131lk&Y%GXk$i91{21Xx>{CdH?gG+~8X; z(mr~~QaWJ}SH9y9t=%gveYby4o0Pu!OYu%xT#1e@SLkBpu1kctMb3p}d7Q>H(IJiS zc^7N!I?tMl&P4}e1x%Ysx-lq#$GlIad*4=S&eF2Krb(ut-Zc(fm z$e)tC50IScb~LJvG#|0-1%@h!fqpVcT4B(kU!mH>nb_hxzK_MSq-MDbW)a} zn3T;yespiD@CSWM&aKZ)T4`2WZ=a1BTC`Aoy?l-~HC>mO=Dqow;C^J8_{ecjIzCmE z&38%rkUQ-RF>RG6tqN&1UDEbNS`*b}oS1lrC$TownB7?g#w|8lOt}szRd^9?udUuz zq}n$?nv^%;V4w;7CUH?(q`EP{p=ADcgh}gstJoAeaq9gqJ=7yTq-lR@i0Q$ z1Uw1@;_?h!r{Du^L7h#NrqX%sQY|R?;o07pKX!^qP{i!$6tf_EruU&uh@!_Dm$CV< zN%i3XSwVjsravQ^qAoRSavMVtz9#m|M=vw8@ZbmEZ z?8=rXcvN9$3TUV*VK<^Br1aI}O~QJoWfgUh33m=@J*yVSVo`a{Teo zm=$9^k~&Srb^J=jRs*xhS6~+HoDzKBv$JGfU5>wgFL#3t-_uT~4;enCe_um8=F#p= z8>@TMW+|CJrLQRxM~{(=tQGX0o4)tz zQCk<#W{BmJNzqhq{YR?5DD-~Iv~*oE3l-wM^50+My}BvCAaZp9y@&7ROIJD>2QpBP z#M;L5Ji&AW+q4ED4h4=|gxhX-#pLK76J9R*p4KDX8;Sm&*5lKQdua_qGLj|3F4tP9 zJ!$L!(Jpf^GwS-53X|ol#UjDs$*i;vt5tKCzVdB{qEnZr$dCMmNa{nmabhuEVnl=XU8vWxq_@%S#vNsT;?5E3@kn2JMQS3+W!| zb!;`9w#%iI&Rz;2W7K)Ni6k|e72nm^e@5lv1%T+zud=|!A5bKG5()pK#p%wt&dFSk z-ilPoNOcOS0*7}^<@(l}=_5#G!-y))8gE5YHB)t)mhhNHSS^WAvGv<_lSjvaNM4DT z+})GR+ay1&5Z)cBw`+NK>iXNHKCVdJ-dtnP*J|9UZHm+;S(i5y$-hSOr?h$Qi3Zviyn9C?YBw2T9Nu~q<&Z%3G+%bG z^wQ(r;~U0-E$+F@+QVbNKkAyO)3==Pyb~q&+dUb@)&ozTO*gR>^w2F z@riRj-;E)kW`vNujJZB<)8LNaKR)#Y-iI?|UGcubS3D8i`4q{U5p4SNH`1Ky^aXv( zKV2_GU>v~qKQ2L|4OcCirOU#gJ9`d&Imm#+D5H(VDYP7yh`7h+gk$QpR$R-v963z} zp&Bi`dXdDVJGa&g(knVH$F~g&em^gP_t0 zsB{72r)>tg-&M0O7Qh^h&<0QnYXsk5R#2&L%Z8L!v67 zMV&_r%p^N$QR7a0Y&N+xGbBZ_RkU!x&3FiC&AlaS47BK_k@s-L9M1AE9=r#m> zZrW^8H!I}9P&|<4NlXi;N~QXoMfIG83CrBchY{DT{y{Rg#Lewb9?TptQC6wQ&GntF ztg@~KlTt-wV?Q_(Z#$l6)W7n0Ut=`cmZ>$(8O=D}eE<`((R9GYR1b4rjd}?FjxcIe z_jj7))nHJmb0`nm8=-XLBF1q!%`<{Ih6?f)NV-smsxS471avBSfPd0D*_sd+ZA*z` zY(eC~*`rJ!=;Y?wdE;t;VmCE%FGq$Pb#)ZzHO4XNPL8PA(R#1T3+vHXlS6`bxaC^UOABxf88PpEvf~*p?9O&c5+9wB>3+1p{pf|3 z-|q-yebagEey^24Ao=gSK{E%sB`2S+5qAZuA(_tJ42o+DQQs)$&;P@&O+zMWn>TQ9 z^Ouqx1KpyR-$wMMb3`{k_$~%`Et44M51zT-Evx?95>ZVZWEr}sS#wT4#g$INd){M? zJ~xvz&X1n4*e$x`TeB#-{X6N%&ZyX;&O2weo8|iUZVTOU2@yt~G!B?K%q=yb%U%iQ?7vt{n(u={7x zsV_FD&@$dr%qfq%^J)%ltQVU`(szocA-0TvkxdKkcDT99BN}hPLe;u1mH7JC-g)`G z)STjx)mcqrgj>&TZZ$79cU5y4RWs+#?M~wn?Q)!G{=J$>3N`Q5(5}oRHCZ8xIk!@} z#u|G++#zYQ*Nc~VI?gh)K$^$Un|<)J$ss?GigsV^JIhM6IakB(5=37 zcL}r#mp+4qTK)gQr8mwbe%aA%D0w)0(EP3|CV9Y?cSVzDN(Z%c4Mn?G`LH$%4m-!K zT;Vr$q7OA=lWH)dmp;46G~@Pd;Ogg+ zZ3n`(G^35b%gFVW!m{@sfjs%R9GMQUr_Hunq@DA#UwKPqEHL@wTo$;v!R%{xEvuUwYE#Q zXdv4c_cz?ReO|=-y8&O}*geP~G$7*!WSn@8t`m3^b;&upOxQo0G%t=YwVaVEj6bKd z-yd$Y<x%0kb8)j#1iw!(T>ebm2O!Fxy~G zZLje$`s&m=#^jiTx3*))(|e1_5S|R-Pk&8k!F08?PKqJl>>Tf;VZGusZ1zKxR+?Q26WsvM5@TfTcv>*Ya-Rh_BlrWfjzx+y}ebcAePK z$)`^Aj=dOby2GK)<|nWj`vv{@g>pxZzU6*@KgRLH0AK9STpA!}K=+;G%9HoI_I@Ex z4)4}gcB41T)5t5!`kAs%OJ2I;Y@L0&w#j|E{3MhZhZe***2G9R%f<^eOMC%h`*B}B z8YXyDL8T0#>3c?M=#EqmoeFob95}u3w(k>5e1sEdZqjKJj_Z=);ZMHFV6VdESa?=$ z+(l=p89$u$`zgyqUnr(5_Z*VWrqdy5a9h1pz7PyMbVyp$^!pj?wFaVH7CiUPt-dlH zV_8#ITYuj0zu20Zx*%P=x3|l!OWjvWTff{O*?N=U`gv1|%AbCKNm7MgHFPK}7?XqB zt2t(*GpBg%xNMTQr}*<%vKdc(Ma|e_R&UfPZtxF7Eymz9V!SXn#}}Zi#t|@ya(d{4 zHuw~op4;ax)8hcqy6FSmB}&H76X`jB?28ih7Ec@ZdrlkIBHOi{vTglO=bE6|_HH2N zXYMvFe|I{q)#+zGlWMi&OJ%+veJ3f&rt`f5~ZFXl{ z(<$2*JlUSdMyzzzyBgV6cgi-cOSW|Fxc+m+h<)$ry{}{NbkUJUyY49YlHI<4l^&#bwbiWw%-PC3PF?49RWs2gr@T4&|wn%VQF+9yXot z>^8JO0iP?HD3gbs%3wx+*NZTJOQX{rgMB(?4VxCzZDjpkI&1joQ>li3{z7a2345j9 zkA7roOt_R8Ob_(T!hmBsjB!IV@j)bT?sT2=Y!0@iaw3GK48FFZDEHT27~P*Ey!C|< zm^*cJ4f=^X)#}xi#HueUzL^U5}n%cxT-5Nk#$WWxDe$Xs9uX zQ|=3mUCXiXv~rbn&G+uNO8C@hA?m8~^_uSB@Oa^dzJ3!S)OW}1aGI1x;gXAcohWj8)u5E9rFi#x=_cG4b~%PN(1|0RnWi_? zpgv2Vh!za(a&}bsaR{dze3N1+zDcokCp@IRhMr7+GM*UngXbB)wcuKi3jMj}1XxeT<@b#W`Zf+9#H2=}51h=Xx65g3khW&&8Bvf?67+MU9H|uKM+GH* zi#RGKP5hAChkfuq9dtbfUGqPer-`qAPTSGhbXkge8NL>6_o* z$KCarcV&35jn1UoXg9~LU16wOz261bF61uPOE*oS zr#f^bpoh)gk?#*~;r}?z+i&6>%$*o#^5Go$aE^~o%STd|PFvt`L#N}S?Wc_TKRivx z>iC&m20@djsp3N*aOd62UPId&I7M#2E{6qO*dZHzDfnNfX&>P?-KM3Z1QtXga+B|T zqM^J!T@RV{%PvCZ)yKUu*PNCYil#rFrtSY+nnx4{)~y&=S)Z7gHR?^L z!iNfFk+=()i@T7yG^092Mv15Ztn#7!lGF9bXMft0m@7zb!DtnhzaRI>|2oQFN})I0=x(a#IK<@e z`$%eK!|Lntffl;e(~J)lH0RUat-uNRhg{ zIcI5~(yMcGK1Y7qFo?_B7a-*ABf&4k%E2iw=;UC5CwRpALNOaEB@QZ0w@3~15Aa1N zO5n^T^GqRH6+Wh*dL~@(;pxu~oQS7e<$8>>1|b+R!OxH~Q+%2v18?xvq#$FOIbS** z@6Xd@F-Qh*JSl!1lKymnS^PSrFja+aB?WaVJ<+#xrbP}DtvQ%Wdd5dcdWMWPM@8mB z2Ed_Zq(KlLe`Kgn?4L@{APW&&_zc->&f=<`!Abu!;->|h@WqFwY(ph8lpff;ci1eH> z^c#&ipmRhzeN2?rFiF?|#s-m*GKPMmu>^F9NGFcbfUW{vCDNnE&~G$aL0d&Sc8m)2 zDbS~uA33+_f{$q}jJkH8)k3?t4G3@8=M=+cgw6Z(dnvyV;lh1u#c&bAMfOTJBC zIP_&wAcM;3S1O0-)uIU(d4f;sqQ1)O$QWsu90}6ulJ7@d)xONZm`jxHJUQR*<=yqeEiyVAnivy<{UQdj;9O zIg~3#uy_TjMerzsM^}(W1RD`-TtPYz^ux1$c_eI06es0QQno~M25=2|Wc`-V;ZpfR zP(H~@eG!sM6NHdtq235d_UTjlJ^6NfKhn6RcSJsfAJm14L>g-z$t==xjR-d8k&Q(IIVXb7 zJW^RSn2TD8$?r|2X)XP=PrqCO#o;1drx7G0-K zA!RK&f|Rusma--t+XnJd4%E7md=kAq#?7RLb~6`mpEyjCPU}VzOY24wN}rZQ(nqAS zkaOE(BfXE@C84f(7$=pPWEYQiKhwvP4J}yLr^)-p#s6EvRWEyl?|)gx<)gatSCYn; zKZumF48oT#i&UZ5$B<~gl-J!@0+&I;;+5os9f`7Tfv=3!TEVsAGZv-dWx`rewIXE@ zP9l7ACCPmyk!yn=w5=pZUx_zKUzu?^W;^LXO`US1lMZA5nUEsXpgL>ZE^-v%qiz?m zB5ZZLNG-y(ZWpOTxX$e&ClEg2c9D|^pA=oBvs*y^BglZ7Ps)n+6{XjxTS(bSt{`P6 zg{ACBRmrd^QVv0-YxfqZI83DI+nQ?+#h}}e@}n^-{{RjB_=L>kOV=J6fE4nxGM@}A z9h?@m3T1 z%5B4XgzMclY(TidZNsw&pLN@?5#dI+4Vw^da@(*O;pQ$jq#x6bhtlz@$grIu8B$i% zno@{bbKfu2nvzgz!R|QjG5w+y_#t@9ev+KB^E2BO&yb3pVWu?Xk+#a^`1P7>mN3yQ zFC^VwzCAylS?J1pi^FsTGylDt^;_D31n;Gyum8Y(%vp z3~;0(ta=vnqi6An7KGyv1~|qeY(&`jtjqE2FLJe1{6d@V^~4lNrIP6mg*@~0g|p=2 z34kLqN#qWpA9lx}jju%`0^ra{5h9;@*9q`XJWC>Xr9?G6%L)z8CJJr)d;oM4;+NQH zq2rdcA@TKi=#0dz&yroc;v$>~I-gAtV)9u4F6NG)*EjG%928TR&j3i`m6GqtLADQ%n_8R!sob;xt`FM&CWDzpQx zB3CDaBedfOFy}moIp;w-_&Slo=}jSSI@9mSNqh#bkOB!*3JuFo%G;BMc$cH)CU((o z;l9NcmHHu+Rgw*RuVz#6XB*a>-Q#iG3#}Sf><*R+FW`Hiqd`0eE9ac<0uk?93?J(dEkod zJ1wU7qM1_*fW=9-~074^}Wp7ils*A3nQr4;mb7Z@X0gJ2QeBi)9zvn zp7NS&_Mh(OqL4Cb9Vz&ejx!=?Tt}>b!a5JZymh4gPoZ1|f)(os|GJKAK(JvQnfSVy zlRooCPQ9+@RO``YttSC{rg1R{#;hmv_Kf8+5zJgqD))@^(RC;1_H+d1gOk7B(=3`T zgE^^j6Mk=~9MtU%;i}eS)wTY}l)Wl8@Bkh<;C(2oaxmA9==SwwM`b8?6~U|P$-zpE z%sqt!9pHAXC(g=vj(Hxf@_91)ji?Acg8JvN^>ayD^kM7g5;f%D_!J>>e*l0KzG3BZ zkSynUl310;Mv)^`Lwn?5B2L$;|6ohVf2$tjs*s@Sc@ncPlq*EA@Od(2Uo_{pAD@QZ zPd4mJ;p)Jxd!C#^uo1z==SkT9bgm7-w&zLy{_~vQ1}r-^kjy{laghi{ZXloj`Cu@8 zr}=u&+Pwwh$HWaUpksJ}lvIauQ;=rL22xW!k;_IfdjsjHKF666G;bh{Z@$J=AXu@1 zY!u^ao4nKg_42D5 z@!7JC@;b`6U?uL9Z)&C6RhWI^q2d?Fg#**LqX-^-fsFjiG_C=`h8M`TzeI8E2)4gK ztl(-ON3)Tr52ka;2qteN*#~2yiV!T?xWKjw`^VjXkSieO2U-CykEF}hqeyXdBe5RL zW=oFT_t(=br^RNB)WXsl_cStJ-3l9yJgEfazxOQ9)Y~QoTnE~ z1OZ7VGUxC#E)T&x6FG=r6@pbJ;&UX8t4FZjL^6*|<2n%RFp&dC(vx+Npflt2KzyBt z?zcQAzRq)YL?7sxjo556{UBXp3muBZZ8-5Ios%Qzmz)AHfxQ{DAZEX`qacNe-WtW_B1P^dve+8KnGrN^A{7W$ zAXu@9d~BV`)gV~2i43+yaVHTxxrt=hhH*^@Hf16)@delm zC?KPcM{#-t^#vs7_-6N()RC*l7qgrZY-0g2*2Z#c5nNk9Dr&>HVg!o|$nn~NT1x>Y z76o_{OZ+9fYES@BxLbupH3h_3J2>_v*Z^ILn5Y31091+93=U=pNZMGS(rvSA<~EOGJCZ!ewqo={J)PPQ-Az2!wOdHt2QxVXf`%<5?8Eh(5kcb? zvirkmZUcfFwvbZ@Rv=ihg>-y4kUNUt(Je%Kau-*RVEq8<)db<5ONBONd3o6+yMj+6p?rSox{~5SYLD`@>B@R zbs*ePL=2xy=UX@~X1l)-v;9cRcWZicx!W$19TAJeh)2-F5y(H86?$O{WkgiJ=1TEGikIlHH?%Ib&9?2;^nVN-5lPZU`|%=%klreb^$rfg55P_gGqEjm-Y zUR<`v2NbUB1!)BnruBPzuZW$nf?9Nf+oIWw8ROG89o>5l*38D;t}?{X{9dV9it{B& zlYY9CTB=9a{Ii(Zc)eLt0Cjbwuj_f%6mO}pR2({cNOLIjP=F9`;Y%|QYyOavJT~k( z-R31U1L_D=1y0O})*-FhY|#;>BEBbpI>I8xr0ec}LT&L8)NmQ98cnITV6uc1DT2xp z0N_hCho?eHcYoaz#NXHx!Ez1D4(1G&o`S(rp2V`FXXX~;(@Mqfi@$EfTzF8$Fm2ta zDEv}KFTTzqVUAFF1$-Fwu+?mgu@ zy0OE!Tozq5TmF7Gb|hB?e$}4xTiw`$TwyUfnBrrHIo9A4l3ZDDZ?gY+?}Ab$$JfXi zzgx%)$(7|Qe|9I=4$1AsfARN&t&5I2QX0XNy%jhDm;v zRmBBkHwG!s76&Cw))g69|88OU5KMCW5*0UDIEA#Qio*|IU*VsN)c!a7VG0CUwZ)oP z>=$BLeQvf?O z#97=!a27Aq{VRK-z`xAobc^GFkHz+2b!>(To}jXDs;ID#*cp}G)O~};>LxAnHl926 zN?8nt^?m}Y*L70|22Vo6_nN-^9W|>Pd-q-~i|K}|!!sbm3K^W*zpISMo@~^dd&&5v zmP*Nh6d#}4Ny%d1RQMia6?&aty3ziIzRN{>obvrWS)JRZXsa+U>F4fHy&XjP)t+pG z!llZ!fozD$+X8WY7*GDb1=7|>TOn;}_ZxrcIcZ zH(Oa&3_G+pq1^}_FBUO5MfoYWtJb{U2F%+g%mh1bn z`lu<@-GwRDwDanv+lgJ2Ah*9r-|u9YM8S+7!8TWySM+5Ea_X|4g1W4{wlBJju$S?Z zR4*TM_GRl>F6QL`A?D>{@AhM}eN?9oTr2Q> z)4XyXZg#n7j#(oOz7gJmsgYmzlB*M_mtCI(tF z;vt$lggwSy!BZijCm^~sQ5TR(UmY+ry<(S^PM`ZU`U**UpVC*y|F-0zw39P>WEanP zI3O_W;q=+~jOU;DUZ9!S&E@hA&(2ih4#qU(ud%3HMTT&@^T6jzrg zhqLnnvnw&(uEbB$RAQc6S$;H})rOQIzD$(pgO}%VGzYq(y8L1|s}I{Px-3pLtLcVr zC_Yz3TfW<2#zwFq+zA&BuJ9sp1REAvgeQxtoo~=Ik`yb#;jz7AqhphygNo|$S_C^V zU5^s#D^;avzNHiJu@%ftz%f+LAga=JXdVO9Xo}#(SJJmE=r%Gj;)UyVx*}zaAj)*URVK&qlhfa;)fnHl0%$2ybNt11Z1o zAUlQ2ASxk)l*dK0aR~b(d~A6%JI{w3PZ(i5DL)g#W^!o=r;&2qPz=Ow{;HvGZuZs zZYZ;x9Q!nu)v%leDqBc-+X!|CSA}pDDL2QlVF+UtL&_`T*vN@ivgL@sU?mLW^H8LaM~t9sQJQ-l;y0f3;S>9LpsAoeUNS3kmL8d^!+ zUvYXu`o|W`(SQHB>kr?#T*>MO`Kf}F^aPB@0n&%Ja3v?~!B;h8{4@+~XZ=~*q;tt>$3R(5Qro;9+ZG`Bcb zJBqdXxEoo7+{g;z*~2WDw!=3Lx7)R1%PUVD%bwtK_Dn+m>?7pt>6X)-_S7NcSUs16 zWkt@OV;SSv*I8W+Jh}$HpB2lh1H)8WoV0>-ROE1=szFs(cSGm^LImF1_B+0hT|n(K0$ z_k32#mvK3!&UG)L(UH3U9UC;6y{~7lB@6NwJv)E->SwYRtwPMP$7Zq*uzgnzVwfEO zGvF;Z>@Ht9i+%fnW{_6^jFw>n0bzh>fF3XrkO9alPsn5+@4p|xqk#7T^?>t$Ho%SY zeVOd!kO`R?6Vj(8OqoAEb?Vd^(aa9 zU@2fNU^Ac$Pzk7sU`))r2%G|(1GECJ0sQV~nBD*_U>G1CkOIgAEC%EQ3IHX5*8v9r z#{nk+Ujmu|R{%^TEC>h#L<97IiGU1179cNj7Q<{rpcwEPpc?QF-~`|dpb2mZ&;bZ| z05ccBU_cxo5s(I$2gn7i2NVHz0jiE|GO{mrODRlb7$xM6muQOb24#3o8PAMA=Chbx ztU6Y;oNZ-?y<=jS4**{RS^(DooEgRk3#!W z8O90V-iC|3DPbDE6Et^8ll#`OSQ9)lItvda{RPzu-0TkP4?qLJaR80$EyA()&Fp$M z;zSL@96am=zeCUlZ~))~{>;P2<`uA4{7sur!!Us5fS5B94sl~j(>My0N9n5w%diIF z<>%qG-!gD_Xak^lnj2G^#!;X=N^2FMKF^F}4mLAP@b?m2ZGkf(OrZi{nWkaNqx8oL zc&Fu9;LGf`;1Gj_Wz2v&fE>m${@`AA?0r-Av&@t~11MGiP483w-W!-PundF$QmSfq zYWjp5s8lIs`Jzg8oNsU?d+hWMwl`Z|{|2irZ`{H55JRB{_OOf$h8<9aLMesvYj3d8 zJ{9%l5mmsAXUeBlu@R=S&tX7hoD}G{h0Rd+QorK+h7ag4034C=Ye01aCkCpL@NVcU zesB10@!8CZ@m1irA|7>uct6C8Pj8_Gi3FSg)PBJ*hdCOrLA>@A)f?Sk=8C&*@!RbC zl20L9{!pY2y}*vG1T(j4U}`=G3@wS3J!cCe4%Pvx)g zV+Z<}e=2{MV&_lg=l8J@5f$y|C2pgH7QA4TCh~H5#C|ryM}MV!;(o}>xmvyobhon; zSZ0@$U(J5xmp8He_jdSTm4MT;A;rn@MDGq zFwBrZU}QK184igB9tk`VI0bkP@H}8t;gD6p1;CqucLBc!{1)&*;CF%F2S!FikkJr$ z@Q{nZDA*7bEGm#;qIv^I01q}HFcN{$z$w7ffad{c0j~mH1H2h{8}MtuuLGk*Q7BQ= z`@kOn!-7$;VAMt6OTf1n=0P7n=E2^;A;5!yqk%^Qj|H9voDQ4?Y+8)K8U)q@Zv)-| z{5o(Y@L}M0fIk5K82B9UdEiUHSNxc0AB-j(a0qZHa5V5R;IY7o!0Es8=+5!)n)2n(HXcbtfhPQ1*rfILwdv zZ3Dynwhb5#`5PRv1CH2n68KBtM%4e!Abq5jYEc5%`K9+cSh=duoB3fnklF9Sj@D__2Xez&hZyz#IM8{+k)L|2E*afDZ#- z0lwzPhC-3hVZg{JbUE;TV8jnt#jpd`!=g}p5aI_J7}hi>$&Vdc$go3q0>1`q@na3h zzyQSzJAljl*aRcPCO}Za8ep{X>u|8^Nx*Q}>#*4McY!~E$r+eD5I7Dv9wsk@$>C_f zp>O%E9VR~klh?!2=sRxC1ujDU-z8D$Oc{t z{3Y=DV;Kin;@fjDW}nf1OgtPd{#^Ohzp~rAO=OsE zz!ji(`!V4tNO%e`YBC(7KzJ7LV&FVrw59Nkz~}+Oi-AjkUju#}7#W8n<8WjgejFJ2 zhMzg zak(^vOr()M(uffQrZhyzlhKF}5JOHRDW)1RrAVoz$l>H@V5gg$M^oRetg$=eb?UmyPlLbU?c9tJ-8naU=OAaJ2>v(B%Vg^sR`%t zW4w%4@Jqao9xoF{;_%R@5FQ$h>6n2Na3bbmJ{IA8EX5UAforiEYj6uTV6%ttLpvR` zxv(FtfrolfEIcF@9_qu>cn;6wCA^GZpcr{bj65Vpa>Pi^C=??(VkAe5PiE7|AKYQY^y?Oj?9Ff+T0N3tO-Wn{h9;VHbAe5quYWu@BGUIlPFM@N@hEZ{RKb z+Ly##z9`agEN0^UI0F58)9!fxTiy zgAZyjcX0^0%Wyv)h{KdIAxs&E`B;EFIfW;un93=pa$(8{78=1+7EfdGG!{-{;j{(F zuxUm-&4{OchM&hFFBw7}k9~hs2;Ub2GbV;GV=@+EF%IFiIOH=tpW!pJLztO^l~{!g zo5`@5`kSS{)T{#z-iX7)>q2;VeH;oHP{4qKkMWZ@JW?0JBlU5Zb2x-KN8>Pid9@Ix^}oC*gyr*H;JRg8x18n6 zS-wmI%QdjP0@udjhXWz}a1gKJP#nqxZJD55od{ud8d`pFjeS4P?QOZ)ht}i!qqHW{h10}U%~ZdDwe5Oo~fbxQEZf##9>W( z2x~I%IG)7M@N@O@)hmd@dY)X*lj}F&Mr_0VcpLA;;V0{@|DSA#L$wiC8*%kvJc@Vl z>o`0$KZK_i;R;-Zg6Jthw81LbV3lm>#-2FTjFYO5$1<$IYj`6L&oqbd%uZ9AWool= zB!p)}9G>mPzBttGxBhFnW)l}~;=<Wj|FHT;6yI%V{CJJQl5vm#vPME3pcB?B!y{)+3bT*sSu2L_5Kk4bpjs5Lviq{UTDujvCy7p{kL;nJJ+>aR_&HmyJ&A0?d?X^Ze;BT z@C`hUC*$ziT_Ltgy+l7G3Xjz4Iy#;YBggc_|J*KNG^w&&J_^IXaM!3La4Kzz|-G z!|Pi@c)bA!a4-&CV?*dl$3?gp8}S7+fGz{*(r}k{f1%@F==c|%*o9WlFRY$7^z(*( z-rQjQziH0j{M3j)<0>6?>+mfjddrC3(!g69c&iYLaR;^_L*8P@TU_`S4<5W=H}zs1 z-qz0B+IjnZJQar?^?TIs;fWre_@$})rK$Vn7x-ly4pmzJhpOW6tD+EoH6L4WZyXM9 zunWkrcSeWs&KT6dI~sULhwtd{h!Gz#;$J61_;s3k_p3L-d9Cw0?8kvP9L=y3mxVla zl&6j!z&G$F-j2g>QiA0-g5@^~{6>LauToL;|JGdp)?6Rskz+jaJ0AEQ5B#nb+tCPq zX9UM*+xRKMHr$WL@Pv9N)q6h<@AZW6-r+c$6hkM)&{eJkR^Xtw(cK!)|hM&iw zZ=7wf@hG_Z1XtfVJg4!|fZ^|Lt3G6vl-pjK^He$3?gd<-Vac zj{Z^d{f~AF{$X^8{$WfUCEgEF;uK!O%W-sfWr*%xhYL`Wes>;f=k8^=5@SrDB>is5 z{N1& z2FqsXXvQ{d!oApr_D5#Cfy4N99Od&^K9A*3N4o{HPK0PyFEU^j17=;tAp==#AUx?a zJeqqDKS#^>PQ87SZ9a1Ec+lM0;lfcAB!3rte=mrm`&7KI%=uL3h0eM1z6$47!{3XY zuXMgPj^eBk#o4$ATRV>a?bmczO0+@ zB3_EaiYh-RCF8KN#Lq6J9cgEx%<)V0zjV5~f_N$WR<3YwRY&2OX!m`Cnz^8Qp6dBN zPfz(gJ>&CIv(GklTs;##pJGWaOLC1e*C=x@;bpvq!}733dDshh7>`P?#!9c!kvH;= zNwZ3&SyssRFW|*EOi$QYNkeOWy0t#t3YcyM%;3%$+?k&t?aIP;@wmt9%v||ao_vb| zGZ`@RDh|bAmNo3JR>G_;*nrKr6Nhm`I<`?dwi&tXVJ<7+vH~tEP_96^N7AKb8OUXi zaM>e0cvw1imvn3t&c{U_ud}~!@TL6CNah&HoObL)o|to4-lpL~4HugC!l|fSp>l;u ztj4Q2B#)aekDG<-a6L9)BQj_%gXRw5HF=)NC^8vE9$rOjJzk46RHUJzejLE-coU7Z z$VlgvO9U&i6T8r3bDqa$@o0(S7&OviBQ56g;&N=oc07si<2Ae?FBBm21;`KXmp@KG zQSgIrKdl#f+%5FDTiAaL&fdcm;WU36GcZbgHz|!9^M9B_VuE2oDSY0&!c2r?FrB z9umJtkgJyuSq8x}h;ady2>D7OUxm%MQ~sypaviTRkTnLfrVaOF7k1+v{8}EE?(te- zBo$mz!6g-IaUHU>f~A#{{4kvxhsTZdaU*^F7@mm3+AKfmX5&uWgCimQD8%7MwOEH- z{v$50s__GPEo!eydry>y@I)mV*b@e}F3soFy0H%GupZr5=f;lf#>=D6@aQwA(Lhrhxnv`kY~I>7&!!^m!NX{z&l+j%U4Dum zg#}oMg0og|*6O%c$D68U$Ti4gn|N$9k8S3$&CR$|X1qgY+#=)6k?~GKQ}xq2>;I=0 z9bAgTmaGuAWFr@E;o>a=I4CvFml_u!*Zqv^>N8}-S!ks7Mq0lCH=+koy$4afdiCnn z^JqPfZe_?;hHS0JZOFr0dAK1{27SK{8(7r9qK5UzuMHY#(7^NN_W2bZIe&_#r;hFQ zwc6(Em9fVe``&zCt&4C4u0nzPp1^&t25Zr@y=U6q+lhN{KOVp{cs35BTl|c?HxBn` z?;h<YMrj4SbZ3tXt$qb)_bWiB507#m9+hafKJ>)V z=-VM0eJ75-lOLk*csqXQeLQ8;-iOMV#c@>NZCS8PeTIF*ux}XfjZOPtGe68$K2!M| zoQzY|^Pw}wYky237JEv5W&Xb6fv?`cBPg)$#4P3BJG}T!i3UaZH>TyA8V%3au#VHt z8-XvNv@h_w4u*7a4Sgq!QU4p>|HcQ-n56S+?8QFUP2V@4#L+$NA-X5k6-TBk%Jhkp zITka}?;M%U_!)kV8qU=4y|Y4eukV3-*P<_>dtT6hk=}C%-^J_5Q<)Q#pN#9#r&i`c zbpPIs>N$VFm(v3bdw>U050u2wgFdw$^r>YZKeCS>J*a~R*TvC4?Fi979f+g*u7v15 z22A2W|sN#+3d?l2Xhi3nv)(!g##ffG}r%pDn$Q$ z&KJ-dzJLzL(W4b1dUS2(9}BQ?t!ec2S73xi)(d16mo-j-ALu51v8abPt}x z^Bq}((d7G=S}jYhmZjxbi2`h?09!fRqq?XgIT$VZZ_|Bh%<@UG(kF!(%=7-syV=n{ z7(JbO-vj@Y2frn;+>*$+%b(Ybl9+oTbP9q4CjWr7^}MzDytVoKr}$YMwvF`%N$I!< z7u%J(WLN64U8kg7r)sqL8|zTLM)exs#p7}Kj~7Dtj~#J%(Xx8cvP!+!>7dI61z%Kf z$0VCJxy~z{SK)Cy>AErOFoqYao!8(gJmY$y>&4FNoY&(yJnuTgb};P4Cg;u0b+|)^ zFWz*1+wN1a=@eUcFR}b3mhbe`*y*XUiywFKmEWS=V&$yE-3;5!u-)3-{cXFk`w48s7nED2T)B1Ea>T*A3bJ@Ni+A6~ zI|_2~E-v0>A@AC&oF`C=Cs4}?>{ZT)b{moBM%WW8m!+I_+QLIEJk-KNEj+Y~M|bgP zi;=e&`JQ~`3+!fjBE6FGNP0!buju%dF6>r8fn5shGH1KY*{(0~I`YIWp4iokeRvCp zZG-X5UY>cCA+Ivz)zLTx4dhh=*?ZLeW6m?3-*20YCt7)8uXa*XSsgC^^49YIG^bJvhyp-tygXXilJA<(B2`}uQ_jW-i+<=d2Rn~#gI6j$ID zY(NIIF~Gm799m7uJ|5f0W36@0>zz0HI@u=}_L-}F=BibNRu$S<*v7)PR%~~DkL#^y z4qMIPJ|5f0WBbI$KC!WH5HGmj>3)}b=Df|Ew=%eu!EFZAW+?Jd5Y-uNg>>f&BKGU8@^*pN#aFksd3;`F5RRyG{wLKm$5q3Qp8p{|6O3 zsNf&Jw1sg!4g=+y5`Nk8YmFB{z^8*Os^i0kh< z=YhZTz~8%3xv!3Sou2S|^g2u%@mlmu|Bh$+n9*K?W32x>=JJl$)OSX?F&dk(Mcy3C zo4pRxC!+fgNPiz#>EW;9gJYcgwcXFz(Swtm=f=?lI|~ysz5e>V{!V+{=_pf2nLZpc z?|AKv^V%Da-ct8^OJxs+DEoi{w zif7rBRd@!^;tjkNhpD1ss;J1z^2W->d@MlgBhUKCtHnC(#Xh`%7ll>c*RtiiWX)#x z`)2q13a>f(nWLXVo+#vr!W(!?Sk2|) zxm-M#g>zXr_b?vCTR1HFEtLEg<7V7~J8=*4ND+_BQ-7ZN^SFK<*Uw90HTK|Pw9w{R zXvGsGzZ0Ex98JR-jaY zQm!lIy3#9nRT3N|!7(nt5>$Sf^2^1}aupw_K82iG6rlayv9F)qW)ctt+DRzAB9>#$yWs{B*RZx|~bO~+2` zLbI{KY&^}GPjlweHCT&B@t74^Gg^K+MxL6BdDw;B@>EWFhEtvy#0%0?gW70N8#!m= zY5W*Jk)|$^rY^=~cmfA-PZdJWc#w|eom)k@lGC2dt(BhuID($`s7f~9Cc4F=Spe1q~03~FG|^QQQDQ~d2F<$b9O{#4|=KNa~Hb^Ki& zfA=Qd_SdMfKSE95c+5m2oM?m-88VR}6H9RgiiL?{VPY-T;S0C}+p!Z5;Sub`K0Jr# z@p1^66R$Y9?!rxfje3{AMjeGZ{FlssuliMVGfH)ELkBl>@_Q%0cdo=T)LWZ8+?>i3@k8l($!kuK3?x#^|UP! z{jXazOd|<@NJ%lVa}_&Rjiq$Tpe)KxL_fStSLiAY(KWh3+VOuh=0HPb8YUO?Xpk<@MPkt740@bFk6)!BV$kC^=oSsr zNFrJrD5eCZiOscRDV;JXi?S()CQ&ZsQ9cz=Ar;dCDxp$ZL93{oDyfQ+R82KhOLbIF z+o*|}X(y%j_)jafQzvy%H}%kAI!edr1ocuMou>Xolw?4X0Z9fV8IaU@QsYVOB^i^f zB8DUxl4MA-mKc&`NRlB*Mx>IgNHSvM6}n18bd7G%EgGhgMD%Q+m=csmg;Y!nsDw%r zQEe{eQ9c!rG7SuAsH7TVPy-_xl2o0DwilcK?Hbswf$bXDZWP;Dw|ytAAeFbPyj{iZ zDsBI^l7_ZxWV?}U-$qT;oQN73+c;uGffAHPV=05O+#AN2(i2frCmp7v=D+C}ouFRo zqHgL*L@lnj4AKR1zon1*X^4)}Wx7IF=`>v=ZL|!~CAyJ_b~9r4SjV?$#4!VQPogZ! zrc{pq1WH$67!#D?_!{QY0$M@UR7q8oqyj3Taw?=^Dy3DFNBN29pt=W@Iq3R9Z5&kR zpt1**eUm}m`b~A~@XcW-F=_nG5$sMxZ@Jm6a<_`z8tv9mHv_sg=AYz^x?8E8I;o5H xXm}ePra`)vh~7@4TvGq-ChDOJq`#gFDoFhIs7IqcD)#8KN5!5SiRhQ<{~sSm7{CAk diff --git a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c index cf19332a2..3af6300e4 100755 --- a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c @@ -976,9 +976,9 @@ int setHighVoltage(int val){ /* parameters - timing, extsig */ -void setTiming( enum externalCommunicationMode arg){ +void setTiming( enum timingMode arg){ - if(arg != GET_EXTERNAL_COMMUNICATION_MODE){ + if(arg != GET_TIMING_MODE){ switch((int)arg){ case AUTO_TIMING: FILE_LOG(logINFO, ("Set Timing: Auto\n")); @@ -996,7 +996,7 @@ void setTiming( enum externalCommunicationMode arg){ } -enum externalCommunicationMode getTiming() { +enum timingMode getTiming() { if (bus_r(EXT_SIGNAL_REG) == EXT_SIGNAL_MSK) return TRIGGER_EXPOSURE; return AUTO_TIMING; diff --git a/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c index b55a77983..b86eed9c0 100755 --- a/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c @@ -1061,9 +1061,9 @@ int setHighVoltage(int val){ /* parameters - timing, extsig */ -void setTiming( enum externalCommunicationMode arg){ +void setTiming( enum timingMode arg){ - if(arg != GET_EXTERNAL_COMMUNICATION_MODE){ + if(arg != GET_TIMING_MODE){ switch((int)arg){ case AUTO_TIMING: FILE_LOG(logINFO, ("Set Timing: Auto\n")); @@ -1081,7 +1081,7 @@ void setTiming( enum externalCommunicationMode arg){ } -enum externalCommunicationMode getTiming() { +enum timingMode getTiming() { if (bus_r(EXT_SIGNAL_REG) == EXT_SIGNAL_MSK) return TRIGGER_EXPOSURE; return AUTO_TIMING; diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h b/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h index 7038b6135..381ea21cb 100755 --- a/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h +++ b/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h @@ -212,8 +212,8 @@ int setHighVoltage(int val); // parameters - timing, extsig -void setTiming( enum externalCommunicationMode arg); -enum externalCommunicationMode getTiming(); +void setTiming( enum timingMode arg); +enum timingMode getTiming(); #ifdef GOTTHARDD void setExtSignal(enum externalSignalFlag mode); int getExtSignal(); diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c index 16aacb94e..79e946b11 100755 --- a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c +++ b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c @@ -167,7 +167,7 @@ const char* getFunctionName(enum detFuncs func) { case F_EXEC_COMMAND: return "F_EXEC_COMMAND"; case F_GET_DETECTOR_TYPE: return "F_GET_DETECTOR_TYPE"; case F_SET_EXTERNAL_SIGNAL_FLAG: return "F_SET_EXTERNAL_SIGNAL_FLAG"; - case F_SET_EXTERNAL_COMMUNICATION_MODE: return "F_SET_EXTERNAL_COMMUNICATION_MODE"; + case F_SET_TIMING_MODE: return "F_SET_TIMING_MODE"; case F_GET_ID: return "F_GET_ID"; case F_DIGITAL_TEST: return "F_DIGITAL_TEST"; case F_SET_DAC: return "F_SET_DAC"; @@ -258,7 +258,7 @@ void function_table() { flist[F_EXEC_COMMAND] = &exec_command; flist[F_GET_DETECTOR_TYPE] = &get_detector_type; flist[F_SET_EXTERNAL_SIGNAL_FLAG] = &set_external_signal_flag; - flist[F_SET_EXTERNAL_COMMUNICATION_MODE] = &set_external_communication_mode; + flist[F_SET_TIMING_MODE] = &set_timing_mode; flist[F_GET_ID] = &get_id; flist[F_DIGITAL_TEST] = &digital_test; flist[F_SET_DAC] = &set_dac; @@ -525,18 +525,18 @@ int set_external_signal_flag(int file_des) { -int set_external_communication_mode(int file_des) { +int set_timing_mode(int file_des) { ret = OK; memset(mess, 0, sizeof(mess)); - enum externalCommunicationMode arg = GET_EXTERNAL_COMMUNICATION_MODE; - enum externalCommunicationMode retval = GET_EXTERNAL_COMMUNICATION_MODE; + enum timingMode arg = GET_TIMING_MODE; + enum timingMode retval = GET_TIMING_MODE; if (receiveData(file_des, &arg, sizeof(arg), INT32) < 0) return printSocketReadError(); FILE_LOG(logDEBUG1, ("Setting external communication mode to %d\n", arg)); // set - if ((arg != GET_EXTERNAL_COMMUNICATION_MODE) && (Server_VerifyLock() == OK)) { + if ((arg != GET_TIMING_MODE) && (Server_VerifyLock() == OK)) { switch (arg) { case AUTO_TIMING: case TRIGGER_EXPOSURE: diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.h b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.h index 26c889650..181d1bd21 100755 --- a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.h +++ b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.h @@ -27,7 +27,7 @@ int M_nofuncMode(int); int exec_command(int); int get_detector_type(int); int set_external_signal_flag(int); -int set_external_communication_mode(int); +int set_timing_mode(int); int get_id(int); int digital_test(int); int set_dac(int); diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 0972d85a6..7664b96e8 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -162,15 +162,13 @@ class Detector { void setDAC(int value, defs::dacIndex index, bool mV, Positions pos = {}); - //TODO: rename externalCommunicationMode: timingMode - Result - getTimingMode(Positions pos = {}) const; + Result getTimingMode(Positions pos = {}) const; /** * [Gotthard, Jungfrau, CTB Options: AUTO_TIMING, TRIGGER_EXPOSURE] * [Eiger Options: AUTO_TIMING, TRIGGER_EXPOSURE, GATED, BURST_TRIGGER] */ - void setTimingMode(defs::externalCommunicationMode value, + void setTimingMode(defs::timingMode value, Positions pos = {}); diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 96f99e2a5..9813dbb33 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -763,9 +763,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns current timing mode */ - externalCommunicationMode setExternalCommunicationMode( - externalCommunicationMode pol = GET_EXTERNAL_COMMUNICATION_MODE, - int detPos = -1);// + timingMode setTimingMode(timingMode pol = GET_TIMING_MODE, int detPos = -1);// /** * Set/get external signal flags (to specify triggerinrising edge etc) diff --git a/slsDetectorSoftware/include/slsDetector.h b/slsDetectorSoftware/include/slsDetector.h index 5eec4a878..b0ea6e672 100755 --- a/slsDetectorSoftware/include/slsDetector.h +++ b/slsDetectorSoftware/include/slsDetector.h @@ -618,8 +618,7 @@ class slsDetector : public virtual slsDetectorDefs { * @param pol timing mode (-1 gets) * @returns current timing mode */ - externalCommunicationMode setExternalCommunicationMode( - externalCommunicationMode pol = GET_EXTERNAL_COMMUNICATION_MODE); + timingMode setTimingMode(timingMode pol = GET_TIMING_MODE); /** * Set/get external signal flags (to specify triggerinrising edge etc) diff --git a/slsDetectorSoftware/include/slsDetectorUsers.h b/slsDetectorSoftware/include/slsDetectorUsers.h index 742d574cf..46c5e4915 100755 --- a/slsDetectorSoftware/include/slsDetectorUsers.h +++ b/slsDetectorSoftware/include/slsDetectorUsers.h @@ -385,7 +385,7 @@ public: /** * Set/get timing mode * @param pol timing mode (-1 gets) - * Options (slsDetectorDefs::externalCommunicationMode) + * Options (slsDetectorDefs::timingMode) * (Eiger: AUTO_TIMING, TRIGGER_EXPOSURE, BURST_TRIGGER, GATED) * (Jungfrau: AUTO_TIMING, TRIGGER_EXPOSURE) * (Gotthard: AUTO_TIMING, TRIGGER_EXPOSURE) diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 8727c1658..aa79fd4ed 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -548,15 +548,13 @@ void Detector::setDAC(int value, defs::dacIndex index, bool mV, Positions pos) { pimpl->Parallel(&slsDetector::setDAC, pos, value, index, mV); } -Result -Detector::getTimingMode(Positions pos) const { - return pimpl->Parallel(&slsDetector::setExternalCommunicationMode, pos, - defs::GET_EXTERNAL_COMMUNICATION_MODE); +Result Detector::getTimingMode(Positions pos) const { + return pimpl->Parallel(&slsDetector::setTimingMode, pos, + defs::GET_TIMING_MODE); } -void Detector::setTimingMode(defs::externalCommunicationMode value, - Positions pos) { - pimpl->Parallel(&slsDetector::setExternalCommunicationMode, pos, value); +void Detector::setTimingMode(defs::timingMode value, Positions pos) { + pimpl->Parallel(&slsDetector::setTimingMode, pos, value); } Result diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index 0ecd1243e..cb0106d8f 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -1110,16 +1110,14 @@ int multiSlsDetector::getADC(dacIndex index, int detPos) { return sls::minusOneIfDifferent(r); } -slsDetectorDefs::externalCommunicationMode -multiSlsDetector::setExternalCommunicationMode(externalCommunicationMode pol, - int detPos) { +slsDetectorDefs::timingMode multiSlsDetector::setTimingMode(timingMode pol, int detPos) { // single if (detPos >= 0) { - return detectors[detPos]->setExternalCommunicationMode(pol); + return detectors[detPos]->setTimingMode(pol); } // multi - auto r = parallelCall(&slsDetector::setExternalCommunicationMode, pol); + auto r = parallelCall(&slsDetector::setTimingMode, pol); return sls::minusOneIfDifferent(r); } diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index b694b12e1..0c6cae087 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -1457,11 +1457,10 @@ int slsDetector::getADC(dacIndex index) { return retval; } -slsDetectorDefs::externalCommunicationMode -slsDetector::setExternalCommunicationMode(externalCommunicationMode pol) { - int fnum = F_SET_EXTERNAL_COMMUNICATION_MODE; +slsDetectorDefs::timingMode slsDetector::setTimingMode(timingMode pol) { + int fnum = F_SET_TIMING_MODE; auto arg = static_cast(pol); - externalCommunicationMode retval = GET_EXTERNAL_COMMUNICATION_MODE; + timingMode retval = GET_TIMING_MODE; FILE_LOG(logDEBUG1) << "Setting communication to mode " << pol; sendToDetector(fnum, arg, retval); FILE_LOG(logDEBUG1) << "Timing Mode: " << retval; diff --git a/slsDetectorSoftware/src/slsDetectorCommand.cpp b/slsDetectorSoftware/src/slsDetectorCommand.cpp index 07134b020..615a6cefa 100755 --- a/slsDetectorSoftware/src/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp @@ -4285,11 +4285,11 @@ std::string slsDetectorCommand::cmdTiming(int narg, const char * const args[], i return helpTiming(HELP_ACTION); } if (action == PUT_ACTION) { - if (myDet->externalCommunicationType(std::string(args[1])) == GET_EXTERNAL_COMMUNICATION_MODE) + if (myDet->timingModeType(std::string(args[1])) == GET_TIMING_MODE) return helpTiming(action); - myDet->setExternalCommunicationMode(myDet->externalCommunicationType(std::string(args[1])), detPos); + myDet->setTimingMode(myDet->timingModeType(std::string(args[1])), detPos); } - return myDet->externalCommunicationType(myDet->setExternalCommunicationMode(GET_EXTERNAL_COMMUNICATION_MODE, detPos)); + return myDet->timingModeType(myDet->setTimingMode(GET_TIMING_MODE, detPos)); } std::string slsDetectorCommand::helpTiming(int action) { diff --git a/slsDetectorSoftware/src/slsDetectorUsers.cpp b/slsDetectorSoftware/src/slsDetectorUsers.cpp index ec24f7dd4..bfdd47be9 100755 --- a/slsDetectorSoftware/src/slsDetectorUsers.cpp +++ b/slsDetectorSoftware/src/slsDetectorUsers.cpp @@ -167,7 +167,7 @@ double slsDetectorUsers::getMeasuredSubFramePeriod(bool inseconds, int detPos) { } int slsDetectorUsers::setTimingMode(int pol, int detPos){ - return detector.setExternalCommunicationMode(slsDetectorDefs::externalCommunicationMode(pol), detPos); + return detector.setTimingMode(slsDetectorDefs::timingMode(pol), detPos); } int slsDetectorUsers::setClockDivider(int value, int detPos) { diff --git a/slsSupportLib/include/sls_detector_defs.h b/slsSupportLib/include/sls_detector_defs.h index f9d2f9b00..b6e91876e 100755 --- a/slsSupportLib/include/sls_detector_defs.h +++ b/slsSupportLib/include/sls_detector_defs.h @@ -337,9 +337,8 @@ format /** communication mode using external signals */ - enum externalCommunicationMode { - GET_EXTERNAL_COMMUNICATION_MODE = - -1, /** Date: Fri, 16 Aug 2019 18:49:08 +0200 Subject: [PATCH 082/108] allowed virtual servers --- .../slsDetectorServer/slsDetectorServer.c | 17 ++++++++--- slsDetectorSoftware/src/multiSlsDetector.cpp | 30 +++++++++++++------ slsDetectorSoftware/src/slsDetector.cpp | 30 +++++++++++-------- slsSupportLib/include/versionAPI.h | 2 +- 4 files changed, 52 insertions(+), 27 deletions(-) diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorServer.c b/slsDetectorServers/slsDetectorServer/slsDetectorServer.c index 669009059..46ede3893 100755 --- a/slsDetectorServers/slsDetectorServer/slsDetectorServer.c +++ b/slsDetectorServers/slsDetectorServer/slsDetectorServer.c @@ -47,7 +47,7 @@ int main(int argc, char *argv[]){ FILE_LOG(logINFO, ("SLS Detector Server %s (0x%x)\n", GITBRANCH, version)); } - int portno = DEFAULT_PORTNO; + int portno = DEFAULT_PORTNO; int retval = OK; int fd = 0; @@ -67,6 +67,17 @@ int main(int argc, char *argv[]){ FILE_LOG(logINFO, ("Detected developer mode\n")); debugflag = 1; } + else if(!strcasecmp(argv[i],"--port")){ + if ((i + 1) >= argc) { + FILE_LOG(logERROR, ("no port value given. Exiting.\n")); + return -1; + } + if (sscanf(argv[i + 1], "%d", &portno) == 0) { + FILE_LOG(logERROR, ("cannot decode port value %s. Exiting.\n", argv[i + 1])); + return -1; + } + FILE_LOG(logINFO, ("Detected port: %d\n", portno)); + } #ifdef GOTTHARDD else if(!strcasecmp(argv[i],"-phaseshift")){ if ((i + 1) >= argc) { @@ -88,20 +99,18 @@ int main(int argc, char *argv[]){ memset(cmd, 0, 100); #endif if (isControlServer) { - portno = DEFAULT_PORTNO; FILE_LOG(logINFO, ("Opening control server on port %d \n", portno)); #ifdef STOP_SERVER { int i; for (i = 0; i < argc; ++i) sprintf(cmd, "%s %s", cmd, argv[i]); - sprintf(cmd,"%s -stopserver&", cmd); + sprintf(cmd,"%s -stopserver --port %d &", cmd, portno + 1); FILE_LOG(logDEBUG1, ("Command to start stop server:%s\n", cmd)); system(cmd); } #endif } else { - portno = DEFAULT_PORTNO + 1; FILE_LOG(logINFO,("Opening stop server on port %d \n", portno)); } diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index cb0106d8f..2564dd221 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -404,25 +404,37 @@ void multiSlsDetector::addMultipleDetectors(const char *name) { void multiSlsDetector::addSlsDetector(const std::string &hostname) { FILE_LOG(logDEBUG1) << "Adding detector " << hostname; + + int port = DEFAULT_PORTNO; + std::string host = hostname; + auto res = sls::split(hostname, ':'); + if (res.size() > 1) { + host = res[0]; + port = std::stoi(res[1]); + } - for (auto &d : detectors) { - if (d->getHostname() == hostname) { - FILE_LOG(logWARNING) - << "Detector " << hostname - << "already part of the multiDetector!" << std::endl - << "Remove it before adding it back in a new position!"; - return; + if (host != "localhost") { + for (auto &d : detectors) { + if (d->getHostname() == host) { + FILE_LOG(logWARNING) + << "Detector " << host + << "already part of the multiDetector!" << std::endl + << "Remove it before adding it back in a new position!"; + return; + } } } // get type by connecting detectorType type = - slsDetector::getTypeFromDetector(hostname, DEFAULT_PORTNO); + slsDetector::getTypeFromDetector(host, port); int pos = (int)detectors.size(); detectors.push_back( sls::make_unique(type, multiId, pos, false)); multi_shm()->numberOfDetectors = detectors.size(); - detectors[pos]->setHostname(hostname); + detectors[pos]->setControlPort(port); + detectors[pos]->setStopPort(port + 1); + detectors[pos]->setHostname(host); multi_shm()->multiDetectorType = getDetectorTypeAsEnum(-1);// -1 needed here } diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index 0c6cae087..226f31fc4 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -23,13 +23,11 @@ using namespace sls; -#define DEFAULT_HOSTNAME "localhost" +// create shm slsDetector::slsDetector(detectorType type, int multi_id, int det_id, bool verify) : detId(det_id), shm(multi_id, det_id) { - /* called from put hostname command, - * so sls shared memory will be created */ // ensure shared memory was not created before if (shm.IsExisting()) { @@ -42,10 +40,9 @@ slsDetector::slsDetector(detectorType type, int multi_id, int det_id, initSharedMemory(type, multi_id, verify); } +// pick up from shm slsDetector::slsDetector(int multi_id, int det_id, bool verify) : detId(det_id), shm(multi_id, det_id) { - /* called from multi constructor to populate structure, - * so sls shared memory will be opened, not created */ // getDetectorType From shm will check if it was already existing detectorType type = getDetectorTypeFromShm(multi_id, verify); @@ -305,8 +302,7 @@ void slsDetector::initSharedMemory(detectorType type, int multi_id, void slsDetector::initializeDetectorStructure(detectorType type) { shm()->shmversion = SLS_SHMVERSION; - shm()->controlPort = DEFAULT_PORTNO; - sls::strcpy_safe(shm()->hostname, DEFAULT_HOSTNAME); + memset(shm()->hostname, 0, MAX_STR_LENGTH); shm()->myDetectorType = type; shm()->multiSize.x = 0; shm()->multiSize.y = 0; @@ -644,9 +640,13 @@ int slsDetector::setControlPort(int port_number) { int retval = -1; FILE_LOG(logDEBUG1) << "Setting control port to " << port_number; if (port_number >= 0 && port_number != shm()->controlPort) { - sendToDetector(F_SET_PORT, port_number, retval); - shm()->controlPort = retval; - FILE_LOG(logDEBUG1) << "Control port: " << retval; + if (strlen(shm()->hostname) > 0) { + sendToDetector(F_SET_PORT, port_number, retval); + shm()->controlPort = retval; + FILE_LOG(logDEBUG1) << "Control port: " << retval; + } else { + shm()->controlPort = port_number; + } } return shm()->controlPort; } @@ -655,9 +655,13 @@ int slsDetector::setStopPort(int port_number) { int retval = -1; FILE_LOG(logDEBUG1) << "Setting stop port to " << port_number; if (port_number >= 0 && port_number != shm()->stopPort) { - sendToDetectorStop(F_SET_PORT, port_number, retval); - shm()->stopPort = retval; - FILE_LOG(logDEBUG1) << "Stop port: " << retval; + if (strlen(shm()->hostname) > 0) { + sendToDetectorStop(F_SET_PORT, port_number, retval); + shm()->stopPort = retval; + FILE_LOG(logDEBUG1) << "Stop port: " << retval; + } else { + shm()->stopPort = port_number; + } } return shm()->stopPort; } diff --git a/slsSupportLib/include/versionAPI.h b/slsSupportLib/include/versionAPI.h index 42e28a900..6da66f7d4 100644 --- a/slsSupportLib/include/versionAPI.h +++ b/slsSupportLib/include/versionAPI.h @@ -4,7 +4,7 @@ #define APILIB 0x190723 #define APIRECEIVER 0x190722 #define APIGUI 0x190723 -#define APIEIGER 0x190816 #define APIGOTTHARD 0x190816 #define APIJUNGFRAU 0x190816 #define APIMOENCH 0x190816 +#define APIEIGER 0x190816 From d10d9462a3bb2b350c6f77751b06c6352e6f54a5 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Fri, 16 Aug 2019 19:31:26 +0200 Subject: [PATCH 083/108] virtual servers using command virtual numdet port --- .../bin/eigerDetectorServer_developer | Bin 302632 -> 302616 bytes .../include/multiSlsDetector.h | 7 ++++ slsDetectorSoftware/src/multiSlsDetector.cpp | 12 ++++++- .../src/slsDetectorCommand.cpp | 30 +++++++++++++++--- 4 files changed, 44 insertions(+), 5 deletions(-) diff --git a/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer b/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer index 4e842b523fce5549bb1d6c2b5c76409461dc0537..b7aa410527d9c9507ac91466b86eb9e60427c18b 100755 GIT binary patch delta 38633 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�NPM3 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 COxr#H delta 37627 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 hostnames; + for (int i = 0; i < numdet; ++i) { + // * 2 is for control and stop port + hostnames.push_back(std::string("localhost:") + std::to_string(port + i * 2)); + } + setHostname(hostnames); +} + void multiSlsDetector::setHostname(const std::vector &name) { // this check is there only to allow the previous detsizechan command if (multi_shm()->numberOfDetectors != 0) { @@ -363,6 +372,7 @@ void multiSlsDetector::setHostname(const std::vector &name) { for (const auto &hostname : name) { addSlsDetector(hostname); } + updateDetectorSize(); } void multiSlsDetector::setHostname(const char *name, int detPos) { @@ -392,7 +402,7 @@ std::string multiSlsDetector::getHostname(int detPos) const { // multi auto r = serialCall(&slsDetector::getHostname); - return sls::concatenateIfDifferent(r); + return sls::concatenateNonEmptyStrings(r); } void multiSlsDetector::addMultipleDetectors(const char *name) { diff --git a/slsDetectorSoftware/src/slsDetectorCommand.cpp b/slsDetectorSoftware/src/slsDetectorCommand.cpp index 615a6cefa..cc3ac0423 100755 --- a/slsDetectorSoftware/src/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp @@ -268,6 +268,14 @@ slsDetectorCommand::slsDetectorCommand(multiSlsDetector *det) { descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdHostname; ++i; + /*! \page config + - virtual [n] [p] \c connects to n virtual detector servers at local host starting at port p \c Returns the list of the hostnames of the multi-detector structure. \c (string) + */ + descrToFuncMap[i].m_pFuncName = "virtual"; + descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdHostname; + ++i; + + /*! \page config - user \c Returns user details from shared memory. Only allowed at multi detector level. Cannot put. \c (string) */ @@ -2345,7 +2353,7 @@ std::string slsDetectorCommand::cmdHostname(int narg, const char * const args[], if (action == PUT_ACTION) { if (detPos >= 0) { - return std::string("Wrong usage - setting hostname/add only from " + return std::string("Wrong usage - setting hostname/virtual only from " "multiDetector level"); } @@ -2357,10 +2365,23 @@ std::string slsDetectorCommand::cmdHostname(int narg, const char * const args[], if (narg > 2) strcat(hostname, "+"); } - - myDet->setHostname(hostname, detPos); + if (cmd == "hostname") { + myDet->setHostname(hostname, detPos); + } + else if (cmd == "virtual") { + int port = -1; + int numDetectors = 0; + if (!sscanf(args[1], "%d", &numDetectors)) { + throw sls::RuntimeError("Cannot scan number of detector servers from virtual command\n"); + } + if (!sscanf(args[2], "%d", &port)) { + throw sls::RuntimeError("Cannot scan port from virtual command\n"); + } + myDet->setVirtualDetectorServers(numDetectors, port); + } else { + throw sls::RuntimeError("unknown command\n"); + } } - return myDet->getHostname(detPos); } @@ -2372,6 +2393,7 @@ std::string slsDetectorCommand::helpHostname(int action) { if (action == PUT_ACTION || action == HELP_ACTION) { os << std::string("hostname name [name name]\t frees shared memory and " "sets the hostname (or IP adress). Only allowed at multi detector level.\n"); + os << std::string("virtual [n] [p]\t connects to n virtual detector servers at local host starting at port p \n"); } return os.str(); } From 7457c56533148297019a449864412d156fdeae9b Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Mon, 19 Aug 2019 09:08:10 +0200 Subject: [PATCH 084/108] slsmultireceiver copied to slsreceiver/src cmake --- CMakeLists.txt | 3 +- slsReceiverSoftware/CMakeLists.txt | 20 +- slsReceiverSoftware/src/multiReceiver.cpp | 306 ++++++++++++++++++++++ 3 files changed, 326 insertions(+), 3 deletions(-) create mode 100755 slsReceiverSoftware/src/multiReceiver.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a1a568e98..71f95561a 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -153,8 +153,7 @@ if (SLS_USE_RECEIVER) if (SLS_USE_HDF5) find_package(HDF5 1.10 COMPONENTS CXX REQUIRED) endif (SLS_USE_HDF5) - add_subdirectory(slsReceiverSoftware) - add_subdirectory(manual/manual-api) + add_subdirectory(slsReceiverSoftware) endif (SLS_USE_RECEIVER) if (SLS_USE_GUI) diff --git a/slsReceiverSoftware/CMakeLists.txt b/slsReceiverSoftware/CMakeLists.txt index a27633663..80f38d4b8 100755 --- a/slsReceiverSoftware/CMakeLists.txt +++ b/slsReceiverSoftware/CMakeLists.txt @@ -88,11 +88,29 @@ target_link_libraries(slsReceiver PUBLIC rt ) +add_executable(slsMultiReceiver + src/multiReceiver.cpp) + + +set_target_properties(slsMultiReceiver PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin +) + +target_link_libraries(slsMultiReceiver PUBLIC + slsProjectOptions + slsProjectWarnings + slsSupportLib + slsReceiverShared + pthread + ${ZeroMQ_LIBRARIES} + rt +) + if (SLS_USE_TESTS) add_subdirectory(tests) endif(SLS_USE_TESTS) -install(TARGETS slsReceiverShared slsReceiver +install(TARGETS slsReceiverShared slsReceiver slsMultiReceiver EXPORT "${TARGETS_EXPORT_NAME}" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} diff --git a/slsReceiverSoftware/src/multiReceiver.cpp b/slsReceiverSoftware/src/multiReceiver.cpp new file mode 100755 index 000000000..7762079e5 --- /dev/null +++ b/slsReceiverSoftware/src/multiReceiver.cpp @@ -0,0 +1,306 @@ +/** + \file mainReceiver.cpp + +This file is an example of how to implement the slsReceiverUsers class +You can compile it linking it to the slsReceiver library + +g++ mainReceiver.cpp -L lib -lSlsReceiver -L/usr/lib64/ -L lib2 -lzmq -pthread -lrt -lm -lstdc++ + +where, + +lib is the location of lSlsReceiver.so + +lib2 is the location of the libzmq.a. +[ libzmq.a is required only when using data call backs and enabling data streaming from receiver to client. +It is linked in manual/manual-api from slsReceiverSoftware/include ] + + */ + +#include "sls_detector_defs.h" +#include "slsReceiverUsers.h" + +#include //SIGINT +#include //system +#include +#include +//#include "utilities.h" +//#include "logger.h" +#include +#include +#include //wait +#include //wait +#include //tid +#include //usleep +using namespace std; + + +/** Define Colors to print data call back in different colors for different recievers */ +#define PRINT_IN_COLOR(c,f, ...) printf ("\033[%dm" f RESET, 30 + c+1, ##__VA_ARGS__) + + +/** Variable is true to continue running, set to false upon interrupt */ +bool keeprunning; + +/** + * Control+C Interrupt Handler + * Sets the variable keeprunning to false, to let all the processes know to exit properly + */ +void sigInterruptHandler(int p){ + keeprunning = false; +} + +/** + * prints usage of this example program + */ +void printHelp() { + cprintf(RESET, "Usage:\n" + "./slsMultiReceiver(detReceiver) [start_tcp_port] [num_receivers] [1 for call back, 0 for none]\n\n"); + exit(EXIT_FAILURE); +} + +/** + * Start Acquisition Call back + * slsReceiver writes data if file write enabled. + * Users get data to write using call back if registerCallBackRawDataReady is registered. + * @param filepath file path + * @param filename file name + * @param fileindex file index + * @param datasize data size in bytes + * @param p pointer to object + * \returns ignored + */ +int StartAcq(char* filepath, char* filename, uint64_t fileindex, uint32_t datasize, void*p){ + cprintf(BLUE, "#### StartAcq: filepath:%s filename:%s fileindex:%llu datasize:%u ####\n", + filepath, filename, (long long unsigned int)fileindex, datasize); + + cprintf(BLUE, "--StartAcq: returning 0\n"); + return 0; +} + +/** + * Acquisition Finished Call back + * @param frames Number of frames caught + * @param p pointer to object + */ +void AcquisitionFinished(uint64_t frames, void*p){ + cprintf(BLUE, "#### AcquisitionFinished: frames:%llu ####\n",(long long unsigned int)frames); +} + + +/** + * Get Receiver Data Call back + * Prints in different colors(for each receiver process) the different headers for each image call back. + * @param metadata sls_receiver_header metadata + * @param datapointer pointer to data + * @param datasize data size in bytes. + * @param p pointer to object + */ +void GetData(char* metadata, char* datapointer, uint32_t datasize, void* p){ + slsDetectorDefs::sls_receiver_header* header = (slsDetectorDefs::sls_receiver_header*)metadata; + slsDetectorDefs::sls_detector_header detectorHeader = header->detHeader; + + PRINT_IN_COLOR (detectorHeader.modId?detectorHeader.modId:detectorHeader.row, + "#### %d GetData: ####\n" + "frameNumber: %lu\t\texpLength: %u\t\tpacketNumber: %u\t\tbunchId: %lu" + "\t\ttimestamp: %lu\t\tmodId: %u\t\t" + "row: %u\t\tcolumn: %u\t\treserved: %u\t\tdebug: %u" + "\t\troundRNumber: %u\t\tdetType: %u\t\tversion: %u" + //"\t\tpacketsMask:%s" + "\t\tfirstbytedata: 0x%x\t\tdatsize: %u\n\n", + detectorHeader.row, (long unsigned int)detectorHeader.frameNumber, + detectorHeader.expLength, detectorHeader.packetNumber, (long unsigned int)detectorHeader.bunchId, + (long unsigned int)detectorHeader.timestamp, detectorHeader.modId, + detectorHeader.row, detectorHeader.column, detectorHeader.reserved, + detectorHeader.debug, detectorHeader.roundRNumber, + detectorHeader.detType, detectorHeader.version, + //header->packetsMask.to_string().c_str(), + ((uint8_t)(*((uint8_t*)(datapointer)))), datasize); +} + + + +/** + * Get Receiver Data Call back (modified) + * Prints in different colors(for each receiver process) the different headers for each image call back. + * @param metadata sls_receiver_header metadata + * @param datapointer pointer to data + * @param datasize data size in bytes. + * @param revDatasize new data size in bytes after the callback. + * This will be the size written/streamed. (only smaller value is allowed). + * @param p pointer to object + */ +void GetData(char* metadata, char* datapointer, uint32_t &revDatasize, void* p){ + slsDetectorDefs::sls_receiver_header* header = (slsDetectorDefs::sls_receiver_header*)metadata; + slsDetectorDefs::sls_detector_header detectorHeader = header->detHeader; + + PRINT_IN_COLOR (detectorHeader.modId?detectorHeader.modId:detectorHeader.row, + "#### %d GetData: ####\n" + "frameNumber: %llu\t\texpLength: %u\t\tpacketNumber: %u\t\tbunchId: %llu" + "\t\ttimestamp: %llu\t\tmodId: %u\t\t" + "row: %u\t\tcolumn: %u\t\treserved: %u\t\tdebug: %u" + "\t\troundRNumber: %u\t\tdetType: %u\t\tversion: %u" + //"\t\tpacketsMask:%s" + "\t\tfirstbytedata: 0x%x\t\tdatsize: %u\n\n", + detectorHeader.row, (long long unsigned int)detectorHeader.frameNumber, + detectorHeader.expLength, detectorHeader.packetNumber, (long long unsigned int)detectorHeader.bunchId, + (long long unsigned int)detectorHeader.timestamp, detectorHeader.modId, + detectorHeader.row, detectorHeader.column, detectorHeader.reserved, + detectorHeader.debug, detectorHeader.roundRNumber, + detectorHeader.detType, detectorHeader.version, + //header->packetsMask.to_string().c_str(), + ((uint8_t)(*((uint8_t*)(datapointer)))), revDatasize); + + // if data is modified, eg ROI and size is reduced + revDatasize = 26000; +} + + + + +/** + * Example of main program using the slsReceiverUsers class + * + * - Defines in file for: + * - Default Number of receivers is 1 + * - Default Start TCP port is 1954 + */ +int main(int argc, char *argv[]) { + + /** - set default values */ + int numReceivers = 1; + int startTCPPort = 1954; + int withCallback = 0; + keeprunning = true; + + /** - get number of receivers and start tcp port from command line arguments */ + if ( (argc != 4) || (!sscanf(argv[1],"%d", &startTCPPort)) || (!sscanf(argv[2],"%d", &numReceivers)) || (!sscanf(argv[3],"%d", &withCallback)) ) + printHelp(); + cprintf(BLUE,"Parent Process Created [ Tid: %ld ]\n", (long)syscall(SYS_gettid)); + cprintf(RESET, "Number of Receivers: %d\n", numReceivers); + cprintf(RESET, "Start TCP Port: %d\n", startTCPPort); + cprintf(RESET, "Callback Enable: %d\n", withCallback); + + + + /** - Catch signal SIGINT to close files and call destructors properly */ + struct sigaction sa; + sa.sa_flags=0; // no flags + sa.sa_handler=sigInterruptHandler; // handler function + sigemptyset(&sa.sa_mask); // dont block additional signals during invocation of handler + if (sigaction(SIGINT, &sa, nullptr) == -1) { + cprintf(RED, "Could not set handler function for SIGINT\n"); + } + + /** - Ignore SIG_PIPE, prevents global signal handler, handle locally, + instead of a server crashing due to client crash when writing, it just gives error */ + struct sigaction asa; + asa.sa_flags=0; // no flags + asa.sa_handler=SIG_IGN; // handler function + sigemptyset(&asa.sa_mask); // dont block additional signals during invocation of handler + if (sigaction(SIGPIPE, &asa, nullptr) == -1) { + cprintf(RED, "Could not set handler function for SIGPIPE\n"); + } + + + /** - loop over number of receivers */ + for (int i = 0; i < numReceivers; ++i) { + + /** - fork process to create child process */ + pid_t pid = fork(); + + /** - if fork failed, raise SIGINT and properly destroy all child processes */ + if (pid < 0) { + cprintf(RED,"fork() failed. Killing all the receiver objects\n"); + raise(SIGINT); + } + + /** - if child process */ + else if (pid == 0) { + cprintf(BLUE,"Child process %d [ Tid: %ld ]\n", i, (long)syscall(SYS_gettid)); + + char temp[10]; + sprintf(temp,"%d",startTCPPort + i); + char* args[] = {(char*)"ignored", (char*)"--rx_tcpport", temp}; + int ret = slsDetectorDefs::OK; + /** - create slsReceiverUsers object with appropriate arguments */ + slsReceiverUsers *receiver = new slsReceiverUsers(3, args, ret); + if(ret==slsDetectorDefs::FAIL){ + delete receiver; + exit(EXIT_FAILURE); + } + + + /** - register callbacks. remember to set file write enable to 0 (using the client) + if we should not write files and you will write data using the callbacks */ + if (withCallback) { + + /** - Call back for start acquisition */ + cprintf(BLUE, "Registering StartAcq()\n"); + receiver->registerCallBackStartAcquisition(StartAcq, nullptr); + + /** - Call back for acquisition finished */ + cprintf(BLUE, "Registering AcquisitionFinished()\n"); + receiver->registerCallBackAcquisitionFinished(AcquisitionFinished, nullptr); + + /* - Call back for raw data */ + cprintf(BLUE, "Registering GetData() \n"); + if (withCallback == 1) receiver->registerCallBackRawDataReady(GetData,nullptr); + else if (withCallback == 2) receiver->registerCallBackRawDataModifyReady(GetData,nullptr); + } + + + + /** - start tcp server thread */ + if (receiver->start() == slsDetectorDefs::FAIL){ + delete receiver; + cprintf(BLUE,"Exiting Child Process [ Tid: %ld ]\n", (long)syscall(SYS_gettid)); + exit(EXIT_FAILURE); + } + + /** - as long as keeprunning is true (changes with Ctrl+C) */ + while(keeprunning) + pause(); + /** - interrupt caught, delete slsReceiverUsers object and exit */ + delete receiver; + cprintf(BLUE,"Exiting Child Process [ Tid: %ld ]\n", (long)syscall(SYS_gettid)); + exit(EXIT_SUCCESS); + break; + } + } + + /** - Parent process ignores SIGINT (exits only when all child process exits) */ + sa.sa_flags=0; // no flags + sa.sa_handler=SIG_IGN; // handler function + sigemptyset(&sa.sa_mask); // dont block additional signals during invocation of handler + if (sigaction(SIGINT, &sa, nullptr) == -1) { + cprintf(RED, "Could not set handler function for SIGINT\n"); + } + + + /** - Print Ready and Instructions how to exit */ + cout << "Ready ... " << endl; + cprintf(RESET, "\n[ Press \'Ctrl+c\' to exit ]\n"); + + /** - Parent process waits for all child processes to exit */ + for(;;) { + pid_t childPid = waitpid (-1, nullptr, 0); + + // no child closed + if (childPid == -1) { + if (errno == ECHILD) { + cprintf(GREEN,"All Child Processes have been closed\n"); + break; + } else { + cprintf(RED, "Unexpected error from waitpid(): (%s)\n",strerror(errno)); + break; + } + } + + //child closed + cprintf(BLUE,"Exiting Child Process [ Tid: %ld ]\n", (long int) childPid); + } + + cout << "Goodbye!" << endl; + return 0; +} + From 26958e99ef6a6e86bed11adc9701e5a034d77e9a Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Mon, 19 Aug 2019 10:48:05 +0200 Subject: [PATCH 085/108] WIP --- .../include/multiSlsDetector.h | 20 +++++-------------- .../include/slsDetectorUsers.h | 9 --------- slsDetectorSoftware/src/Detector.cpp | 10 ++-------- slsDetectorSoftware/src/multiSlsDetector.cpp | 18 +++++++---------- .../src/slsDetectorCommand.cpp | 4 ++-- slsDetectorSoftware/src/slsDetectorUsers.cpp | 7 ------- 6 files changed, 16 insertions(+), 52 deletions(-) diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index a66abfa57..248638f2e 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -56,11 +56,8 @@ struct sharedMultiSlsDetector { /** Number of detectors operated at once */ slsDetectorDefs::xy numberOfDetector; - /** total number of channels for all detectors */ - slsDetectorDefs::xy numberOfChannels; - - /** max number of channels for complete detector*/ - slsDetectorDefs::xy maxNumberOfChannels; + /** max number of channels for complete detector*/ + slsDetectorDefs::xy numberOfChannels; /** flag for acquiring */ bool acquiringFlag; @@ -374,25 +371,18 @@ class multiSlsDetector : public virtual slsDetectorDefs { /** * Returns the total number of channels of all sls detectors including gap pixels - * @param d dimension d * @param detPos -1 for all detectors in list or specific detector position * @returns the total number of channels of all sls detectors including gap pixels */ - slsDetectorDefs::xy getNumberOfChannels(int detPos = -1);// - - /** - * Returns maximum number of channels of all sls detectors in each - * dimension d from shared memory - * @returns maximum number of channels of all sls detectors - */ - slsDetectorDefs::xy getMaxNumberOfChannels() const; // + slsDetectorDefs::xy getNumberOfChannels(int detPos = -1) const;// /** + * Must be set before setting hostname * Sets maximum number of channels of all sls detectors in each * dimension d from shared memory * @param c maximum number of channels of all sls detectors */ - void setMaxNumberOfChannels(const slsDetectorDefs::xy c); // + void setNumberOfChannels(const slsDetectorDefs::xy c); // /** * Get Quad Type (Only for Eiger Quad detector hardware) diff --git a/slsDetectorSoftware/include/slsDetectorUsers.h b/slsDetectorSoftware/include/slsDetectorUsers.h index 46c5e4915..eacf25992 100755 --- a/slsDetectorSoftware/include/slsDetectorUsers.h +++ b/slsDetectorSoftware/include/slsDetectorUsers.h @@ -101,15 +101,6 @@ public: */ int size() const; - /** - * Returns the maximum number of channels of all detectors - * (provided by user in config file using detsizechan command) - * number of channels in x and y are calculated according to these dimensions - * @param nx number of channels in horizontal - * @param ny number of channels in vertical - * @returns the maximum number of channels of all detectors - */ - int getMaximumDetectorSize(int &nx, int &ny); /** * Returns the size of detector/multi detector diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index aa79fd4ed..8f5bcbc0b 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -66,21 +66,15 @@ defs::xy Detector::getModuleGeometry() const { } Result Detector::getModuleSize(Positions pos) const { - if (pos.empty() || - (pos.size() == 1 && - pos[0] == -1)) { // TODO: also check condition that pos.size == - // pimpl->size()?? for other occurences as well - return {pimpl->getNumberOfChannels()}; - } return pimpl->Parallel(&slsDetector::getNumberOfChannels, pos); } defs::xy Detector::getDetectorSize() const { - return pimpl->getMaxNumberOfChannels(); + return pimpl->getNumberOfChannels(); } void Detector::setDetectorSize(const defs::xy value) { - pimpl->setMaxNumberOfChannels(value); + pimpl->setNumberOfChannels(value); } Result Detector::getQuad(Positions pos) const { diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index 0f3c801fa..e2f76a495 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -280,8 +280,6 @@ void multiSlsDetector::initializeDetectorStructure() { multi_shm()->numberOfDetector.y = 0; multi_shm()->numberOfChannels.x = 0; multi_shm()->numberOfChannels.y = 0; - multi_shm()->maxNumberOfChannels.x = 0; - multi_shm()->maxNumberOfChannels.y = 0; multi_shm()->acquiringFlag = false; multi_shm()->receiver_upstream = false; } @@ -453,7 +451,7 @@ void multiSlsDetector::updateDetectorSize() { const slsDetectorDefs::xy det_size = detectors[0]->getNumberOfChannels(); - int maxy = multi_shm()->maxNumberOfChannels.y; + int maxy = multi_shm()->numberOfChannels.y; if (maxy == 0) { maxy = det_size.y * size(); } @@ -483,7 +481,6 @@ void multiSlsDetector::updateDetectorSize() { for (auto &d : detectors) { d->updateMultiSize(multi_shm()->numberOfDetector); } - multi_shm()->maxNumberOfChannels = multi_shm()->numberOfChannels; } slsDetectorDefs::detectorType multiSlsDetector::getDetectorTypeAsEnum() const { @@ -519,7 +516,7 @@ slsDetectorDefs::xy multiSlsDetector::getNumberOfDetectors() const { return multi_shm()->numberOfDetector; } -slsDetectorDefs::xy multiSlsDetector::getNumberOfChannels(int detPos) { +slsDetectorDefs::xy multiSlsDetector::getNumberOfChannels(int detPos) const { // single if (detPos >= 0) { return detectors[detPos]->getNumberOfChannels(); @@ -529,12 +526,11 @@ slsDetectorDefs::xy multiSlsDetector::getNumberOfChannels(int detPos) { return multi_shm()->numberOfChannels; } -slsDetectorDefs::xy multiSlsDetector::getMaxNumberOfChannels() const { - return multi_shm()->maxNumberOfChannels; -} - -void multiSlsDetector::setMaxNumberOfChannels(const slsDetectorDefs::xy c) { - multi_shm()->maxNumberOfChannels = c; +void multiSlsDetector::setNumberOfChannels(const slsDetectorDefs::xy c) { + if (size() > 1) { + throw RuntimeError("Set the number of channels before setting hostname."); + } + multi_shm()->numberOfChannels = c; } int multiSlsDetector::getQuad(int detPos) { diff --git a/slsDetectorSoftware/src/slsDetectorCommand.cpp b/slsDetectorSoftware/src/slsDetectorCommand.cpp index cc3ac0423..7d56ba929 100755 --- a/slsDetectorSoftware/src/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp @@ -3306,7 +3306,7 @@ std::string slsDetectorCommand::cmdDetectorSize(int narg, const char * const arg slsDetectorDefs::xy res; res.x = val; res.y = val2; - myDet->setMaxNumberOfChannels(res); + myDet->setNumberOfChannels(res); } if(cmd=="quad"){ @@ -3342,7 +3342,7 @@ std::string slsDetectorCommand::cmdDetectorSize(int narg, const char * const arg ROI roi = myDet->getROI(detPos); return (std::string("[") + std::to_string(roi.xmin) + std::string(",") + std::to_string(roi.xmax) + std::string("]")); } else if (cmd == "detsizechan") { - slsDetectorDefs::xy res = myDet->getMaxNumberOfChannels(); + slsDetectorDefs::xy res = myDet->getNumberOfChannels(); sprintf(ans, "%d %d", res.x, res.y); return std::string(ans); } else if (cmd=="quad") { diff --git a/slsDetectorSoftware/src/slsDetectorUsers.cpp b/slsDetectorSoftware/src/slsDetectorUsers.cpp index bfdd47be9..7dd0069a8 100755 --- a/slsDetectorSoftware/src/slsDetectorUsers.cpp +++ b/slsDetectorSoftware/src/slsDetectorUsers.cpp @@ -8,13 +8,6 @@ int slsDetectorUsers::size() const { return detector.size(); } -int slsDetectorUsers::getMaximumDetectorSize(int &nx, int &ny){ - slsDetectorDefs::xy res = detector.getMaxNumberOfChannels(); - nx=res.x; - ny=res.y; - return nx*ny; -} - int slsDetectorUsers::getDetectorSize(int &nx, int &ny, int detPos){ slsDetectorDefs::xy res = detector.getNumberOfChannels(); nx=res.x; From eebd1552f2b9a744ff95766b91080fe254adfadc Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Mon, 19 Aug 2019 15:55:42 +0200 Subject: [PATCH 086/108] WIP --- slsDetectorSoftware/include/Detector.h | 440 +++++++++++++------------ slsDetectorSoftware/src/Detector.cpp | 80 ++--- 2 files changed, 271 insertions(+), 249 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 7664b96e8..c0fe335f7 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -156,7 +156,7 @@ class Detector { * TEMPERATURE_FPGA3 * [CTB] Options: SLOW_ADC_TEMP */ - Result getTemp(defs::dacIndex index, Positions pos = {}) const; + Result getTemperature(defs::dacIndex index, Positions pos = {}) const; Result getDAC(defs::dacIndex index, bool mV, Positions pos = {}) const; @@ -215,6 +215,9 @@ class Detector { /** [Eiger][Jungfrau] */ void setStartingFrameNumber(uint64_t value, Positions pos); + /** [Eiger] Sends an internal software trigger to the detector */ + void sendSoftwareTrigger(Positions pos = {}); + //TODO: remove resetframescaught in receiver @@ -224,7 +227,10 @@ class Detector { * * * ************************************************/ - /** Configures the destination for UDP packets in the detector */ + /** Configures the destination for UDP packets in the detector + * Needed only if you use a custm receiver (not slsReceiver) + * as it is already included in setReceiverHostname. + */ void configureMAC(Positions pos = {});//TODO: find a reasonable name Result getSourceUDPMAC(Positions pos = {}) const; @@ -253,81 +259,47 @@ class Detector { /** MAC of the interface in receiver that the detector sends data to * Only needed if you use a custom receiver (not slsReceiver) + * Must be followed by configuremac. */ void setDestinationUDPMAC(const std::string &udpmac, Positions pos = {}); + Result getDestinationUDPPort(Positions pos = {}) const; - Result getReceiverUDPPort(Positions pos = {}) const; - - void setReceiverUDPPort(int udpport, Positions pos = {}); + /** + * module_id is -1 for all detectors, ports for each module is calculated (increments) + */ + void setDestinationUDPPort(int udpport, int module_id = -1); /** [Eiger right port][Jungfrau bottom half] */ - Result getReceiverUDPPort2(Positions pos = {}) const; + Result getDestinationUDPPort2(Positions pos = {}) const; - /** [Eiger right port][Jungfrau bottom half] */ - void setReceiverUDPPort2(int udpport, Positions pos = {}); + /** [Eiger right port][Jungfrau bottom half] + * module_id is -1 for all detectors, ports for each module is calculated (increments) + */ + void setDestinationUDPPort2(int udpport, int module_id = -1); - Result printReceiverConfiguration(Positions pos = {}) const; + Result printRxConfiguration(Positions pos = {}) const; /** [Eiger, Jungfrau] */ - Result getFlowControl10G(Positions pos = {}) const; + Result getTenGigaGFlowControl(Positions pos = {}) const; /** [Eiger, Jungfrau] */ - void setFlowControl10G(bool enable, Positions pos = {}); + void setTenGigaGFlowControl(bool enable, Positions pos = {}); /** [Eiger, Jungfrau] */ Result getTransmissionDelayFrame(Positions pos = {}) const; /** * [Jungfrau]: Sets the transmission delay of the first UDP packet being - * streamed out of the module Options: 0 - 31, each value represenets 1 ms + * streamed out of the module. Options: 0 - 31, each value represenets 1 ms * [Eiger]: Sets the transmission delay of entire frame streamed out for both - * left and right UDP ports + * left and right UDP ports. Options: //TODO possible values */ void setTransmissionDelayFrame(int value, Positions pos = {}); - /** [Jungfrau] */ - Result getNumberofUDPInterfaces(Positions pos = {}) const; - - /** [Jungfrau] Also restarts client and receiver sockets */ - void setNumberofUDPInterfaces(int n, Positions pos = {}); - - /** [Jungfrau] */ - Result getSelectedUDPInterface(Positions pos = {}) const; - - /** - * [Jungfrau: - * Effective only when number of interfaces is 1. - * Options: 0 (outer, default), 1(inner)] - */ - void selectUDPInterface(int interface, Positions pos = {}); - - /** [Jungfrau] bottom half */ - Result getDetectorMAC2(Positions pos = {}) const; - - /** [Jungfrau] bottom half */ - void setDetectorMAC2(const std::string &detectorMAC, Positions pos = {}); - - /** [Jungfrau] bottom half */ - Result getDetectorIP2(Positions pos = {}) const; - - /** [Jungfrau] bottom half */ - void setDetectorIP2(const std::string &detectorIP, Positions pos = {}); - - /** [Jungfrau bottom half] */ - Result getReceiverUDPIP2(Positions pos = {}) const; - - /** [Jungfrau bottom half] */ - void setReceiverUDPIP2(const std::string &udpip, Positions pos = {}); - - /** [Jungfrau bottom half] */ - Result getReceiverUDPMAC2(Positions pos = {}) const; - - /** [Jungfrau bottom half] */ - void setReceiverUDPMAC2(const std::string &udpmac, Positions pos = {}); - /** [Eiger] */ Result getTransmissionDelayLeft(Positions pos = {}) const; + /** * [Eiger] * Sets the transmission delay of first packet streamed out of the left UDP @@ -345,6 +317,47 @@ class Detector { */ void setTransmissionDelayRight(int value, Positions pos = {}); + /** [Jungfrau] */ + Result getNumberofUDPInterfaces(Positions pos = {}) const; + + /** [Jungfrau] Also restarts client and receiver sockets */ + void setNumberofUDPInterfaces(int n, Positions pos = {}); + + /** [Jungfrau] */ + Result getSelectedUDPInterface(Positions pos = {}) const; + + /** + * [Jungfrau: + * Effective only when number of interfaces is 1. + * Options: 0 (outer, default), 1(inner)] //TODO: enum? + */ + void selectUDPInterface(int interface, Positions pos = {}); + + /** [Jungfrau] bottom half */ + Result getDetectorMAC2(Positions pos = {}) const; + + /** [Jungfrau] bottom half */ + void setDetectorMAC2(const std::string &detectorMAC, Positions pos = {}); + + /** [Jungfrau] bottom half */ + Result getDetectorIP2(Positions pos = {}) const; + + /** [Jungfrau] bottom half */ + void setDetectorIP2(const std::string &detectorIP, Positions pos = {}); + + /** [Jungfrau bottom half] */ + Result getDestinationUDPIP2(Positions pos = {}) const; + + /** [Jungfrau bottom half] */ + void setDestinationUDPIP2(const std::string &udpip, Positions pos = {}); + + /** [Jungfrau bottom half] */ + Result getDestinationUDPMAC2(Positions pos = {}) const; + + /** [Jungfrau bottom half] */ + void setDestinationUDPMAC2(const std::string &udpmac, Positions pos = {}); + + /************************************************** @@ -356,7 +369,7 @@ class Detector { /** true when slsReceiver is used */ Result getUseReceiverFlag(Positions pos = {}) const; - Result getReceiverHostname(Positions pos = {}) const; + Result getRxHostname(Positions pos = {}) const; /** * Validates and sets the receiver. @@ -364,49 +377,54 @@ class Detector { * Configures the detector to the receiver as UDP destination * @param receiver receiver hostname or IP address */ - void setReceiverHostname(const std::string &receiver, Positions pos = {}); + void setRxHostname(const std::string &receiver, Positions pos = {}); - Result getReceiverPort(Positions pos = {}) const; + Result getRxPort(Positions pos = {}) const; /** Receiver TCP port (for client communication with Receiver) */ - void setReceiverPort(int value, Positions pos = {}); + void setRxPort(int value, Positions pos = {}); - Result getReceiverFifoDepth(Positions pos = {}) const; + Result getRxFifoDepth(Positions pos = {}) const; - void setReceiverFifoDepth(int nframes, Positions pos = {}); + /** fifo between udp listening and processing threads */ + void setRxFifoDepth(int nframes, Positions pos = {}); - Result getReceiverSilentMode(Positions pos = {}) const; + Result getRxSilentMode(Positions pos = {}) const; - void setReceiverSilentMode(bool value, Positions pos = {}); + /** receiver prints hardly any information while acquiring */ + void setRxSilentMode(bool value, Positions pos = {}); Result - getReceiverFrameDiscardPolicy(Positions pos = {}) const; + getRxFrameDiscardPolicy(Positions pos = {}) const; /** * default NO_DISCARD * Options: NO_DISCARD, DISCARD_EMPTY_FRAMES, DISCARD_PARTIAL_FRAMES + * discard partial frames is the fastest */ - void setReceiverFrameDiscardPolicy(defs::frameDiscardPolicy f, + void setRxFrameDiscardPolicy(defs::frameDiscardPolicy f, Positions pos = {}); Result getPartialFramesPadding(Positions pos = {}) const; - /** padding enabled */ + /** padding enabled. Disabling padding is the fastest */ void setPartialFramesPadding(bool value, Positions pos = {}); - Result getReceiverUDPSocketBufferSize(Positions pos = {}) const; + Result getRxUDPSocketBufferSize(Positions pos = {}) const; - void setReceiverUDPSocketBufferSize(int64_t udpsockbufsize, + void setRxUDPSocketBufferSize(int64_t udpsockbufsize, Positions pos = {}); + /** TODO: + * Linux kernel allocates twice the amount you set for bookkeeping purposes */ Result - getReceiverRealUDPSocketBufferSize(Positions pos = {}) const; + getRxRealUDPSocketBufferSize(Positions pos = {}) const; - Result getReceiverLock(Positions pos = {}); + Result getRxLock(Positions pos = {}); /** locks receiver server to client IP */ - void setReceiverLock(bool value, Positions pos = {}); + void setRxLock(bool value, Positions pos = {}); - Result getReceiverLastClientIP(Positions pos = {}) const; + Result getRxLastClientIP(Positions pos = {}) const; /************************************************** * * @@ -426,12 +444,15 @@ class Detector { Result getFileNamePrefix(Positions pos = {}) const; - /** default run */ + /** default run + * File Name: [file name prefix]_d[module index]_f[file index]_[acquisition index].[file format] + * eg. run_d0_f0_5.raw + */ void setFileNamePrefix(const std::string &fname, Positions pos = {}); - Result getFileIndex(Positions pos = {}) const; + Result getAcquisitonIndex(Positions pos = {}) const; - void setFileIndex(int i, Positions pos = {}); + void setAcquisitionIndex(int i, Positions pos = {}); Result getFileWrite(Positions pos = {}) const; @@ -440,6 +461,7 @@ class Detector { Result getMasterFileWrite(Positions pos = {}) const; + /* default writes */ void setMasterFileWrite(bool value, Positions pos = {}); Result getFileOverWrite(Positions pos = {}) const; @@ -449,108 +471,64 @@ class Detector { Result getFramesPerFile(Positions pos = {}) const; + /** -1 will set frames per file to unlimited //TODO check if it is -1 or 0 */ void setFramesPerFile(int n, Positions pos = {}); /************************************************** * * - * ZMQ Streaming Parameters * + * ZMQ Streaming Parameters (Receiver<->Client)* * * * ************************************************/ + //TODO callback functions - Result getDataStreamingFromReceiver(Positions pos = {}) const; + Result getRxZmqDataStream(Positions pos = {}) const; - void setDataStreamingFromReceiver(bool value, Positions pos = {}); + void setRxZmqDataStream(bool value, Positions pos = {}); - bool getDataStreamingToClient() const; - - void setDataStreamingToClient(bool value); - - Result getReceiverStreamingFrequency(Positions pos = {}) const; + Result getRxZmqFrequency(Positions pos = {}) const; /** @param freq nth frame streamed out of receiver. * If 0, streaming timer is the timeout, * after which current frame sent out. Default is 0 at 200 ms. - * For every frame, set freq to 1. + * Default is 0. This is more for gui purposes to not send every frame. + * If you want every frame, set freq to 1. */ - void setReceiverStreamingFrequency(int freq, Positions pos = {}); + void setRxZmqFrequency(int freq, Positions pos = {}); - Result getReceiverStreamingTimer(Positions pos = {}) const; + Result getRxZmqTimer(Positions pos = {}) const; /** * If receiver streaming frequency is 0 (default), then this timer between * each data stream is set. Default is 200 ms. */ - void setReceiverStreamingTimer(int time_in_ms, Positions pos = {}); + void setRxZmqTimer(int time_in_ms, Positions pos = {}); + + Result getRxZmqPort(Positions pos = {}) const; - Result getClientStreamingPort(Positions pos = {}) const; /** - * pos can be for a single module or all modules, not a subset - * If pos for all modules, ports for each module is calculated (increments) - * Restarts client zmq sockets + * module_id is -1 for all detectors, ports for each module is calculated (increments) + * Restarts receiver zmq sockets only if it was already enabled */ - void setClientDataStreamingInPort(int port, Positions pos = {}); + void setRxZmqPort(int port, int module_id = -1); - Result getReceiverStreamingPort(Positions pos = {}) const; - /** - * pos can be for a single module or all modules, not a subset - * If pos for all modules, ports for each module is calculated (increments) - * Restarts receiver zmq sockets - */ - void setReceiverDataStreamingOutPort(int port, Positions pos = {}); + Result getRxZmqIP(Positions pos = {}) const; - Result getClientStreamingIP(Positions pos = {}) const; - - // TODO these should probably be the same ?? same as what? - void setClientDataStreamingInIP(const std::string &ip, Positions pos = {}); - - Result getReceiverStreamingIP(Positions pos = {}) const; - - void setReceiverDataStreamingOutIP(const std::string &ip, + void setRxZmqIP(const std::string &ip, Positions pos = {}); - /** [Moench] */ - Result getAdditionalJsonHeader(Positions pos = {}) const; - - /** [Moench] */ - void setAdditionalJsonHeader(const std::string &jsonheader, - Positions pos = {}); - - /** [Moench] */ - Result getAdditionalJsonParameter(const std::string &key, - Positions pos = {}) const; + Result getClientZmqPort(Positions pos = {}) const; + /** - * [Moench] - * Sets the value for additional json header parameter if found, - * else appends the parameter key and value - * The value cannot be empty + * Needed only when using the client call back to get reconstructed data from multi modules + * module_id is -1 for all detectors, ports for each module is calculated (increments) + * Restarts client zmq sockets oonly if it was already enabled */ - void setAdditionalJsonParameter(const std::string &key, - const std::string &value, - Positions pos = {}); + void setClientZmqPort(int port, int module_id = -1); - /** [Moench] TODO! How do we do this best??? Can be refactored to something - * else? Use a generic zmq message passing system... - * For now limiting to all detectors working the same*/ - /** [Moench: -1 if not found or cannot convert to int] */ - Result getDetectorMinMaxEnergyThreshold(const bool isEmax, - Positions pos = {}) const; + Result getClientZmqIp(Positions pos = {}) const; - /** [Moench] */ - void setDetectorMinMaxEnergyThreshold(const bool isEmax, const int value, - Positions pos = {}); - - /** [Moench: -1 if unknown mode] */ - Result getFrameMode(Positions pos = {}) const; - - /** [Moench] */ - void setFrameMode(defs::frameModeType value, Positions pos = {}); - - /** [Moench: -1 if unknown mode] */ - Result getDetectorMode(Positions pos = {}) const; - - /** [Moench] */ - void setDetectorMode(defs::detectorModeType value, Positions pos = {}); + void setClientZmqIp(const std::string &ip, Positions pos = {}); /************************************************** @@ -561,12 +539,6 @@ class Detector { Result getDynamicRange(Positions pos = {}) const; - /** [Eiger] */ - Result getTenGigaEnabled(Positions pos = {}) const; - - /** [Eiger] */ - void setTenGigaEnabled(bool value, Positions pos = {}); - /** * [Eiger] * Options: 4, 8, 16, 32 @@ -574,7 +546,13 @@ class Detector { */ void setDynamicRange(int value); - /** [Eiger] in 32 bit mode */ + /** [Eiger] */ + Result getTenGiga(Positions pos = {}) const; + + /** [Eiger] */ + void setTenGiga(bool enable, Positions pos = {}); + + /** [Eiger] in 32 bit mode */ Result getSubExptime(Positions pos = {}) const; /** [Eiger] in 32 bit mode */ @@ -603,15 +581,15 @@ class Detector { /** [Eiger] */ void loadTrimbits(const std::string &fname, Positions pos = {}); - /**[Eiger] */ - Result getGapPixelsEnable(Positions pos = {}) const; + /**[Eiger] */ + Result getRxAddGapPixels(Positions pos = {}) const; /** * [Eiger] * 4 bit mode not implemented in Receiver, but in client data call back * Fills in gap pixels in data */ - void setGapPixelsEnable(bool enable); + void setRxAddGapPixels(bool enable); /** [Eiger] */ Result getParallelMode(Positions pos = {}) const; @@ -625,15 +603,13 @@ class Detector { /** [Eiger] */ void setOverFlowMode(bool value, Positions pos = {}); - /** [Eiger] */ + /** [Eiger] */ Result getBottom(Positions pos = {}) const; - /** [Eiger] for gui purposes */ + /** [Eiger] for client call back (gui) purposes */ void setBottom(bool value, Positions pos = {}); - /** [Eiger] - * @returns -1 if they are all different - */ + /** [Eiger] -1 if they are all different */ Result getAllTrimbits(Positions pos = {}) const; /**[Eiger] */ @@ -645,19 +621,14 @@ class Detector { /** [Eiger] Set the energies where the detector is trimmed */ void setTrimEnergies(std::vector energies, Positions pos = {}); - /** [Eiger] - * @returns deadtime in ns, 0 = disabled - */ - Result getRateCorrection(Positions pos = {}) const; + /** [Eiger] deadtime in ns, 0 = disabled */ + Result getRateCorrection(Positions pos = {}) const; - /** + /** //TODO: default, get, set * [Eiger] Set Rate correction - * 0 disable correction, <0 set to default, >0 deadtime in ns + * 0 disable correction, < 0: default dead time from trimbit file, > 0 custom deadtime (advanced) */ - void setRateCorrection(int64_t dead_time_ns, Positions pos = {}); - - /** [Eiger] Sends an internal software trigger to the detector */ - void sendSoftwareTrigger(Positions pos = {}); + void setRateCorrection(ns dead_time, Positions pos = {}); /** [Eiger] */ Result getPartialReadout(Positions pos = {}) const; @@ -668,36 +639,17 @@ class Detector { */ void setPartialReadout(const int lines, Positions pos = {}); - /** [Eiger] */ - Result getIODelay(Positions pos = {}) const; - - /** [Eiger] */ - void setIODelay(int value, Positions pos = {}); - /** [Eiger] */ Result getInterruptSubframe(Positions pos = {}) const; - /** [Eiger] when set, the last subframe is interrupted at end of acq */ + /** [Eiger] when set, the last subframe is interrupted at end of acq */ void setInterruptSubframe(const bool enable, Positions pos = {}); + /** [Eiger] minimum two frames */ + Result getMeasuredPeriod(Positions pos = {}) const; + /** [Eiger] */ - Result getCounterBit(Positions pos = {}) const; - - /** [Eiger] If it is set, it resets chips completely (else partially) before - * an acquisition TODO: if it makes sense */ - void setCounterBit(bool value, Positions pos = {}); - - /** - * [Eiger] Pulse Pixel n times at x and y coordinates - */ - void pulsePixel(int n, int x, int y, Positions pos = {}); - - /** [Eiger] Pulse Pixel n times and move by a relative value of x and y - * coordinates */ - void pulsePixelNMove(int n, int x, int y, Positions pos = {}); - - /** [Eiger] Pulse chip n times */ - void pulseChip(int n, Positions pos = {}); + Result getMeasuredSubFramePeriod(Positions pos = {}) const; /** [Eiger] */ Result getActive(Positions pos = {}) const; @@ -706,12 +658,30 @@ class Detector { void setActive(bool active, Positions pos = {}); /** [Eiger] */ - Result getRxPadDeactivatedMod(Positions pos = {}) const; + Result getRxPadDeactivatedMode(Positions pos = {}) const; - /** - * [Eiger] Set deactivated Receiver padding mode - */ - void setRxPadDeactivatedMod(bool pad, Positions pos = {}); + /** [Eiger] Advanced */ + Result getPartialReset(Positions pos = {}) const; + + /** [Eiger] Advanced + * used for pulsing chips */ + void setPartialReset(bool enable, Positions pos = {}); + + /** [Eiger] Advanced + * Pulse Pixel n times at x and y coordinates */ + void pulsePixel(int n, defs:: pixel, Positions pos = {}); + + /** [Eiger] Advanced + * Pulse Pixel n times and move by a relative value of x and y + * coordinates */ + void pulsePixelNMove(int n, defs:: pixel, Positions pos = {}); + + /** [Eiger] Advanced + * Pulse chip n times */ + void pulseChip(int n, Positions pos = {}); + + /** [Eiger] Pad deactivated modules in receiver */ + void setRxPadDeactivatedMode(bool pad, Positions pos = {}); /** [Eiger] with specific quad hardware */ Result getQuad(Positions pos = {}) const; @@ -719,11 +689,6 @@ class Detector { /** [Eiger] with specific quad hardware */ void setQuad(const bool enable); - /** [Eiger] minimum two frames */ - Result getMeasuredPeriod(Positions pos = {}) const; - - /** [Eiger] */ - Result getMeasuredSubFramePeriod(Positions pos = {}) const; /************************************************** * * @@ -740,7 +705,7 @@ class Detector { * and temperature control is enabled, * power to chip will be switched off and * temperature event will be set - * @param val value in millidegrees TODO! Verify + * @param val value in degrees */ void setThresholdTemperature(int temp, Positions pos = {}); @@ -754,7 +719,7 @@ class Detector { Result getTemperatureEvent(Positions pos = {}) const; /** [Jungfrau] */ - void ResetTemperatureEvent(Positions pos = {}); + void resetTemperatureEvent(Positions pos = {}); /** [Jungfrau] */ Result getPowerChip(Positions pos = {}) const; @@ -765,10 +730,13 @@ class Detector { /** [Jungfrau] */ Result getAutoCompDisable(Positions pos = {}) const; - /** [Jungfrau] TODO??? fix docs ? */ + /** [Jungfrau] Advanced + * //TODO naming + * By default, the on-chip gain switching is active during the entire exposure. + * This mode disables the on-chip gain switching comparator automatically after 93.75% of exposure time (only for longer than 100us). */ void setAutoCompDisable(bool value, Positions pos = {}); - /** [Jungfrau] Advanced */ + /** [Jungfrau] Advanced TODO naming */ Result getNumberOfAdditionalStorageCells() const; /** [Jungfrau] Advanced */ @@ -807,7 +775,7 @@ class Detector { */ void setROI(defs::ROI value, int moduleId); - /** [Gotthard] */ + /** [Gotthard] TODO: check with jiaguo if he needs any of these functions */ Result getExptimeLeft(Positions pos = {}) const; /** [Gotthard] */ @@ -821,11 +789,11 @@ class Detector { void setExternalSignalFlags(defs::externalSignalFlag value, Positions pos = {}); - /** [Gotthard] subset modules not allowed */ - void loadDarkImage(const std::string &fname, Positions pos = {}); + /** [Gotthard] */ + void loadDarkImage(const std::string &fname, int module_id = -1); - /** [Gotthard] subset modules not allowed */ - void loadGainImage(const std::string &fname, Positions pos = {}); + /** [Gotthard] */ + void loadGainImage(const std::string &fname, int module_id = -1); /** * [Gotthard] subset modules not allowed @@ -1061,6 +1029,56 @@ class Detector { */ void setPatternBitMask(uint64_t mask, Positions pos = {}); + /************************************************** + * * + * Moench * + * * + * ************************************************/ + + + /** [Moench] */ + Result getAdditionalJsonHeader(Positions pos = {}) const; + + /** [Moench] */ + void setAdditionalJsonHeader(const std::string &jsonheader, + Positions pos = {}); + + /** [Moench] */ + Result getAdditionalJsonParameter(const std::string &key, + Positions pos = {}) const; + /** + * [Moench] + * Sets the value for additional json header parameter if found, + * else appends the parameter key and value + * The value cannot be empty + */ + void setAdditionalJsonParameter(const std::string &key, + const std::string &value, + Positions pos = {}); + + /** [Moench] TODO! How do we do this best??? Can be refactored to something + * else? Use a generic zmq message passing system... + * For now limiting to all detectors working the same*/ + /** [Moench: -1 if not found or cannot convert to int] */ + Result getDetectorMinMaxEnergyThreshold(const bool isEmax, + Positions pos = {}) const; + + /** [Moench] */ + void setDetectorMinMaxEnergyThreshold(const bool isEmax, const int value, + Positions pos = {}); + + /** [Moench: -1 if unknown mode] */ + Result getFrameMode(Positions pos = {}) const; + + /** [Moench] */ + void setFrameMode(defs::frameModeType value, Positions pos = {}); + + /** [Moench: -1 if unknown mode] */ + Result getDetectorMode(Positions pos = {}) const; + + /** [Moench] */ + void setDetectorMode(defs::detectorModeType value, Positions pos = {}); + /************************************************** * * * Advanced * diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 8f5bcbc0b..990fa5bac 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -682,11 +682,11 @@ void Detector::setDetectorIP2(const std::string &detectorIP, Positions pos) { pimpl->Parallel(&slsDetector::setDetectorIP2, pos, detectorIP); } -Result Detector::getReceiverHostname(Positions pos) const { +Result Detector::getRxHostname(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverHostname, pos); } -void Detector::setReceiverHostname(const std::string &receiver, Positions pos) { +void Detector::setRxHostname(const std::string &receiver, Positions pos) { pimpl->Parallel(&slsDetector::setReceiverHostname, pos, receiver); } @@ -698,7 +698,7 @@ void Detector::setDestinationUDPIP(const std::string &udpip, Positions pos) { pimpl->Parallel(&slsDetector::setReceiverUDPIP, pos, udpip); } -Result Detector::getReceiverUDPIP2(Positions pos) const { +Result Detector::getRxUDPIP2(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverUDPIP2, pos); } @@ -778,11 +778,11 @@ void Detector::setClientDataStreamingInPort(int port, Positions pos) { pimpl->setClientDataStreamingInPort(port, pos.empty() ? -1 : pos[0]); } -Result Detector::getReceiverStreamingPort(Positions pos) const { +Result Detector::getRxStreamingPort(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverStreamingPort, pos); } -void Detector::setReceiverDataStreamingOutPort(int port, Positions pos) { +void Detector::setRxDataStreamingOutPort(int port, Positions pos) { if (pos.size() > 1 && pos.size() < pimpl->size()) { throw RuntimeError( "Cannot set receiver streaming port to a subset of modules"); @@ -805,11 +805,11 @@ void Detector::setClientDataStreamingInIP(const std::string &ip, } } -Result Detector::getReceiverStreamingIP(Positions pos) const { +Result Detector::getRxStreamingIP(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverStreamingIP, pos); } -void Detector::setReceiverDataStreamingOutIP(const std::string &ip, +void Detector::setRxDataStreamingOutIP(const std::string &ip, Positions pos) { bool previouslyReceiverStreaming = getDataStreamingFromReceiver(pos).squash(false); @@ -1011,7 +1011,7 @@ Result Detector::getCounterBit(Positions pos) const { } void Detector::setCounterBit(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setCounterBit, pos, value); + pimpl->Parallel(&slsDetector::setCounterBit, pos, !value); } Result Detector::getROI(Positions pos) const { @@ -1057,19 +1057,19 @@ void Detector::setExternalSampling(bool value, Positions pos) { pimpl->Parallel(&slsDetector::setExternalSampling, pos, value); } -Result> Detector::getReceiverDbitList(Positions pos) const { +Result> Detector::getRxDbitList(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverDbitList, pos); } -void Detector::setReceiverDbitList(std::vector list, Positions pos) { +void Detector::setRxDbitList(std::vector list, Positions pos) { pimpl->Parallel(&slsDetector::setReceiverDbitList, pos, list); } -Result Detector::getReceiverDbitOffset(Positions pos) const { +Result Detector::getRxDbitOffset(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverDbitOffset, pos); } -void Detector::setReceiverDbitOffset(int value, Positions pos) { +void Detector::setRxDbitOffset(int value, Positions pos) { pimpl->Parallel(&slsDetector::setReceiverDbitOffset, pos, value); } @@ -1130,11 +1130,15 @@ void Detector::pulseChip(int n, Positions pos) { } Result Detector::getThresholdTemperature(Positions pos) const { - return pimpl->Parallel(&slsDetector::setThresholdTemperature, pos, -1); + auto res = pimpl->Parallel(&slsDetector::setThresholdTemperature, pos, -1); + for (auto &it : res) { + it /= 1000; + } + return res; } void Detector::setThresholdTemperature(int temp, Positions pos) { - pimpl->Parallel(&slsDetector::setThresholdTemperature, pos, temp); + pimpl->Parallel(&slsDetector::setThresholdTemperature, pos, temp * 1000); } Result Detector::getTemperatureControl(Positions pos) const { @@ -1207,7 +1211,7 @@ void Detector::setAutoCompDisable(bool value, Positions pos) { static_cast(value)); } -Result Detector::getRateCorrection(Positions pos) const { +Result Detector::getRateCorrection(Positions pos) const { return pimpl->Parallel(&slsDetector::getRateCorrection, pos); } @@ -1312,43 +1316,43 @@ Result Detector::getUseReceiverFlag(Positions pos) const { return pimpl->Parallel(&slsDetector::getUseReceiverFlag, pos); } -Result Detector::printReceiverConfiguration(Positions pos) const { +Result Detector::printRxConfiguration(Positions pos) const { return pimpl->Parallel(&slsDetector::printReceiverConfiguration, pos); } -Result Detector::getReceiverPort(Positions pos) const { +Result Detector::getRxPort(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverPort, pos); } -void Detector::setReceiverPort(int value, Positions pos) { +void Detector::setRxPort(int value, Positions pos) { pimpl->Parallel(&slsDetector::setReceiverPort, pos, value); } -Result Detector::getReceiverLock(Positions pos) { +Result Detector::getRxLock(Positions pos) { return pimpl->Parallel(&slsDetector::lockReceiver, pos, -1); } -void Detector::setReceiverLock(bool value, Positions pos) { +void Detector::setRxLock(bool value, Positions pos) { pimpl->Parallel(&slsDetector::lockReceiver, pos, static_cast(value)); } -Result Detector::getReceiverLastClientIP(Positions pos) const { +Result Detector::getRxLastClientIP(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverLastClientIP, pos); } -Result Detector::getReceiverStreamingFrequency(Positions pos) const { +Result Detector::getRxStreamingFrequency(Positions pos) const { return pimpl->Parallel(&slsDetector::setReceiverStreamingTimer, pos, -1); } -void Detector::setReceiverStreamingFrequency(int freq, Positions pos) { +void Detector::setRxStreamingFrequency(int freq, Positions pos) { pimpl->Parallel(&slsDetector::setReceiverStreamingFrequency, pos, freq); } -Result Detector::getReceiverStreamingTimer(Positions pos) const { +Result Detector::getRxStreamingTimer(Positions pos) const { return pimpl->Parallel(&slsDetector::setReceiverStreamingTimer, pos, -1); } -void Detector::setReceiverStreamingTimer(int time_in_ms, Positions pos) { +void Detector::setRxStreamingTimer(int time_in_ms, Positions pos) { pimpl->Parallel(&slsDetector::setReceiverStreamingTimer, pos, time_in_ms); } @@ -1360,39 +1364,39 @@ void Detector::setDataStreamingToClient(bool enable) { pimpl->enableDataStreamingToClient(static_cast(enable)); } -Result Detector::getDataStreamingFromReceiver(Positions pos) const { +Result Detector::getDataStreamingFromRx(Positions pos) const { return pimpl->Parallel(&slsDetector::enableDataStreamingFromReceiver, pos, -1); } -void Detector::setDataStreamingFromReceiver(bool enable, Positions pos) { +void Detector::setDataStreamingFromRx(bool enable, Positions pos) { pimpl->Parallel(&slsDetector::enableDataStreamingFromReceiver, pos, static_cast(enable)); } -Result Detector::getReceiverFifoDepth(Positions pos) const { +Result Detector::getRxFifoDepth(Positions pos) const { return pimpl->Parallel(&slsDetector::setReceiverFifoDepth, pos, -1); } -void Detector::setReceiverFifoDepth(int nframes, Positions pos) { +void Detector::setRxFifoDepth(int nframes, Positions pos) { pimpl->Parallel(&slsDetector::setReceiverFifoDepth, pos, nframes); } -Result Detector::getReceiverSilentMode(Positions pos) const { +Result Detector::getRxSilentMode(Positions pos) const { return pimpl->Parallel(&slsDetector::setReceiverSilentMode, pos, -1); } -void Detector::setReceiverSilentMode(bool value, Positions pos) { +void Detector::setRxSilentMode(bool value, Positions pos) { pimpl->Parallel(&slsDetector::setReceiverSilentMode, pos, static_cast(value)); } Result -Detector::getReceiverFrameDiscardPolicy(Positions pos) const { +Detector::getRxFrameDiscardPolicy(Positions pos) const { return pimpl->Parallel(&slsDetector::setReceiverFramesDiscardPolicy, pos, defs::GET_FRAME_DISCARD_POLICY); } -void Detector::setReceiverFrameDiscardPolicy(defs::frameDiscardPolicy f, +void Detector::setRxFrameDiscardPolicy(defs::frameDiscardPolicy f, Positions pos) { pimpl->Parallel(&slsDetector::setReceiverFramesDiscardPolicy, pos, f); } @@ -1414,18 +1418,18 @@ void Detector::setRxPadDeactivatedMod(bool pad, Positions pos) { static_cast(pad)); } -Result Detector::getReceiverUDPSocketBufferSize(Positions pos) const { +Result Detector::getRxUDPSocketBufferSize(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverUDPSocketBufferSize, pos); } -void Detector::setReceiverUDPSocketBufferSize(int64_t udpsockbufsize, +void Detector::setRxUDPSocketBufferSize(int64_t udpsockbufsize, Positions pos) { pimpl->Parallel(&slsDetector::setReceiverUDPSocketBufferSize, pos, udpsockbufsize); } Result -Detector::getReceiverRealUDPSocketBufferSize(Positions pos) const { +Detector::getRxRealUDPSocketBufferSize(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverRealUDPSocketBufferSize, pos); } @@ -1455,7 +1459,7 @@ void Detector::sendSoftwareTrigger(Positions pos) { pimpl->Parallel(&slsDetector::sendSoftwareTrigger, pos); } -Result Detector::getReceiverStatus(Positions pos) const { +Result Detector::getRxStatus(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverStatus, pos); } @@ -1463,7 +1467,7 @@ Result Detector::getFramesCaught(Positions pos) const { return pimpl->Parallel(&slsDetector::getFramesCaughtByReceiver, pos); } -Result Detector::getReceiverCurrentFrameIndex(Positions pos) const { +Result Detector::getRxCurrentFrameIndex(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverCurrentFrameIndex, pos); } From 0d2598bd77396e72218017774a01cd6fa6abe328 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Mon, 19 Aug 2019 16:00:23 +0200 Subject: [PATCH 087/108] WIP --- 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 7d56ba929..3a9e56f10 100755 --- a/slsDetectorSoftware/src/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp @@ -4845,7 +4845,7 @@ std::string slsDetectorCommand::helpAdvanced(int action) { os << "led s \t sets led status (0 off, 1 on)" << std::endl; os << "diodelay m v \tsets the delay for the digital IO pins selected by mask m and delay set by v. mask is upto 64 bits in hex, delay max is 775ps, and set in steps of 25 ps. Used for MOENCH/CTB only." << std::endl; os << "powerchip i \t powers on or off the chip. i = 1 for on, i = 0 for off" << std::endl; - os << "auto_comp_disable i \t Currently not implemented. this mode disables the on-chip gain switching comparator automatically after 93.75% of exposure time (only for longer than 100us). 1 enables mode, 0 disables mode. By default, mode is disabled (comparator is enabled throughout). (JUNGFRAU only). " << std::endl; + os << "auto_comp_disable i \t this mode disables the on-chip gain switching comparator automatically after 93.75% of exposure time (only for longer than 100us). 1 enables mode, 0 disables mode. By default, mode is disabled (comparator is enabled throughout). (JUNGFRAU only). " << std::endl; } if (action == GET_ACTION || action == HELP_ACTION) { @@ -4855,7 +4855,7 @@ std::string slsDetectorCommand::helpAdvanced(int action) { os << "readnlines \t gets the number of rows to read out per half module. Used for EIGER only. " << std::endl; os << "led \t returns led status (0 off, 1 on)" << std::endl; os << "powerchip \t gets if the chip has been powered on or off" << std::endl; - os << "auto_comp_disable \t Currently not implemented. gets if the automatic comparator diable mode is enabled/disabled" << std::endl; + os << "auto_comp_disable \t gets if the automatic comparator diable mode is enabled/disabled" << std::endl; } return os.str(); } From d2e8c3bebca8ebf4e291a4be22f92e2684b430bf Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Mon, 19 Aug 2019 16:33:53 +0200 Subject: [PATCH 088/108] WIP --- slsDetectorSoftware/src/Detector.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 990fa5bac..23e125a3b 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -52,8 +52,6 @@ Result Detector::getReceiverVersion(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverSoftwareVersion, pos); } -std::string Detector::getUserDetails() const { return pimpl->getUserDetails(); } - Result Detector::getDetectorType(Positions pos) const { return pimpl->Parallel(&slsDetector::getDetectorTypeAsEnum, pos); @@ -1540,4 +1538,7 @@ void Detector::setPatternBitMask(uint64_t mask, Positions pos) { pimpl->Parallel(&slsDetector::setPatternBitMask, pos, mask); } + +std::string Detector::getUserDetails() const { return pimpl->getUserDetails(); } + } // namespace sls \ No newline at end of file From ee4aa94bbe2cecd33e4674678f079709fcd971e3 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Mon, 19 Aug 2019 18:03:19 +0200 Subject: [PATCH 089/108] WIP --- slsDetectorSoftware/include/Detector.h | 2 +- slsDetectorSoftware/src/Detector.cpp | 300 ++++++++++++++----------- 2 files changed, 170 insertions(+), 132 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index c0fe335f7..304159b93 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -116,7 +116,7 @@ class Detector { Result getNumberOfFramesLeft(Positions pos = {}) const; /** [Gotthard][Jungfrau][CTB] */ - Result getNumberOfCyclesLeft(Positions pos = {}) const; + Result getNumberOfTriggersLeft(Positions pos = {}) const; /** [Gotthard][Jungfrau][CTB] */ Result getDelayAfterTriggerLeft(Positions pos = {}) const; diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 23e125a3b..3a670b64c 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -75,6 +75,174 @@ void Detector::setDetectorSize(const defs::xy value) { pimpl->setNumberOfChannels(value); } +Result Detector::getSettings(Positions pos) const { + return pimpl->Parallel(&slsDetector::getSettings, pos); +} + +void Detector::setSettings(defs::detectorSettings value, Positions pos) { + pimpl->Parallel(&slsDetector::setSettings, pos, value); +} + + + +// Acquisition Parameters + +Result Detector::getNumberOfFrames() const { + return pimpl->Parallel(&slsDetector::setTimer, {}, defs::FRAME_NUMBER, -1); +} + +void Detector::setNumberOfFrames(int64_t value) { + pimpl->Parallel(&slsDetector::setTimer, {}, defs::FRAME_NUMBER, value); +} + +Result Detector::getNumberOfTriggers() const { + return pimpl->Parallel(&slsDetector::setTimer, {}, defs::CYCLES_NUMBER, -1); +} + +void Detector::setNumberOfTriggers(int64_t value) { + pimpl->Parallel(&slsDetector::setTimer, {}, defs::CYCLES_NUMBER, value); +} + + +Result Detector::getExptime(Positions pos) const { + return pimpl->Parallel(&slsDetector::setTimer, pos, defs::ACQUISITION_TIME, + -1); +} + +void Detector::setExptime(ns t, Positions pos) { + pimpl->Parallel(&slsDetector::setTimer, pos, defs::ACQUISITION_TIME, + t.count()); +} + +Result Detector::getPeriod(Positions pos) const { + return pimpl->Parallel(&slsDetector::setTimer, pos, defs::FRAME_PERIOD, -1); +} + +void Detector::setPeriod(ns t, Positions pos) { + pimpl->Parallel(&slsDetector::setTimer, pos, defs::FRAME_PERIOD, t.count()); +} + +Result Detector::getDelayAfterTrigger(Positions pos) const { + return pimpl->Parallel(&slsDetector::setTimer, pos, + defs::DELAY_AFTER_TRIGGER, -1); +} + +void Detector::setDelayAfterTrigger(ns value, Positions pos) { + pimpl->Parallel(&slsDetector::setTimer, pos, defs::DELAY_AFTER_TRIGGER, + value.count()); +} + +Result Detector::getNumberOfFramesLeft(Positions pos) const { + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::FRAME_NUMBER); +} + +Result Detector::getNumberOfTriggersLeft(Positions pos) const { + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::CYCLES_NUMBER); +} + +Result Detector::getDelayAfterTriggerLeft(Positions pos) const { + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, + defs::DELAY_AFTER_TRIGGER); +} + +Result Detector::getSpeed(Positions pos) const { + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::CLOCK_DIVIDER, -1, + 0); +} + +void Detector::setSpeed(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setSpeed, pos, defs::CLOCK_DIVIDER, value, 0); +} + +Result Detector::getADCPhase(bool inDeg, Positions pos) const { + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_PHASE, -1, + inDeg); +} + +void Detector::setADCPhase(int value, bool inDeg, Positions pos) { + pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_PHASE, value, inDeg); +} + +Result Detector::getMaxADCPhaseShift(Positions pos) const { + return pimpl->Parallel(&slsDetector::setSpeed, pos, + defs::MAX_ADC_PHASE_SHIFT, -1, 0); +} + +Result Detector::getHighVoltage(Positions pos) const { + return pimpl->Parallel(&slsDetector::setDAC, pos, -1, defs::HIGH_VOLTAGE, + 0); +} + +void Detector::setHighVoltage(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setDAC, pos, value, defs::HIGH_VOLTAGE, 0); +} + +Result Detector::getTemperature(defs::dacIndex index, Positions pos) const { + switch (index) { + case defs::TEMPERATURE_ADC: + case defs::TEMPERATURE_FPGA: + case defs::TEMPERATURE_FPGAEXT: + case defs::TEMPERATURE_10GE: + case defs::TEMPERATURE_DCDC: + case defs::TEMPERATURE_SODL: + case defs::TEMPERATURE_SODR: + case defs::TEMPERATURE_FPGA2: + case defs::TEMPERATURE_FPGA3: + case defs::SLOW_ADC_TEMP: + break; + default: + throw RuntimeError("Unknown Temperature Index"); + } + auto res = pimpl->Parallel(&slsDetector::getADC, pos, index); + switch (getDetectorType().squash()) { + case defs::EIGER: + case defs::JUNGFRAU: + for (auto &it : res) { + it /= 1000; + } + break; + default: + break; + } + return res; +} + +Result Detector::getDAC(defs::dacIndex index, bool mV, + Positions pos) const { + return pimpl->Parallel(&slsDetector::setDAC, pos, -1, index, mV); +} + +void Detector::setDAC(int value, defs::dacIndex index, bool mV, Positions pos) { + pimpl->Parallel(&slsDetector::setDAC, pos, value, index, mV); +} + +Result Detector::getTimingMode(Positions pos) const { + return pimpl->Parallel(&slsDetector::setTimingMode, pos, + defs::GET_TIMING_MODE); +} + +void Detector::setTimingMode(defs::timingMode value, Positions pos) { + pimpl->Parallel(&slsDetector::setTimingMode, pos, value); +} + + + +// Acquisition + +void Detector::acquire() { pimpl->acquire(); } + + + + + + + + + + + + + Result Detector::getQuad(Positions pos) const { return pimpl->Parallel(&slsDetector::getQuad, pos); } @@ -123,13 +291,7 @@ void Detector::execCommand(const std::string &value, Positions pos) { pimpl->Parallel(&slsDetector::execCommand, pos, value); } -Result Detector::getSettings(Positions pos) const { - return pimpl->Parallel(&slsDetector::getSettings, pos); -} -void Detector::setSettings(defs::detectorSettings value, Positions pos) { - pimpl->Parallel(&slsDetector::setSettings, pos, value); -} Result Detector::getThresholdEnergy(Positions pos) const { return pimpl->Parallel(&slsDetector::getThresholdEnergy, pos); @@ -156,21 +318,6 @@ void Detector::configureMAC(Positions pos) { pimpl->Parallel(&slsDetector::configureMAC, pos); } -Result Detector::getNumberOfFrames() const { - return pimpl->Parallel(&slsDetector::setTimer, {}, defs::FRAME_NUMBER, -1); -} - -void Detector::setNumberOfFrames(int64_t value) { - pimpl->Parallel(&slsDetector::setTimer, {}, defs::FRAME_NUMBER, value); -} - -Result Detector::getNumberOfTriggers() const { - return pimpl->Parallel(&slsDetector::setTimer, {}, defs::CYCLES_NUMBER, -1); -} - -void Detector::setNumberOfTriggers(int64_t value) { - pimpl->Parallel(&slsDetector::setTimer, {}, defs::CYCLES_NUMBER, value); -} Result Detector::getNumberOfAdditionalStorageCells() const { return pimpl->Parallel(&slsDetector::setTimer, {}, @@ -209,33 +356,6 @@ void Detector::setNumberOfDigitalSamples(int64_t value, Positions pos) { pimpl->Parallel(&slsDetector::setTimer, pos, defs::DIGITAL_SAMPLES, value); } -Result Detector::getExptime(Positions pos) const { - return pimpl->Parallel(&slsDetector::setTimer, pos, defs::ACQUISITION_TIME, - -1); -} - -void Detector::setExptime(ns t, Positions pos) { - pimpl->Parallel(&slsDetector::setTimer, pos, defs::ACQUISITION_TIME, - t.count()); -} - -Result Detector::getPeriod(Positions pos) const { - return pimpl->Parallel(&slsDetector::setTimer, pos, defs::FRAME_PERIOD, -1); -} - -void Detector::setPeriod(ns t, Positions pos) { - pimpl->Parallel(&slsDetector::setTimer, pos, defs::FRAME_PERIOD, t.count()); -} - -Result Detector::getDelayAfterTrigger(Positions pos) const { - return pimpl->Parallel(&slsDetector::setTimer, pos, - defs::DELAY_AFTER_TRIGGER, -1); -} - -void Detector::setDelayAfterTrigger(ns value, Positions pos) { - pimpl->Parallel(&slsDetector::setTimer, pos, defs::DELAY_AFTER_TRIGGER, - value.count()); -} Result Detector::getSubExptime(Positions pos) const { return pimpl->Parallel(&slsDetector::setTimer, pos, @@ -267,14 +387,6 @@ void Detector::setStorageCellDelay(ns value, Positions pos) { value.count()); } -Result Detector::getNumberOfFramesLeft(Positions pos) const { - return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::FRAME_NUMBER); -} - -Result Detector::getNumberOfCyclesLeft(Positions pos) const { - return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::CYCLES_NUMBER); -} - Result Detector::getExptimeLeft(Positions pos) const { return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::ACQUISITION_TIME); @@ -284,10 +396,7 @@ Result Detector::getPeriodLeft(Positions pos) const { return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::FRAME_PERIOD); } -Result Detector::getDelayAfterTriggerLeft(Positions pos) const { - return pimpl->Parallel(&slsDetector::getTimeLeft, pos, - defs::DELAY_AFTER_TRIGGER); -} + Result Detector::getNumberOfFramesFromStart(Positions pos) const { return pimpl->Parallel(&slsDetector::getTimeLeft, pos, @@ -313,28 +422,10 @@ Result Detector::getMeasuredSubFramePeriod(Positions pos) const { defs::MEASURED_SUBPERIOD); } -Result Detector::getSpeed(Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::CLOCK_DIVIDER, -1, - 0); -} -void Detector::setSpeed(int value, Positions pos) { - pimpl->Parallel(&slsDetector::setSpeed, pos, defs::CLOCK_DIVIDER, value, 0); -} -Result Detector::getADCPhase(bool inDeg, Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_PHASE, -1, - inDeg); -} -void Detector::setADCPhase(int value, bool inDeg, Positions pos) { - pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_PHASE, value, inDeg); -} -Result Detector::getMaxADCPhaseShift(Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, - defs::MAX_ADC_PHASE_SHIFT, -1, 0); -} Result Detector::getDBITPhase(bool inDeg, Positions pos) const { return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PHASE, -1, @@ -406,15 +497,6 @@ Result Detector::getDynamicRange(Positions pos) const { void Detector::setDynamicRange(int value) { pimpl->setDynamicRange(value); } -Result Detector::getHighVoltage(Positions pos) const { - return pimpl->Parallel(&slsDetector::setDAC, pos, -1, defs::HIGH_VOLTAGE, - 0); -} - -void Detector::setHighVoltage(int value, Positions pos) { - pimpl->Parallel(&slsDetector::setDAC, pos, value, defs::HIGH_VOLTAGE, 0); -} - Result Detector::getIODelay(Positions pos) const { return pimpl->Parallel(&slsDetector::setDAC, pos, -1, defs::IO_DELAY, 0); } @@ -423,35 +505,6 @@ void Detector::setIODelay(int value, Positions pos) { pimpl->Parallel(&slsDetector::setDAC, pos, value, defs::IO_DELAY, 0); } -Result Detector::getTemp(defs::dacIndex index, Positions pos) const { - switch (index) { - case defs::TEMPERATURE_ADC: - case defs::TEMPERATURE_FPGA: - case defs::TEMPERATURE_FPGAEXT: - case defs::TEMPERATURE_10GE: - case defs::TEMPERATURE_DCDC: - case defs::TEMPERATURE_SODL: - case defs::TEMPERATURE_SODR: - case defs::TEMPERATURE_FPGA2: - case defs::TEMPERATURE_FPGA3: - case defs::SLOW_ADC_TEMP: - break; - default: - throw RuntimeError("Unknown Temperature Index"); - } - auto res = pimpl->Parallel(&slsDetector::getADC, pos, index); - switch (getDetectorType().squash()) { - case defs::EIGER: - case defs::JUNGFRAU: - for (auto &it : res) { - it /= 1000; - } - break; - default: - break; - } - return res; -} Result Detector::getVrefVoltage(bool mV, Positions pos) const { return pimpl->Parallel(&slsDetector::setDAC, pos, -1, defs::ADC_VPP, mV); @@ -531,23 +584,9 @@ Result Detector::getSlowADC(defs::dacIndex index, Positions pos) const { return pimpl->Parallel(&slsDetector::getADC, pos, index); } -Result Detector::getDAC(defs::dacIndex index, bool mV, - Positions pos) const { - return pimpl->Parallel(&slsDetector::setDAC, pos, -1, index, mV); -} -void Detector::setDAC(int value, defs::dacIndex index, bool mV, Positions pos) { - pimpl->Parallel(&slsDetector::setDAC, pos, value, index, mV); -} -Result Detector::getTimingMode(Positions pos) const { - return pimpl->Parallel(&slsDetector::setTimingMode, pos, - defs::GET_TIMING_MODE); -} -void Detector::setTimingMode(defs::timingMode value, Positions pos) { - pimpl->Parallel(&slsDetector::setTimingMode, pos, value); -} Result Detector::getExternalSignalFlags(Positions pos) const { @@ -1433,7 +1472,6 @@ Detector::getRxRealUDPSocketBufferSize(Positions pos) const { } // Acquisition -void Detector::acquire() { pimpl->acquire(); } void Detector::clearAcquiringFlag() { pimpl->setAcquiringFlag(0); } From 3881e2cd21f57783bfe8220fb20ed21172b905a5 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Mon, 19 Aug 2019 20:36:42 +0200 Subject: [PATCH 090/108] WIP --- slsDetectorSoftware/include/Detector.h | 152 +- slsDetectorSoftware/src/Detector.cpp | 1821 ++++++++++++------------ 2 files changed, 1004 insertions(+), 969 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 304159b93..d34b586b4 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -196,6 +196,7 @@ class Detector { * If no receiver enabled, you can skip this for normal acquisition (no abort) */ void stopAcquisition();//TODO: cannot do this. for acquire, to stop acquisition, must not also do stop receiver(mutex) + // TODO: stopAcquire?? /** * Clears the acquiring flag. This has to be done manually @@ -218,7 +219,7 @@ class Detector { /** [Eiger] Sends an internal software trigger to the detector */ void sendSoftwareTrigger(Positions pos = {}); -//TODO: remove resetframescaught in receiver + //TODO: remove resetframescaught in receiver /************************************************** @@ -228,11 +229,41 @@ class Detector { * ************************************************/ /** Configures the destination for UDP packets in the detector - * Needed only if you use a custm receiver (not slsReceiver) + * Needed only if you use a custom receiver (not slsReceiver) * as it is already included in setReceiverHostname. */ void configureMAC(Positions pos = {});//TODO: find a reasonable name + /** [Jungfrau] */ + Result getNumberofUDPInterfaces(Positions pos = {}) const; + + /** [Jungfrau] Also restarts client and receiver sockets */ + void setNumberofUDPInterfaces(int n, Positions pos = {}); + + /** [Jungfrau] */ + Result getSelectedUDPInterface(Positions pos = {}) const; + + /** + * [Jungfrau: + * Effective only when number of interfaces is 1. + * Options: 0 (outer, default), 1(inner)] //TODO: enum? + */ + void selectUDPInterface(int interface, Positions pos = {}); + + Result getSourceUDPIP(Positions pos = {}) const; + + /* For Eiger 1G, the detector will replace with its own DHCP IP + * 10G Eiger and other detectors, the source UDP IP must be in the + * same subnet of the destination UDP IP + */ + void setSourceUDPIP(const std::string &ip, Positions pos = {}); + + /** [Jungfrau] bottom half */ + Result getSourceUDPIP2(Positions pos = {}) const; + + /** [Jungfrau] bottom half */ + void setSourceUDPIP2(const std::string &ip, Positions pos = {}); + Result getSourceUDPMAC(Positions pos = {}) const; /* For Eiger 1G, the detector will replace with its own DHCP MAC @@ -240,35 +271,44 @@ class Detector { * Others can be anything (beware of certain bits) */ - void setSourceUDPMAC(const std::string &detectorMAC, Positions pos = {}); + void setSourceUDPMAC(const std::string &mac, Positions pos = {}); - Result getSourceUDPIP(Positions pos = {}) const; + /** [Jungfrau] bottom half */ + Result getSourceUDPMAC2(Positions pos = {}) const; - /* For Eiger 1G, the detector will replace with its own DHCP IP - * 10G Eiger and other detectors, the source UDP IP must be in the - * same subnet of the destination UDP IP - */ - void setSourceUDPIP(const std::string &detectorIP, Positions pos = {}); + /** [Jungfrau] bottom half */ + void setSourceUDPMAC2(const std::string &mac, Positions pos = {}); Result getDestinationUDPIP(Positions pos = {}) const; /** IP of the interface in receiver that the detector sends data to */ - void setDestinationUDPIP(const std::string &udpip, Positions pos = {}); + void setDestinationUDPIP(const std::string &ip, Positions pos = {}); + /** [Jungfrau bottom half] */ + Result getDestinationUDPIP2(Positions pos = {}) const; + + /** [Jungfrau bottom half] */ + void setDestinationUDPIP2(const std::string &ip, Positions pos = {}); + Result getDestinationUDPMAC(Positions pos = {}) const; /** MAC of the interface in receiver that the detector sends data to * Only needed if you use a custom receiver (not slsReceiver) * Must be followed by configuremac. */ - void setDestinationUDPMAC(const std::string &udpmac, Positions pos = {}); + void setDestinationUDPMAC(const std::string &mac, Positions pos = {}); + + /** [Jungfrau bottom half] */ + Result getDestinationUDPMAC2(Positions pos = {}) const; + + /** [Jungfrau bottom half] */ + void setDestinationUDPMAC2(const std::string &mac, Positions pos = {}); Result getDestinationUDPPort(Positions pos = {}) const; - /** - * module_id is -1 for all detectors, ports for each module is calculated (increments) - */ - void setDestinationUDPPort(int udpport, int module_id = -1); + /** module_id is -1 for all detectors, ports for each module is calculated (increments) */ + //TODO if Parallel takes a vector, can send multiple vaues to set in slsdetector.cp + void setDestinationUDPPort(int port, int module_id = -1); /** [Eiger right port][Jungfrau bottom half] */ Result getDestinationUDPPort2(Positions pos = {}) const; @@ -276,10 +316,16 @@ class Detector { /** [Eiger right port][Jungfrau bottom half] * module_id is -1 for all detectors, ports for each module is calculated (increments) */ - void setDestinationUDPPort2(int udpport, int module_id = -1); + void setDestinationUDPPort2(int port, int module_id = -1); Result printRxConfiguration(Positions pos = {}) const; + /** [Eiger][CTB] */ + Result getTenGiga(Positions pos = {}) const; + + /** [Eiger][CTB] */ + void setTenGiga(bool enable, Positions pos = {}); + /** [Eiger, Jungfrau] */ Result getTenGigaGFlowControl(Positions pos = {}) const; @@ -317,48 +363,6 @@ class Detector { */ void setTransmissionDelayRight(int value, Positions pos = {}); - /** [Jungfrau] */ - Result getNumberofUDPInterfaces(Positions pos = {}) const; - - /** [Jungfrau] Also restarts client and receiver sockets */ - void setNumberofUDPInterfaces(int n, Positions pos = {}); - - /** [Jungfrau] */ - Result getSelectedUDPInterface(Positions pos = {}) const; - - /** - * [Jungfrau: - * Effective only when number of interfaces is 1. - * Options: 0 (outer, default), 1(inner)] //TODO: enum? - */ - void selectUDPInterface(int interface, Positions pos = {}); - - /** [Jungfrau] bottom half */ - Result getDetectorMAC2(Positions pos = {}) const; - - /** [Jungfrau] bottom half */ - void setDetectorMAC2(const std::string &detectorMAC, Positions pos = {}); - - /** [Jungfrau] bottom half */ - Result getDetectorIP2(Positions pos = {}) const; - - /** [Jungfrau] bottom half */ - void setDetectorIP2(const std::string &detectorIP, Positions pos = {}); - - /** [Jungfrau bottom half] */ - Result getDestinationUDPIP2(Positions pos = {}) const; - - /** [Jungfrau bottom half] */ - void setDestinationUDPIP2(const std::string &udpip, Positions pos = {}); - - /** [Jungfrau bottom half] */ - Result getDestinationUDPMAC2(Positions pos = {}) const; - - /** [Jungfrau bottom half] */ - void setDestinationUDPMAC2(const std::string &udpmac, Positions pos = {}); - - - /************************************************** * * @@ -426,10 +430,10 @@ class Detector { Result getRxLastClientIP(Positions pos = {}) const; + /************************************************** * * - * FILE, anything concerning file writing or * - * reading goes here * + * FILE * * * * ************************************************/ Result getFileFormat(Positions pos = {}) const; @@ -546,12 +550,6 @@ class Detector { */ void setDynamicRange(int value); - /** [Eiger] */ - Result getTenGiga(Positions pos = {}) const; - - /** [Eiger] */ - void setTenGiga(bool enable, Positions pos = {}); - /** [Eiger] in 32 bit mode */ Result getSubExptime(Positions pos = {}) const; @@ -660,6 +658,9 @@ class Detector { /** [Eiger] */ Result getRxPadDeactivatedMode(Positions pos = {}) const; + /** [Eiger] Pad deactivated modules in receiver */ + void setRxPadDeactivatedMode(bool pad, Positions pos = {}); + /** [Eiger] Advanced */ Result getPartialReset(Positions pos = {}) const; @@ -669,20 +670,17 @@ class Detector { /** [Eiger] Advanced * Pulse Pixel n times at x and y coordinates */ - void pulsePixel(int n, defs:: pixel, Positions pos = {}); + void pulsePixel(int n, defs::xy pixel, Positions pos = {}); /** [Eiger] Advanced * Pulse Pixel n times and move by a relative value of x and y * coordinates */ - void pulsePixelNMove(int n, defs:: pixel, Positions pos = {}); + void pulsePixelNMove(int n, defs::xy pixel, Positions pos = {}); /** [Eiger] Advanced * Pulse chip n times */ void pulseChip(int n, Positions pos = {}); - /** [Eiger] Pad deactivated modules in receiver */ - void setRxPadDeactivatedMode(bool pad, Positions pos = {}); - /** [Eiger] with specific quad hardware */ Result getQuad(Positions pos = {}) const; @@ -941,16 +939,16 @@ class Detector { void setExternalSampling(bool value, Positions pos = {}); /** [CTB] */ - Result> getReceiverDbitList(Positions pos = {}) const; + Result> getRxDbitList(Positions pos = {}) const; /** [CTB] list contains the set of bits (0-63) to save */ - void setReceiverDbitList(std::vector list, Positions pos = {}); + void setRxDbitList(std::vector list, Positions pos = {}); /** [CTB] */ - Result getReceiverDbitOffset(Positions pos = {}) const; + Result getRxDbitOffset(Positions pos = {}) const; /** [CTB] Set number of bytes of digital data to skip in the Receiver */ - void setReceiverDbitOffset(int value, Positions pos = {}); + void setRxDbitOffset(int value, Positions pos = {}); /** * [CTB] Set Digital IO Delay @@ -1174,8 +1172,10 @@ class Detector { std::string getUserDetails() const; - Result getReceiverCurrentFrameIndex(Positions pos = {}) const; + Result getRxCurrentFrameIndex(Positions pos = {}) const; +private: +std::vector getPortNumbers(int start_port); }; diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 3a670b64c..fe355206e 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -231,131 +231,481 @@ void Detector::setTimingMode(defs::timingMode value, Positions pos) { void Detector::acquire() { pimpl->acquire(); } - - - - - - - - - - - - -Result Detector::getQuad(Positions pos) const { - return pimpl->Parallel(&slsDetector::getQuad, pos); +void Detector::startAcquisition() { + if (getUseReceiverFlag({}).squash()) + pimpl->Parallel(&slsDetector::startReceiver, {}); + pimpl->Parallel(&slsDetector::startAcquisition, {}); } -void Detector::setQuad(const bool value) { - pimpl->setQuad(value); +void Detector::stopAcquisition() { + pimpl->Parallel(&slsDetector::stopAcquisition, {}); + if (getUseReceiverFlag({}).squash()) //TODO: problem for acquire() + pimpl->Parallel(&slsDetector::stopReceiver, {}); } -Result Detector::getPartialReadout(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReadNLines, pos); +void Detector::clearAcquiringFlag() { pimpl->setAcquiringFlag(0); } + +Result Detector::getDetectorStatus(Positions pos) const{ + return pimpl->Parallel(&slsDetector::getRunStatus, pos); } -void Detector::setPartialReadout(const int lines, Positions pos) { - pimpl->Parallel(&slsDetector::setReadNLines, pos, lines); +Result Detector::getReceiverStatus(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverStatus, pos); } -Result Detector::getControlPort(Positions pos) const { - return pimpl->Parallel(&slsDetector::getControlPort, pos); +Result Detector::getFramesCaught(Positions pos) const { + return pimpl->Parallel(&slsDetector::getFramesCaughtByReceiver, pos); } -void Detector::setControlPort(int value, Positions pos) { - pimpl->Parallel(&slsDetector::setControlPort, pos, value); +Result Detector::getStartingFrameNumber(Positions pos) const { + return pimpl->Parallel(&slsDetector::getStartingFrameNumber, pos); } -Result Detector::getStopPort(Positions pos) const { - return pimpl->Parallel(&slsDetector::getStopPort, pos); +void Detector::setStartingFrameNumber(uint64_t value, Positions pos) { + pimpl->Parallel(&slsDetector::setStartingFrameNumber, pos, value); } -void Detector::setStopPort(int value, Positions pos) { - pimpl->Parallel(&slsDetector::setStopPort, pos, value); -} - -Result Detector::getDetectorLock(Positions pos) const { - return pimpl->Parallel(&slsDetector::lockServer, pos, -1); -} - -void Detector::setDetectorLock(bool lock, Positions pos) { - pimpl->Parallel(&slsDetector::lockServer, pos, static_cast(lock)); -} - -Result Detector::getLastClientIP(Positions pos) const { - return pimpl->Parallel(&slsDetector::getLastClientIP, pos); -} - -void Detector::execCommand(const std::string &value, Positions pos) { - pimpl->Parallel(&slsDetector::execCommand, pos, value); +void Detector::sendSoftwareTrigger(Positions pos) { + pimpl->Parallel(&slsDetector::sendSoftwareTrigger, pos); } -Result Detector::getThresholdEnergy(Positions pos) const { - return pimpl->Parallel(&slsDetector::getThresholdEnergy, pos); -} - -void Detector::setThresholdEnergy(int threshold_ev, defs::detectorSettings settings, - bool trimbits, Positions pos) { - pimpl->Parallel(&slsDetector::setThresholdEnergy, pos, threshold_ev, settings, static_cast(trimbits)); -} - -Result Detector::getSettingsDir(Positions pos) const { - return pimpl->Parallel(&slsDetector::getSettingsDir, pos); -} - -void Detector::setSettingsDir(const std::string &value, Positions pos) { - pimpl->Parallel(&slsDetector::setSettingsDir, pos, value); -} - -void Detector::loadTrimbits(const std::string &value, Positions pos) { - pimpl->Parallel(&slsDetector::loadSettingsFile, pos, value); -} +// Network Configuration (Detector<->Receiver) void Detector::configureMAC(Positions pos) { pimpl->Parallel(&slsDetector::configureMAC, pos); } - -Result Detector::getNumberOfAdditionalStorageCells() const { - return pimpl->Parallel(&slsDetector::setTimer, {}, - defs::STORAGE_CELL_NUMBER, -1); +Result Detector::getNumberofUDPInterfaces(Positions pos) const { + return pimpl->Parallel(&slsDetector::getNumberofUDPInterfaces, pos); } -void Detector::setNumberOfAdditionalStorageCells(int64_t value) { - pimpl->Parallel(&slsDetector::setTimer, {}, defs::STORAGE_CELL_NUMBER, - value); +void Detector::setNumberofUDPInterfaces(int n, Positions pos) { + int previouslyClientStreaming = pimpl->enableDataStreamingToClient(); + bool previouslyReceiverStreaming = true;//getRxZmqIP(pos).squash(false); //FIXME TODO + pimpl->Parallel(&slsDetector::setNumberofUDPInterfaces, pos, n); + // redo the zmq sockets if enabled + if (previouslyClientStreaming != 0) { + pimpl->enableDataStreamingToClient(0); + pimpl->enableDataStreamingToClient(1); + } + if (previouslyReceiverStreaming) { + setRxZmqDataStream(false, pos); + setRxZmqDataStream(true, pos); + } } -Result Detector::getStorageCellStart(Positions pos) const { - return pimpl->Parallel(&slsDetector::setStoragecellStart, pos, -1); +Result Detector::getSelectedUDPInterface(Positions pos) const { + return pimpl->Parallel(&slsDetector::getSelectedUDPInterface, pos); } -void Detector::setStoragecellStart(int cell, Positions pos) { - pimpl->Parallel(&slsDetector::setStoragecellStart, pos, cell); +void Detector::selectUDPInterface(int interface, Positions pos) { + pimpl->Parallel(&slsDetector::selectUDPInterface, pos, interface); +} + +Result Detector::getSourceUDPIP(Positions pos) const { + return pimpl->Parallel(&slsDetector::getDetectorIP, pos); +} + +void Detector::setSourceUDPIP(const std::string &ip, Positions pos) { + pimpl->Parallel(&slsDetector::setDetectorIP, pos, ip); +} + +Result Detector::getSourceUDPIP2(Positions pos) const { + return pimpl->Parallel(&slsDetector::getDetectorIP2, pos); +} + +void Detector::setSourceUDPIP2(const std::string &ip, Positions pos) { + pimpl->Parallel(&slsDetector::setDetectorIP2, pos, ip); +} + +Result Detector::getSourceUDPMAC(Positions pos) const { + return pimpl->Parallel(&slsDetector::getDetectorMAC, pos); +} + +void Detector::setSourceUDPMAC(const std::string &mac, Positions pos) { + pimpl->Parallel(&slsDetector::setDetectorMAC, pos, mac); +} + +Result Detector::getSourceUDPMAC2(Positions pos) const { + return pimpl->Parallel(&slsDetector::getDetectorMAC2, pos); +} + +void Detector::setSourceUDPMAC2(const std::string &mac, Positions pos) { + pimpl->Parallel(&slsDetector::setDetectorMAC2, pos, mac); +} + +Result Detector::getDestinationUDPIP(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverUDPIP, pos); +} + +void Detector::setDestinationUDPIP(const std::string &ip, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverUDPIP, pos, ip); +} + +Result Detector::getDestinationUDPIP2(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverUDPIP2, pos); +} + +void Detector::setDestinationUDPIP2(const std::string &ip, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverUDPIP2, pos, ip); +} + +Result Detector::getDestinationUDPMAC(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverUDPMAC, pos); +} + +void Detector::setDestinationUDPMAC(const std::string &mac, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverUDPMAC, pos, mac); +} + +Result Detector::getDestinationUDPMAC2(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverUDPMAC2, pos); +} + +void Detector::setDestinationUDPMAC2(const std::string &mac, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverUDPMAC2, pos, mac); +} + +Result Detector::getDestinationUDPPort(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverUDPPort, pos); +} + +void Detector::setDestinationUDPPort(int port, int module_id) { + if (module_id == -1) { + std::vector port_list = getPortNumbers(port); + for (int idet = 0; idet < size(); ++idet) { + pimpl->Parallel(&slsDetector::setReceiverUDPPort, {idet}, port_list[idet]); + } + } else { + pimpl->Parallel(&slsDetector::setReceiverUDPPort, {module_id}, port); + } +} + +Result Detector::getDestinationUDPPort2(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverUDPPort2, pos); +} + +void Detector::setDestinationUDPPort2(int port, int module_id) { + if (module_id == -1) { + std::vector port_list = getPortNumbers(port); + for (int idet = 0; idet < size(); ++idet) { + pimpl->Parallel(&slsDetector::setReceiverUDPPort2, {idet}, port_list[idet]); + } + } else { + pimpl->Parallel(&slsDetector::setReceiverUDPPort2, {module_id}, port ); + } +} + +Result Detector::printRxConfiguration(Positions pos) const { + return pimpl->Parallel(&slsDetector::printReceiverConfiguration, pos); +} + +Result Detector::getTenGiga(Positions pos) const { + return pimpl->Parallel(&slsDetector::enableTenGigabitEthernet, pos, -1); +} + +void Detector::setTenGiga(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::enableTenGigabitEthernet, pos, + static_cast(value)); +} + +Result Detector::getTenGigaGFlowControl(Positions pos) const { + return pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, + defs::FLOW_CONTROL_10G, -1); +} + +void Detector::setTenGigaGFlowControl(bool enable, Positions pos) { + pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, + defs::FLOW_CONTROL_10G, static_cast(enable)); +} + +Result Detector::getTransmissionDelayFrame(Positions pos) const { + return pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, + defs::DETECTOR_TXN_DELAY_FRAME, -1); +} + +void Detector::setTransmissionDelayFrame(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, + defs::DETECTOR_TXN_DELAY_FRAME, value); +} + +Result Detector::getTransmissionDelayLeft(Positions pos) const { + return pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, + defs::DETECTOR_TXN_DELAY_LEFT, -1); +} + +void Detector::setTransmissionDelayLeft(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, + defs::DETECTOR_TXN_DELAY_LEFT, value); +} + +Result Detector::getTransmissionDelayRight(Positions pos) const { + return pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, + defs::DETECTOR_TXN_DELAY_RIGHT, -1); +} + +void Detector::setTransmissionDelayRight(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, + defs::DETECTOR_TXN_DELAY_RIGHT, value); } -Result Detector::getNumberOfAnalogSamples(Positions pos) const { - return pimpl->Parallel(&slsDetector::setTimer, pos, defs::ANALOG_SAMPLES, - -1); + +// Receiver + +Result Detector::getUseReceiverFlag(Positions pos) const { + return pimpl->Parallel(&slsDetector::getUseReceiverFlag, pos); } -void Detector::setNumberOfAnalogSamples(int64_t value, Positions pos) { - pimpl->Parallel(&slsDetector::setTimer, pos, defs::ANALOG_SAMPLES, value); +Result Detector::getRxHostname(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverHostname, pos); } -Result Detector::getNumberOfDigitalSamples(Positions pos) const { - return pimpl->Parallel(&slsDetector::setTimer, pos, defs::DIGITAL_SAMPLES, - -1); +void Detector::setRxHostname(const std::string &receiver, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverHostname, pos, receiver); } -void Detector::setNumberOfDigitalSamples(int64_t value, Positions pos) { - pimpl->Parallel(&slsDetector::setTimer, pos, defs::DIGITAL_SAMPLES, value); +Result Detector::getRxPort(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverPort, pos); } +void Detector::setRxPort(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverPort, pos, value); +} + +Result Detector::getRxFifoDepth(Positions pos) const { + return pimpl->Parallel(&slsDetector::setReceiverFifoDepth, pos, -1); +} + +void Detector::setRxFifoDepth(int nframes, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverFifoDepth, pos, nframes); +} + +Result Detector::getRxSilentMode(Positions pos) const { + return pimpl->Parallel(&slsDetector::setReceiverSilentMode, pos, -1); +} + +void Detector::setRxSilentMode(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverSilentMode, pos, + static_cast(value)); +} + +Result +Detector::getRxFrameDiscardPolicy(Positions pos) const { + return pimpl->Parallel(&slsDetector::setReceiverFramesDiscardPolicy, pos, + defs::GET_FRAME_DISCARD_POLICY); +} + +void Detector::setRxFrameDiscardPolicy(defs::frameDiscardPolicy f, + Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverFramesDiscardPolicy, pos, f); +} + +Result Detector::getPartialFramesPadding(Positions pos) const { + return pimpl->Parallel(&slsDetector::getPartialFramesPadding, pos); +} + +void Detector::setPartialFramesPadding(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setPartialFramesPadding, pos, value); +} + +Result Detector::getRxUDPSocketBufferSize(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverUDPSocketBufferSize, pos); +} + +void Detector::setRxUDPSocketBufferSize(int64_t udpsockbufsize, + Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverUDPSocketBufferSize, pos, + udpsockbufsize); +} + +Result +Detector::getRxRealUDPSocketBufferSize(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverRealUDPSocketBufferSize, + pos); +} + +Result Detector::getRxLock(Positions pos) { + return pimpl->Parallel(&slsDetector::lockReceiver, pos, -1); +} + +void Detector::setRxLock(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::lockReceiver, pos, static_cast(value)); +} + +Result Detector::getRxLastClientIP(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverLastClientIP, pos); +} + + + +// File + +Result Detector::getFileFormat(Positions pos) const { + return pimpl->Parallel(&slsDetector::getFileFormat, pos); +} + +void Detector::setFileFormat(defs::fileFormat f, Positions pos) { + pimpl->Parallel(&slsDetector::setFileFormat, pos, f); +} + +Result Detector::getFilePath(Positions pos) const { + return pimpl->Parallel(&slsDetector::getFilePath, pos); +} + +void Detector::setFilePath(const std::string &fpath, Positions pos) { + pimpl->Parallel(&slsDetector::setFilePath, pos, fpath); +} + +Result Detector::getFileNamePrefix(Positions pos) const { + return pimpl->Parallel(&slsDetector::setFileName, pos, ""); +} +void Detector::setFileNamePrefix(const std::string &fname, Positions pos) { + pimpl->Parallel(&slsDetector::setFileName, pos, fname); +} + +Result Detector::getAcquisitonIndex(Positions pos) const { + return pimpl->Parallel(&slsDetector::getFileIndex, pos); +} + +void Detector::setAcquisitionIndex(int i, Positions pos) { + pimpl->Parallel(&slsDetector::setFileIndex, pos, i); +} + +Result Detector::getFileWrite(Positions pos) const { + return pimpl->Parallel(&slsDetector::getFileWrite, pos); +} + +void Detector::setFileWrite(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setFileWrite, pos, value); +} + +void Detector::setMasterFileWrite(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setMasterFileWrite, pos, value); +} + +Result Detector::getMasterFileWrite(Positions pos) const { + return pimpl->Parallel(&slsDetector::getMasterFileWrite, pos); +} + +Result Detector::getFileOverWrite(Positions pos) const { + return pimpl->Parallel(&slsDetector::getFileOverWrite, pos); +} + +void Detector::setFileOverWrite(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setFileOverWrite, pos, value); +} + +Result Detector::getFramesPerFile(Positions pos) const { + return pimpl->Parallel(&slsDetector::getFramesPerFile, pos); +} + +void Detector::setFramesPerFile(int n, Positions pos) { + pimpl->Parallel(&slsDetector::setFramesPerFile, pos, n); +} + + + +// Zmq Streaming (Receiver<->Client) + +Result Detector::getRxZmqDataStream(Positions pos) const { + return pimpl->Parallel(&slsDetector::enableDataStreamingFromReceiver, pos, -1); +} + +void Detector::setRxZmqDataStream(bool enable, Positions pos) { + pimpl->Parallel(&slsDetector::enableDataStreamingFromReceiver, pos, + static_cast(enable)); +} + +Result Detector::getRxZmqFrequency(Positions pos) const { + return pimpl->Parallel(&slsDetector::setReceiverStreamingTimer, pos, -1); +} + +void Detector::setRxZmqFrequency(int freq, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverStreamingFrequency, pos, freq); +} + +Result Detector::getRxZmqTimer(Positions pos) const { + return pimpl->Parallel(&slsDetector::setReceiverStreamingTimer, pos, -1); +} + +void Detector::setRxZmqTimer(int time_in_ms, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverStreamingTimer, pos, time_in_ms); +} + +Result Detector::getRxZmqPort(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverStreamingPort, pos); +} + +void Detector::setRxZmqPort(int port, int module_id) { + if (module_id == -1) { + std::vector port_list = getPortNumbers(port); + for (int idet = 0; idet < size(); ++idet) { + pimpl->Parallel(&slsDetector::setReceiverStreamingPort, {idet}, port_list[idet]); + } + } else { + pimpl->Parallel(&slsDetector::setReceiverStreamingPort, {module_id}, port); + } +} + +Result Detector::getRxZmqIP(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverStreamingIP, pos); +} + +void Detector::setRxZmqIP(const std::string &ip, + Positions pos) { + bool previouslyReceiverStreaming = + getRxZmqDataStream(pos).squash(false); + // TODO! probably in one call + pimpl->Parallel(&slsDetector::setReceiverStreamingIP, pos, ip); + if (previouslyReceiverStreaming) { + setRxZmqDataStream(false, pos); + setRxZmqDataStream(true, pos); + } +} + +Result Detector::getClientZmqPort(Positions pos) const { + return pimpl->Parallel(&slsDetector::getClientStreamingPort, pos); +} + +void Detector::setClientZmqPort(int port, int module_id) { + if (module_id == -1) { + std::vector port_list = getPortNumbers(port); + for (int idet = 0; idet < size(); ++idet) { + pimpl->Parallel(&slsDetector::setClientStreamingPort, {idet}, port_list[idet]); + } + } else { + pimpl->Parallel(&slsDetector::setClientStreamingPort, {module_id}, port); + } +} + +Result Detector::getClientZmqIp(Positions pos) const { + return pimpl->Parallel(&slsDetector::getClientStreamingIP, pos); +} + +void Detector::setClientZmqIp(const std::string &ip, + Positions pos) { + int previouslyClientStreaming = pimpl->enableDataStreamingToClient(-1); + // TODO! probably in one call ?? + pimpl->Parallel(&slsDetector::setClientStreamingIP, pos, ip); + if (previouslyClientStreaming != 0) { + pimpl->enableDataStreamingToClient(0); + pimpl->enableDataStreamingToClient(1); + } +} + + + +// Eiger Specific + +Result Detector::getDynamicRange(Positions pos) const { + return pimpl->Parallel(&slsDetector::setDynamicRange, pos, -1); +} + +void Detector::setDynamicRange(int value) { pimpl->setDynamicRange(value); } + Result Detector::getSubExptime(Positions pos) const { return pimpl->Parallel(&slsDetector::setTimer, pos, @@ -377,39 +727,111 @@ void Detector::setSubDeadTime(ns value, Positions pos) { value.count()); } -Result Detector::getStorageCellDelay(Positions pos) const { - return pimpl->Parallel(&slsDetector::setTimer, pos, - defs::STORAGE_CELL_DELAY, -1); +Result Detector::getThresholdEnergy(Positions pos) const { + return pimpl->Parallel(&slsDetector::getThresholdEnergy, pos); } -void Detector::setStorageCellDelay(ns value, Positions pos) { - pimpl->Parallel(&slsDetector::setTimer, pos, defs::STORAGE_CELL_DELAY, - value.count()); +void Detector::setThresholdEnergy(int threshold_ev, defs::detectorSettings settings, + bool trimbits, Positions pos) { + pimpl->Parallel(&slsDetector::setThresholdEnergy, pos, threshold_ev, settings, static_cast(trimbits)); } -Result Detector::getExptimeLeft(Positions pos) const { - return pimpl->Parallel(&slsDetector::getTimeLeft, pos, - defs::ACQUISITION_TIME); +Result Detector::getSettingsDir(Positions pos) const { + return pimpl->Parallel(&slsDetector::getSettingsDir, pos); } -Result Detector::getPeriodLeft(Positions pos) const { - return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::FRAME_PERIOD); +void Detector::setSettingsDir(const std::string &value, Positions pos) { + pimpl->Parallel(&slsDetector::setSettingsDir, pos, value); } - - -Result Detector::getNumberOfFramesFromStart(Positions pos) const { - return pimpl->Parallel(&slsDetector::getTimeLeft, pos, - defs::FRAMES_FROM_START); +void Detector::loadTrimbits(const std::string &value, Positions pos) { + pimpl->Parallel(&slsDetector::loadSettingsFile, pos, value); } -Result Detector::getActualTime(Positions pos) const { - return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::ACTUAL_TIME); +Result Detector::getRxAddGapPixels(Positions pos) const { + return pimpl->Parallel(&slsDetector::enableGapPixels, pos, -1); } -Result Detector::getMeasurementTime(Positions pos) const { - return pimpl->Parallel(&slsDetector::getTimeLeft, pos, - defs::MEASUREMENT_TIME); +void Detector::setRxAddGapPixels(bool enable) { + pimpl->setGapPixelsEnable(enable, {}); +} + +Result Detector::getParallelMode(Positions pos) const { + auto res = pimpl->Parallel(&slsDetector::setReadOutFlags, pos, + defs::GET_READOUT_FLAGS); + Result booleanRes; + for (unsigned int i = 0; i < res.size(); ++i) { + booleanRes[i] = (res[i] & defs::PARALLEL) ? true : false; + } + return booleanRes; +} + +void Detector::setParallelMode(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setReadOutFlags, pos, + value ? defs::PARALLEL : defs::NONPARALLEL); +} + +Result Detector::getOverFlowMode(Positions pos) const { + auto res = pimpl->Parallel(&slsDetector::setReadOutFlags, pos, + defs::GET_READOUT_FLAGS); + Result booleanRes; + for (unsigned int i = 0; i < res.size(); ++i) { + booleanRes[i] = (res[i] & defs::SHOW_OVERFLOW) ? true : false; + } + return booleanRes; +} + +void Detector::setOverFlowMode(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setReadOutFlags, pos, + value ? defs::SHOW_OVERFLOW : defs::NOOVERFLOW); +} + +Result Detector::getBottom(Positions pos) const { + return pimpl->Parallel(&slsDetector::getFlippedDataX, pos); +} + +void Detector::setBottom(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setFlippedDataX, pos, static_cast(value)); +} + +Result Detector::getAllTrimbits(Positions pos) const { + return pimpl->Parallel(&slsDetector::setAllTrimbits, pos, -1); +} + +void Detector::setAllTrimbits(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setAllTrimbits, pos, value); +} + +Result> Detector::getTrimEnergies(Positions pos) const { + return pimpl->Parallel(&slsDetector::getTrimEn, pos); +} + +void Detector::setTrimEnergies(std::vector energies, Positions pos) { + pimpl->Parallel(&slsDetector::setTrimEn, pos, energies); +} + +Result Detector::getRateCorrection(Positions pos) const { + return pimpl->Parallel(&slsDetector::getRateCorrection, pos); +} + +void Detector::setRateCorrection(ns dead_time, Positions pos) { + pimpl->Parallel(&slsDetector::setRateCorrection, pos, 0);//FIXME TODO dead_time); +} + +Result Detector::getPartialReadout(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReadNLines, pos); +} + +void Detector::setPartialReadout(const int lines, Positions pos) { + pimpl->Parallel(&slsDetector::setReadNLines, pos, lines); +} + +Result Detector::getInterruptSubframe(Positions pos) const { + return pimpl->Parallel(&slsDetector::getInterruptSubframe, pos); +} + +void Detector::setInterruptSubframe(const bool enable, Positions pos) { + pimpl->Parallel(&slsDetector::setInterruptSubframe, pos, enable); } Result Detector::getMeasuredPeriod(Positions pos) const { @@ -422,10 +844,272 @@ Result Detector::getMeasuredSubFramePeriod(Positions pos) const { defs::MEASURED_SUBPERIOD); } +Result Detector::getActive(Positions pos) const { + return pimpl->Parallel(&slsDetector::activate, pos, -1); +} + +void Detector::setActive(bool active, Positions pos) { + pimpl->Parallel(&slsDetector::activate, pos, static_cast(active)); +} + +Result Detector::getRxPadDeactivatedMode(Positions pos) const { + return pimpl->Parallel(&slsDetector::setDeactivatedRxrPaddingMode, pos, -1); +} + +void Detector::setRxPadDeactivatedMode(bool pad, Positions pos) { + pimpl->Parallel(&slsDetector::setDeactivatedRxrPaddingMode, pos, + static_cast(pad)); +} + +Result Detector::getPartialReset(Positions pos) const { + return pimpl->Parallel(&slsDetector::setCounterBit, pos, -1); +} + +void Detector::setPartialReset(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setCounterBit, pos, !value); +} + +void Detector::pulsePixel(int n,defs::xy pixel, Positions pos) { + pimpl->Parallel(&slsDetector::pulsePixel, pos, n, pixel.x, pixel.y); +} + +void Detector::pulsePixelNMove(int n, defs::xy pixel, Positions pos) { + pimpl->Parallel(&slsDetector::pulsePixelNMove, pos, n, pixel.x, pixel.y); +} + +void Detector::pulseChip(int n, Positions pos) { + pimpl->Parallel(&slsDetector::pulseChip, pos, n); +} + +Result Detector::getQuad(Positions pos) const { + return pimpl->Parallel(&slsDetector::getQuad, pos); +} + +void Detector::setQuad(const bool value) { + pimpl->setQuad(value); +} +// Jungfrau Specific +Result Detector::getThresholdTemperature(Positions pos) const { + auto res = pimpl->Parallel(&slsDetector::setThresholdTemperature, pos, -1); + for (auto &it : res) { + it /= 1000; + } + return res; +} + +void Detector::setThresholdTemperature(int temp, Positions pos) { + pimpl->Parallel(&slsDetector::setThresholdTemperature, pos, temp * 1000); +} + +Result Detector::getTemperatureControl(Positions pos) const { + return pimpl->Parallel(&slsDetector::setTemperatureControl, pos, -1); +} + +void Detector::setTemperatureControl(bool enable, Positions pos) { + pimpl->Parallel(&slsDetector::setTemperatureControl, pos, + static_cast(enable)); +} + +Result Detector::getTemperatureEvent(Positions pos) const { + return pimpl->Parallel(&slsDetector::setTemperatureEvent, pos, -1); +} + +void Detector::resetTemperatureEvent(Positions pos) { + pimpl->Parallel(&slsDetector::setTemperatureEvent, pos, 0); +} + +Result Detector::getPowerChip(Positions pos) const { + return pimpl->Parallel(&slsDetector::powerChip, pos, -1); +} + +void Detector::setPowerChip(bool on, Positions pos) { + if (on && pimpl->size() > 3) { + for (unsigned int i = 0; i != pimpl->size(); ++i) { + pimpl->powerChip(static_cast(on), i); + usleep(1000 * 1000); + } + } else { + pimpl->Parallel(&slsDetector::powerChip, pos, static_cast(on)); + } +} + +Result Detector::getAutoCompDisable(Positions pos) const { + return pimpl->Parallel(&slsDetector::setAutoComparatorDisableMode, pos, -1); +} + +void Detector::setAutoCompDisable(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setAutoComparatorDisableMode, pos, + static_cast(value)); +} + +Result Detector::getNumberOfAdditionalStorageCells() const { + return pimpl->Parallel(&slsDetector::setTimer, {}, + defs::STORAGE_CELL_NUMBER, -1); +} + +void Detector::setNumberOfAdditionalStorageCells(int64_t value) { + pimpl->Parallel(&slsDetector::setTimer, {}, defs::STORAGE_CELL_NUMBER, + value); +} + +Result Detector::getStorageCellStart(Positions pos) const { + return pimpl->Parallel(&slsDetector::setStoragecellStart, pos, -1); +} + +void Detector::setStoragecellStart(int cell, Positions pos) { + pimpl->Parallel(&slsDetector::setStoragecellStart, pos, cell); +} + +Result Detector::getStorageCellDelay(Positions pos) const { + return pimpl->Parallel(&slsDetector::setTimer, pos, + defs::STORAGE_CELL_DELAY, -1); +} + +void Detector::setStorageCellDelay(ns value, Positions pos) { + pimpl->Parallel(&slsDetector::setTimer, pos, defs::STORAGE_CELL_DELAY, + value.count()); +} + + + +// Gotthard Specific + + +Result Detector::getROI(Positions pos) const { + return pimpl->Parallel(&slsDetector::getROI, pos); +} + +void Detector::setROI(defs::ROI value, int moduleId) { + if (moduleId < 0 && size() > 1) { + throw RuntimeError("Cannot set ROI for all modules simultaneously"); + } + pimpl->Parallel(&slsDetector::setROI, {moduleId}, value); +} + +Result Detector::getExptimeLeft(Positions pos) const { + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, + defs::ACQUISITION_TIME); +} + +Result Detector::getPeriodLeft(Positions pos) const { + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::FRAME_PERIOD); +} + +Result +Detector::getExternalSignalFlags(Positions pos) const { + return pimpl->Parallel(&slsDetector::setExternalSignalFlags, pos, + defs::GET_EXTERNAL_SIGNAL_FLAG); +} + +void Detector::setExternalSignalFlags(defs::externalSignalFlag value, + Positions pos) { + pimpl->Parallel(&slsDetector::setExternalSignalFlags, pos, value); +} + +void Detector::loadDarkImage(const std::string &fname, int module_id) { + if (module_id == -1) { + pimpl->loadImageToDetector(defs::DARK_IMAGE, fname, -1); + } + pimpl->Parallel(&slsDetector::loadImageToDetector, {module_id}, defs::DARK_IMAGE, + fname); +} + +void Detector::loadGainImage(const std::string &fname, int module_id) { + if (module_id == -1) { + pimpl->loadImageToDetector(defs::GAIN_IMAGE, fname, -1); + } + pimpl->Parallel(&slsDetector::loadImageToDetector, {module_id}, defs::GAIN_IMAGE, + fname); +} + +void Detector::getCounterMemoryBlock(const std::string &fname, bool startACQ, + Positions pos) { + if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) { + pimpl->writeCounterBlockFile(fname, static_cast(startACQ), -1); + } + if (pos.size() > 1) { + throw RuntimeError( + "Cannot load get counter memory block on a subset of modules"); + } + pimpl->Parallel(&slsDetector::writeCounterBlockFile, pos, fname, + static_cast(startACQ)); +} + +void Detector::resetCounterBlock(bool startACQ, Positions pos) { + pimpl->Parallel(&slsDetector::resetCounterBlock, pos, + static_cast(startACQ)); +} + +Result Detector::getDigitalTestBit(Positions pos) { + return pimpl->Parallel(&slsDetector::digitalTest, pos, + defs::DIGITAL_BIT_TEST, -1); +} + +Result Detector::setDigitalTestBit(int value, Positions pos) { + return pimpl->Parallel(&slsDetector::digitalTest, pos, + defs::DIGITAL_BIT_TEST, value); +} + + + +// CTB Specific + +Result Detector::getNumberOfAnalogSamples(Positions pos) const { + return pimpl->Parallel(&slsDetector::setTimer, pos, defs::ANALOG_SAMPLES, + -1); +} + +void Detector::setNumberOfAnalogSamples(int64_t value, Positions pos) { + pimpl->Parallel(&slsDetector::setTimer, pos, defs::ANALOG_SAMPLES, value); +} + +Result Detector::getNumberOfDigitalSamples(Positions pos) const { + return pimpl->Parallel(&slsDetector::setTimer, pos, defs::DIGITAL_SAMPLES, + -1); +} + +void Detector::setNumberOfDigitalSamples(int64_t value, Positions pos) { + pimpl->Parallel(&slsDetector::setTimer, pos, defs::DIGITAL_SAMPLES, value); +} + +Result Detector::getSignalType(Positions pos) const { + auto res = pimpl->Parallel(&slsDetector::setReadOutFlags, pos, + defs::GET_READOUT_FLAGS); + for (auto &it : res) { + if (it & defs::ANALOG_AND_DIGITAL) { + it = 2; + } else if (it & defs::DIGITAL_ONLY) { + it = 1; + } else if (it == defs::NORMAL_READOUT) { + it = 0; + } else { + throw RuntimeError("Unknown Signal Type"); + } + } + return res; +} + +void Detector::setSignalType(int value, Positions pos) { + defs::readOutFlags flag; + switch (value) { + case 0: + flag = defs::NORMAL_READOUT; + break; + case 1: + flag = defs::DIGITAL_ONLY; + break; + case 2: + flag = defs::ANALOG_AND_DIGITAL; + break; + default: + throw RuntimeError("Unknown Signal Type"); + } + pimpl->Parallel(&slsDetector::setReadOutFlags, pos, flag); +} Result Detector::getDBITPhase(bool inDeg, Positions pos) const { return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PHASE, -1, @@ -491,20 +1175,6 @@ void Detector::setDBITPipeline(int value, Positions pos) { pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PIPELINE, value, 0); } -Result Detector::getDynamicRange(Positions pos) const { - return pimpl->Parallel(&slsDetector::setDynamicRange, pos, -1); -} - -void Detector::setDynamicRange(int value) { pimpl->setDynamicRange(value); } - -Result Detector::getIODelay(Positions pos) const { - return pimpl->Parallel(&slsDetector::setDAC, pos, -1, defs::IO_DELAY, 0); -} - -void Detector::setIODelay(int value, Positions pos) { - pimpl->Parallel(&slsDetector::setDAC, pos, value, defs::IO_DELAY, 0); -} - Result Detector::getVrefVoltage(bool mV, Positions pos) const { return pimpl->Parallel(&slsDetector::setDAC, pos, -1, defs::ADC_VPP, mV); @@ -584,318 +1254,143 @@ Result Detector::getSlowADC(defs::dacIndex index, Positions pos) const { return pimpl->Parallel(&slsDetector::getADC, pos, index); } - - - - -Result -Detector::getExternalSignalFlags(Positions pos) const { - return pimpl->Parallel(&slsDetector::setExternalSignalFlags, pos, - defs::GET_EXTERNAL_SIGNAL_FLAG); +Result Detector::getADCEnableMask(Positions pos) const { + return pimpl->Parallel(&slsDetector::getADCEnableMask, pos); } -void Detector::setExternalSignalFlags(defs::externalSignalFlag value, - Positions pos) { - pimpl->Parallel(&slsDetector::setExternalSignalFlags, pos, value); +void Detector::setADCEnableMask(uint32_t mask, Positions pos) { + pimpl->Parallel(&slsDetector::setADCEnableMask, pos, mask); } -Result Detector::getParallelMode(Positions pos) const { - auto res = pimpl->Parallel(&slsDetector::setReadOutFlags, pos, - defs::GET_READOUT_FLAGS); - Result booleanRes; - for (unsigned int i = 0; i < res.size(); ++i) { - booleanRes[i] = (res[i] & defs::PARALLEL) ? true : false; - } - return booleanRes; +Result Detector::getADCInvert(Positions pos) const { + return pimpl->Parallel(&slsDetector::getADCInvert, pos); } -void Detector::setParallelMode(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setReadOutFlags, pos, - value ? defs::PARALLEL : defs::NONPARALLEL); +void Detector::setADCInvert(uint32_t value, Positions pos) { + pimpl->Parallel(&slsDetector::setADCInvert, pos, value); } -Result Detector::getOverFlowMode(Positions pos) const { - auto res = pimpl->Parallel(&slsDetector::setReadOutFlags, pos, - defs::GET_READOUT_FLAGS); - Result booleanRes; - for (unsigned int i = 0; i < res.size(); ++i) { - booleanRes[i] = (res[i] & defs::SHOW_OVERFLOW) ? true : false; - } - return booleanRes; +Result Detector::getExternalSamplingSource(Positions pos) const { + return pimpl->Parallel(&slsDetector::getExternalSamplingSource, pos); } -void Detector::setOverFlowMode(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setReadOutFlags, pos, - value ? defs::SHOW_OVERFLOW : defs::NOOVERFLOW); +void Detector::setExternalSamplingSource(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setExternalSamplingSource, pos, value); } -Result Detector::getSignalType(Positions pos) const { - auto res = pimpl->Parallel(&slsDetector::setReadOutFlags, pos, - defs::GET_READOUT_FLAGS); - for (auto &it : res) { - if (it & defs::ANALOG_AND_DIGITAL) { - it = 2; - } else if (it & defs::DIGITAL_ONLY) { - it = 1; - } else if (it == defs::NORMAL_READOUT) { - it = 0; - } else { - throw RuntimeError("Unknown Signal Type"); - } - } - return res; +Result Detector::getExternalSampling(Positions pos) const { + return pimpl->Parallel(&slsDetector::getExternalSampling, pos); } -void Detector::setSignalType(int value, Positions pos) { - defs::readOutFlags flag; - switch (value) { - case 0: - flag = defs::NORMAL_READOUT; - break; - case 1: - flag = defs::DIGITAL_ONLY; - break; - case 2: - flag = defs::ANALOG_AND_DIGITAL; - break; - default: - throw RuntimeError("Unknown Signal Type"); - } - pimpl->Parallel(&slsDetector::setReadOutFlags, pos, flag); +void Detector::setExternalSampling(bool value, Positions pos) { + pimpl->Parallel(&slsDetector::setExternalSampling, pos, value); } -// Erik -Result Detector::getInterruptSubframe(Positions pos) const { - return pimpl->Parallel(&slsDetector::getInterruptSubframe, pos); +Result> Detector::getRxDbitList(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverDbitList, pos); } -void Detector::setInterruptSubframe(const bool enable, Positions pos) { - pimpl->Parallel(&slsDetector::setInterruptSubframe, pos, enable); +void Detector::setRxDbitList(std::vector list, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverDbitList, pos, list); } -void Detector::writeRegister(uint32_t addr, uint32_t val, Positions pos) { - pimpl->Parallel(&slsDetector::writeRegister, pos, addr, val); +Result Detector::getRxDbitOffset(Positions pos) const { + return pimpl->Parallel(&slsDetector::getReceiverDbitOffset, pos); } -Result Detector::readRegister(uint32_t addr, Positions pos) const { - return pimpl->Parallel(&slsDetector::readRegister, pos, addr); +void Detector::setRxDbitOffset(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setReceiverDbitOffset, pos, value); } -void Detector::setBit(uint32_t addr, int bitnr, Positions pos) { - pimpl->Parallel(&slsDetector::setBit, pos, addr, bitnr); +void Detector::setDigitalIODelay(uint64_t pinMask, int delay, Positions pos) { + pimpl->Parallel(&slsDetector::setDigitalIODelay, pos, pinMask, delay); } -void Detector::clearBit(uint32_t addr, int bitnr, Positions pos) { - pimpl->Parallel(&slsDetector::clearBit, pos, addr, bitnr); +Result Detector::getLEDEnable(Positions pos) const { + return pimpl->Parallel(&slsDetector::setLEDEnable, pos, -1); } -Result Detector::getSourceUDPMAC(Positions pos) const { - return pimpl->Parallel(&slsDetector::getDetectorMAC, pos); -} -void Detector::setSourceUDPMAC(const std::string &detectorMAC, Positions pos) { - pimpl->Parallel(&slsDetector::setDetectorMAC, pos, detectorMAC); +void Detector::setLEDEnable(bool enable, Positions pos) { + pimpl->Parallel(&slsDetector::setLEDEnable, pos, static_cast(enable)); } -Result Detector::getDetectorMAC2(Positions pos) const { - return pimpl->Parallel(&slsDetector::getDetectorMAC2, pos); -} -void Detector::setDetectorMAC2(const std::string &detectorMAC, Positions pos) { - pimpl->Parallel(&slsDetector::setDetectorMAC2, pos, detectorMAC); + + +// Pattern + +void Detector::setPattern(const std::string &fname, Positions pos) { + pimpl->Parallel(&slsDetector::setPattern, pos, fname); } -Result Detector::getSourceUDPIP(Positions pos) const { - return pimpl->Parallel(&slsDetector::getDetectorIP, pos); +Result Detector::getPatternIOControl(Positions pos) const { + return pimpl->Parallel(&slsDetector::setPatternIOControl, pos, -1); } -void Detector::setSourceUDPIP(const std::string &detectorIP, Positions pos) { - pimpl->Parallel(&slsDetector::setDetectorIP, pos, detectorIP); +void Detector::setPatternIOControl(uint64_t word, Positions pos) { + pimpl->Parallel(&slsDetector::setPatternIOControl, pos, word); } -Result Detector::getDetectorIP2(Positions pos) const { - return pimpl->Parallel(&slsDetector::getDetectorIP2, pos); +Result Detector::getPatternClockControl(Positions pos) const { + return pimpl->Parallel(&slsDetector::setPatternClockControl, pos, -1); } -void Detector::setDetectorIP2(const std::string &detectorIP, Positions pos) { - pimpl->Parallel(&slsDetector::setDetectorIP2, pos, detectorIP); +void Detector::setPatternClockControl(uint64_t word, Positions pos) { + pimpl->Parallel(&slsDetector::setPatternClockControl, pos, word); } -Result Detector::getRxHostname(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverHostname, pos); +void Detector::setPatternWord(int addr, uint64_t word, Positions pos) { + pimpl->Parallel(&slsDetector::setPatternWord, pos, addr, word); } -void Detector::setRxHostname(const std::string &receiver, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverHostname, pos, receiver); +Result> Detector::getPatternLoops(int level, + Positions pos) const { + return pimpl->Parallel(&slsDetector::setPatternLoops, pos, level, -1, -1, + -1); } -Result Detector::getDestinationUDPIP(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverUDPIP, pos); +void Detector::setPatternLoops(int level, int start, int stop, int n, + Positions pos) { + pimpl->Parallel(&slsDetector::setPatternLoops, pos, level, start, stop, n); } -void Detector::setDestinationUDPIP(const std::string &udpip, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverUDPIP, pos, udpip); +Result Detector::getPatternWaitAddr(int level, Positions pos) const { + return pimpl->Parallel(&slsDetector::setPatternWaitAddr, pos, level, -1); } -Result Detector::getRxUDPIP2(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverUDPIP2, pos); +void Detector::setPatternWaitAddr(int level, int addr, Positions pos) { + pimpl->Parallel(&slsDetector::setPatternWaitAddr, pos, level, addr); } -void Detector::setReceiverUDPIP2(const std::string &udpip, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverUDPIP2, pos, udpip); +Result Detector::getPatternWaitTime(int level, Positions pos) const { + return pimpl->Parallel(&slsDetector::setPatternWaitTime, pos, level, -1); } -Result Detector::getDestinationUDPMAC(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverUDPMAC, pos); +void Detector::setPatternWaitTime(int level, uint64_t t, Positions pos) { + pimpl->Parallel(&slsDetector::setPatternWaitTime, pos, level, t); } -void Detector::setDestinationUDPMAC(const std::string &udpmac, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverUDPMAC, pos, udpmac); +Result Detector::getPatternMask(Positions pos) { + return pimpl->Parallel(&slsDetector::getPatternMask, pos); } -Result Detector::getReceiverUDPMAC2(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverUDPMAC2, pos); +void Detector::setPatternMask(uint64_t mask, Positions pos) { + pimpl->Parallel(&slsDetector::setPatternMask, pos, mask); } -void Detector::setReceiverUDPMAC2(const std::string &udpmac, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverUDPMAC2, pos, udpmac); +Result Detector::getPatternBitMask(Positions pos) const { + return pimpl->Parallel(&slsDetector::getPatternBitMask, pos); } -Result Detector::getReceiverUDPPort(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverUDPPort, pos); +void Detector::setPatternBitMask(uint64_t mask, Positions pos) { + pimpl->Parallel(&slsDetector::setPatternBitMask, pos, mask); } -void Detector::setReceiverUDPPort(int udpport, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverUDPPort, pos, udpport); -} -Result Detector::getReceiverUDPPort2(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverUDPPort2, pos); -} -void Detector::setReceiverUDPPort2(int udpport, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverUDPPort2, pos, udpport); -} +// Moench -Result Detector::getNumberofUDPInterfaces(Positions pos) const { - return pimpl->Parallel(&slsDetector::getNumberofUDPInterfaces, pos); -} - -void Detector::setNumberofUDPInterfaces(int n, Positions pos) { - bool previouslyClientStreaming = getDataStreamingToClient(); - bool previouslyReceiverStreaming = - getDataStreamingFromReceiver(pos).squash(false); - pimpl->Parallel(&slsDetector::setNumberofUDPInterfaces, pos, n); - // redo the zmq sockets if enabled - if (previouslyClientStreaming) { - setDataStreamingToClient(false); - setDataStreamingToClient(true); - } - if (previouslyReceiverStreaming) { - setDataStreamingFromReceiver(false, pos); - setDataStreamingFromReceiver(true, pos); - } -} - -Result Detector::getSelectedUDPInterface(Positions pos) const { - return pimpl->Parallel(&slsDetector::getSelectedUDPInterface, pos); -} - -void Detector::selectUDPInterface(int interface, Positions pos) { - pimpl->Parallel(&slsDetector::selectUDPInterface, pos, interface); -} - -Result Detector::getClientStreamingPort(Positions pos) const { - return pimpl->Parallel(&slsDetector::getClientStreamingPort, pos); -} - -void Detector::setClientDataStreamingInPort(int port, Positions pos) { - if (pos.size() > 1 && pos.size() < pimpl->size()) { - throw RuntimeError( - "Cannot set client streaming port to a subset of modules"); - } - pimpl->setClientDataStreamingInPort(port, pos.empty() ? -1 : pos[0]); -} - -Result Detector::getRxStreamingPort(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverStreamingPort, pos); -} - -void Detector::setRxDataStreamingOutPort(int port, Positions pos) { - if (pos.size() > 1 && pos.size() < pimpl->size()) { - throw RuntimeError( - "Cannot set receiver streaming port to a subset of modules"); - } - pimpl->setReceiverDataStreamingOutPort(port, pos.empty() ? -1 : pos[0]); -} - -Result Detector::getClientStreamingIP(Positions pos) const { - return pimpl->Parallel(&slsDetector::getClientStreamingIP, pos); -} - -void Detector::setClientDataStreamingInIP(const std::string &ip, - Positions pos) { - bool previouslyClientStreaming = getDataStreamingToClient(); - // TODO! probably in one call ?? - pimpl->Parallel(&slsDetector::setClientStreamingIP, pos, ip); - if (previouslyClientStreaming) { - setDataStreamingToClient(false); - setDataStreamingToClient(true); - } -} - -Result Detector::getRxStreamingIP(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverStreamingIP, pos); -} - -void Detector::setRxDataStreamingOutIP(const std::string &ip, - Positions pos) { - bool previouslyReceiverStreaming = - getDataStreamingFromReceiver(pos).squash(false); - // TODO! probably in one call - pimpl->Parallel(&slsDetector::setReceiverStreamingIP, pos, ip); - if (previouslyReceiverStreaming) { - setDataStreamingFromReceiver(false, pos); - setDataStreamingFromReceiver(true, pos); - } -} - -Result Detector::getFlowControl10G(Positions pos) const { - return pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, - defs::FLOW_CONTROL_10G, -1); -} - -void Detector::setFlowControl10G(bool enable, Positions pos) { - pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, - defs::FLOW_CONTROL_10G, static_cast(enable)); -} - -Result Detector::getTransmissionDelayFrame(Positions pos) const { - return pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, - defs::DETECTOR_TXN_DELAY_FRAME, -1); -} - -void Detector::setTransmissionDelayFrame(int value, Positions pos) { - pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, - defs::DETECTOR_TXN_DELAY_FRAME, value); -} - -Result Detector::getTransmissionDelayLeft(Positions pos) const { - return pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, - defs::DETECTOR_TXN_DELAY_LEFT, -1); -} - -void Detector::setTransmissionDelayLeft(int value, Positions pos) { - pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, - defs::DETECTOR_TXN_DELAY_LEFT, value); -} - -Result Detector::getTransmissionDelayRight(Positions pos) const { - return pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, - defs::DETECTOR_TXN_DELAY_RIGHT, -1); -} - -void Detector::setTransmissionDelayRight(int value, Positions pos) { - pimpl->Parallel(&slsDetector::setDetectorNetworkParameter, pos, - defs::DETECTOR_TXN_DELAY_RIGHT, value); +Result Detector::getAdditionalJsonHeader(Positions pos) const { + return pimpl->Parallel(&slsDetector::getAdditionalJsonHeader, pos); } void Detector::setAdditionalJsonHeader(const std::string &jsonheader, @@ -903,10 +1398,6 @@ void Detector::setAdditionalJsonHeader(const std::string &jsonheader, pimpl->Parallel(&slsDetector::setAdditionalJsonHeader, pos, jsonheader); } -Result Detector::getAdditionalJsonHeader(Positions pos) const { - return pimpl->Parallel(&slsDetector::getAdditionalJsonHeader, pos); -} - Result Detector::getAdditionalJsonParameter(const std::string &key, Positions pos) const { return pimpl->Parallel(&slsDetector::getAdditionalJsonParameter, pos, key); @@ -981,219 +1472,9 @@ void Detector::setDetectorMode(defs::detectorModeType value, Positions pos) { "detectorMode", defs::getDetectorModeType(value)); } -Result Detector::getDigitalTestBit(Positions pos) { - return pimpl->Parallel(&slsDetector::digitalTest, pos, - defs::DIGITAL_BIT_TEST, -1); -} -Result Detector::setDigitalTestBit(int value, Positions pos) { - return pimpl->Parallel(&slsDetector::digitalTest, pos, - defs::DIGITAL_BIT_TEST, value); -} -Result Detector::executeFirmwareTest(Positions pos) { - return pimpl->Parallel(&slsDetector::digitalTest, pos, - defs::DETECTOR_FIRMWARE_TEST, -1); -} - -Result Detector::executeBusTest(Positions pos) { - return pimpl->Parallel(&slsDetector::digitalTest, pos, - defs::DETECTOR_BUS_TEST, -1); -} - -void Detector::loadDarkImage(const std::string &fname, Positions pos) { - // TODO! optimize away multiple loads in multi - if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) { - pimpl->loadImageToDetector(defs::DARK_IMAGE, fname, -1); - } - if (pos.size() > 1) { - throw RuntimeError("Cannot load dark image on a subset of modules"); - } - pimpl->Parallel(&slsDetector::loadImageToDetector, pos, defs::DARK_IMAGE, - fname); -} - -void Detector::loadGainImage(const std::string &fname, Positions pos) { - // TODO! optimize away multiple loadsin multi - if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) { - pimpl->loadImageToDetector(defs::GAIN_IMAGE, fname, -1); - } - if (pos.size() > 1) { - throw RuntimeError("Cannot load gain image on a subset of modules"); - } - pimpl->Parallel(&slsDetector::loadImageToDetector, pos, defs::GAIN_IMAGE, - fname); -} - -void Detector::getCounterMemoryBlock(const std::string &fname, bool startACQ, - Positions pos) { - if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) { - pimpl->writeCounterBlockFile(fname, static_cast(startACQ), -1); - } - if (pos.size() > 1) { - throw RuntimeError( - "Cannot load get counter memory block on a subset of modules"); - } - pimpl->Parallel(&slsDetector::writeCounterBlockFile, pos, fname, - static_cast(startACQ)); -} - -void Detector::resetCounterBlock(bool startACQ, Positions pos) { - pimpl->Parallel(&slsDetector::resetCounterBlock, pos, - static_cast(startACQ)); -} - -Result Detector::getCounterBit(Positions pos) const { - return pimpl->Parallel(&slsDetector::setCounterBit, pos, -1); -} - -void Detector::setCounterBit(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setCounterBit, pos, !value); -} - -Result Detector::getROI(Positions pos) const { - return pimpl->Parallel(&slsDetector::getROI, pos); -} - -void Detector::setROI(defs::ROI value, int moduleId) { - if (moduleId < 0 && size() > 1) { - throw RuntimeError("Cannot set ROI for all modules simultaneously"); - } - pimpl->Parallel(&slsDetector::setROI, {moduleId}, value); -} - -Result Detector::getADCEnableMask(Positions pos) const { - return pimpl->Parallel(&slsDetector::getADCEnableMask, pos); -} - -void Detector::setADCEnableMask(uint32_t mask, Positions pos) { - pimpl->Parallel(&slsDetector::setADCEnableMask, pos, mask); -} - -Result Detector::getADCInvert(Positions pos) const { - return pimpl->Parallel(&slsDetector::getADCInvert, pos); -} - -void Detector::setADCInvert(uint32_t value, Positions pos) { - pimpl->Parallel(&slsDetector::setADCInvert, pos, value); -} - -Result Detector::getExternalSamplingSource(Positions pos) const { - return pimpl->Parallel(&slsDetector::getExternalSamplingSource, pos); -} - -void Detector::setExternalSamplingSource(int value, Positions pos) { - pimpl->Parallel(&slsDetector::setExternalSamplingSource, pos, value); -} - -Result Detector::getExternalSampling(Positions pos) const { - return pimpl->Parallel(&slsDetector::getExternalSampling, pos); -} - -void Detector::setExternalSampling(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setExternalSampling, pos, value); -} - -Result> Detector::getRxDbitList(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverDbitList, pos); -} - -void Detector::setRxDbitList(std::vector list, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverDbitList, pos, list); -} - -Result Detector::getRxDbitOffset(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverDbitOffset, pos); -} - -void Detector::setRxDbitOffset(int value, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverDbitOffset, pos, value); -} - -void Detector::writeAdcRegister(uint32_t addr, uint32_t value, Positions pos) { - pimpl->Parallel(&slsDetector::writeAdcRegister, pos, addr, value); -} - -Result Detector::getActive(Positions pos) const { - return pimpl->Parallel(&slsDetector::activate, pos, -1); -} - -void Detector::setActive(bool active, Positions pos) { - pimpl->Parallel(&slsDetector::activate, pos, static_cast(active)); -} - -Result Detector::getBottom(Positions pos) const { - return pimpl->Parallel(&slsDetector::getFlippedDataX, pos); -} - -void Detector::setBottom(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setFlippedDataX, pos, static_cast(value)); -} - -Result Detector::getAllTrimbits(Positions pos) const { - return pimpl->Parallel(&slsDetector::setAllTrimbits, pos, -1); -} - -void Detector::setAllTrimbits(int value, Positions pos) { - pimpl->Parallel(&slsDetector::setAllTrimbits, pos, value); -} - -Result Detector::getGapPixelsEnable(Positions pos) const { - return pimpl->Parallel(&slsDetector::enableGapPixels, pos, -1); -} - -void Detector::setGapPixelsEnable(bool enable) { - pimpl->setGapPixelsEnable(enable, {}); -} - -Result> Detector::getTrimEnergies(Positions pos) const { - return pimpl->Parallel(&slsDetector::getTrimEn, pos); -} - -void Detector::setTrimEnergies(std::vector energies, Positions pos) { - pimpl->Parallel(&slsDetector::setTrimEn, pos, energies); -} - -void Detector::pulsePixel(int n, int x, int y, Positions pos) { - pimpl->Parallel(&slsDetector::pulsePixel, pos, n, x, y); -} - -void Detector::pulsePixelNMove(int n, int x, int y, Positions pos) { - pimpl->Parallel(&slsDetector::pulsePixelNMove, pos, n, x, y); -} - -void Detector::pulseChip(int n, Positions pos) { - pimpl->Parallel(&slsDetector::pulseChip, pos, n); -} - -Result Detector::getThresholdTemperature(Positions pos) const { - auto res = pimpl->Parallel(&slsDetector::setThresholdTemperature, pos, -1); - for (auto &it : res) { - it /= 1000; - } - return res; -} - -void Detector::setThresholdTemperature(int temp, Positions pos) { - pimpl->Parallel(&slsDetector::setThresholdTemperature, pos, temp * 1000); -} - -Result Detector::getTemperatureControl(Positions pos) const { - return pimpl->Parallel(&slsDetector::setTemperatureControl, pos, -1); -} - -void Detector::setTemperatureControl(bool enable, Positions pos) { - pimpl->Parallel(&slsDetector::setTemperatureControl, pos, - static_cast(enable)); -} - -Result Detector::getTemperatureEvent(Positions pos) const { - return pimpl->Parallel(&slsDetector::setTemperatureEvent, pos, -1); -} - -void Detector::ResetTemperatureEvent(Positions pos) { - pimpl->Parallel(&slsDetector::setTemperatureEvent, pos, 0); -} +// Advanced void Detector::programFPGA(const std::string &fname, Positions pos) { FILE_LOG(logINFO) << "Updating Firmware. This can take awhile. Please be patient..."; @@ -1224,359 +1505,113 @@ void Detector::updateFirmwareAndServer(const std::string &sname, rebootController(pos); } -Result Detector::getPowerChip(Positions pos) const { - return pimpl->Parallel(&slsDetector::powerChip, pos, -1); +Result Detector::readRegister(uint32_t addr, Positions pos) const { + return pimpl->Parallel(&slsDetector::readRegister, pos, addr); } -void Detector::setPowerChip(bool on, Positions pos) { - if (on && pimpl->size() > 3) { - for (unsigned int i = 0; i != pimpl->size(); ++i) { - pimpl->powerChip(static_cast(on), i); - usleep(1000 * 1000); - } - } else { - pimpl->Parallel(&slsDetector::powerChip, pos, static_cast(on)); - } +void Detector::writeRegister(uint32_t addr, uint32_t val, Positions pos) { + pimpl->Parallel(&slsDetector::writeRegister, pos, addr, val); } -Result Detector::getAutoCompDisable(Positions pos) const { - return pimpl->Parallel(&slsDetector::setAutoComparatorDisableMode, pos, -1); +void Detector::setBit(uint32_t addr, int bitnr, Positions pos) { + pimpl->Parallel(&slsDetector::setBit, pos, addr, bitnr); } -void Detector::setAutoCompDisable(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setAutoComparatorDisableMode, pos, - static_cast(value)); +void Detector::clearBit(uint32_t addr, int bitnr, Positions pos) { + pimpl->Parallel(&slsDetector::clearBit, pos, addr, bitnr); } -Result Detector::getRateCorrection(Positions pos) const { - return pimpl->Parallel(&slsDetector::getRateCorrection, pos); +Result Detector::executeFirmwareTest(Positions pos) { + return pimpl->Parallel(&slsDetector::digitalTest, pos, + defs::DETECTOR_FIRMWARE_TEST, -1); } -void Detector::setRateCorrection(int64_t dead_time_ns, Positions pos) { - pimpl->Parallel(&slsDetector::setRateCorrection, pos, dead_time_ns); +Result Detector::executeBusTest(Positions pos) { + return pimpl->Parallel(&slsDetector::digitalTest, pos, + defs::DETECTOR_BUS_TEST, -1); } -Result Detector::getStartingFrameNumber(Positions pos) const { - return pimpl->Parallel(&slsDetector::getStartingFrameNumber, pos); +void Detector::writeAdcRegister(uint32_t addr, uint32_t value, Positions pos) { + pimpl->Parallel(&slsDetector::writeAdcRegister, pos, addr, value); } -void Detector::setStartingFrameNumber(uint64_t value, Positions pos) { - pimpl->Parallel(&slsDetector::setStartingFrameNumber, pos, value); + + +// Insignificant + + +Result Detector::getControlPort(Positions pos) const { + return pimpl->Parallel(&slsDetector::getControlPort, pos); } -Result Detector::getTenGigaEnabled(Positions pos) const { - return pimpl->Parallel(&slsDetector::enableTenGigabitEthernet, pos, -1); +void Detector::setControlPort(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setControlPort, pos, value); } -void Detector::setTenGigaEnabled(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::enableTenGigabitEthernet, pos, - static_cast(value)); +Result Detector::getStopPort(Positions pos) const { + return pimpl->Parallel(&slsDetector::getStopPort, pos); } -Result Detector::getLEDEnable(Positions pos) const { - return pimpl->Parallel(&slsDetector::setLEDEnable, pos, -1); +void Detector::setStopPort(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setStopPort, pos, value); } -void Detector::setLEDEnable(bool enable, Positions pos) { - pimpl->Parallel(&slsDetector::setLEDEnable, pos, static_cast(enable)); +Result Detector::getDetectorLock(Positions pos) const { + return pimpl->Parallel(&slsDetector::lockServer, pos, -1); } -void Detector::setDigitalIODelay(uint64_t pinMask, int delay, Positions pos) { - pimpl->Parallel(&slsDetector::setDigitalIODelay, pos, pinMask, delay); -} -// File -Result Detector::getFileFormat(Positions pos) const { - return pimpl->Parallel(&slsDetector::getFileFormat, pos); +void Detector::setDetectorLock(bool lock, Positions pos) { + pimpl->Parallel(&slsDetector::lockServer, pos, static_cast(lock)); } -void Detector::setFileFormat(defs::fileFormat f, Positions pos) { - pimpl->Parallel(&slsDetector::setFileFormat, pos, f); +Result Detector::getLastClientIP(Positions pos) const { + return pimpl->Parallel(&slsDetector::getLastClientIP, pos); } -Result Detector::getFilePath(Positions pos) const { - return pimpl->Parallel(&slsDetector::getFilePath, pos); +void Detector::execCommand(const std::string &value, Positions pos) { + pimpl->Parallel(&slsDetector::execCommand, pos, value); } -void Detector::setFilePath(const std::string &fpath, Positions pos) { - pimpl->Parallel(&slsDetector::setFilePath, pos, fpath); +Result Detector::getNumberOfFramesFromStart(Positions pos) const { + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, + defs::FRAMES_FROM_START); } -Result Detector::getFileNamePrefix(Positions pos) const { - return pimpl->Parallel(&slsDetector::setFileName, pos, ""); -} -void Detector::setFileNamePrefix(const std::string &fname, Positions pos) { - pimpl->Parallel(&slsDetector::setFileName, pos, fname); +Result Detector::getActualTime(Positions pos) const { + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, defs::ACTUAL_TIME); } -Result Detector::getFileIndex(Positions pos) const { - return pimpl->Parallel(&slsDetector::getFileIndex, pos); +Result Detector::getMeasurementTime(Positions pos) const { + return pimpl->Parallel(&slsDetector::getTimeLeft, pos, + defs::MEASUREMENT_TIME); } -void Detector::setFileIndex(int i, Positions pos) { - pimpl->Parallel(&slsDetector::setFileIndex, pos, i); -} +std::string Detector::getUserDetails() const { return pimpl->getUserDetails(); } -Result Detector::getFileWrite(Positions pos) const { - return pimpl->Parallel(&slsDetector::getFileWrite, pos); -} - -void Detector::setFileWrite(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setFileWrite, pos, value); -} - -void Detector::setMasterFileWrite(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setMasterFileWrite, pos, value); -} - -Result Detector::getMasterFileWrite(Positions pos) const { - return pimpl->Parallel(&slsDetector::getMasterFileWrite, pos); -} - -Result Detector::getFileOverWrite(Positions pos) const { - return pimpl->Parallel(&slsDetector::getFileOverWrite, pos); -} - -void Detector::setFileOverWrite(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setFileOverWrite, pos, value); -} - -Result Detector::getFramesPerFile(Positions pos) const { - return pimpl->Parallel(&slsDetector::getFramesPerFile, pos); -} - -void Detector::setFramesPerFile(int n, Positions pos) { - pimpl->Parallel(&slsDetector::setFramesPerFile, pos, n); -} - -// Receiver -Result Detector::getUseReceiverFlag(Positions pos) const { - return pimpl->Parallel(&slsDetector::getUseReceiverFlag, pos); -} - -Result Detector::printRxConfiguration(Positions pos) const { - return pimpl->Parallel(&slsDetector::printReceiverConfiguration, pos); -} - -Result Detector::getRxPort(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverPort, pos); -} - -void Detector::setRxPort(int value, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverPort, pos, value); -} - -Result Detector::getRxLock(Positions pos) { - return pimpl->Parallel(&slsDetector::lockReceiver, pos, -1); -} - -void Detector::setRxLock(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::lockReceiver, pos, static_cast(value)); -} - -Result Detector::getRxLastClientIP(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverLastClientIP, pos); -} - -Result Detector::getRxStreamingFrequency(Positions pos) const { - return pimpl->Parallel(&slsDetector::setReceiverStreamingTimer, pos, -1); -} - -void Detector::setRxStreamingFrequency(int freq, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverStreamingFrequency, pos, freq); -} - -Result Detector::getRxStreamingTimer(Positions pos) const { - return pimpl->Parallel(&slsDetector::setReceiverStreamingTimer, pos, -1); -} - -void Detector::setRxStreamingTimer(int time_in_ms, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverStreamingTimer, pos, time_in_ms); -} - -bool Detector::getDataStreamingToClient() const { - return pimpl->enableDataStreamingToClient(-1); -} - -void Detector::setDataStreamingToClient(bool enable) { - pimpl->enableDataStreamingToClient(static_cast(enable)); -} - -Result Detector::getDataStreamingFromRx(Positions pos) const { - return pimpl->Parallel(&slsDetector::enableDataStreamingFromReceiver, pos, -1); -} - -void Detector::setDataStreamingFromRx(bool enable, Positions pos) { - pimpl->Parallel(&slsDetector::enableDataStreamingFromReceiver, pos, - static_cast(enable)); -} - -Result Detector::getRxFifoDepth(Positions pos) const { - return pimpl->Parallel(&slsDetector::setReceiverFifoDepth, pos, -1); -} - -void Detector::setRxFifoDepth(int nframes, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverFifoDepth, pos, nframes); -} - -Result Detector::getRxSilentMode(Positions pos) const { - return pimpl->Parallel(&slsDetector::setReceiverSilentMode, pos, -1); -} - -void Detector::setRxSilentMode(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverSilentMode, pos, - static_cast(value)); -} - -Result -Detector::getRxFrameDiscardPolicy(Positions pos) const { - return pimpl->Parallel(&slsDetector::setReceiverFramesDiscardPolicy, pos, - defs::GET_FRAME_DISCARD_POLICY); -} - -void Detector::setRxFrameDiscardPolicy(defs::frameDiscardPolicy f, - Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverFramesDiscardPolicy, pos, f); -} - -Result Detector::getPartialFramesPadding(Positions pos) const { - return pimpl->Parallel(&slsDetector::getPartialFramesPadding, pos); -} - -void Detector::setPartialFramesPadding(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setPartialFramesPadding, pos, value); -} - -Result Detector::getRxPadDeactivatedMod(Positions pos) const { - return pimpl->Parallel(&slsDetector::setDeactivatedRxrPaddingMode, pos, -1); -} - -void Detector::setRxPadDeactivatedMod(bool pad, Positions pos) { - pimpl->Parallel(&slsDetector::setDeactivatedRxrPaddingMode, pos, - static_cast(pad)); -} - -Result Detector::getRxUDPSocketBufferSize(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverUDPSocketBufferSize, pos); -} - -void Detector::setRxUDPSocketBufferSize(int64_t udpsockbufsize, - Positions pos) { - pimpl->Parallel(&slsDetector::setReceiverUDPSocketBufferSize, pos, - udpsockbufsize); -} - -Result -Detector::getRxRealUDPSocketBufferSize(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverRealUDPSocketBufferSize, - pos); -} - -// Acquisition - -void Detector::clearAcquiringFlag() { pimpl->setAcquiringFlag(0); } - -Result Detector::getDetectorStatus(Positions pos) const{ - return pimpl->Parallel(&slsDetector::getRunStatus, pos); -} - -void Detector::startAcquisition() { - if (getUseReceiverFlag({}).squash()) - pimpl->Parallel(&slsDetector::startReceiver, {}); - pimpl->Parallel(&slsDetector::startAcquisition, {}); -} - -void Detector::stopAcquisition() { - pimpl->Parallel(&slsDetector::stopAcquisition, {}); - if (getUseReceiverFlag({}).squash()) //TODO: problem for acquire() - pimpl->Parallel(&slsDetector::stopReceiver, {}); -} - -void Detector::sendSoftwareTrigger(Positions pos) { - pimpl->Parallel(&slsDetector::sendSoftwareTrigger, pos); -} - -Result Detector::getRxStatus(Positions pos) const { - return pimpl->Parallel(&slsDetector::getReceiverStatus, pos); -} - -Result Detector::getFramesCaught(Positions pos) const { - return pimpl->Parallel(&slsDetector::getFramesCaughtByReceiver, pos); -} Result Detector::getRxCurrentFrameIndex(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverCurrentFrameIndex, pos); } -// pattern - -void Detector::setPattern(const std::string &fname, Positions pos) { - pimpl->Parallel(&slsDetector::setPattern, pos, fname); +std::vector Detector::getPortNumbers(int start_port) { + int num_sockets_per_detector = 1; + switch (getDetectorType({}).squash()) { + case defs::EIGER: + num_sockets_per_detector *= 2; + break; + case defs::JUNGFRAU: + if(getNumberofUDPInterfaces({}).squash() == 2) { + num_sockets_per_detector *= 2; + } + break; + default: + break; + } + std::vector res; + for (int idet = 0; idet < size(); ++idet) { + res.push_back(start_port + (idet * num_sockets_per_detector)); + } + return res; } -Result Detector::getPatternIOControl(Positions pos) const { - return pimpl->Parallel(&slsDetector::setPatternIOControl, pos, -1); -} - -void Detector::setPatternIOControl(uint64_t word, Positions pos) { - pimpl->Parallel(&slsDetector::setPatternIOControl, pos, word); -} - -Result Detector::getPatternClockControl(Positions pos) const { - return pimpl->Parallel(&slsDetector::setPatternClockControl, pos, -1); -} - -void Detector::setPatternClockControl(uint64_t word, Positions pos) { - pimpl->Parallel(&slsDetector::setPatternClockControl, pos, word); -} - -void Detector::setPatternWord(int addr, uint64_t word, Positions pos) { - pimpl->Parallel(&slsDetector::setPatternWord, pos, addr, word); -} - -Result> Detector::getPatternLoops(int level, - Positions pos) const { - return pimpl->Parallel(&slsDetector::setPatternLoops, pos, level, -1, -1, - -1); -} - -void Detector::setPatternLoops(int level, int start, int stop, int n, - Positions pos) { - pimpl->Parallel(&slsDetector::setPatternLoops, pos, level, start, stop, n); -} - -Result Detector::getPatternWaitAddr(int level, Positions pos) const { - return pimpl->Parallel(&slsDetector::setPatternWaitAddr, pos, level, -1); -} - -void Detector::setPatternWaitAddr(int level, int addr, Positions pos) { - pimpl->Parallel(&slsDetector::setPatternWaitAddr, pos, level, addr); -} - -Result Detector::getPatternWaitTime(int level, Positions pos) const { - return pimpl->Parallel(&slsDetector::setPatternWaitTime, pos, level, -1); -} - -void Detector::setPatternWaitTime(int level, uint64_t t, Positions pos) { - pimpl->Parallel(&slsDetector::setPatternWaitTime, pos, level, t); -} - -Result Detector::getPatternMask(Positions pos) { - return pimpl->Parallel(&slsDetector::getPatternMask, pos); -} - -void Detector::setPatternMask(uint64_t mask, Positions pos) { - pimpl->Parallel(&slsDetector::setPatternMask, pos, mask); -} - -Result Detector::getPatternBitMask(Positions pos) const { - return pimpl->Parallel(&slsDetector::getPatternBitMask, pos); -} - -void Detector::setPatternBitMask(uint64_t mask, Positions pos) { - pimpl->Parallel(&slsDetector::setPatternBitMask, pos, mask); -} - - -std::string Detector::getUserDetails() const { return pimpl->getUserDetails(); } - } // namespace sls \ No newline at end of file From 3e874a365058e857d4cb449be793fcc094d8965e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Fr=C3=B6jdh?= Date: Mon, 19 Aug 2019 20:40:50 +0200 Subject: [PATCH 091/108] removed symlinks in jf server (#49) --- slsDetectorServers/jungfrauDetectorServer/AD9257.h | 1 - .../jungfrauDetectorServer/ALTERA_PLL.h | 1 - slsDetectorServers/jungfrauDetectorServer/LTC2620.h | 1 - slsDetectorServers/jungfrauDetectorServer/MAX1932.h | 1 - slsDetectorServers/jungfrauDetectorServer/Makefile | 13 ++++++++----- slsDetectorServers/jungfrauDetectorServer/ansi.h | 1 - .../jungfrauDetectorServer/blackfin.h | 1 - slsDetectorServers/jungfrauDetectorServer/common.h | 1 - .../jungfrauDetectorServer/commonServerFunctions.h | 1 - .../jungfrauDetectorServer/communication_funcs.c | 1 - .../jungfrauDetectorServer/communication_funcs.h | 1 - .../communication_funcs_UDP.h | 1 - slsDetectorServers/jungfrauDetectorServer/logger.h | 1 - .../jungfrauDetectorServer/programfpga.h | 1 - .../slsDetectorFunctionList.h | 1 - .../jungfrauDetectorServer/slsDetectorServer.c | 1 - .../slsDetectorServer_funcs.c | 1 - .../slsDetectorServer_funcs.h | 1 - .../jungfrauDetectorServer/sls_detector_defs.h | 1 - .../jungfrauDetectorServer/sls_detector_funcs.h | 1 - .../jungfrauDetectorServer/versionAPI.h | 1 - slsSupportLib/include/versionAPI.h | 2 +- 22 files changed, 9 insertions(+), 26 deletions(-) delete mode 120000 slsDetectorServers/jungfrauDetectorServer/AD9257.h delete mode 120000 slsDetectorServers/jungfrauDetectorServer/ALTERA_PLL.h delete mode 120000 slsDetectorServers/jungfrauDetectorServer/LTC2620.h delete mode 120000 slsDetectorServers/jungfrauDetectorServer/MAX1932.h delete mode 120000 slsDetectorServers/jungfrauDetectorServer/ansi.h delete mode 120000 slsDetectorServers/jungfrauDetectorServer/blackfin.h delete mode 120000 slsDetectorServers/jungfrauDetectorServer/common.h delete mode 120000 slsDetectorServers/jungfrauDetectorServer/commonServerFunctions.h delete mode 120000 slsDetectorServers/jungfrauDetectorServer/communication_funcs.c delete mode 120000 slsDetectorServers/jungfrauDetectorServer/communication_funcs.h delete mode 120000 slsDetectorServers/jungfrauDetectorServer/communication_funcs_UDP.h delete mode 120000 slsDetectorServers/jungfrauDetectorServer/logger.h delete mode 120000 slsDetectorServers/jungfrauDetectorServer/programfpga.h delete mode 120000 slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.h delete mode 120000 slsDetectorServers/jungfrauDetectorServer/slsDetectorServer.c delete mode 120000 slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_funcs.c delete mode 120000 slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_funcs.h delete mode 120000 slsDetectorServers/jungfrauDetectorServer/sls_detector_defs.h delete mode 120000 slsDetectorServers/jungfrauDetectorServer/sls_detector_funcs.h delete mode 120000 slsDetectorServers/jungfrauDetectorServer/versionAPI.h diff --git a/slsDetectorServers/jungfrauDetectorServer/AD9257.h b/slsDetectorServers/jungfrauDetectorServer/AD9257.h deleted file mode 120000 index 87b70e097..000000000 --- a/slsDetectorServers/jungfrauDetectorServer/AD9257.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/AD9257.h \ No newline at end of file diff --git a/slsDetectorServers/jungfrauDetectorServer/ALTERA_PLL.h b/slsDetectorServers/jungfrauDetectorServer/ALTERA_PLL.h deleted file mode 120000 index e665f009d..000000000 --- a/slsDetectorServers/jungfrauDetectorServer/ALTERA_PLL.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/ALTERA_PLL.h \ No newline at end of file diff --git a/slsDetectorServers/jungfrauDetectorServer/LTC2620.h b/slsDetectorServers/jungfrauDetectorServer/LTC2620.h deleted file mode 120000 index 13157cb8b..000000000 --- a/slsDetectorServers/jungfrauDetectorServer/LTC2620.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/LTC2620.h \ No newline at end of file diff --git a/slsDetectorServers/jungfrauDetectorServer/MAX1932.h b/slsDetectorServers/jungfrauDetectorServer/MAX1932.h deleted file mode 120000 index 8f7b239ea..000000000 --- a/slsDetectorServers/jungfrauDetectorServer/MAX1932.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/MAX1932.h \ No newline at end of file diff --git a/slsDetectorServers/jungfrauDetectorServer/Makefile b/slsDetectorServers/jungfrauDetectorServer/Makefile index f197d60dd..e9f4db5c4 100755 --- a/slsDetectorServers/jungfrauDetectorServer/Makefile +++ b/slsDetectorServers/jungfrauDetectorServer/Makefile @@ -1,13 +1,16 @@ +current_dir = $(shell pwd) +main_server = ../slsDetectorServer/ +support_lib = ../../slsSupportLib/include/ + CROSS = bfin-uclinux- CC = $(CROSS)gcc -CFLAGS += -Wall -DJUNGFRAUD -DSTOP_SERVER #-DVERBOSEI #-DVERBOSE -LDLIBS += -lm -lstdc++ - +CFLAGS += -Wall -DJUNGFRAUD -DSTOP_SERVER -I$(main_server) -I$(support_lib) -I$(current_dir)#-DVERBOSEI #-DVERBOSE +LDLIBS += -lm PROGS = jungfrauDetectorServer DESTDIR ?= bin INSTMODE = 0777 -SRC_CLNT = communication_funcs.c slsDetectorServer.c slsDetectorServer_funcs.c slsDetectorFunctionList.c +SRC_CLNT = $(main_server)communication_funcs.c $(main_server)slsDetectorServer.c $(main_server)slsDetectorServer_funcs.c slsDetectorFunctionList.c OBJS = $(SRC_CLNT:.c=.o) all: clean versioning $(PROGS) @@ -23,7 +26,7 @@ versioning: $(PROGS): $(OBJS) # echo $(OBJS) mkdir -p $(DESTDIR) - $(CC) -o $@ $^ $(CFLAGS) $(LDLIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LDLIBS) mv $(PROGS) $(DESTDIR) rm *.gdb diff --git a/slsDetectorServers/jungfrauDetectorServer/ansi.h b/slsDetectorServers/jungfrauDetectorServer/ansi.h deleted file mode 120000 index 4a82d0575..000000000 --- a/slsDetectorServers/jungfrauDetectorServer/ansi.h +++ /dev/null @@ -1 +0,0 @@ -../../slsSupportLib/include/ansi.h \ No newline at end of file diff --git a/slsDetectorServers/jungfrauDetectorServer/blackfin.h b/slsDetectorServers/jungfrauDetectorServer/blackfin.h deleted file mode 120000 index 2873c7dc6..000000000 --- a/slsDetectorServers/jungfrauDetectorServer/blackfin.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/blackfin.h \ No newline at end of file diff --git a/slsDetectorServers/jungfrauDetectorServer/common.h b/slsDetectorServers/jungfrauDetectorServer/common.h deleted file mode 120000 index 6776eb607..000000000 --- a/slsDetectorServers/jungfrauDetectorServer/common.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/common.h \ No newline at end of file diff --git a/slsDetectorServers/jungfrauDetectorServer/commonServerFunctions.h b/slsDetectorServers/jungfrauDetectorServer/commonServerFunctions.h deleted file mode 120000 index 33bdd8d53..000000000 --- a/slsDetectorServers/jungfrauDetectorServer/commonServerFunctions.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/commonServerFunctions.h \ No newline at end of file diff --git a/slsDetectorServers/jungfrauDetectorServer/communication_funcs.c b/slsDetectorServers/jungfrauDetectorServer/communication_funcs.c deleted file mode 120000 index 30435fdc4..000000000 --- a/slsDetectorServers/jungfrauDetectorServer/communication_funcs.c +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/communication_funcs.c \ No newline at end of file diff --git a/slsDetectorServers/jungfrauDetectorServer/communication_funcs.h b/slsDetectorServers/jungfrauDetectorServer/communication_funcs.h deleted file mode 120000 index c0c144994..000000000 --- a/slsDetectorServers/jungfrauDetectorServer/communication_funcs.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/communication_funcs.h \ No newline at end of file diff --git a/slsDetectorServers/jungfrauDetectorServer/communication_funcs_UDP.h b/slsDetectorServers/jungfrauDetectorServer/communication_funcs_UDP.h deleted file mode 120000 index 0d434a97d..000000000 --- a/slsDetectorServers/jungfrauDetectorServer/communication_funcs_UDP.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/communication_funcs_UDP.h \ No newline at end of file diff --git a/slsDetectorServers/jungfrauDetectorServer/logger.h b/slsDetectorServers/jungfrauDetectorServer/logger.h deleted file mode 120000 index ff1930ce3..000000000 --- a/slsDetectorServers/jungfrauDetectorServer/logger.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/logger.h \ No newline at end of file diff --git a/slsDetectorServers/jungfrauDetectorServer/programfpga.h b/slsDetectorServers/jungfrauDetectorServer/programfpga.h deleted file mode 120000 index 72c54d21d..000000000 --- a/slsDetectorServers/jungfrauDetectorServer/programfpga.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/programfpga.h \ No newline at end of file diff --git a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.h b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.h deleted file mode 120000 index 345b8c029..000000000 --- a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/slsDetectorFunctionList.h \ No newline at end of file diff --git a/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer.c b/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer.c deleted file mode 120000 index a7eb59acb..000000000 --- a/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer.c +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/slsDetectorServer.c \ No newline at end of file diff --git a/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_funcs.c b/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_funcs.c deleted file mode 120000 index a7532ccd4..000000000 --- a/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_funcs.c +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/slsDetectorServer_funcs.c \ No newline at end of file diff --git a/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_funcs.h b/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_funcs.h deleted file mode 120000 index 7569daf47..000000000 --- a/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_funcs.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/slsDetectorServer_funcs.h \ No newline at end of file diff --git a/slsDetectorServers/jungfrauDetectorServer/sls_detector_defs.h b/slsDetectorServers/jungfrauDetectorServer/sls_detector_defs.h deleted file mode 120000 index 2af30d73a..000000000 --- a/slsDetectorServers/jungfrauDetectorServer/sls_detector_defs.h +++ /dev/null @@ -1 +0,0 @@ -../../slsSupportLib/include/sls_detector_defs.h \ No newline at end of file diff --git a/slsDetectorServers/jungfrauDetectorServer/sls_detector_funcs.h b/slsDetectorServers/jungfrauDetectorServer/sls_detector_funcs.h deleted file mode 120000 index 3f48959a9..000000000 --- a/slsDetectorServers/jungfrauDetectorServer/sls_detector_funcs.h +++ /dev/null @@ -1 +0,0 @@ -../../slsSupportLib/include/sls_detector_funcs.h \ No newline at end of file diff --git a/slsDetectorServers/jungfrauDetectorServer/versionAPI.h b/slsDetectorServers/jungfrauDetectorServer/versionAPI.h deleted file mode 120000 index 5e580d8bb..000000000 --- a/slsDetectorServers/jungfrauDetectorServer/versionAPI.h +++ /dev/null @@ -1 +0,0 @@ -../../slsSupportLib/include/versionAPI.h \ No newline at end of file diff --git a/slsSupportLib/include/versionAPI.h b/slsSupportLib/include/versionAPI.h index 6da66f7d4..fb289063e 100644 --- a/slsSupportLib/include/versionAPI.h +++ b/slsSupportLib/include/versionAPI.h @@ -5,6 +5,6 @@ #define APIRECEIVER 0x190722 #define APIGUI 0x190723 #define APIGOTTHARD 0x190816 -#define APIJUNGFRAU 0x190816 #define APIMOENCH 0x190816 #define APIEIGER 0x190816 +#define APIJUNGFRAU 0x190819 From 498a8bda9fbe9d77d8575dbed8c7a7e734fc4d72 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Mon, 19 Aug 2019 21:09:44 +0200 Subject: [PATCH 092/108] WIP --- .../gotthardDetectorServer/AD9252.h | 1 - .../gotthardDetectorServer/AD9257.h | 1 - .../gotthardDetectorServer/LTC2620.h | 1 - .../gotthardDetectorServer/Makefile | 17 ++++++++++------- .../gotthardDetectorServer/ansi.h | 1 - .../bin/gotthardDetectorServer_developer | Bin 116932 -> 117276 bytes .../gotthardDetectorServer/blackfin.h | 1 - .../gotthardDetectorServer/common.h | 1 - .../commonServerFunctions.h | 1 - .../communication_funcs.c | 1 - .../communication_funcs.h | 1 - .../gotthardDetectorServer/logger.h | 1 - .../slsDetectorFunctionList.h | 1 - .../slsDetectorServer.c | 1 - .../slsDetectorServer_funcs.c | 1 - .../slsDetectorServer_funcs.h | 1 - .../sls_detector_defs.h | 1 - .../sls_detector_funcs.h | 1 - .../gotthardDetectorServer/versionAPI.h | 1 - .../jungfrauDetectorServer/Makefile | 6 +++--- .../bin/jungfrauDetectorServer_developer | Bin 123844 -> 124224 bytes slsSupportLib/include/versionAPI.h | 2 +- 22 files changed, 14 insertions(+), 28 deletions(-) delete mode 120000 slsDetectorServers/gotthardDetectorServer/AD9252.h delete mode 120000 slsDetectorServers/gotthardDetectorServer/AD9257.h delete mode 120000 slsDetectorServers/gotthardDetectorServer/LTC2620.h delete mode 120000 slsDetectorServers/gotthardDetectorServer/ansi.h delete mode 120000 slsDetectorServers/gotthardDetectorServer/blackfin.h delete mode 120000 slsDetectorServers/gotthardDetectorServer/common.h delete mode 120000 slsDetectorServers/gotthardDetectorServer/commonServerFunctions.h delete mode 120000 slsDetectorServers/gotthardDetectorServer/communication_funcs.c delete mode 120000 slsDetectorServers/gotthardDetectorServer/communication_funcs.h delete mode 120000 slsDetectorServers/gotthardDetectorServer/logger.h delete mode 120000 slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.h delete mode 120000 slsDetectorServers/gotthardDetectorServer/slsDetectorServer.c delete mode 120000 slsDetectorServers/gotthardDetectorServer/slsDetectorServer_funcs.c delete mode 120000 slsDetectorServers/gotthardDetectorServer/slsDetectorServer_funcs.h delete mode 120000 slsDetectorServers/gotthardDetectorServer/sls_detector_defs.h delete mode 120000 slsDetectorServers/gotthardDetectorServer/sls_detector_funcs.h delete mode 120000 slsDetectorServers/gotthardDetectorServer/versionAPI.h diff --git a/slsDetectorServers/gotthardDetectorServer/AD9252.h b/slsDetectorServers/gotthardDetectorServer/AD9252.h deleted file mode 120000 index 2ab1ed191..000000000 --- a/slsDetectorServers/gotthardDetectorServer/AD9252.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/AD9252.h \ No newline at end of file diff --git a/slsDetectorServers/gotthardDetectorServer/AD9257.h b/slsDetectorServers/gotthardDetectorServer/AD9257.h deleted file mode 120000 index 87b70e097..000000000 --- a/slsDetectorServers/gotthardDetectorServer/AD9257.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/AD9257.h \ No newline at end of file diff --git a/slsDetectorServers/gotthardDetectorServer/LTC2620.h b/slsDetectorServers/gotthardDetectorServer/LTC2620.h deleted file mode 120000 index 13157cb8b..000000000 --- a/slsDetectorServers/gotthardDetectorServer/LTC2620.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/LTC2620.h \ No newline at end of file diff --git a/slsDetectorServers/gotthardDetectorServer/Makefile b/slsDetectorServers/gotthardDetectorServer/Makefile index 9d606f0c6..81f23deb3 100755 --- a/slsDetectorServers/gotthardDetectorServer/Makefile +++ b/slsDetectorServers/gotthardDetectorServer/Makefile @@ -1,14 +1,17 @@ -CROSS = bfin-uclinux- -CC = $(CROSS)gcc -CFLAGS += -Wall -DGOTTHARDD -DSTOP_SERVER # -DVERBOSE -LDLIBS += -lm -lstdc++ +current_dir = $(shell pwd) +main_server = ../slsDetectorServer/ +support_lib = ../../slsSupportLib/include/ +CROSS = bfin-uclinux- +CC = $(CROSS)gcc +CFLAGS += -Wall -DGOTTHARDD -DSTOP_SERVER -I$(main_server) -I$(support_lib) -I$(current_dir)#-DVERBOSEI #-DVERBOSE +LDLIBS += -lm PROGS = gotthardDetectorServer DESTDIR ?= bin INSTMODE = 0777 -SRCS = communication_funcs.c slsDetectorServer.c slsDetectorServer_funcs.c slsDetectorFunctionList.c -OBJS = $(SRCS:%.c=%.o) +SRCS = $(main_server)communication_funcs.c $(main_server)slsDetectorServer.c $(main_server)slsDetectorServer_funcs.c slsDetectorFunctionList.c +OBJS = $(SRCS:.c=.o) all: clean versioning $(PROGS) @@ -29,7 +32,7 @@ $(PROGS): $(OBJS) rm *.gdb clean: - rm -rf $(DESTDIR)/$(PROGS) *.o *.gdb + rm -rf $(DESTDIR)/$(PROGS) *.o *.gdb $(main_server)*.o diff --git a/slsDetectorServers/gotthardDetectorServer/ansi.h b/slsDetectorServers/gotthardDetectorServer/ansi.h deleted file mode 120000 index 4a82d0575..000000000 --- a/slsDetectorServers/gotthardDetectorServer/ansi.h +++ /dev/null @@ -1 +0,0 @@ -../../slsSupportLib/include/ansi.h \ No newline at end of file diff --git a/slsDetectorServers/gotthardDetectorServer/bin/gotthardDetectorServer_developer b/slsDetectorServers/gotthardDetectorServer/bin/gotthardDetectorServer_developer index 42cfebe0918eda63005c77fb2ec6b0223a067285..70f74637b99338a237926b9234524a179560ffcc 100755 GIT binary patch delta 41652 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 delta 41791 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 K8B{_w)c*fX@x!73 diff --git a/slsDetectorServers/gotthardDetectorServer/blackfin.h b/slsDetectorServers/gotthardDetectorServer/blackfin.h deleted file mode 120000 index 2873c7dc6..000000000 --- a/slsDetectorServers/gotthardDetectorServer/blackfin.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/blackfin.h \ No newline at end of file diff --git a/slsDetectorServers/gotthardDetectorServer/common.h b/slsDetectorServers/gotthardDetectorServer/common.h deleted file mode 120000 index 6776eb607..000000000 --- a/slsDetectorServers/gotthardDetectorServer/common.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/common.h \ No newline at end of file diff --git a/slsDetectorServers/gotthardDetectorServer/commonServerFunctions.h b/slsDetectorServers/gotthardDetectorServer/commonServerFunctions.h deleted file mode 120000 index 33bdd8d53..000000000 --- a/slsDetectorServers/gotthardDetectorServer/commonServerFunctions.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/commonServerFunctions.h \ No newline at end of file diff --git a/slsDetectorServers/gotthardDetectorServer/communication_funcs.c b/slsDetectorServers/gotthardDetectorServer/communication_funcs.c deleted file mode 120000 index 30435fdc4..000000000 --- a/slsDetectorServers/gotthardDetectorServer/communication_funcs.c +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/communication_funcs.c \ No newline at end of file diff --git a/slsDetectorServers/gotthardDetectorServer/communication_funcs.h b/slsDetectorServers/gotthardDetectorServer/communication_funcs.h deleted file mode 120000 index c0c144994..000000000 --- a/slsDetectorServers/gotthardDetectorServer/communication_funcs.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/communication_funcs.h \ No newline at end of file diff --git a/slsDetectorServers/gotthardDetectorServer/logger.h b/slsDetectorServers/gotthardDetectorServer/logger.h deleted file mode 120000 index ff1930ce3..000000000 --- a/slsDetectorServers/gotthardDetectorServer/logger.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/logger.h \ No newline at end of file diff --git a/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.h b/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.h deleted file mode 120000 index 345b8c029..000000000 --- a/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/slsDetectorFunctionList.h \ No newline at end of file diff --git a/slsDetectorServers/gotthardDetectorServer/slsDetectorServer.c b/slsDetectorServers/gotthardDetectorServer/slsDetectorServer.c deleted file mode 120000 index a7eb59acb..000000000 --- a/slsDetectorServers/gotthardDetectorServer/slsDetectorServer.c +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/slsDetectorServer.c \ No newline at end of file diff --git a/slsDetectorServers/gotthardDetectorServer/slsDetectorServer_funcs.c b/slsDetectorServers/gotthardDetectorServer/slsDetectorServer_funcs.c deleted file mode 120000 index a7532ccd4..000000000 --- a/slsDetectorServers/gotthardDetectorServer/slsDetectorServer_funcs.c +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/slsDetectorServer_funcs.c \ No newline at end of file diff --git a/slsDetectorServers/gotthardDetectorServer/slsDetectorServer_funcs.h b/slsDetectorServers/gotthardDetectorServer/slsDetectorServer_funcs.h deleted file mode 120000 index 7569daf47..000000000 --- a/slsDetectorServers/gotthardDetectorServer/slsDetectorServer_funcs.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/slsDetectorServer_funcs.h \ No newline at end of file diff --git a/slsDetectorServers/gotthardDetectorServer/sls_detector_defs.h b/slsDetectorServers/gotthardDetectorServer/sls_detector_defs.h deleted file mode 120000 index 2af30d73a..000000000 --- a/slsDetectorServers/gotthardDetectorServer/sls_detector_defs.h +++ /dev/null @@ -1 +0,0 @@ -../../slsSupportLib/include/sls_detector_defs.h \ No newline at end of file diff --git a/slsDetectorServers/gotthardDetectorServer/sls_detector_funcs.h b/slsDetectorServers/gotthardDetectorServer/sls_detector_funcs.h deleted file mode 120000 index 3f48959a9..000000000 --- a/slsDetectorServers/gotthardDetectorServer/sls_detector_funcs.h +++ /dev/null @@ -1 +0,0 @@ -../../slsSupportLib/include/sls_detector_funcs.h \ No newline at end of file diff --git a/slsDetectorServers/gotthardDetectorServer/versionAPI.h b/slsDetectorServers/gotthardDetectorServer/versionAPI.h deleted file mode 120000 index 5e580d8bb..000000000 --- a/slsDetectorServers/gotthardDetectorServer/versionAPI.h +++ /dev/null @@ -1 +0,0 @@ -../../slsSupportLib/include/versionAPI.h \ No newline at end of file diff --git a/slsDetectorServers/jungfrauDetectorServer/Makefile b/slsDetectorServers/jungfrauDetectorServer/Makefile index e9f4db5c4..c2b2ad18e 100755 --- a/slsDetectorServers/jungfrauDetectorServer/Makefile +++ b/slsDetectorServers/jungfrauDetectorServer/Makefile @@ -10,8 +10,8 @@ PROGS = jungfrauDetectorServer DESTDIR ?= bin INSTMODE = 0777 -SRC_CLNT = $(main_server)communication_funcs.c $(main_server)slsDetectorServer.c $(main_server)slsDetectorServer_funcs.c slsDetectorFunctionList.c -OBJS = $(SRC_CLNT:.c=.o) +SRCS = $(main_server)communication_funcs.c $(main_server)slsDetectorServer.c $(main_server)slsDetectorServer_funcs.c slsDetectorFunctionList.c +OBJS = $(SRCS:.c=.o) all: clean versioning $(PROGS) @@ -31,7 +31,7 @@ $(PROGS): $(OBJS) rm *.gdb clean: - rm -rf $(DESTDIR)/$(PROGS) *.o *.gdb + rm -rf $(DESTDIR)/$(PROGS) *.o *.gdb $(main_server)*.o \ No newline at end of file diff --git a/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer b/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer index 9cbf3a8b0539258f9048a40150b86a036d3683bc..3f3b9d796195149cdf21cc8899f0756a5506178a 100755 GIT binary patch delta 43670 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 delta 43399 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 diff --git a/slsSupportLib/include/versionAPI.h b/slsSupportLib/include/versionAPI.h index fb289063e..20bff5287 100644 --- a/slsSupportLib/include/versionAPI.h +++ b/slsSupportLib/include/versionAPI.h @@ -4,7 +4,7 @@ #define APILIB 0x190723 #define APIRECEIVER 0x190722 #define APIGUI 0x190723 -#define APIGOTTHARD 0x190816 #define APIMOENCH 0x190816 #define APIEIGER 0x190816 #define APIJUNGFRAU 0x190819 +#define APIGOTTHARD 0x190819 From 0d787788ea954b078d0a34fb340b2f848f396bbb Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Mon, 19 Aug 2019 21:14:45 +0200 Subject: [PATCH 093/108] WIP ctb --- slsDetectorServers/ctbDetectorServer/AD7689.h | 1 - slsDetectorServers/ctbDetectorServer/AD9257.h | 1 - .../ctbDetectorServer/ALTERA_PLL.h | 1 - slsDetectorServers/ctbDetectorServer/I2C.h | 1 - slsDetectorServers/ctbDetectorServer/INA226.h | 1 - .../ctbDetectorServer/LTC2620.h | 1 - .../ctbDetectorServer/MAX1932.h | 1 - slsDetectorServers/ctbDetectorServer/Makefile | 18 ++++++++++-------- .../UDPPacketHeaderGenerator.h | 1 - slsDetectorServers/ctbDetectorServer/ansi.h | 1 - .../bin/ctbDetectorServer_developer | Bin 155444 -> 155792 bytes .../ctbDetectorServer/blackfin.h | 1 - slsDetectorServers/ctbDetectorServer/common.h | 1 - .../ctbDetectorServer/commonServerFunctions.h | 1 - .../ctbDetectorServer/communication_funcs.c | 1 - .../ctbDetectorServer/communication_funcs.h | 1 - .../communication_funcs_UDP.h | 1 - slsDetectorServers/ctbDetectorServer/logger.h | 1 - .../ctbDetectorServer/programfpga.h | 1 - .../slsDetectorFunctionList.h | 1 - .../ctbDetectorServer/slsDetectorServer.c | 1 - .../slsDetectorServer_funcs.c | 1 - .../slsDetectorServer_funcs.h | 1 - .../ctbDetectorServer/sls_detector_defs.h | 1 - .../ctbDetectorServer/sls_detector_funcs.h | 1 - .../ctbDetectorServer/versionAPI.h | 1 - slsSupportLib/include/versionAPI.h | 2 +- 27 files changed, 11 insertions(+), 33 deletions(-) delete mode 120000 slsDetectorServers/ctbDetectorServer/AD7689.h delete mode 120000 slsDetectorServers/ctbDetectorServer/AD9257.h delete mode 120000 slsDetectorServers/ctbDetectorServer/ALTERA_PLL.h delete mode 120000 slsDetectorServers/ctbDetectorServer/I2C.h delete mode 120000 slsDetectorServers/ctbDetectorServer/INA226.h delete mode 120000 slsDetectorServers/ctbDetectorServer/LTC2620.h delete mode 120000 slsDetectorServers/ctbDetectorServer/MAX1932.h delete mode 120000 slsDetectorServers/ctbDetectorServer/UDPPacketHeaderGenerator.h delete mode 120000 slsDetectorServers/ctbDetectorServer/ansi.h delete mode 120000 slsDetectorServers/ctbDetectorServer/blackfin.h delete mode 120000 slsDetectorServers/ctbDetectorServer/common.h delete mode 120000 slsDetectorServers/ctbDetectorServer/commonServerFunctions.h delete mode 120000 slsDetectorServers/ctbDetectorServer/communication_funcs.c delete mode 120000 slsDetectorServers/ctbDetectorServer/communication_funcs.h delete mode 120000 slsDetectorServers/ctbDetectorServer/communication_funcs_UDP.h delete mode 120000 slsDetectorServers/ctbDetectorServer/logger.h delete mode 120000 slsDetectorServers/ctbDetectorServer/programfpga.h delete mode 120000 slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.h delete mode 120000 slsDetectorServers/ctbDetectorServer/slsDetectorServer.c delete mode 120000 slsDetectorServers/ctbDetectorServer/slsDetectorServer_funcs.c delete mode 120000 slsDetectorServers/ctbDetectorServer/slsDetectorServer_funcs.h delete mode 120000 slsDetectorServers/ctbDetectorServer/sls_detector_defs.h delete mode 120000 slsDetectorServers/ctbDetectorServer/sls_detector_funcs.h delete mode 120000 slsDetectorServers/ctbDetectorServer/versionAPI.h diff --git a/slsDetectorServers/ctbDetectorServer/AD7689.h b/slsDetectorServers/ctbDetectorServer/AD7689.h deleted file mode 120000 index fe4d6e3ce..000000000 --- a/slsDetectorServers/ctbDetectorServer/AD7689.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/AD7689.h \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/AD9257.h b/slsDetectorServers/ctbDetectorServer/AD9257.h deleted file mode 120000 index 87b70e097..000000000 --- a/slsDetectorServers/ctbDetectorServer/AD9257.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/AD9257.h \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/ALTERA_PLL.h b/slsDetectorServers/ctbDetectorServer/ALTERA_PLL.h deleted file mode 120000 index e665f009d..000000000 --- a/slsDetectorServers/ctbDetectorServer/ALTERA_PLL.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/ALTERA_PLL.h \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/I2C.h b/slsDetectorServers/ctbDetectorServer/I2C.h deleted file mode 120000 index 88ae4a2f3..000000000 --- a/slsDetectorServers/ctbDetectorServer/I2C.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/I2C.h \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/INA226.h b/slsDetectorServers/ctbDetectorServer/INA226.h deleted file mode 120000 index 685ac1f8f..000000000 --- a/slsDetectorServers/ctbDetectorServer/INA226.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/INA226.h \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/LTC2620.h b/slsDetectorServers/ctbDetectorServer/LTC2620.h deleted file mode 120000 index 13157cb8b..000000000 --- a/slsDetectorServers/ctbDetectorServer/LTC2620.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/LTC2620.h \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/MAX1932.h b/slsDetectorServers/ctbDetectorServer/MAX1932.h deleted file mode 120000 index 8f7b239ea..000000000 --- a/slsDetectorServers/ctbDetectorServer/MAX1932.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/MAX1932.h \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/Makefile b/slsDetectorServers/ctbDetectorServer/Makefile index 2d44d49e6..6d8ddd9f4 100755 --- a/slsDetectorServers/ctbDetectorServer/Makefile +++ b/slsDetectorServers/ctbDetectorServer/Makefile @@ -1,17 +1,19 @@ +current_dir = $(shell pwd) +main_server = ../slsDetectorServer/ +support_lib = ../../slsSupportLib/include/ + CROSS = bfin-uclinux- CC = $(CROSS)gcc -CFLAGS += -Wall -DCHIPTESTBOARDD -DSTOP_SERVER #-DDEBUG1 #-DJCTB -DVERBOSEI #-DVERBOSE -LDLIBS += -lm -lstdc++ - +CFLAGS += -Wall -DCHIPTESTBOARDD -DSTOP_SERVER -I$(main_server) -I$(support_lib) -I$(current_dir)#-DVERBOSEI #-DVERBOSE +LDLIBS += -lm PROGS = ctbDetectorServer DESTDIR ?= bin INSTMODE = 0777 -SRC_CLNT = communication_funcs.c slsDetectorServer.c slsDetectorServer_funcs.c slsDetectorFunctionList.c -OBJS = $(SRC_CLNT:.c=.o) +SRCS = $(main_server)communication_funcs.c $(main_server)slsDetectorServer.c $(main_server)slsDetectorServer_funcs.c slsDetectorFunctionList.c +OBJS = $(SRCS:.c=.o) -#all: clean versioning $(PROGS) -all: clean $(PROGS) +all: clean versioning $(PROGS) boot: $(OBJS) @@ -29,7 +31,7 @@ $(PROGS): $(OBJS) rm *.gdb clean: - rm -rf $(DESTDIR)/$(PROGS) *.o *.gdb + rm -rf $(DESTDIR)/$(PROGS) *.o *.gdb $(main_server)*.o diff --git a/slsDetectorServers/ctbDetectorServer/UDPPacketHeaderGenerator.h b/slsDetectorServers/ctbDetectorServer/UDPPacketHeaderGenerator.h deleted file mode 120000 index eb0223a3e..000000000 --- a/slsDetectorServers/ctbDetectorServer/UDPPacketHeaderGenerator.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/UDPPacketHeaderGenerator.h \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/ansi.h b/slsDetectorServers/ctbDetectorServer/ansi.h deleted file mode 120000 index 4a82d0575..000000000 --- a/slsDetectorServers/ctbDetectorServer/ansi.h +++ /dev/null @@ -1 +0,0 @@ -../../slsSupportLib/include/ansi.h \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer b/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer index 42f66de081da4eaff165aad7bcc626395ca5ea9d..449ef09f5e44ca766de80a1081cfeb434fbc819a 100755 GIT binary patch delta 55153 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 diff --git a/slsDetectorServers/ctbDetectorServer/blackfin.h b/slsDetectorServers/ctbDetectorServer/blackfin.h deleted file mode 120000 index 2873c7dc6..000000000 --- a/slsDetectorServers/ctbDetectorServer/blackfin.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/blackfin.h \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/common.h b/slsDetectorServers/ctbDetectorServer/common.h deleted file mode 120000 index 6776eb607..000000000 --- a/slsDetectorServers/ctbDetectorServer/common.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/common.h \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/commonServerFunctions.h b/slsDetectorServers/ctbDetectorServer/commonServerFunctions.h deleted file mode 120000 index 33bdd8d53..000000000 --- a/slsDetectorServers/ctbDetectorServer/commonServerFunctions.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/commonServerFunctions.h \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/communication_funcs.c b/slsDetectorServers/ctbDetectorServer/communication_funcs.c deleted file mode 120000 index 30435fdc4..000000000 --- a/slsDetectorServers/ctbDetectorServer/communication_funcs.c +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/communication_funcs.c \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/communication_funcs.h b/slsDetectorServers/ctbDetectorServer/communication_funcs.h deleted file mode 120000 index c0c144994..000000000 --- a/slsDetectorServers/ctbDetectorServer/communication_funcs.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/communication_funcs.h \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/communication_funcs_UDP.h b/slsDetectorServers/ctbDetectorServer/communication_funcs_UDP.h deleted file mode 120000 index 0d434a97d..000000000 --- a/slsDetectorServers/ctbDetectorServer/communication_funcs_UDP.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/communication_funcs_UDP.h \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/logger.h b/slsDetectorServers/ctbDetectorServer/logger.h deleted file mode 120000 index ff1930ce3..000000000 --- a/slsDetectorServers/ctbDetectorServer/logger.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/logger.h \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/programfpga.h b/slsDetectorServers/ctbDetectorServer/programfpga.h deleted file mode 120000 index 72c54d21d..000000000 --- a/slsDetectorServers/ctbDetectorServer/programfpga.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/programfpga.h \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.h b/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.h deleted file mode 120000 index 345b8c029..000000000 --- a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/slsDetectorFunctionList.h \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/slsDetectorServer.c b/slsDetectorServers/ctbDetectorServer/slsDetectorServer.c deleted file mode 120000 index a7eb59acb..000000000 --- a/slsDetectorServers/ctbDetectorServer/slsDetectorServer.c +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/slsDetectorServer.c \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/slsDetectorServer_funcs.c b/slsDetectorServers/ctbDetectorServer/slsDetectorServer_funcs.c deleted file mode 120000 index a7532ccd4..000000000 --- a/slsDetectorServers/ctbDetectorServer/slsDetectorServer_funcs.c +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/slsDetectorServer_funcs.c \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/slsDetectorServer_funcs.h b/slsDetectorServers/ctbDetectorServer/slsDetectorServer_funcs.h deleted file mode 120000 index 7569daf47..000000000 --- a/slsDetectorServers/ctbDetectorServer/slsDetectorServer_funcs.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/slsDetectorServer_funcs.h \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/sls_detector_defs.h b/slsDetectorServers/ctbDetectorServer/sls_detector_defs.h deleted file mode 120000 index 2af30d73a..000000000 --- a/slsDetectorServers/ctbDetectorServer/sls_detector_defs.h +++ /dev/null @@ -1 +0,0 @@ -../../slsSupportLib/include/sls_detector_defs.h \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/sls_detector_funcs.h b/slsDetectorServers/ctbDetectorServer/sls_detector_funcs.h deleted file mode 120000 index 3f48959a9..000000000 --- a/slsDetectorServers/ctbDetectorServer/sls_detector_funcs.h +++ /dev/null @@ -1 +0,0 @@ -../../slsSupportLib/include/sls_detector_funcs.h \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/versionAPI.h b/slsDetectorServers/ctbDetectorServer/versionAPI.h deleted file mode 120000 index 5e580d8bb..000000000 --- a/slsDetectorServers/ctbDetectorServer/versionAPI.h +++ /dev/null @@ -1 +0,0 @@ -../../slsSupportLib/include/versionAPI.h \ No newline at end of file diff --git a/slsSupportLib/include/versionAPI.h b/slsSupportLib/include/versionAPI.h index 20bff5287..943f78d64 100644 --- a/slsSupportLib/include/versionAPI.h +++ b/slsSupportLib/include/versionAPI.h @@ -1,6 +1,5 @@ /** API versions */ #define GITBRANCH "developer" -#define APICTB 0x190604 #define APILIB 0x190723 #define APIRECEIVER 0x190722 #define APIGUI 0x190723 @@ -8,3 +7,4 @@ #define APIEIGER 0x190816 #define APIJUNGFRAU 0x190819 #define APIGOTTHARD 0x190819 +#define APICTB 0x190819 From 0f37481972c590ec4fec25957893516e1aa41652 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Mon, 19 Aug 2019 21:17:52 +0200 Subject: [PATCH 094/108] WIP --- .../moenchDetectorServer/AD9257.h | 1 - .../moenchDetectorServer/ALTERA_PLL.h | 1 - .../moenchDetectorServer/LTC2620.h | 1 - .../moenchDetectorServer/MAX1932.h | 1 - .../moenchDetectorServer/Makefile | 17 ++++++++++------- .../UDPPacketHeaderGenerator.h | 1 - slsDetectorServers/moenchDetectorServer/ansi.h | 1 - .../moenchDetectorServer/blackfin.h | 1 - .../moenchDetectorServer/common.h | 1 - .../commonServerFunctions.h | 1 - .../moenchDetectorServer/communication_funcs.c | 1 - .../moenchDetectorServer/communication_funcs.h | 1 - .../communication_funcs_UDP.h | 1 - .../moenchDetectorServer/logger.h | 1 - .../moenchDetectorServer/programfpga.h | 1 - .../slsDetectorFunctionList.h | 1 - .../moenchDetectorServer/slsDetectorServer.c | 1 - .../slsDetectorServer_funcs.c | 1 - .../slsDetectorServer_funcs.h | 1 - .../moenchDetectorServer/sls_detector_defs.h | 1 - .../moenchDetectorServer/sls_detector_funcs.h | 1 - .../moenchDetectorServer/versionAPI.h | 1 - slsSupportLib/include/versionAPI.h | 2 +- 23 files changed, 11 insertions(+), 29 deletions(-) delete mode 120000 slsDetectorServers/moenchDetectorServer/AD9257.h delete mode 120000 slsDetectorServers/moenchDetectorServer/ALTERA_PLL.h delete mode 120000 slsDetectorServers/moenchDetectorServer/LTC2620.h delete mode 120000 slsDetectorServers/moenchDetectorServer/MAX1932.h delete mode 120000 slsDetectorServers/moenchDetectorServer/UDPPacketHeaderGenerator.h delete mode 120000 slsDetectorServers/moenchDetectorServer/ansi.h delete mode 120000 slsDetectorServers/moenchDetectorServer/blackfin.h delete mode 120000 slsDetectorServers/moenchDetectorServer/common.h delete mode 120000 slsDetectorServers/moenchDetectorServer/commonServerFunctions.h delete mode 120000 slsDetectorServers/moenchDetectorServer/communication_funcs.c delete mode 120000 slsDetectorServers/moenchDetectorServer/communication_funcs.h delete mode 120000 slsDetectorServers/moenchDetectorServer/communication_funcs_UDP.h delete mode 120000 slsDetectorServers/moenchDetectorServer/logger.h delete mode 120000 slsDetectorServers/moenchDetectorServer/programfpga.h delete mode 120000 slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.h delete mode 120000 slsDetectorServers/moenchDetectorServer/slsDetectorServer.c delete mode 120000 slsDetectorServers/moenchDetectorServer/slsDetectorServer_funcs.c delete mode 120000 slsDetectorServers/moenchDetectorServer/slsDetectorServer_funcs.h delete mode 120000 slsDetectorServers/moenchDetectorServer/sls_detector_defs.h delete mode 120000 slsDetectorServers/moenchDetectorServer/sls_detector_funcs.h delete mode 120000 slsDetectorServers/moenchDetectorServer/versionAPI.h diff --git a/slsDetectorServers/moenchDetectorServer/AD9257.h b/slsDetectorServers/moenchDetectorServer/AD9257.h deleted file mode 120000 index 87b70e097..000000000 --- a/slsDetectorServers/moenchDetectorServer/AD9257.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/AD9257.h \ No newline at end of file diff --git a/slsDetectorServers/moenchDetectorServer/ALTERA_PLL.h b/slsDetectorServers/moenchDetectorServer/ALTERA_PLL.h deleted file mode 120000 index e665f009d..000000000 --- a/slsDetectorServers/moenchDetectorServer/ALTERA_PLL.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/ALTERA_PLL.h \ No newline at end of file diff --git a/slsDetectorServers/moenchDetectorServer/LTC2620.h b/slsDetectorServers/moenchDetectorServer/LTC2620.h deleted file mode 120000 index 13157cb8b..000000000 --- a/slsDetectorServers/moenchDetectorServer/LTC2620.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/LTC2620.h \ No newline at end of file diff --git a/slsDetectorServers/moenchDetectorServer/MAX1932.h b/slsDetectorServers/moenchDetectorServer/MAX1932.h deleted file mode 120000 index 8f7b239ea..000000000 --- a/slsDetectorServers/moenchDetectorServer/MAX1932.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/MAX1932.h \ No newline at end of file diff --git a/slsDetectorServers/moenchDetectorServer/Makefile b/slsDetectorServers/moenchDetectorServer/Makefile index 65960a021..2f2cda415 100755 --- a/slsDetectorServers/moenchDetectorServer/Makefile +++ b/slsDetectorServers/moenchDetectorServer/Makefile @@ -1,15 +1,18 @@ +current_dir = $(shell pwd) +main_server = ../slsDetectorServer/ +support_lib = ../../slsSupportLib/include/ + CROSS = bfin-uclinux- CC = $(CROSS)gcc -CFLAGS += -Wall -DMOENCHD -DSTOP_SERVER -DDEBUG1# -DVERBOSEI #-DVERBOSE -LDLIBS += -lm -lstdc++ - +CFLAGS += -Wall -DMOENCHD -DSTOP_SERVER -I$(main_server) -I$(support_lib) -I$(current_dir)#-DVERBOSEI #-DVERBOSE +LDLIBS += -lm PROGS = moenchDetectorServer DESTDIR ?= bin INSTMODE = 0777 -SRC_CLNT = communication_funcs.c slsDetectorServer.c slsDetectorServer_funcs.c slsDetectorFunctionList.c -OBJS = $(SRC_CLNT:.c=.o) - +SRCS = $(main_server)communication_funcs.c $(main_server)slsDetectorServer.c $(main_server)slsDetectorServer_funcs.c slsDetectorFunctionList.c +OBJS = $(SRCS:.c=.o) + all: clean versioning $(PROGS) boot: $(OBJS) @@ -28,7 +31,7 @@ $(PROGS): $(OBJS) rm *.gdb clean: - rm -rf $(DESTDIR)/$(PROGS) *.o *.gdb + rm -rf $(DESTDIR)/$(PROGS) *.o *.gdb $(main_server)*.o \ No newline at end of file diff --git a/slsDetectorServers/moenchDetectorServer/UDPPacketHeaderGenerator.h b/slsDetectorServers/moenchDetectorServer/UDPPacketHeaderGenerator.h deleted file mode 120000 index eb0223a3e..000000000 --- a/slsDetectorServers/moenchDetectorServer/UDPPacketHeaderGenerator.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/UDPPacketHeaderGenerator.h \ No newline at end of file diff --git a/slsDetectorServers/moenchDetectorServer/ansi.h b/slsDetectorServers/moenchDetectorServer/ansi.h deleted file mode 120000 index 4a82d0575..000000000 --- a/slsDetectorServers/moenchDetectorServer/ansi.h +++ /dev/null @@ -1 +0,0 @@ -../../slsSupportLib/include/ansi.h \ No newline at end of file diff --git a/slsDetectorServers/moenchDetectorServer/blackfin.h b/slsDetectorServers/moenchDetectorServer/blackfin.h deleted file mode 120000 index 2873c7dc6..000000000 --- a/slsDetectorServers/moenchDetectorServer/blackfin.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/blackfin.h \ No newline at end of file diff --git a/slsDetectorServers/moenchDetectorServer/common.h b/slsDetectorServers/moenchDetectorServer/common.h deleted file mode 120000 index 6776eb607..000000000 --- a/slsDetectorServers/moenchDetectorServer/common.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/common.h \ No newline at end of file diff --git a/slsDetectorServers/moenchDetectorServer/commonServerFunctions.h b/slsDetectorServers/moenchDetectorServer/commonServerFunctions.h deleted file mode 120000 index 33bdd8d53..000000000 --- a/slsDetectorServers/moenchDetectorServer/commonServerFunctions.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/commonServerFunctions.h \ No newline at end of file diff --git a/slsDetectorServers/moenchDetectorServer/communication_funcs.c b/slsDetectorServers/moenchDetectorServer/communication_funcs.c deleted file mode 120000 index 30435fdc4..000000000 --- a/slsDetectorServers/moenchDetectorServer/communication_funcs.c +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/communication_funcs.c \ No newline at end of file diff --git a/slsDetectorServers/moenchDetectorServer/communication_funcs.h b/slsDetectorServers/moenchDetectorServer/communication_funcs.h deleted file mode 120000 index c0c144994..000000000 --- a/slsDetectorServers/moenchDetectorServer/communication_funcs.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/communication_funcs.h \ No newline at end of file diff --git a/slsDetectorServers/moenchDetectorServer/communication_funcs_UDP.h b/slsDetectorServers/moenchDetectorServer/communication_funcs_UDP.h deleted file mode 120000 index 0d434a97d..000000000 --- a/slsDetectorServers/moenchDetectorServer/communication_funcs_UDP.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/communication_funcs_UDP.h \ No newline at end of file diff --git a/slsDetectorServers/moenchDetectorServer/logger.h b/slsDetectorServers/moenchDetectorServer/logger.h deleted file mode 120000 index ff1930ce3..000000000 --- a/slsDetectorServers/moenchDetectorServer/logger.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/logger.h \ No newline at end of file diff --git a/slsDetectorServers/moenchDetectorServer/programfpga.h b/slsDetectorServers/moenchDetectorServer/programfpga.h deleted file mode 120000 index 72c54d21d..000000000 --- a/slsDetectorServers/moenchDetectorServer/programfpga.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/programfpga.h \ No newline at end of file diff --git a/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.h b/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.h deleted file mode 120000 index 345b8c029..000000000 --- a/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/slsDetectorFunctionList.h \ No newline at end of file diff --git a/slsDetectorServers/moenchDetectorServer/slsDetectorServer.c b/slsDetectorServers/moenchDetectorServer/slsDetectorServer.c deleted file mode 120000 index a7eb59acb..000000000 --- a/slsDetectorServers/moenchDetectorServer/slsDetectorServer.c +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/slsDetectorServer.c \ No newline at end of file diff --git a/slsDetectorServers/moenchDetectorServer/slsDetectorServer_funcs.c b/slsDetectorServers/moenchDetectorServer/slsDetectorServer_funcs.c deleted file mode 120000 index a7532ccd4..000000000 --- a/slsDetectorServers/moenchDetectorServer/slsDetectorServer_funcs.c +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/slsDetectorServer_funcs.c \ No newline at end of file diff --git a/slsDetectorServers/moenchDetectorServer/slsDetectorServer_funcs.h b/slsDetectorServers/moenchDetectorServer/slsDetectorServer_funcs.h deleted file mode 120000 index 7569daf47..000000000 --- a/slsDetectorServers/moenchDetectorServer/slsDetectorServer_funcs.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/slsDetectorServer_funcs.h \ No newline at end of file diff --git a/slsDetectorServers/moenchDetectorServer/sls_detector_defs.h b/slsDetectorServers/moenchDetectorServer/sls_detector_defs.h deleted file mode 120000 index 2af30d73a..000000000 --- a/slsDetectorServers/moenchDetectorServer/sls_detector_defs.h +++ /dev/null @@ -1 +0,0 @@ -../../slsSupportLib/include/sls_detector_defs.h \ No newline at end of file diff --git a/slsDetectorServers/moenchDetectorServer/sls_detector_funcs.h b/slsDetectorServers/moenchDetectorServer/sls_detector_funcs.h deleted file mode 120000 index 3f48959a9..000000000 --- a/slsDetectorServers/moenchDetectorServer/sls_detector_funcs.h +++ /dev/null @@ -1 +0,0 @@ -../../slsSupportLib/include/sls_detector_funcs.h \ No newline at end of file diff --git a/slsDetectorServers/moenchDetectorServer/versionAPI.h b/slsDetectorServers/moenchDetectorServer/versionAPI.h deleted file mode 120000 index 5e580d8bb..000000000 --- a/slsDetectorServers/moenchDetectorServer/versionAPI.h +++ /dev/null @@ -1 +0,0 @@ -../../slsSupportLib/include/versionAPI.h \ No newline at end of file diff --git a/slsSupportLib/include/versionAPI.h b/slsSupportLib/include/versionAPI.h index 943f78d64..b88b5af91 100644 --- a/slsSupportLib/include/versionAPI.h +++ b/slsSupportLib/include/versionAPI.h @@ -3,8 +3,8 @@ #define APILIB 0x190723 #define APIRECEIVER 0x190722 #define APIGUI 0x190723 -#define APIMOENCH 0x190816 #define APIEIGER 0x190816 #define APIJUNGFRAU 0x190819 #define APIGOTTHARD 0x190819 #define APICTB 0x190819 +#define APIMOENCH 0x190819 From 29c788b9f70cfeacc924bac11ecf78ab4c738daa Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Mon, 19 Aug 2019 21:28:53 +0200 Subject: [PATCH 095/108] WIP --- .../eigerDetectorServer/Makefile | 24 ++++++++++-------- slsDetectorServers/eigerDetectorServer/ansi.h | 1 - .../bin/eigerDetectorServer_developer | Bin 302616 -> 302608 bytes .../eigerDetectorServer/common.h | 1 - .../eigerDetectorServer/communication_funcs.c | 1 - .../eigerDetectorServer/communication_funcs.h | 1 - .../communication_funcs_UDP.h | 1 - .../eigerDetectorServer/logger.h | 1 - .../slsDetectorFunctionList.h | 1 - .../eigerDetectorServer/slsDetectorServer.c | 1 - .../slsDetectorServer_funcs.c | 1 - .../slsDetectorServer_funcs.h | 1 - .../eigerDetectorServer/sls_detector_defs.h | 1 - .../eigerDetectorServer/sls_detector_funcs.h | 1 - .../eigerDetectorServer/versionAPI.h | 1 - slsSupportLib/include/versionAPI.h | 2 +- 16 files changed, 14 insertions(+), 25 deletions(-) delete mode 120000 slsDetectorServers/eigerDetectorServer/ansi.h delete mode 120000 slsDetectorServers/eigerDetectorServer/common.h delete mode 120000 slsDetectorServers/eigerDetectorServer/communication_funcs.c delete mode 120000 slsDetectorServers/eigerDetectorServer/communication_funcs.h delete mode 120000 slsDetectorServers/eigerDetectorServer/communication_funcs_UDP.h delete mode 120000 slsDetectorServers/eigerDetectorServer/logger.h delete mode 120000 slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.h delete mode 120000 slsDetectorServers/eigerDetectorServer/slsDetectorServer.c delete mode 120000 slsDetectorServers/eigerDetectorServer/slsDetectorServer_funcs.c delete mode 120000 slsDetectorServers/eigerDetectorServer/slsDetectorServer_funcs.h delete mode 120000 slsDetectorServers/eigerDetectorServer/sls_detector_defs.h delete mode 120000 slsDetectorServers/eigerDetectorServer/sls_detector_funcs.h delete mode 120000 slsDetectorServers/eigerDetectorServer/versionAPI.h diff --git a/slsDetectorServers/eigerDetectorServer/Makefile b/slsDetectorServers/eigerDetectorServer/Makefile index 88ec734f7..f81cbd82e 100755 --- a/slsDetectorServers/eigerDetectorServer/Makefile +++ b/slsDetectorServers/eigerDetectorServer/Makefile @@ -1,16 +1,18 @@ -CC = powerpc-4xx-softfloat-gcc -BLACKFIN_CC = bfin-uclinux-gcc -CFLAGS += -Wall -DEIGERD -DSTOP_SERVER #-DVERBOSEI #-DVERBOSE -DPCCOMPILE -DMARTIN -LDLIBS += -lm -lstdc++ +current_dir = $(shell pwd) +main_server = ../slsDetectorServer/ +support_lib = ../../slsSupportLib/include/ +CROSS = powerpc-4xx-softfloat- +BLACKFIN_CC = bfin-uclinux-gcc +CC = $(CROSS)gcc +CFLAGS += -Wall -DEIGERD -DSTOP_SERVER -I$(main_server) -I$(support_lib) -I$(current_dir)#-DVERBOSEI #-DVERBOSE +LDLIBS += -lm PROGS = eigerDetectorServer DESTDIR ?= bin INSTMODE = 0777 - -SRC_CLNT = communication_funcs.c slsDetectorServer.c slsDetectorServer_funcs.c slsDetectorFunctionList.c HardwareIO.c LocalLinkInterface.c FebInterface.c FebControl.c Beb.c -OBJS = $(SRC_CLNT:.c=.o) - +SRCS = $(main_server)communication_funcs.c $(main_server)slsDetectorServer.c $(main_server)slsDetectorServer_funcs.c slsDetectorFunctionList.c HardwareIO.c LocalLinkInterface.c FebInterface.c FebControl.c Beb.c +OBJS = $(SRCS:.c=.o) all: clean versioning $(PROGS) #hv9m_blackfin_server @@ -26,16 +28,16 @@ versioning: $(PROGS): $(OBJS) # echo $(OBJS) mkdir -p $(DESTDIR) - $(CC) -o $@ $(SRC_CLNT) $(CFLAGS) $(LDLIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LDLIBS) mv $(PROGS) $(DESTDIR) hv9m_blackfin_server:9mhvserial_bf.c $(BLACKFIN_CC) -o hv9m_blackfin_server 9mhvserial_bf.c -Wall #-DVERBOSE mv hv9m_blackfin_server $(DESTDIR) - rm hv9m_blackfin_server.gdb + rm hv9m_blackfin_server.gdb $(main_server)*.o clean: - rm -rf $(DESTDIR)/$(PROGS) *.o $(DESTDIR)/hv9m_blackfin_server + rm -rf $(DESTDIR)/$(PROGS) *.o $(DESTDIR)/hv9m_blackfin_server $(main_server)*.o diff --git a/slsDetectorServers/eigerDetectorServer/ansi.h b/slsDetectorServers/eigerDetectorServer/ansi.h deleted file mode 120000 index 4a82d0575..000000000 --- a/slsDetectorServers/eigerDetectorServer/ansi.h +++ /dev/null @@ -1 +0,0 @@ -../../slsSupportLib/include/ansi.h \ No newline at end of file diff --git a/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer b/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer index b7aa410527d9c9507ac91466b86eb9e60427c18b..802dbd8416febb8ebdd55306101e2fde8c1c7377 100755 GIT binary patch delta 53578 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 delta 53547 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 diff --git a/slsDetectorServers/eigerDetectorServer/common.h b/slsDetectorServers/eigerDetectorServer/common.h deleted file mode 120000 index 6776eb607..000000000 --- a/slsDetectorServers/eigerDetectorServer/common.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/common.h \ No newline at end of file diff --git a/slsDetectorServers/eigerDetectorServer/communication_funcs.c b/slsDetectorServers/eigerDetectorServer/communication_funcs.c deleted file mode 120000 index 30435fdc4..000000000 --- a/slsDetectorServers/eigerDetectorServer/communication_funcs.c +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/communication_funcs.c \ No newline at end of file diff --git a/slsDetectorServers/eigerDetectorServer/communication_funcs.h b/slsDetectorServers/eigerDetectorServer/communication_funcs.h deleted file mode 120000 index c0c144994..000000000 --- a/slsDetectorServers/eigerDetectorServer/communication_funcs.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/communication_funcs.h \ No newline at end of file diff --git a/slsDetectorServers/eigerDetectorServer/communication_funcs_UDP.h b/slsDetectorServers/eigerDetectorServer/communication_funcs_UDP.h deleted file mode 120000 index 0d434a97d..000000000 --- a/slsDetectorServers/eigerDetectorServer/communication_funcs_UDP.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/communication_funcs_UDP.h \ No newline at end of file diff --git a/slsDetectorServers/eigerDetectorServer/logger.h b/slsDetectorServers/eigerDetectorServer/logger.h deleted file mode 120000 index ff1930ce3..000000000 --- a/slsDetectorServers/eigerDetectorServer/logger.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/logger.h \ No newline at end of file diff --git a/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.h b/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.h deleted file mode 120000 index 345b8c029..000000000 --- a/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/slsDetectorFunctionList.h \ No newline at end of file diff --git a/slsDetectorServers/eigerDetectorServer/slsDetectorServer.c b/slsDetectorServers/eigerDetectorServer/slsDetectorServer.c deleted file mode 120000 index a7eb59acb..000000000 --- a/slsDetectorServers/eigerDetectorServer/slsDetectorServer.c +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/slsDetectorServer.c \ No newline at end of file diff --git a/slsDetectorServers/eigerDetectorServer/slsDetectorServer_funcs.c b/slsDetectorServers/eigerDetectorServer/slsDetectorServer_funcs.c deleted file mode 120000 index a7532ccd4..000000000 --- a/slsDetectorServers/eigerDetectorServer/slsDetectorServer_funcs.c +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/slsDetectorServer_funcs.c \ No newline at end of file diff --git a/slsDetectorServers/eigerDetectorServer/slsDetectorServer_funcs.h b/slsDetectorServers/eigerDetectorServer/slsDetectorServer_funcs.h deleted file mode 120000 index 7569daf47..000000000 --- a/slsDetectorServers/eigerDetectorServer/slsDetectorServer_funcs.h +++ /dev/null @@ -1 +0,0 @@ -../slsDetectorServer/slsDetectorServer_funcs.h \ No newline at end of file diff --git a/slsDetectorServers/eigerDetectorServer/sls_detector_defs.h b/slsDetectorServers/eigerDetectorServer/sls_detector_defs.h deleted file mode 120000 index 2af30d73a..000000000 --- a/slsDetectorServers/eigerDetectorServer/sls_detector_defs.h +++ /dev/null @@ -1 +0,0 @@ -../../slsSupportLib/include/sls_detector_defs.h \ No newline at end of file diff --git a/slsDetectorServers/eigerDetectorServer/sls_detector_funcs.h b/slsDetectorServers/eigerDetectorServer/sls_detector_funcs.h deleted file mode 120000 index 3f48959a9..000000000 --- a/slsDetectorServers/eigerDetectorServer/sls_detector_funcs.h +++ /dev/null @@ -1 +0,0 @@ -../../slsSupportLib/include/sls_detector_funcs.h \ No newline at end of file diff --git a/slsDetectorServers/eigerDetectorServer/versionAPI.h b/slsDetectorServers/eigerDetectorServer/versionAPI.h deleted file mode 120000 index 5e580d8bb..000000000 --- a/slsDetectorServers/eigerDetectorServer/versionAPI.h +++ /dev/null @@ -1 +0,0 @@ -../../slsSupportLib/include/versionAPI.h \ No newline at end of file diff --git a/slsSupportLib/include/versionAPI.h b/slsSupportLib/include/versionAPI.h index b88b5af91..c1c9c91c8 100644 --- a/slsSupportLib/include/versionAPI.h +++ b/slsSupportLib/include/versionAPI.h @@ -3,8 +3,8 @@ #define APILIB 0x190723 #define APIRECEIVER 0x190722 #define APIGUI 0x190723 -#define APIEIGER 0x190816 #define APIJUNGFRAU 0x190819 #define APIGOTTHARD 0x190819 #define APICTB 0x190819 #define APIMOENCH 0x190819 +#define APIEIGER 0x190819 From 51a3f3fd4de49cb3038e0aaae15d159b6bc2f9bc Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Tue, 20 Aug 2019 08:48:12 +0200 Subject: [PATCH 096/108] changed logger.h to clogger.h for c files --- .../bin/ctbDetectorServer_developer | Bin 155792 -> 155792 bytes .../slsDetectorFunctionList.c | 2 +- slsDetectorServers/eigerDetectorServer/Beb.c | 2 +- .../eigerDetectorServer/CMakeLists.txt | 11 ++++++++--- .../eigerDetectorServer/FebControl.c | 2 +- .../eigerDetectorServer/FebInterface.c | 2 +- .../eigerDetectorServer/LocalLinkInterface.c | 2 +- .../bin/eigerDetectorServer_developer | Bin 302608 -> 302608 bytes .../slsDetectorFunctionList.c | 2 +- .../bin/gotthardDetectorServer_developer | Bin 117276 -> 117276 bytes .../slsDetectorFunctionList.c | 2 +- .../jungfrauDetectorServer/CMakeLists.txt | 11 ++++++++--- .../bin/jungfrauDetectorServer_developer | Bin 124224 -> 124224 bytes .../slsDetectorFunctionList.c | 2 +- .../slsDetectorFunctionList.c | 2 +- .../UDPPacketHeaderGenerator.h | 2 +- .../slsDetectorServer/{logger.h => clogger.h} | 0 .../slsDetectorServer/communication_funcs.c | 2 +- .../communication_funcs_UDP.h | 2 +- .../slsDetectorFunctionList.h | 2 +- .../slsDetectorServer/slsDetectorServer.c | 2 +- .../slsDetectorServer_funcs.c | 2 +- .../slsDetectorServer_funcs.h | 2 +- slsSupportLib/include/versionAPI.h | 10 +++++----- 24 files changed, 37 insertions(+), 27 deletions(-) rename slsDetectorServers/slsDetectorServer/{logger.h => clogger.h} (100%) diff --git a/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer b/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer index 449ef09f5e44ca766de80a1081cfeb434fbc819a..61e1d440bb9904cb7e5ce82dda2630362bfaa4f9 100755 GIT binary patch delta 925 zcmXYvT}TvB9L4{48%@n@Otzib%AGaPG&ReJjReP#3KQBgBdUijtS1FSdnlolA|euY zyVBP7p+bZ&k&?^odd;r~k?O&~poap7D_s%OH{;Ic0lQ3aO&gu9?|b`3H%>|KzWIqjx zAtyIYgUF4?@MYP2Vq#B9KI6ajO{|Ukyn16hO^C^)iZk4$3HWZs3JlW@qXm*@XjZ&- zT5ixRR?O>v?o>&Y9Iv+r^h zk;hcXQw#0~Z-Qa)KG+A&fp5VDa8V&`1CeHc0k8^e23x@%@D4Zvjwz(46X{tX`gQc{ z@agdB@agdBpTVyR<$JSEGh|=ignU- H?J)iT>L*2~ delta 986 zcmXw%T}TvB9L4{48*7!#2F-S6O`SE+{HiUBzDP#t3p3fuA|z;|MS761>>(;jE24;E zw~3V1Qi4K)pv-M|9TN?rARiR0hw8!GH3JLUAju%w&Q1k;_IKyrbIzSRGlAjM0DeVt z>Sr?BTE8;o(I(lsqfnXcmRIIC%E3ymbuoyD7RfsIBL#_0rkjjGSmIKjN;PRn(RdEvTgY*Y%%8sXY2dt!D^sz2J@YR^=3-h%`rYMIYG7$e+6GxH(Q zXatoKR%bj_^3H0k$vkSUZDvhatLXT7Xx-F!BHhiSI{%IaNX%y~W~;U5O4b5bNe6cF zd(0KF=9txTnMSdCE|jTN^Gg|NkQ_{ilQU#ejON=F z{EK%i-cPZFxNBT-xepKgh)3PL>9^g!7_Y4djgTm#36op0UjBu;kdd;nueWKi7vX5GgciX-I-k#8*?{MyO!gmGr^qQ|A#1tC^!><$;@sv3zL zoNCNmh|w}@v;b%N`{5bw;oS4la3mUL@w}9VFi}I~!E2Vj^=t)^vq~c87O)z;23`km zgLl9;;9GDCoR&z*B~tRi^ diff --git a/slsDetectorServers/eigerDetectorServer/FebInterface.c b/slsDetectorServers/eigerDetectorServer/FebInterface.c index 9c7d33051..d4fa1815c 100755 --- a/slsDetectorServers/eigerDetectorServer/FebInterface.c +++ b/slsDetectorServers/eigerDetectorServer/FebInterface.c @@ -1,7 +1,7 @@ #include "FebInterface.h" #include "LocalLinkInterface.h" #include "xparameters.h" -#include "logger.h" +#include "clogger.h" #include diff --git a/slsDetectorServers/eigerDetectorServer/LocalLinkInterface.c b/slsDetectorServers/eigerDetectorServer/LocalLinkInterface.c index 3e47cd61a..0e3cc52bc 100755 --- a/slsDetectorServers/eigerDetectorServer/LocalLinkInterface.c +++ b/slsDetectorServers/eigerDetectorServer/LocalLinkInterface.c @@ -1,6 +1,6 @@ #include "LocalLinkInterface.h" #include "HardwareMMappingDefs.h" -#include "logger.h" +#include "clogger.h" #include #include diff --git a/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer b/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer index 802dbd8416febb8ebdd55306101e2fde8c1c7377..2caab4127a7ee9f93566a1dd9ce43c7be99d6ce6 100755 GIT binary patch delta 35 qcmbQRM`*$xp$&`885K4!F^^xzsL;&vtexcufXL-iVvjYGF7!BS4 delta 35 qcmbQRM`*$xp$&`886`I_F^^xzDA~;NtexcufXL-iVvjYGD>kZHV diff --git a/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c index 2cbc68982..eedc0b4d6 100755 --- a/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c @@ -1,6 +1,6 @@ #include "slsDetectorFunctionList.h" #include "versionAPI.h" -#include "logger.h" +#include "clogger.h" #include "common.h" #ifndef VIRTUAL diff --git a/slsDetectorServers/gotthardDetectorServer/bin/gotthardDetectorServer_developer b/slsDetectorServers/gotthardDetectorServer/bin/gotthardDetectorServer_developer index 70f74637b99338a237926b9234524a179560ffcc..a6acd6dcf9cffd338eb7c14bd6c1335396420c70 100755 GIT binary patch delta 28014 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 Pt5DRUV_UvdmOK0(R1`HY diff --git a/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c index c8b277102..9c2bbebb7 100755 --- a/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c @@ -1,6 +1,6 @@ #include "slsDetectorFunctionList.h" #include "versionAPI.h" -#include "logger.h" +#include "clogger.h" #include "RegisterDefs.h" #ifndef VIRTUAL diff --git a/slsDetectorServers/jungfrauDetectorServer/CMakeLists.txt b/slsDetectorServers/jungfrauDetectorServer/CMakeLists.txt index 50574aa34..a7461a986 100644 --- a/slsDetectorServers/jungfrauDetectorServer/CMakeLists.txt +++ b/slsDetectorServers/jungfrauDetectorServer/CMakeLists.txt @@ -1,8 +1,13 @@ add_executable(jungfrauDetectorServer slsDetectorFunctionList.c - slsDetectorServer.c - slsDetectorServer_funcs.c - communication_funcs.c + ../slsDetectorServer/slsDetectorServer.c + ../slsDetectorServer/slsDetectorServer_funcs.c + ../slsDetectorServer/communication_funcs.c +) + +include_directories( + ../slsDetectorServer/ + ../../slsSupportLib/include ) target_include_directories(jungfrauDetectorServer diff --git a/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer b/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer index 3f3b9d796195149cdf21cc8899f0756a5506178a..085e1a7aa7cd945dc0c72c9edc5e7d70b2bf910d 100755 GIT binary patch delta 921 zcmXAnTSyd99LE2L)=OqFwro4ImCjmZTAJF+7E-ezAsV=97pRx*Zcv~ofoZxc^b!Uu zC$y`q5m8UA80@acYAp#d=mI|UAhE-dlCBnXp^)v{>EWB-nRCAH`_F+%OlKvgvqHs7 z4h^0htOzl6q*`&-ZBT!QmCC}?O25}kHZX{!w}*0F3i%ZgFuhY7>lI;`pBf1Anz@Y( zS{Wxf#dP70Z}gM=%yhh;<-<+~JHw;S0{1dBtWpefeIunMZ!$x8E$y74e;FQR!2-_ABM_?DD0@V&P!6T{X;RBp_MO{Niw&@D1(E zkHjM9>L#|xAFBma1& zytY~{(kqKYJJH3n-@EfY@AH1|;l!rWV^itv zMJcuM>5kHNruH3B>_-dLUm>Neph*ck>n{c!2~+u3>&2FlUxAKU_S3 zN%d}C8cois$}JYh6CJgcZsscx^+fVht4G}J$$*p~*$%78tVv`+@+-CTpqXW3?G}VR zFivZwY{m#`JNFEp{~txN>!#vNHY&#`DH)VJKFakp0GQZ4o@V)+nR1(Eahe&(a(aZbHv>|F33>Ggaf;F! ztBPOwfyIX@nvhS8I}TUF$j|tYOEmwnTJsdVUL-=Ygci6k=he_cvd8ZcVJsg`E-&-0 z=;9)rkj%KLi&oT-%%nK~X5M2r#nBb>ldl{vzWmF4!nl!_Gq63k_!cWRPKAo{H7Cgp z*lLciN43MO)?ufAAD+=2${!dB^?pok3=uU(&R%CrWo`S3?3EU>9|Aq#J@7vG80-Px zf$zaZaLGbyK9O1g?gjUQ=fDf#L$C`R0b>@@tVEg(M81Z64L%J%4L%J%Ee?LSP`+a= zkt5SWj#khQJ_DbF{or6E9%j3;vWGEz6yd)RzJlh@XkP3npI|MilPISn;R$vvEwvLZ u-4XX&R+myTis$2q*^Xy!5TBc)!9rf#+lza94}(V#xeAeKk=P9L=lli4WM6my diff --git a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c index 3af6300e4..4c2fb1fbb 100755 --- a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c @@ -1,6 +1,6 @@ #include "slsDetectorFunctionList.h" #include "versionAPI.h" -#include "logger.h" +#include "clogger.h" #include #include "AD9257.h" // commonServerFunctions.h, blackfin.h, ansi.h #include "LTC2620.h" // dacs diff --git a/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c index b86eed9c0..9dcca2085 100755 --- a/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c @@ -1,6 +1,6 @@ #include "slsDetectorFunctionList.h" #include "versionAPI.h" -#include "logger.h" +#include "clogger.h" #include "communication_funcs_UDP.h" #include "UDPPacketHeaderGenerator.h" diff --git a/slsDetectorServers/slsDetectorServer/UDPPacketHeaderGenerator.h b/slsDetectorServers/slsDetectorServer/UDPPacketHeaderGenerator.h index 9350d4bd6..7e9c47263 100755 --- a/slsDetectorServers/slsDetectorServer/UDPPacketHeaderGenerator.h +++ b/slsDetectorServers/slsDetectorServer/UDPPacketHeaderGenerator.h @@ -1,6 +1,6 @@ #pragma once -#include "logger.h" +#include "clogger.h" #include "sls_detector_defs.h" diff --git a/slsDetectorServers/slsDetectorServer/logger.h b/slsDetectorServers/slsDetectorServer/clogger.h similarity index 100% rename from slsDetectorServers/slsDetectorServer/logger.h rename to slsDetectorServers/slsDetectorServer/clogger.h diff --git a/slsDetectorServers/slsDetectorServer/communication_funcs.c b/slsDetectorServers/slsDetectorServer/communication_funcs.c index 3c4bae02e..756530280 100755 --- a/slsDetectorServers/slsDetectorServer/communication_funcs.c +++ b/slsDetectorServers/slsDetectorServer/communication_funcs.c @@ -1,5 +1,5 @@ #include "communication_funcs.h" -#include "logger.h" +#include "clogger.h" #include #include diff --git a/slsDetectorServers/slsDetectorServer/communication_funcs_UDP.h b/slsDetectorServers/slsDetectorServer/communication_funcs_UDP.h index 622e92694..0182ae46e 100755 --- a/slsDetectorServers/slsDetectorServer/communication_funcs_UDP.h +++ b/slsDetectorServers/slsDetectorServer/communication_funcs_UDP.h @@ -1,6 +1,6 @@ #pragma once -#include "logger.h" +#include "clogger.h" #include "sls_detector_defs.h" diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h b/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h index 381ea21cb..03734d2e5 100755 --- a/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h +++ b/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h @@ -1,7 +1,7 @@ #include "sls_detector_defs.h" #include "slsDetectorServer_defs.h" // DAC_INDEX, ADC_INDEX, also include RegisterDefs.h #ifdef GOTTHARDD -#include "logger.h" // runState(enum TLogLevel) +#include "clogger.h" // runState(enum TLogLevel) #endif #include #include // FILE diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorServer.c b/slsDetectorServers/slsDetectorServer/slsDetectorServer.c index 46ede3893..64c64a4b6 100755 --- a/slsDetectorServers/slsDetectorServer/slsDetectorServer.c +++ b/slsDetectorServers/slsDetectorServer/slsDetectorServer.c @@ -2,7 +2,7 @@ The port number is passed as an argument */ #include "sls_detector_defs.h" -#include "logger.h" +#include "clogger.h" #include "communication_funcs.h" #include "slsDetectorServer_funcs.h" #include "slsDetectorServer_defs.h" diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c index 79e946b11..5e23140ce 100755 --- a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c +++ b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c @@ -1,7 +1,7 @@ #include "slsDetectorServer_funcs.h" #include "slsDetectorFunctionList.h" #include "communication_funcs.h" -#include "logger.h" +#include "clogger.h" #include #include diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.h b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.h index 181d1bd21..90f5836f2 100755 --- a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.h +++ b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.h @@ -1,6 +1,6 @@ #pragma once #include "sls_detector_defs.h" -#include "logger.h" +#include "clogger.h" enum numberMode {DEC, HEX}; #define GOODBYE (-200) diff --git a/slsSupportLib/include/versionAPI.h b/slsSupportLib/include/versionAPI.h index c1c9c91c8..38452d4d8 100644 --- a/slsSupportLib/include/versionAPI.h +++ b/slsSupportLib/include/versionAPI.h @@ -3,8 +3,8 @@ #define APILIB 0x190723 #define APIRECEIVER 0x190722 #define APIGUI 0x190723 -#define APIJUNGFRAU 0x190819 -#define APIGOTTHARD 0x190819 -#define APICTB 0x190819 -#define APIMOENCH 0x190819 -#define APIEIGER 0x190819 +#define APICTB 0x190820 +#define APIGOTTHARD 0x190820 +#define APIJUNGFRAU 0x190820 +#define APIMOENCH 0x190820 +#define APIEIGER 0x190820 From 08ac9b4ce8834d44da2082712cc272133b095b12 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Tue, 20 Aug 2019 09:12:32 +0200 Subject: [PATCH 097/108] other detectors made to cmake --- slsDetectorServers/CMakeLists.txt | 3 +++ .../ctbDetectorServer/Makefile.virtual | 27 ------------------- .../gotthardDetectorServer/Makefile.virtual | 27 ------------------- .../slsDetectorFunctionList.c | 3 +-- .../moenchDetectorServer/Makefile.virtual | 27 ------------------- 5 files changed, 4 insertions(+), 83 deletions(-) delete mode 100755 slsDetectorServers/ctbDetectorServer/Makefile.virtual delete mode 100755 slsDetectorServers/gotthardDetectorServer/Makefile.virtual delete mode 100755 slsDetectorServers/moenchDetectorServer/Makefile.virtual diff --git a/slsDetectorServers/CMakeLists.txt b/slsDetectorServers/CMakeLists.txt index a495e3cf4..7a05de417 100644 --- a/slsDetectorServers/CMakeLists.txt +++ b/slsDetectorServers/CMakeLists.txt @@ -1,2 +1,5 @@ +add_subdirectory(ctbDetectorServer) add_subdirectory(eigerDetectorServer) +add_subdirectory(gotthardDetectorServer) add_subdirectory(jungfrauDetectorServer) +#add_subdirectory(moenchDetectorServer) \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/Makefile.virtual b/slsDetectorServers/ctbDetectorServer/Makefile.virtual deleted file mode 100755 index cfaacf70e..000000000 --- a/slsDetectorServers/ctbDetectorServer/Makefile.virtual +++ /dev/null @@ -1,27 +0,0 @@ -CC = gcc -CFLAGS += -Wall -DCHIPTESTBOARDD -DVIRTUAL -DSTOP_SERVER #-DVERBOSEI #-DVERBOSE -LDLIBS += -lm -lstdc++ -pthread - -PROGS = ctbDetectorServer_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/gotthardDetectorServer/Makefile.virtual b/slsDetectorServers/gotthardDetectorServer/Makefile.virtual deleted file mode 100755 index 65174a82f..000000000 --- a/slsDetectorServers/gotthardDetectorServer/Makefile.virtual +++ /dev/null @@ -1,27 +0,0 @@ -CC = gcc -CFLAGS += -Wall -DGOTTHARDD -DVIRTUAL -DSTOP_SERVER #-DVERBOSEI #-DVERBOSE -LDLIBS += -lm -lstdc++ -pthread - -PROGS = gotthardDetectorServer_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 - \ No newline at end of file diff --git a/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c index 9c2bbebb7..d00b0d3e0 100755 --- a/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c @@ -3,11 +3,10 @@ #include "clogger.h" #include "RegisterDefs.h" -#ifndef VIRTUAL #include "AD9257.h" // commonServerFunctions.h, blackfin.h, ansi.h #include "AD9252.h" // old board compatibility #include "LTC2620.h" // dacs -#else +#ifdef VIRTUAL #include "blackfin.h" #include #include diff --git a/slsDetectorServers/moenchDetectorServer/Makefile.virtual b/slsDetectorServers/moenchDetectorServer/Makefile.virtual deleted file mode 100755 index f502da862..000000000 --- a/slsDetectorServers/moenchDetectorServer/Makefile.virtual +++ /dev/null @@ -1,27 +0,0 @@ -CC = gcc -CFLAGS += -Wall -DMOENCHD -DVIRTUAL -DSTOP_SERVER #-DVERBOSEI #-DVERBOSE -LDLIBS += -lm -lstdc++ -pthread - -PROGS = moenchDetectorServer_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 - From 38b7e23ac45e7703a1fb36ac6dea375ecfbf99b4 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Tue, 20 Aug 2019 10:55:55 +0200 Subject: [PATCH 098/108] WIP --- .../ctbDetectorServer/CMakeLists.txt | 31 +++++++++++++ .../gotthardDetectorServer/CMakeLists.txt | 31 +++++++++++++ .../moenchDetectorServer/CMakeLists.txt | 31 +++++++++++++ slsDetectorSoftware/include/Detector.h | 32 ++++++++----- slsDetectorSoftware/src/Detector.cpp | 45 ++++++++++++------- 5 files changed, 143 insertions(+), 27 deletions(-) create mode 100644 slsDetectorServers/ctbDetectorServer/CMakeLists.txt create mode 100644 slsDetectorServers/gotthardDetectorServer/CMakeLists.txt create mode 100644 slsDetectorServers/moenchDetectorServer/CMakeLists.txt diff --git a/slsDetectorServers/ctbDetectorServer/CMakeLists.txt b/slsDetectorServers/ctbDetectorServer/CMakeLists.txt new file mode 100644 index 000000000..eb5133635 --- /dev/null +++ b/slsDetectorServers/ctbDetectorServer/CMakeLists.txt @@ -0,0 +1,31 @@ +add_executable(ctbDetectorServer + slsDetectorFunctionList.c + ../slsDetectorServer/slsDetectorServer.c + ../slsDetectorServer/slsDetectorServer_funcs.c + ../slsDetectorServer/communication_funcs.c +) + +include_directories( + ../slsDetectorServer/ + ../../slsSupportLib/include +) + +target_include_directories(ctbDetectorServer + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} +) + +target_compile_definitions(ctbDetectorServer + PUBLIC CHIPTESTBOARDD VIRTUAL STOP_SERVER +) + +target_link_libraries(ctbDetectorServer + PUBLIC pthread rt +) + +set_target_properties(ctbDetectorServer PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin +) + +install(TARGETS ctbDetectorServer + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) diff --git a/slsDetectorServers/gotthardDetectorServer/CMakeLists.txt b/slsDetectorServers/gotthardDetectorServer/CMakeLists.txt new file mode 100644 index 000000000..fa72c7d09 --- /dev/null +++ b/slsDetectorServers/gotthardDetectorServer/CMakeLists.txt @@ -0,0 +1,31 @@ +add_executable(gotthardDetectorServer + slsDetectorFunctionList.c + ../slsDetectorServer/slsDetectorServer.c + ../slsDetectorServer/slsDetectorServer_funcs.c + ../slsDetectorServer/communication_funcs.c +) + +include_directories( + ../slsDetectorServer/ + ../../slsSupportLib/include +) + +target_include_directories(gotthardDetectorServer + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} +) + +target_compile_definitions(gotthardDetectorServer + PUBLIC GOTTHARDD VIRTUAL STOP_SERVER +) + +target_link_libraries(gotthardDetectorServer + PUBLIC pthread rt +) + +set_target_properties(gotthardDetectorServer PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin +) + +install(TARGETS gotthardDetectorServer + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) diff --git a/slsDetectorServers/moenchDetectorServer/CMakeLists.txt b/slsDetectorServers/moenchDetectorServer/CMakeLists.txt new file mode 100644 index 000000000..f8b47a602 --- /dev/null +++ b/slsDetectorServers/moenchDetectorServer/CMakeLists.txt @@ -0,0 +1,31 @@ +add_executable(moenchDetectorServer + slsDetectorFunctionList.c + ../slsDetectorServer/slsDetectorServer.c + ../slsDetectorServer/slsDetectorServer_funcs.c + ../slsDetectorServer/communication_funcs.c +) + +include_directories( + ../slsDetectorServer/ + ../../slsSupportLib/include +) + +target_include_directories(moenchDetectorServer + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} +) + +target_compile_definitions(moenchDetectorServer + PUBLIC MOENCHD VIRTUAL STOP_SERVER +) + +target_link_libraries(moenchDetectorServer + PUBLIC pthread rt +) + +set_target_properties(moenchDetectorServer PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin +) + +install(TARGETS moenchDetectorServer + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index d34b586b4..b01e4ada5 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -130,14 +130,20 @@ class Detector { void setSpeed(int value, Positions pos = {}); /** [Gotthard][Jungfrau][CTB] */ - Result getADCPhase(bool inDeg, Positions pos = {}) const; + Result getADCPhase(Positions pos = {}) const; /** [Gotthard][Jungfrau][CTB] */ - void setADCPhase(int value, bool inDeg, Positions pos = {}); + void setADCPhase(int value, Positions pos = {}); /** [Jungfrau][CTB] */ Result getMaxADCPhaseShift(Positions pos = {}) const; + /** [Gotthard][Jungfrau][CTB] */ + Result getADCPhaseInDegrees(Positions pos = {}) const; + + /** [Gotthard][Jungfrau][CTB] */ + void setADCPhaseInDegrees(int value, Positions pos = {}); + Result getHighVoltage(Positions pos = {}) const; /** @@ -832,21 +838,27 @@ class Detector { void setNumberOfDigitalSamples(int64_t value, Positions pos = {}); /** [CTB] */ - Result getSignalType(Positions pos = {}) const; + Result getReadoutMode(Positions pos = {}) const; - /** [CTB] Options: NORMAL_READOUT = 0, DIGITAL_ONLY = 1, ANALOG_AND_DIGITAL + /** [CTB] Options: NORMAL_READOUT = 0, DIGITAL_ONLY = 1, ANALOG_AND_DIGITAL //TODO ANALOG_ONLY, make enum * = 2 */ - void setSignalType(int value, Positions pos = {}); + void setReadoutMode(int value, Positions pos = {}); /** [CTB] */ - Result getDBITPhase(bool inDeg, Positions pos = {}) const; + Result getDBITPhase(Positions pos = {}) const; /** [CTB] */ - void setDBITPhase(int value, bool inDeg, Positions pos = {}); + void setDBITPhase(int value, Positions pos = {}); /** [CTB] */ Result getMaxDBITPhaseShift(Positions pos = {}) const; + /** [CTB] */ + Result getDBITPhaseInDegrees(Positions pos = {}) const; + + /** [CTB] */ + void setDBITPhaseInDegrees(int value, Positions pos = {}); + /** [CTB] */ Result getADCClock(Positions pos = {}) const; @@ -1137,8 +1149,6 @@ class Detector { * * * ************************************************/ - - Result getControlPort(Positions pos = {}) const; /** Detector Control TCP port (for client communication with Detector @@ -1158,8 +1168,8 @@ class Detector { /** Get last client IP saved on detector server */ Result getLastClientIP(Positions pos = {}) const; - /** Execute a command on the detector server */ - void execCommand(const std::string &value, Positions pos = {}); + /** Execute a command on the detector server console */ + void executeCommand(const std::string &value, Positions pos = {}); /** [Gotthard][Jungfrau][CTB] */ Result getNumberOfFramesFromStart(Positions pos = {}) const; diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index fe355206e..ca146d8ae 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -154,13 +154,12 @@ void Detector::setSpeed(int value, Positions pos) { pimpl->Parallel(&slsDetector::setSpeed, pos, defs::CLOCK_DIVIDER, value, 0); } -Result Detector::getADCPhase(bool inDeg, Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_PHASE, -1, - inDeg); +Result Detector::getADCPhase(Positions pos) const { + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_PHASE, -1, 0); } -void Detector::setADCPhase(int value, bool inDeg, Positions pos) { - pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_PHASE, value, inDeg); +void Detector::setADCPhase(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_PHASE, value, 0); } Result Detector::getMaxADCPhaseShift(Positions pos) const { @@ -168,6 +167,14 @@ Result Detector::getMaxADCPhaseShift(Positions pos) const { defs::MAX_ADC_PHASE_SHIFT, -1, 0); } +Result Detector::getADCPhaseInDegrees(Positions pos) const { + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_PHASE, -1, 1); +} + +void Detector::setADCPhaseInDegrees(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_PHASE, value, 1); +} + Result Detector::getHighVoltage(Positions pos) const { return pimpl->Parallel(&slsDetector::setDAC, pos, -1, defs::HIGH_VOLTAGE, 0); @@ -283,7 +290,7 @@ Result Detector::getNumberofUDPInterfaces(Positions pos) const { void Detector::setNumberofUDPInterfaces(int n, Positions pos) { int previouslyClientStreaming = pimpl->enableDataStreamingToClient(); - bool previouslyReceiverStreaming = true;//getRxZmqIP(pos).squash(false); //FIXME TODO + bool previouslyReceiverStreaming = getRxZmqDataStream(pos).squash(true); pimpl->Parallel(&slsDetector::setNumberofUDPInterfaces, pos, n); // redo the zmq sockets if enabled if (previouslyClientStreaming != 0) { @@ -815,7 +822,7 @@ Result Detector::getRateCorrection(Positions pos) const { } void Detector::setRateCorrection(ns dead_time, Positions pos) { - pimpl->Parallel(&slsDetector::setRateCorrection, pos, 0);//FIXME TODO dead_time); + pimpl->Parallel(&slsDetector::setRateCorrection, pos, dead_time.count()); } Result Detector::getPartialReadout(Positions pos) const { @@ -1076,7 +1083,7 @@ void Detector::setNumberOfDigitalSamples(int64_t value, Positions pos) { pimpl->Parallel(&slsDetector::setTimer, pos, defs::DIGITAL_SAMPLES, value); } -Result Detector::getSignalType(Positions pos) const { +Result Detector::getReadoutMode(Positions pos) const { auto res = pimpl->Parallel(&slsDetector::setReadOutFlags, pos, defs::GET_READOUT_FLAGS); for (auto &it : res) { @@ -1093,7 +1100,7 @@ Result Detector::getSignalType(Positions pos) const { return res; } -void Detector::setSignalType(int value, Positions pos) { +void Detector::setReadoutMode(int value, Positions pos) { defs::readOutFlags flag; switch (value) { case 0: @@ -1111,14 +1118,12 @@ void Detector::setSignalType(int value, Positions pos) { pimpl->Parallel(&slsDetector::setReadOutFlags, pos, flag); } -Result Detector::getDBITPhase(bool inDeg, Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PHASE, -1, - inDeg); +Result Detector::getDBITPhase(Positions pos) const { + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PHASE, -1, 0); } -void Detector::setDBITPhase(int value, bool inDeg, Positions pos) { - pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PHASE, value, - inDeg); +void Detector::setDBITPhase(int value, Positions pos) { + pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PHASE, value, 0); } Result Detector::getMaxDBITPhaseShift(Positions pos) const { @@ -1126,6 +1131,14 @@ Result Detector::getMaxDBITPhaseShift(Positions pos) const { defs::MAX_DBIT_PHASE_SHIFT, -1, 0); } +Result Detector::getDBITPhaseInDegrees(Positions pos) const { + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PHASE, -1, 1); +} + +void Detector::setDBITPhaseInDegrees(int value,Positions pos) { + pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PHASE, value, 1); +} + Result Detector::getADCClock(Positions pos) const { return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_CLOCK, -1, 0); } @@ -1568,7 +1581,7 @@ Result Detector::getLastClientIP(Positions pos) const { return pimpl->Parallel(&slsDetector::getLastClientIP, pos); } -void Detector::execCommand(const std::string &value, Positions pos) { +void Detector::executeCommand(const std::string &value, Positions pos) { pimpl->Parallel(&slsDetector::execCommand, pos, value); } From 0c4ae89cd9f63e0591eda953081beb9f43d6c479 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Tue, 20 Aug 2019 11:20:12 +0200 Subject: [PATCH 099/108] WIP --- slsDetectorSoftware/include/Detector.h | 3 +-- slsDetectorSoftware/include/multiSlsDetector.h | 3 --- slsDetectorSoftware/src/Detector.cpp | 2 -- slsDetectorSoftware/src/multiSlsDetector.cpp | 13 ++----------- 4 files changed, 3 insertions(+), 18 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index b01e4ada5..695266dea 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -201,8 +201,7 @@ class Detector { * Stops detector acquisition and then receiver (if enabled) * If no receiver enabled, you can skip this for normal acquisition (no abort) */ - void stopAcquisition();//TODO: cannot do this. for acquire, to stop acquisition, must not also do stop receiver(mutex) - // TODO: stopAcquire?? + void stopAcquisition(); /** * Clears the acquiring flag. This has to be done manually diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 248638f2e..7995c4808 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -2268,9 +2268,6 @@ class multiSlsDetector : public virtual slsDetectorDefs { /** mutex to synchronize main and data processing threads */ mutable std::mutex mp; - /** mutex to synchronizedata processing and plotting threads */ - mutable std::mutex mg; - /** sets when the acquisition is finished */ bool jointhread{false}; diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index ca146d8ae..627233e54 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -665,7 +665,6 @@ void Detector::setRxZmqIP(const std::string &ip, Positions pos) { bool previouslyReceiverStreaming = getRxZmqDataStream(pos).squash(false); - // TODO! probably in one call pimpl->Parallel(&slsDetector::setReceiverStreamingIP, pos, ip); if (previouslyReceiverStreaming) { setRxZmqDataStream(false, pos); @@ -695,7 +694,6 @@ Result Detector::getClientZmqIp(Positions pos) const { void Detector::setClientZmqIp(const std::string &ip, Positions pos) { int previouslyClientStreaming = pimpl->enableDataStreamingToClient(-1); - // TODO! probably in one call ?? pimpl->Parallel(&slsDetector::setClientStreamingIP, pos, ip); if (previouslyClientStreaming != 0) { pimpl->enableDataStreamingToClient(0); diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index e2f76a495..cb2a978f1 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -830,9 +830,6 @@ void multiSlsDetector::startAcquisition(int detPos) { } void multiSlsDetector::stopAcquisition(int detPos) { - // locks to synchronize using client->receiver simultaneously (processing - // thread) - std::lock_guard lock(mg); if (detPos >= 0) { detectors[detPos]->stopAcquisition(); } else { @@ -3743,7 +3740,6 @@ int multiSlsDetector::acquire() { // verify receiver is idle if (receiver) { - std::lock_guard lock(mg); if (getReceiverStatus() != IDLE) { stopReceiver(); } @@ -3754,13 +3750,11 @@ int multiSlsDetector::acquire() { // resets frames caught in receiver if (receiver) { - std::lock_guard lock(mg); resetFramesCaught(); } // start receiver if (receiver) { - std::lock_guard lock(mg); startReceiver(); // let processing thread listen to these packets sem_post(&sem_newRTAcquisition); @@ -3770,7 +3764,6 @@ int multiSlsDetector::acquire() { // stop receiver if (receiver) { - std::lock_guard lock(mg); stopReceiver(); if (dataReady != nullptr) { sem_wait(&sem_endRTAcquisition); // waits for receiver's @@ -3832,10 +3825,8 @@ void multiSlsDetector::processData() { } } // get progress - { - std::lock_guard lock(mg); - caught = getFramesCaughtByReceiver(0); - } + caught = getFramesCaughtByReceiver(0); + // updating progress if (caught != -1) { setCurrentProgress(caught); From d1ea74120da779764cd869756a8f7b4e8d864d04 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Tue, 20 Aug 2019 12:17:42 +0200 Subject: [PATCH 100/108] added string concat to ToString --- CMakeLists.txt | 8 +++--- python/src/DetectorPythonInterface.h | 38 +++++++++++++-------------- python/src/main.cpp | 12 ++++----- slsSupportLib/include/ToString.h | 13 +++++++-- slsSupportLib/tests/test-ToString.cpp | 9 +++++++ 5 files changed, 49 insertions(+), 31 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 71f95561a..bc37d79e6 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,11 +103,11 @@ endif() if(SLS_USE_SANITIZER) - target_compile_options(slsProjectOptions INTERFACE -fsanitize=address,undefined -fno-omit-frame-pointer) + # target_compile_options(slsProjectOptions INTERFACE -fsanitize=address,undefined -fno-omit-frame-pointer) #target_compile_options(slsProjectOptions INTERFACE -fsanitize=address,undefined) - target_link_libraries(slsProjectOptions INTERFACE -fsanitize=address,undefined) - # target_compile_options(slsProjectOptions INTERFACE -fsanitize=thread) - # target_link_libraries(slsProjectOptions INTERFACE -fsanitize=thread) + # target_link_libraries(slsProjectOptions INTERFACE -fsanitize=address,undefined) + target_compile_options(slsProjectOptions INTERFACE -fsanitize=thread) + target_link_libraries(slsProjectOptions INTERFACE -fsanitize=thread) endif() #rapidjson diff --git a/python/src/DetectorPythonInterface.h b/python/src/DetectorPythonInterface.h index 58993377d..202fb2680 100755 --- a/python/src/DetectorPythonInterface.h +++ b/python/src/DetectorPythonInterface.h @@ -264,21 +264,21 @@ class DetectorPythonInterface { return det.setPatternWaitTime(level, -1, detPos); } - bool getFlippedDataX(int i) { - return det.getFlippedData(slsDetectorDefs::dimension::X, i); - } + // bool getFlippedDataX(int i) { + // return det.getFlippedData(slsDetectorDefs::dimension::X, i); + // } - bool getFlippedDataY(int i) { - return det.getFlippedData(slsDetectorDefs::dimension::Y, i); - } + // bool getFlippedDataY(int i) { + // return det.getFlippedData(slsDetectorDefs::dimension::Y, i); + // } - void setFlippedDataX(int i, bool value) { - det.setFlippedData(slsDetectorDefs::dimension::X, value, i); - } + // void setFlippedDataX(int i, bool value) { + // det.setFlippedData(slsDetectorDefs::dimension::X, value, i); + // } - void setFlippedDataY(int i, bool value) { - det.setFlippedData(slsDetectorDefs::dimension::Y, value, i); - } + // void setFlippedDataY(int i, bool value) { + // det.setFlippedData(slsDetectorDefs::dimension::Y, value, i); + // } /*** Frame and file settings ***/ void setFileName(std::string fname) { det.setFileName(fname); } @@ -520,13 +520,13 @@ class DetectorPythonInterface { det.setTimer(slsDetectorDefs::timerIndex::FRAME_NUMBER, nframes); } - std::string getTimingMode() { - return det.externalCommunicationType( - det.setExternalCommunicationMode()); - } - void setTimingMode(const std::string mode) { - det.setExternalCommunicationMode(det.externalCommunicationType(mode)); - } + // std::string getTimingMode() { + // return det.externalCommunicationType( + // det.setExternalCommunicationMode()); + // } + // void setTimingMode(const std::string mode) { + // det.setExternalCommunicationMode(det.externalCommunicationType(mode)); + // } void freeSharedMemory() { det.freeSharedMemory(); } diff --git a/python/src/main.cpp b/python/src/main.cpp index bf0ca5d39..0df93d2e2 100755 --- a/python/src/main.cpp +++ b/python/src/main.cpp @@ -183,8 +183,8 @@ PYBIND11_MODULE(_sls_detector, m) { .def("setNumberOfStorageCells", &DetectorPythonInterface::setNumberOfStorageCells) .def("getNumberOfStorageCells", &DetectorPythonInterface::getNumberOfStorageCells) - .def("getTimingMode", &DetectorPythonInterface::getTimingMode) - .def("setTimingMode", &DetectorPythonInterface::setTimingMode) + // .def("getTimingMode", &DetectorPythonInterface::getTimingMode) + // .def("setTimingMode", &DetectorPythonInterface::setTimingMode) .def("getDetectorType", &DetectorPythonInterface::getDetectorType) @@ -282,10 +282,10 @@ PYBIND11_MODULE(_sls_detector, m) { &DetectorPythonInterface::getReceiverCurrentFrameIndex) .def("getGapPixels", &DetectorPythonInterface::getGapPixels) .def("setGapPixels", &DetectorPythonInterface::setGapPixels) - .def("getFlippedDataX", &DetectorPythonInterface::getFlippedDataX) - .def("getFlippedDataY", &DetectorPythonInterface::getFlippedDataY) - .def("setFlippedDataX", &DetectorPythonInterface::setFlippedDataX) - .def("setFlippedDataY", &DetectorPythonInterface::setFlippedDataY) + // .def("getFlippedDataX", &DetectorPythonInterface::getFlippedDataX) + // .def("getFlippedDataY", &DetectorPythonInterface::getFlippedDataY) + // .def("setFlippedDataX", &DetectorPythonInterface::setFlippedDataX) + // .def("setFlippedDataY", &DetectorPythonInterface::setFlippedDataY) .def("getServerLock", &DetectorPythonInterface::getServerLock) .def("setServerLock", &DetectorPythonInterface::setServerLock) diff --git a/slsSupportLib/include/ToString.h b/slsSupportLib/include/ToString.h index 03d601fa3..750e6585a 100644 --- a/slsSupportLib/include/ToString.h +++ b/slsSupportLib/include/ToString.h @@ -19,8 +19,17 @@ namespace sls { -// std::string ToString(const std::vector &vec, -// const char delimiter = ' '); +inline std::string ToString(const std::vector &vec, + const char delimiter = ' ') { + std::ostringstream os; + if(!vec.empty()){ + auto it = vec.begin(); + os << *it++; + while(it != vec.end()) + os << delimiter << *it++; + } + return os.str(); +} /** Convert std::chrono::duration with specified output unit */ template diff --git a/slsSupportLib/tests/test-ToString.cpp b/slsSupportLib/tests/test-ToString.cpp index dfc255d48..b3119b4c5 100644 --- a/slsSupportLib/tests/test-ToString.cpp +++ b/slsSupportLib/tests/test-ToString.cpp @@ -95,4 +95,13 @@ TEST_CASE("Convert types with str method"){ sls::IpAddr addr; REQUIRE(ToString(addr) == "0.0.0.0"); REQUIRE(ToString(sls::IpAddr{}) == "0.0.0.0"); +} + +TEST_CASE("vector of strings"){ + std::vector vec{"5", "s"}; + REQUIRE(ToString(vec) == "5 s"); + + std::vector vec2{"some", "strange", "words", "75"}; + REQUIRE(ToString(vec2) == "some strange words 75"); + } \ No newline at end of file From ea5ac6ad0375f1b22179c185d4aa5785802c3ae0 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Tue, 20 Aug 2019 13:20:25 +0200 Subject: [PATCH 101/108] WIP --- slsDetectorSoftware/include/Detector.h | 6 +++--- slsDetectorSoftware/src/slsDetector.cpp | 2 +- slsDetectorSoftware/src/slsDetectorCommand.cpp | 6 +++--- slsReceiverSoftware/src/slsReceiverImplementation.cpp | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 695266dea..386abfcb0 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -480,7 +480,7 @@ class Detector { Result getFramesPerFile(Positions pos = {}) const; - /** -1 will set frames per file to unlimited //TODO check if it is -1 or 0 */ + /** 0 will set frames per file to unlimited */ void setFramesPerFile(int n, Positions pos = {}); @@ -500,8 +500,8 @@ class Detector { /** @param freq nth frame streamed out of receiver. * If 0, streaming timer is the timeout, * after which current frame sent out. Default is 0 at 200 ms. - * Default is 0. This is more for gui purposes to not send every frame. - * If you want every frame, set freq to 1. + * Default is 1: send every frame. + * If you want just to see some frames for gui purposes, set to 0 (200ms default timer). */ void setRxZmqFrequency(int freq, Positions pos = {}); diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index 226f31fc4..9e300c2f3 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -356,7 +356,7 @@ void slsDetector::initializeDetectorStructure(detectorType type) { shm()->rxZmqport = DEFAULT_ZMQ_RX_PORTNO + (detId * ((shm()->myDetectorType == EIGER) ? 2 : 1)); shm()->rxUpstream = false; - shm()->rxReadFreq = 0; + shm()->rxReadFreq = 1; shm()->zmqip = 0u; shm()->rxZmqip = 0u; shm()->gappixels = 0u; diff --git a/slsDetectorSoftware/src/slsDetectorCommand.cpp b/slsDetectorSoftware/src/slsDetectorCommand.cpp index 3a9e56f10..3dc96c33f 100755 --- a/slsDetectorSoftware/src/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp @@ -1826,7 +1826,7 @@ slsDetectorCommand::slsDetectorCommand(multiSlsDetector *det) { ++i; /*! \page receiver - - rx_readfreq [i] sets/gets the stream frequency of data from receiver to client. i > 0 is the nth frame being streamed. 0 sets frequency to a default timer (200ms). \c Returns \c (int) + - rx_readfreq [i] sets/gets the stream frequency of data from receiver to client. i > 0 is the nth frame being streamed. 0 sets frequency to a default timer (200ms). Default: sends every frame \c Returns \c (int) */ descrToFuncMap[i].m_pFuncName = "rx_readfreq"; descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdReceiver; @@ -5076,7 +5076,7 @@ std::string slsDetectorCommand::helpReceiver(int action) { if (action == PUT_ACTION || action == HELP_ACTION) { os << "receiver [status] \t starts/stops the receiver to listen to detector packets. - can be start, stop." << std::endl; os << "resetframescaught [any value] \t resets frames caught by receiver" << std::endl; - os << "rx_readfreq \t sets the gui read frequency of the receiver, 0 if gui requests frame, >0 if receiver sends every nth frame to gui" << std::endl; + os << "rx_readfreq \t sets the gui read frequency of the receiver, 0 if gui requests frame, >0 if receiver sends every nth frame to gui. Default : 1" << std::endl; os << "tengiga \t sets system to be configure for 10Gbe if set to 1, else 1Gbe if set to 0" << std::endl; os << "rx_fifodepth [val]\t sets receiver fifo depth to val" << std::endl; os << "rx_silent [i]\t sets receiver in silent mode, ie. it will not print anything during real time acquisition. 1 sets, 0 unsets." << std::endl; @@ -5093,7 +5093,7 @@ std::string slsDetectorCommand::helpReceiver(int action) { os << "receiver \t returns the status of receiver - can be running or idle" << std::endl; os << "framescaught \t returns the number of frames caught by receiver(average for multi)" << std::endl; os << "frameindex \t returns the current frame index of receiver(average for multi)" << std::endl; - os << "rx_readfreq \t returns the gui read frequency of the receiver" << std::endl; + os << "rx_readfreq \t returns the gui read frequency of the receiver. DEfault: 1" << std::endl; os << "tengiga \t returns 1 if the system is configured for 10Gbe else 0 for 1Gbe" << std::endl; os << "rx_fifodepth \t returns receiver fifo depth" << std::endl; os << "rx_silent \t returns receiver silent mode enable. 1 is silent, 0 not silent." << std::endl; diff --git a/slsReceiverSoftware/src/slsReceiverImplementation.cpp b/slsReceiverSoftware/src/slsReceiverImplementation.cpp index f4788a177..4791a66d7 100755 --- a/slsReceiverSoftware/src/slsReceiverImplementation.cpp +++ b/slsReceiverSoftware/src/slsReceiverImplementation.cpp @@ -107,7 +107,7 @@ void slsReceiverImplementation::InitializeMembers() { roi.xmin = -1; roi.xmax = -1; adcEnableMask = BIT32_MASK; - streamingFrequency = 0; + streamingFrequency = 1; streamingTimerInMs = DEFAULT_STREAMING_TIMER_IN_MS; dataStreamEnable = false; streamingPort = 0; From 9ebff9c8a8cb352be1fd91ecae3cfdc785ac4349 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Tue, 20 Aug 2019 13:30:22 +0200 Subject: [PATCH 102/108] updated gui to have the timer/freq --- slsDetectorGui/forms/form_tab_plot.ui | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/slsDetectorGui/forms/form_tab_plot.ui b/slsDetectorGui/forms/form_tab_plot.ui index ca05edbc6..66c98e264 100755 --- a/slsDetectorGui/forms/form_tab_plot.ui +++ b/slsDetectorGui/forms/form_tab_plot.ui @@ -2000,16 +2000,10 @@ Displays minimum, maximum and sum of values for each plot. - <nobr> -Streaming Interval between 2 plots. Default is time interval with 200 ms. -</nobr><br><br><nobr> -<b>Time Interval</b>: Streaming time interval when an image should be streamed. -</nobr><br><nobr> -<b>Every nth Image</b>: Only every nth image is streamed. -</nobr> + <html><head/><body><p>Sets the pace at which the receiver streams out images. Images in between the timeout or frequency are not sent out.<br/><br/><span style=" font-weight:600;">Time Interval</span>: Streaming time interval when an image should be streamed. <br/><span style=" font-weight:600;">Every nth Image</span>: Only every nth image is streamed. </p><p><br/></p><p><br/></p></body></html> - Interval between Plots + Receiver Streaming Frequency / Timer Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter From 11c1fb0e1195b8d59984ec5263bee8f88423ec05 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Tue, 20 Aug 2019 13:42:26 +0200 Subject: [PATCH 103/108] Added roi to master file --- slsReceiverSoftware/include/BinaryFileStatic.h | 3 +++ slsReceiverSoftware/include/HDF5FileStatic.h | 8 ++++++++ slsReceiverSoftware/include/receiver_defs.h | 2 ++ slsReceiverSoftware/src/slsReceiverImplementation.cpp | 2 ++ 4 files changed, 15 insertions(+) diff --git a/slsReceiverSoftware/include/BinaryFileStatic.h b/slsReceiverSoftware/include/BinaryFileStatic.h index 132eb203d..49f42eae1 100755 --- a/slsReceiverSoftware/include/BinaryFileStatic.h +++ b/slsReceiverSoftware/include/BinaryFileStatic.h @@ -140,6 +140,7 @@ class BinaryFileStatic { "ADC Mask : %d\n" "Dbit Offset : %d\n" "Dbit Bitset : %lld\n" + "Roi (xmin, xmax) : %d %d\n" "Timestamp : %s\n\n" "#Frame Header\n" @@ -179,6 +180,8 @@ class BinaryFileStatic { attr.adcmask, attr.dbitoffset, (long long int)attr.dbitlist, + attr.roiXmin, + attr.roiXmax, ctime(&t)); if (strlen(message) > MAX_MASTER_FILE_LENGTH) { FILE_LOG(logERROR) << "Master File Size " << strlen(message) << diff --git a/slsReceiverSoftware/include/HDF5FileStatic.h b/slsReceiverSoftware/include/HDF5FileStatic.h index d7f0ca915..7008478d5 100755 --- a/slsReceiverSoftware/include/HDF5FileStatic.h +++ b/slsReceiverSoftware/include/HDF5FileStatic.h @@ -431,6 +431,14 @@ public: dataset = group5.createDataSet ( "dbit bitset list", PredType::STD_U64LE, dataspace ); dataset.write ( &(attr.periodNs), PredType::STD_U64LE); + // Roi xmin + dataset = group5.createDataSet ( "roi xmin", PredType::NATIVE_INT, dataspace ); + dataset.write ( &(attr.roiXmin), PredType::NATIVE_INT); + + // Roi xmax + dataset = group5.createDataSet ( "roi xmax", PredType::NATIVE_INT, dataspace ); + dataset.write ( &(attr.roiXmax), PredType::NATIVE_INT); + //Timestamp time_t t = time(0); dataset = group5.createDataSet ( "timestamp", strdatatype, dataspace ); diff --git a/slsReceiverSoftware/include/receiver_defs.h b/slsReceiverSoftware/include/receiver_defs.h index 2122ac88e..e4f6b30e4 100755 --- a/slsReceiverSoftware/include/receiver_defs.h +++ b/slsReceiverSoftware/include/receiver_defs.h @@ -71,4 +71,6 @@ struct masterAttributes { uint32_t adcmask; uint32_t dbitoffset; uint64_t dbitlist; + uint32_t roiXmin; + uint32_t roiXmax; }; \ No newline at end of file diff --git a/slsReceiverSoftware/src/slsReceiverImplementation.cpp b/slsReceiverSoftware/src/slsReceiverImplementation.cpp index 4791a66d7..4bf587362 100755 --- a/slsReceiverSoftware/src/slsReceiverImplementation.cpp +++ b/slsReceiverSoftware/src/slsReceiverImplementation.cpp @@ -1659,6 +1659,8 @@ int slsReceiverImplementation::SetupWriter() { attr.adcmask = adcEnableMask; attr.dbitoffset = ctbDbitOffset; attr.dbitlist = 0; + attr.roiXmin = roi.xmin; + attr.roiXmax = roi.xmax; for (auto &i : ctbDbitList) { attr.dbitlist |= (1 << i); } From 28963e313b3e3288954ffa9d3a76246dcf0453d6 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Tue, 20 Aug 2019 18:18:34 +0200 Subject: [PATCH 104/108] removed gotthard functions not used --- .../bin/ctbDetectorServer_developer | Bin 155792 -> 154752 bytes .../bin/eigerDetectorServer_developer | Bin 302608 -> 302510 bytes .../bin/gotthardDetectorServer_developer | Bin 117276 -> 114176 bytes .../slsDetectorFunctionList.c | 129 ++--------------- .../bin/jungfrauDetectorServer_developer | Bin 124224 -> 123184 bytes .../slsDetectorFunctionList.h | 9 +- .../slsDetectorServer_funcs.c | 133 +----------------- .../slsDetectorServer_funcs.h | 3 - slsDetectorSoftware/include/Detector.h | 30 +--- .../include/multiSlsDetector.h | 29 +--- slsDetectorSoftware/include/slsDetector.h | 36 +---- .../include/slsDetectorCommand.h | 2 - slsDetectorSoftware/src/Detector.cpp | 42 +----- slsDetectorSoftware/src/multiSlsDetector.cpp | 58 -------- slsDetectorSoftware/src/slsDetector.cpp | 59 -------- .../src/slsDetectorCommand.cpp | 117 +++------------ slsSupportLib/include/sls_detector_defs.h | 7 +- slsSupportLib/include/sls_detector_funcs.h | 8 +- slsSupportLib/include/versionAPI.h | 6 +- 19 files changed, 54 insertions(+), 614 deletions(-) diff --git a/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer b/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer index 61e1d440bb9904cb7e5ce82dda2630362bfaa4f9..a2f52fdb6899eec746e0d5278846cbb50191bb0e 100755 GIT binary patch delta 57414 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 G*7P5^Ip(SW delta 58456 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 diff --git a/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer b/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer index 2caab4127a7ee9f93566a1dd9ce43c7be99d6ce6..444b16287ce270cc3c8f6d5fac3896d8cd48eed3 100755 GIT binary patch delta 45042 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�v(8na_l2 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 N6og_>4yr)S{|;Rebawy% diff --git a/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c index d00b0d3e0..f8f06ca0e 100755 --- a/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c @@ -32,7 +32,6 @@ int detectorFirstServer = 1; int dacValues[NDAC] = {0}; enum detectorSettings thisSettings = UNINITIALIZED; enum externalSignalFlag signalMode = 0; -int digitalTestBit = 0; // roi configuration int adcConfigured = -1; @@ -245,12 +244,7 @@ int detectorTest( enum digitalTestMode arg, int ival) { return OK; #endif switch(arg){ - case DIGITAL_BIT_TEST: - if (ival > -1) { - digitalTestBit = (ival == 0) ? 0 : 1; - FILE_LOG(logINFO, ("Digital Test bit set: %d\n", digitalTestBit)); - } - return digitalTestBit; + case IMAGE_TEST: return testImage(ival); case DETECTOR_FIRMWARE_TEST: return testFpga(); case DETECTOR_BUS_TEST: return testBus(); default: @@ -260,6 +254,19 @@ int detectorTest( enum digitalTestMode arg, int ival) { return OK; } +int testImage(int ival) { + uint32_t addr = MULTI_PURPOSE_REG; + if (ival >= 0) { + if (ival == 0) { + FILE_LOG(logINFO, ("Switching on Image Test\n")); + bus_w (addr, bus_r(addr) & ~DGTL_TST_MSK); + } else { + FILE_LOG(logINFO, ("Switching off Image Test\n")); + bus_w (addr, bus_r(addr) | DGTL_TST_MSK); + } + } + return ((bus_r(addr) & DGTL_TST_MSK) >> DGTL_TST_OFST); +} /* Ids */ @@ -1351,13 +1358,6 @@ int configureMAC(uint32_t destip, uint64_t destmac, uint64_t sourcemac, uint32_t (long long unsigned int)destmac)); FILE_LOG(logINFO, ("\tDest. Port : %d (0x%08x)\n",udpport, udpport)); - // set/ unset the digital test bit - if (digitalTestBit) - bus_w (addr, bus_r(addr) | DGTL_TST_MSK); - else - bus_w (addr, bus_r(addr) & ~DGTL_TST_MSK); - FILE_LOG(logDEBUG1, ("\tDigital Test Bit. MultiPurpose reg: 0x%x\n", bus_r(addr))); - //reset mac bus_w (addr, bus_r(addr) | RST_MSK); FILE_LOG(logDEBUG1, ("\tReset Mac. MultiPurpose reg: 0x%x\n", bus_r(addr))); @@ -1518,107 +1518,6 @@ int getAdcConfigured(){ } -/* gotthard specific - loadimage, read/reset counter block */ - -void loadImage(enum imageType index, short int imageVals[]){ - u_int32_t addr = DARK_IMAGE_REG; - if (index == GAIN_IMAGE) - addr = GAIN_IMAGE_REG; - int dataBytes = calculateDataBytes(); - - volatile u_int16_t *ptr = (u_int16_t*)(CSP0BASE + addr * 2); - memcpy((char*)ptr, (char*)imageVals, dataBytes); - - FILE_LOG(logINFO, ("Loaded %s image at 0x%p\n", - (index == GAIN_IMAGE) ? "Gain" : "Dark", (void*) ptr)); -} - -int readCounterBlock(int startACQ, short int counterVals[]){ - FILE_LOG(logINFO, ("Reading Counter Block with start Acq :%d\n", startACQ)); - - // stop any current acquisition - if (runBusy()) { - if (stopStateMachine() == FAIL) - return FAIL; - // waiting for the last frame read to be done - while(runBusy()) - usleep(500); - FILE_LOG(logDEBUG1, ("State machine stopped\n")); - } - - // copy memory - u_int32_t addr = COUNTER_MEMORY_REG; - volatile u_int16_t *ptr = (u_int16_t*)(CSP0BASE + addr * 2); - int dataBytes = calculateDataBytes(); - memcpy((char*)counterVals, (char*)ptr, dataBytes); - - // unreset counter - addr = MULTI_PURPOSE_REG; - bus_w(addr, (bus_r(addr) &~ RST_CNTR_MSK)); - FILE_LOG(logDEBUG1, ("\tUnsetting reset Counter. Multi Purpose Reg: 0x%x\n", bus_r(addr))); - - // start state machine - if (startACQ == 1){ - startStateMachine(); - if (runBusy()) { - FILE_LOG(logINFO, ("State machine RUNNING\n")); - } else { - FILE_LOG(logINFO, ("State machine IDLE\n")); - } - } - return OK; -} - -int resetCounterBlock(int startACQ){ - FILE_LOG(logINFO, ("Resetting Counter Block with start Acq :%d\n", startACQ)); - - // stop any current acquisition - if (runBusy()) { - if (stopStateMachine() == FAIL) - return FAIL; - // waiting for the last frame read to be done - while(runBusy()) - usleep(500); - FILE_LOG(logDEBUG1, ("State machine stopped\n")); - } - - // reset counter - u_int32_t addr = MULTI_PURPOSE_REG; - bus_w(addr, (bus_r(addr) | RST_CNTR_MSK)); - FILE_LOG(logDEBUG1, ("\tResetting Counter. Multi Purpose Reg: 0x%x\n", bus_r(addr))); - - // copy memory - addr = COUNTER_MEMORY_REG; - volatile u_int16_t *ptr = (u_int16_t*)(CSP0BASE + addr * 2); - int dataBytes = calculateDataBytes(); - char *counterVals = NULL; - counterVals = realloc(counterVals, dataBytes); - memcpy((char*)counterVals, (char*)ptr, dataBytes); - - // unreset counter - addr = MULTI_PURPOSE_REG; - bus_w(addr, (bus_r(addr) &~ RST_CNTR_MSK)); - FILE_LOG(logDEBUG1, ("\tUnsetting reset Counter. Multi Purpose Reg: 0x%x\n", bus_r(addr))); - - // start state machine - if (startACQ == 1){ - startStateMachine(); - if (runBusy()) { - FILE_LOG(logINFO, ("State machine RUNNING\n")); - } else { - FILE_LOG(logINFO, ("State machine IDLE\n")); - } - } - - if (sizeof(counterVals) <= 0){ - FILE_LOG(logERROR, ("\tSize of counterVals: %d\n", (int)sizeof(counterVals))); - return FAIL; - } - - return OK; -} - - /* aquisition */ int startStateMachine(){ diff --git a/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer b/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer index 085e1a7aa7cd945dc0c72c9edc5e7d70b2bf910d..5eb78885fc076251af9d75835a406cb2c50e051f 100755 GIT binary patch delta 45606 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 delta 46509 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 SKBOf#)w2Zvbt4F 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

2;kj-f9)& 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 Pitp+4Jr&;@pppLvl=u6k diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h b/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h index 03734d2e5..b6de7aff7 100755 --- a/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h +++ b/slsDetectorServers/slsDetectorServer/slsDetectorFunctionList.h @@ -27,6 +27,7 @@ int testBus(); #ifdef GOTTHARDD int detectorTest(enum digitalTestMode arg, int ival); +int testImage(int ival); #elif defined(JUNGFRAUD) || defined(CHIPTESTBOARDD) || defined(MOENCHD) int detectorTest(enum digitalTestMode arg); #endif @@ -301,14 +302,8 @@ void setPatternBitMask(uint64_t mask); uint64_t getPatternBitMask(); #endif -// gotthard specific - image, pedestal -#ifdef GOTTHARDD -void loadImage(enum imageType index, short int imageVals[]); -int readCounterBlock(int startACQ, short int counterVals[]); -int resetCounterBlock(int startACQ); - // jungfrau specific - powerchip, autocompdisable, clockdiv, asictimer, clock, pll, flashing firmware -#elif JUNGFRAUD +#ifdef JUNGFRAUD void initReadoutConfiguration(); int powerChip (int on); int autoCompDisable(int on); diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c index 5e23140ce..f6aa66775 100755 --- a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c +++ b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.c @@ -197,9 +197,6 @@ const char* getFunctionName(enum detFuncs func) { case F_SET_PORT: return "F_SET_PORT"; case F_UPDATE_CLIENT: return "F_UPDATE_CLIENT"; case F_CONFIGURE_MAC: return "F_CONFIGURE_MAC"; - case F_LOAD_IMAGE: return "F_LOAD_IMAGE"; - case F_READ_COUNTER_BLOCK: return "F_READ_COUNTER_BLOCK"; - case F_RESET_COUNTER_BLOCK: return "F_RESET_COUNTER_BLOCK"; case F_ENABLE_TEN_GIGA: return "F_ENABLE_TEN_GIGA"; case F_SET_ALL_TRIMBITS: return "F_SET_ALL_TRIMBITS"; case F_SET_PATTERN_IO_CONTROL: return "F_SET_PATTERN_IO_CONTROL"; @@ -288,9 +285,6 @@ void function_table() { flist[F_SET_PORT] = &set_port; flist[F_UPDATE_CLIENT] = &update_client; flist[F_CONFIGURE_MAC] = &configure_mac; - flist[F_LOAD_IMAGE] = &load_image; - flist[F_READ_COUNTER_BLOCK] = &read_counter_block; - flist[F_RESET_COUNTER_BLOCK] = &reset_counter_block; flist[F_ENABLE_TEN_GIGA] = &enable_ten_giga; flist[F_SET_ALL_TRIMBITS] = &set_all_trimbits; flist[F_SET_PATTERN_IO_CONTROL] = &set_pattern_io_control; @@ -619,7 +613,7 @@ int digital_test(int file_des) { case DETECTOR_FIRMWARE_TEST: case DETECTOR_BUS_TEST: #ifdef GOTTHARDD - case DIGITAL_BIT_TEST: + case IMAGE_TEST: retval = detectorTest(mode, ival); break; #else @@ -2498,131 +2492,6 @@ int configure_mac(int file_des) { - - -int load_image(int file_des) { - ret = OK; - memset(mess, 0, sizeof(mess)); - int args[2] = {-1, -1}; - - if (receiveData(file_des, args, sizeof(args), INT32) < 0) - return printSocketReadError(); - - enum imageType index = args[0]; - int numChannels = args[1]; - short int imageVals[numChannels]; - memset(imageVals, 0, numChannels * sizeof(short int)); - if (numChannels > 0) { - if (receiveData(file_des, imageVals, numChannels * sizeof(short int), OTHER) < 0) { - return printSocketReadError(); - } - } - FILE_LOG(logDEBUG1, ("Loading %s image (ind:%d)\n", (index == DARK_IMAGE) ? "dark" : - ((index == GAIN_IMAGE) ? "gain" : "unknown"), index)); - -#ifndef GOTTHARDD - functionNotImplemented(); -#else - - // set only - if (Server_VerifyLock() == OK) { - switch (index) { - case DARK_IMAGE : - case GAIN_IMAGE : - // size of image does not match expected size - if (numChannels != (calculateDataBytes()/sizeof(short int))) { - ret = FAIL; - sprintf(mess, "Could not load image. " - "Number of Channels do not match. Expected %d, got %d\n", - calculateDataBytes(), numChannels); - FILE_LOG(logERROR,(mess)); - } else - loadImage(index, imageVals); - break; - default: - modeNotImplemented("Image index", (int)index); - break; - } - } -#endif - return Server_SendResult(file_des, INT32, UPDATE, NULL, 0); -} - - - - - - -int read_counter_block(int file_des) { - ret = OK; - memset(mess, 0, sizeof(mess)); - int args[2] = {-1, -1}; - - if (receiveData(file_des, args, sizeof(args), INT32) < 0) - return printSocketReadError(); - int startACQ = args[0]; - int numChannels = args[1]; - short int retval[numChannels]; - memset(retval, 0, numChannels * sizeof(short int)); - FILE_LOG(logDEBUG1, ("Read counter block with start acq bit: %d\n", startACQ)); - -#ifndef GOTTHARDD - functionNotImplemented(); -#else - - // only set - if (Server_VerifyLock() == OK) { - // size of image does not match expected size - if (numChannels != (calculateDataBytes()/sizeof(short int))) { - ret = FAIL; - sprintf(mess, "Could not load image. " - "Number of Channels do not match. Expected %d, got %d\n", - calculateDataBytes(), numChannels); - FILE_LOG(logERROR,(mess)); - } else { - ret = readCounterBlock(startACQ, retval); - if (ret == FAIL) { - strcpy(mess, "Could not read counter block\n"); - FILE_LOG(logERROR,(mess)); - } - } - } -#endif - return Server_SendResult(file_des, OTHER, UPDATE, retval, numChannels * sizeof(short int)); -} - - - - - -int reset_counter_block(int file_des) { - ret = OK; - memset(mess, 0, sizeof(mess)); - int startACQ = -1; - - if (receiveData(file_des, &startACQ, sizeof(startACQ), INT32) < 0) - return printSocketReadError(); - FILE_LOG(logDEBUG1, ("Reset counter block with start acq bit: %d\n", startACQ)); - -#ifndef GOTTHARDD - functionNotImplemented(); -#else - // only set - if (Server_VerifyLock() == OK) { - ret = resetCounterBlock(startACQ); - if (ret == FAIL) { - strcpy(mess, "Could not reset counter block\n"); - FILE_LOG(logERROR, (mess)); - } - } -#endif - return Server_SendResult(file_des, INT32, UPDATE, NULL, 0); -} - - - - - int enable_ten_giga(int file_des) { ret = OK; memset(mess, 0, sizeof(mess)); diff --git a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.h b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.h index 90f5836f2..7779308f2 100755 --- a/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.h +++ b/slsDetectorServers/slsDetectorServer/slsDetectorServer_funcs.h @@ -58,9 +58,6 @@ int set_port(int); int update_client(int); int send_update(int); int configure_mac(int); -int load_image(int); -int read_counter_block(int); -int reset_counter_block(int); int calibrate_pedestal(int); int enable_ten_giga(int); int set_all_trimbits(int); diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 386abfcb0..dfe1451bf 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -778,10 +778,10 @@ class Detector { */ void setROI(defs::ROI value, int moduleId); - /** [Gotthard] TODO: check with jiaguo if he needs any of these functions */ + /** [Gotthard] TODO: check with jiaguo if he needs any of these functions // TODO remove */ Result getExptimeLeft(Positions pos = {}) const; - /** [Gotthard] */ + /** [Gotthard] TODO remove */ Result getPeriodLeft(Positions pos = {}) const; /** [Gotthard] */ @@ -793,30 +793,10 @@ class Detector { Positions pos = {}); /** [Gotthard] */ - void loadDarkImage(const std::string &fname, int module_id = -1); + Result getImageTestMode(Positions pos = {}); - /** [Gotthard] */ - void loadGainImage(const std::string &fname, int module_id = -1); - - /** - * [Gotthard] subset modules not allowed - * @param startACQ if start acq after reading counter - */ - void getCounterMemoryBlock(const std::string &fname, bool startACQ, - Positions pos = {}); - - /** - * [Gotthard] - * @param startACQ if start acq after resetting counter - * TODO! does it make sense to call one detector? - */ - void resetCounterBlock(bool startACQ, Positions pos = {}); - - /** [Gotthard] */ - Result getDigitalTestBit(Positions pos = {}); - - /** [Gotthard] */ - Result setDigitalTestBit(const int value, Positions pos = {}); + /** [Gotthard] If 1, adds channel intensity with precalculated values. Default is 0 */ + Result setImageTestMode(const int value, Positions pos = {}); /************************************************** * * diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 7995c4808..07f544700 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -1229,39 +1229,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { int setFlowControl10G(int enable = -1, int detPos = -1); // /** - * Execute a digital test (Gotthard) + * Execute a digital test (Gotthard, Jungfrau, CTB) * @param mode testmode type - * @param value 1 to set or 0 to clear the digital test bit + * @param value 1 to set or 0 to clear the image test bit (Gotthard) * @param detPos -1 for all detectors in list or specific detector position * @returns result of test */ int digitalTest(digitalTestMode mode, int ival = -1, int detPos = -1); - /** - * Load dark or gain image to detector (Gotthard) - * @param index image type - * @param fname file name from which to load image - * @param detPos -1 for all detectors in list or specific detector position - */ - void loadImageToDetector(imageType index, const std::string &fname, - int detPos = -1); // - - /** - * Writes the counter memory block from the detector (Gotthard) - * @param fname file name to load data from - * @param startACQ is 1 to start acquisition after reading counter - * @param detPos -1 for all detectors in list or specific detector position - */ - void writeCounterBlockFile(const std::string &fname, int startACQ = 0, - int detPos = -1); - - /** - * Resets counter in detector (Gotthard) - * @param startACQ is 1 to start acquisition after resetting counter - * @param detPos -1 for all detectors in list or specific detector position - */ - void resetCounterBlock(int startACQ = 0, int detPos = -1); // - /** * Set/get counter bit in detector (Eiger) * @param i is -1 to get, 0 to reset and any other value to set the counter diff --git a/slsDetectorSoftware/include/slsDetector.h b/slsDetectorSoftware/include/slsDetector.h index b0ea6e672..81b9d6842 100755 --- a/slsDetectorSoftware/include/slsDetector.h +++ b/slsDetectorSoftware/include/slsDetector.h @@ -979,47 +979,13 @@ class slsDetector : public virtual slsDetectorDefs { int64_t getReceiverRealUDPSocketBufferSize() const; /** - * Execute a digital test (Gotthard, Mythen) + * Execute a digital test (Gotthard, Jungfrau, CTB) * @param mode testmode type * @param value 1 to set or 0 to clear the digital test bit * @returns result of test */ int digitalTest(digitalTestMode mode, int ival = -1); - /** - * Load dark or gain image to detector (Gotthard) - * @param index image type, 0 for dark image and 1 for gain image - * @param fname file name from which to load image - */ - void loadImageToDetector(imageType index, const std::string &fname); - - /** - * Called from loadImageToDetector to send the image to detector - * @param index image type, 0 for dark image and 1 for gain image - * @param imageVals image - */ - void sendImageToDetector(imageType index, int16_t imageVals[]); - - /** - * Writes the counter memory block from the detector (Gotthard) - * @param fname file name to load data from - * @param startACQ is 1 to start acquisition after reading counter - */ - void writeCounterBlockFile(const std::string &fname, int startACQ = 0); - - /** - * Gets counter memory block in detector (Gotthard) - * @param image counter memory block from detector - * @param startACQ 1 to start acquisition afterwards, else 0 - */ - void getCounterBlock(int16_t image[], int startACQ = 0); - - /** - * Resets counter in detector - * @param startACQ is 1 to start acquisition after resetting counter - */ - void resetCounterBlock(int startACQ = 0); - /** * Set/get counter bit in detector (Gotthard) * @param i is -1 to get, 0 to reset and any other value to set the counter diff --git a/slsDetectorSoftware/include/slsDetectorCommand.h b/slsDetectorSoftware/include/slsDetectorCommand.h index 9116d9e45..053f716d3 100755 --- a/slsDetectorSoftware/include/slsDetectorCommand.h +++ b/slsDetectorSoftware/include/slsDetectorCommand.h @@ -73,7 +73,6 @@ class slsDetectorCommand : public virtual slsDetectorDefs { static std::string helpSpeed(int action); static std::string helpAdvanced(int action); static std::string helpConfiguration(int action); - static std::string helpImage(int action); static std::string helpCounter(int action); static std::string helpADC(int action); static std::string helpTempControl(int action); @@ -134,7 +133,6 @@ class slsDetectorCommand : public virtual slsDetectorDefs { 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); diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 627233e54..395c2e312 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -1015,48 +1015,14 @@ void Detector::setExternalSignalFlags(defs::externalSignalFlag value, pimpl->Parallel(&slsDetector::setExternalSignalFlags, pos, value); } -void Detector::loadDarkImage(const std::string &fname, int module_id) { - if (module_id == -1) { - pimpl->loadImageToDetector(defs::DARK_IMAGE, fname, -1); - } - pimpl->Parallel(&slsDetector::loadImageToDetector, {module_id}, defs::DARK_IMAGE, - fname); -} - -void Detector::loadGainImage(const std::string &fname, int module_id) { - if (module_id == -1) { - pimpl->loadImageToDetector(defs::GAIN_IMAGE, fname, -1); - } - pimpl->Parallel(&slsDetector::loadImageToDetector, {module_id}, defs::GAIN_IMAGE, - fname); -} - -void Detector::getCounterMemoryBlock(const std::string &fname, bool startACQ, - Positions pos) { - if (pos.empty() || (pos.size() == 1 && pos[0] == -1)) { - pimpl->writeCounterBlockFile(fname, static_cast(startACQ), -1); - } - if (pos.size() > 1) { - throw RuntimeError( - "Cannot load get counter memory block on a subset of modules"); - } - pimpl->Parallel(&slsDetector::writeCounterBlockFile, pos, fname, - static_cast(startACQ)); -} - -void Detector::resetCounterBlock(bool startACQ, Positions pos) { - pimpl->Parallel(&slsDetector::resetCounterBlock, pos, - static_cast(startACQ)); -} - -Result Detector::getDigitalTestBit(Positions pos) { +Result Detector::getImageTestMode(Positions pos) { return pimpl->Parallel(&slsDetector::digitalTest, pos, - defs::DIGITAL_BIT_TEST, -1); + defs::IMAGE_TEST, -1); } -Result Detector::setDigitalTestBit(int value, Positions pos) { +Result Detector::setImageTestMode(int value, Positions pos) { return pimpl->Parallel(&slsDetector::digitalTest, pos, - defs::DIGITAL_BIT_TEST, value); + defs::IMAGE_TEST, value); } diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index cb2a978f1..599321e53 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -1889,64 +1889,6 @@ int multiSlsDetector::digitalTest(digitalTestMode mode, int ival, int detPos) { return sls::minusOneIfDifferent(r); } -void multiSlsDetector::loadImageToDetector(imageType index, - const std::string &fname, - int detPos) { - // single - if (detPos >= 0) { - detectors[detPos]->loadImageToDetector(index, fname); - } - - // multi - - // read image for all - int nch = getNumberOfChannels().x; - short int imageVals[nch]; - if (readDataFile(fname, imageVals, nch) < nch * (int)sizeof(short int)) { - throw RuntimeError("Could not open file or not enough data in file to " - "load image to detector."); - } - - // send image to all - for (size_t idet = 0; idet < detectors.size(); ++idet) { - detectors[idet]->sendImageToDetector(index, imageVals + idet * detectors[idet]->getNumberOfChannels().x); - } -} - -void multiSlsDetector::writeCounterBlockFile(const std::string &fname, - int startACQ, int detPos) { - // single - if (detPos >= 0) { - detectors[detPos]->writeCounterBlockFile(fname, startACQ); - } - - // multi - int nch = getNumberOfChannels().x; - short int imageVals[nch]; - for (size_t idet = 0; idet < detectors.size(); ++idet) { - detectors[idet]->getCounterBlock( - imageVals + idet * detectors[idet]->getNumberOfChannels().x, - startACQ); - } - - if (writeDataFile(fname, nch, imageVals) < nch * (int)sizeof(short int)) { - throw RuntimeError( - "Could not open file to write or did not write enough data" - " in file to write counter block file from detector."); - } - -} - -void multiSlsDetector::resetCounterBlock(int startACQ, int detPos) { - // single - if (detPos >= 0) { - detectors[detPos]->resetCounterBlock(startACQ); - } - - // multi - parallelCall(&slsDetector::resetCounterBlock, startACQ); -} - int multiSlsDetector::setCounterBit(int i, int detPos) { // single if (detPos >= 0) { diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index 9e300c2f3..92ed065b8 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -2167,65 +2167,6 @@ int slsDetector::digitalTest(digitalTestMode mode, int ival) { return retval; } -void slsDetector::loadImageToDetector(imageType index, - const std::string &fname) { - int nChan = getNumberOfChannels().x; - int16_t args[nChan]; - FILE_LOG(logDEBUG1) << "Loading " << (index == 0u ? "Dark" : "Gain") - << "image from file " << fname; - - if (readDataFile(fname, args, nChan) != 0) { - sendImageToDetector(index, args); - } else { - throw RuntimeError( - "slsDetector::loadImageToDetector: Could not open file: " + fname); - } -} - -void slsDetector::sendImageToDetector(imageType index, int16_t imageVals[]) { - int fnum = F_LOAD_IMAGE; - int nChan = getNumberOfChannels().x; - int args[]{static_cast(index), nChan}; - FILE_LOG(logDEBUG1) << "Sending image to detector"; - auto client = DetectorSocket(shm()->hostname, shm()->controlPort); - client.Send(&fnum, sizeof(fnum)); - client.Send(args, sizeof(args)); - client.Send(imageVals, nChan * sizeof(int16_t)); - int ret = FAIL; - client.Receive(&ret, sizeof(ret)); - char mess[MAX_STR_LENGTH]{}; - client.Receive(mess, MAX_STR_LENGTH); - throw DetectorError("Detector " + std::to_string(detId) + - " returned error: " + std::string(mess)); - if (ret == FORCE_UPDATE) { - updateCachedDetectorVariables(); - } -} - -void slsDetector::writeCounterBlockFile(const std::string &fname, - int startACQ) { - int nChan = getNumberOfChannels().x; - int16_t retvals[nChan]; - FILE_LOG(logDEBUG1) << "Reading Counter to " << fname - << (startACQ != 0 ? " and Restarting Acquisition" - : "\n"); - getCounterBlock(retvals, startACQ); - writeDataFile(fname, nChan, retvals); -} - -void slsDetector::getCounterBlock(int16_t image[], int startACQ) { - int fnum = F_READ_COUNTER_BLOCK; - int nChan = getNumberOfChannels().x; - int args[] = {startACQ, nChan}; - FILE_LOG(logDEBUG1) << "Reading Counter block with startacq: " << startACQ; - sendToDetector(fnum, args, sizeof(args), image, nChan * sizeof(int16_t)); -} - -void slsDetector::resetCounterBlock(int startACQ) { - FILE_LOG(logDEBUG1) << "Resetting Counter with startacq: " << startACQ; - sendToDetector(F_RESET_COUNTER_BLOCK, startACQ, nullptr); -} - int slsDetector::setCounterBit(int cb) { int retval = -1; FILE_LOG(logDEBUG1) << "Sending counter bit " << cb; diff --git a/slsDetectorSoftware/src/slsDetectorCommand.cpp b/slsDetectorSoftware/src/slsDetectorCommand.cpp index 3dc96c33f..68985ad85 100755 --- a/slsDetectorSoftware/src/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp @@ -125,9 +125,9 @@ slsDetectorCommand::slsDetectorCommand(multiSlsDetector *det) { /* digital test and debugging */ /*! \page test - - digibittest:[i] performs digital test of the module i. Returns 0 if succeeded, otherwise error mask. Gotthard only. Only put! + - imagetest [i] If 1, adds channel intensity with precalculated values. Default is 0. Gotthard only. */ - descrToFuncMap[i].m_pFuncName = "digibittest"; + descrToFuncMap[i].m_pFuncName = "imagetest"; descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdDigiTest; ++i; @@ -213,20 +213,6 @@ slsDetectorCommand::slsDetectorCommand(multiSlsDetector *det) { descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdData; ++i; - /*! \page acquisition - - readctr Reads the counters from the detector memory (analog detector returning values translated into number of photons - only GOTTHARD). Cannot put. - */ - descrToFuncMap[i].m_pFuncName = "readctr"; - descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdCounter; - ++i; - - /*! \page acquisition - - resetctr i Resets counter in detector, restarts acquisition if i=1(analog detector returning values translated into number of photons - only GOTTHARD). Cannot put. - */ - descrToFuncMap[i].m_pFuncName = "resetctr"; - descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdCounter; - ++i; - /*! \page acquisition - resmat i sets/resets counter bit in detector.gets the counter bit in Eiger */ @@ -856,19 +842,6 @@ slsDetectorCommand::slsDetectorCommand(multiSlsDetector *det) { // descrToFuncMap[i].m_pFuncPtr=&slsDetectorCommand::cmdThreaded; // ++i; - /*! \page data - - darkimage fn Loads the dark image to the detector from file fn (pedestal image). Cannot get. For Gotthard only. - */ - descrToFuncMap[i].m_pFuncName = "darkimage"; - descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdImage; - ++i; - - /*! \page data - - gainimage fn Loads the gain image to the detector from file fn (gain map for translation into number of photons of an analog detector). Cannot get. For Gotthard only. - */ - descrToFuncMap[i].m_pFuncName = "gainimage"; - descrToFuncMap[i].m_pFuncPtr = &slsDetectorCommand::cmdImage; - ++i; /*! \page settings Detector settings commands Commands to setup the settings of the detector @@ -2733,36 +2706,6 @@ std::string slsDetectorCommand::helpThreaded(int action) { return os.str(); } -std::string slsDetectorCommand::cmdImage(int narg, const char * const args[], int action, int detPos) { - std::string sval; - if (action == HELP_ACTION) - return helpImage(HELP_ACTION); - else if (action == GET_ACTION) - return std::string("Cannot get"); - - sval = std::string(args[1]); - - if (std::string(args[0]) == std::string("darkimage")) - myDet->loadImageToDetector(DARK_IMAGE, sval, detPos); - else if (std::string(args[0]) == std::string("gainimage")) - myDet->loadImageToDetector(GAIN_IMAGE, sval, detPos); - - return std::string("Image loaded succesfully"); -} - -std::string slsDetectorCommand::helpImage(int action) { - std::ostringstream os; - if (action == PUT_ACTION || action == HELP_ACTION) { - os << "darkimage f \t loads the image to detector from file f" << std::endl; - os << "gainimage f \t loads the image to detector from file f" << std::endl; - } - if (action == GET_ACTION || action == HELP_ACTION) { - os << "darkimage \t Cannot get" << std::endl; - os << "gainimage \t Cannot get" << std::endl; - } - return os.str(); -} - std::string slsDetectorCommand::cmdCounter(int narg, const char * const args[], int action, int detPos) { int ival; char answer[100]; @@ -2773,27 +2716,7 @@ std::string slsDetectorCommand::cmdCounter(int narg, const char * const args[], else if (action == PUT_ACTION) ival = atoi(args[1]); - - if (std::string(args[0]) == std::string("readctr")) { - if (action == PUT_ACTION) - return std::string("Cannot put"); - else { - if (narg < 3) - return std::string("should specify I/O file"); - sval = std::string(args[2]); - myDet->writeCounterBlockFile(sval, ival, detPos); - return std::string("Counter read succesfully"); - } - } else if (std::string(args[0]) == std::string("resetctr")) { - if (action == GET_ACTION) - return std::string("Cannot get"); - else { - myDet->resetCounterBlock(ival, detPos); - return std::string("successful"); - } - } - - else if (std::string(args[0]) == std::string("resmat")) { + if (std::string(args[0]) == std::string("resmat")) { if (action == PUT_ACTION) { if (!sscanf(args[1], "%d", &ival)) return std::string("Could not scan resmat input ") + std::string(args[1]); @@ -2814,13 +2737,9 @@ std::string slsDetectorCommand::helpCounter(int action) { std::ostringstream os; os << std::endl; if (action == PUT_ACTION || action == HELP_ACTION) { - os << "readctr \t Cannot put" << std::endl; - os << "resetctr i \t resets counter in detector, restarts acquisition if i=1" << std::endl; os << "resmat i \t sets/resets counter bit in detector" << std::endl; } if (action == GET_ACTION || action == HELP_ACTION) { - os << "readctr i fname\t reads counter in detector to file fname, restarts acquisition if i=1" << std::endl; - os << "resetctr \t Cannot get" << std::endl; os << "resmat i \t gets the counter bit in detector" << std::endl; } return os.str(); @@ -3606,18 +3525,17 @@ std::string slsDetectorCommand::cmdDigiTest(int narg, const char * const args[], return std::string(answer); } - else if (cmd == "digibittest") { - if (action == GET_ACTION) - return std::string("cannot get ") + cmd; - int ival = -1; - if (sscanf(args[1], "%d", &ival)) { - if ((ival == 0) || (ival == 1)) { - sprintf(answer, "%d", myDet->digitalTest(DIGITAL_BIT_TEST, ival, detPos)); - return std::string(answer); - } else - return std::string("Use only 0 or 1 to set/clear digital test bit\n"); - } else - return std::string("undefined number"); + else if (cmd == "imagetest") { + if (action == PUT_ACTION) { + int ival = -1; + if (!sscanf(args[1], "%d", &ival)) { + return std::string("could not scan parameter for imagetest\n"); + } + ival = (ival == 0) ? 0 : 1; + myDet->digitalTest(IMAGE_TEST, ival, detPos); + } + + return std::to_string(myDet->digitalTest(IMAGE_TEST, -1, detPos)); } return std::string("unknown test mode ") + cmd; @@ -3627,7 +3545,12 @@ std::string slsDetectorCommand::helpDigiTest(int action) { std::ostringstream os; if (action == GET_ACTION || action == HELP_ACTION) { - os << "digibittest:i \t performs digital test of the module i. Returns 0 if succeeded, otherwise error mask.Gotthard only." << std::endl; + os << "imagetest i \t If 1, adds channel intensity with precalculated values. Default is 0. Gotthard only." << std::endl; + os << "bustest \t performs test of the bus interface between FPGA and embedded Linux system. Can last up to a few minutes. Jungfrau only." << std::endl; + os << "firmwaretest \t performs the firmware test. Jungfrau only." << std::endl; + } + if (action == PUT_ACTION || action == HELP_ACTION) { + os << "imagetest i \t If 1, adds channel intensity with precalculated values. Default is 0. Gotthard only." << std::endl; os << "bustest \t performs test of the bus interface between FPGA and embedded Linux system. Can last up to a few minutes. Jungfrau only." << std::endl; os << "firmwaretest \t performs the firmware test. Jungfrau only." << std::endl; } diff --git a/slsSupportLib/include/sls_detector_defs.h b/slsSupportLib/include/sls_detector_defs.h index b6e91876e..a3f854b32 100755 --- a/slsSupportLib/include/sls_detector_defs.h +++ b/slsSupportLib/include/sls_detector_defs.h @@ -368,7 +368,7 @@ format enum digitalTestMode { DETECTOR_FIRMWARE_TEST, /**< test detector system firmware */ DETECTOR_BUS_TEST, /**< test detector system CPU-FPGA bus */ - DIGITAL_BIT_TEST /**< gotthard digital bit test */ + IMAGE_TEST /**< gotthard digital bit test */ }; /** @@ -542,11 +542,6 @@ format IS_SLAVE /**< is slave */ }; - enum imageType { - DARK_IMAGE, /**< dark image */ - GAIN_IMAGE /**< gain image */ - }; - /** * frame mode for processor */ diff --git a/slsSupportLib/include/sls_detector_funcs.h b/slsSupportLib/include/sls_detector_funcs.h index 603bfa6ca..e9418da70 100755 --- a/slsSupportLib/include/sls_detector_funcs.h +++ b/slsSupportLib/include/sls_detector_funcs.h @@ -42,10 +42,7 @@ enum detFuncs{ F_GET_LAST_CLIENT_IP, /**< returns the IP of the client last connected to the detector */ F_SET_PORT, /**< Changes communication port of the server */ F_UPDATE_CLIENT, /**< Returns all the important parameters to update the shared memory of the client */ - F_CONFIGURE_MAC, /**< Configures MAC for Gotthard readout */ - F_LOAD_IMAGE, /**< Loads Dark/Gain image to the Gotthard detector */ - F_READ_COUNTER_BLOCK, /**< reads the counter block memory for gotthard */ - F_RESET_COUNTER_BLOCK, /**< resets the counter block memory for gotthard */ + F_CONFIGURE_MAC, /**< Configures MAC */ F_ENABLE_TEN_GIGA, /**< enable 10Gbe */ F_SET_ALL_TRIMBITS, /** < set all trimbits to this value */ F_SET_PATTERN_IO_CONTROL, /** < set pattern i/o control */ @@ -194,9 +191,6 @@ static const char* getFunctionNameFromEnum(enum detFuncs func) { case F_SET_PORT: return "F_SET_PORT"; case F_UPDATE_CLIENT: return "F_UPDATE_CLIENT"; case F_CONFIGURE_MAC: return "F_CONFIGURE_MAC"; - case F_LOAD_IMAGE: return "F_LOAD_IMAGE"; - case F_READ_COUNTER_BLOCK: return "F_READ_COUNTER_BLOCK"; - case F_RESET_COUNTER_BLOCK: return "F_RESET_COUNTER_BLOCK"; case F_ENABLE_TEN_GIGA: return "F_ENABLE_TEN_GIGA"; case F_SET_ALL_TRIMBITS: return "F_SET_ALL_TRIMBITS"; case F_SET_PATTERN_IO_CONTROL: return "F_SET_PATTERN_IO_CONTROL"; diff --git a/slsSupportLib/include/versionAPI.h b/slsSupportLib/include/versionAPI.h index 38452d4d8..a21736ff5 100644 --- a/slsSupportLib/include/versionAPI.h +++ b/slsSupportLib/include/versionAPI.h @@ -3,8 +3,8 @@ #define APILIB 0x190723 #define APIRECEIVER 0x190722 #define APIGUI 0x190723 -#define APICTB 0x190820 -#define APIGOTTHARD 0x190820 -#define APIJUNGFRAU 0x190820 #define APIMOENCH 0x190820 +#define APIGOTTHARD 0x190820 +#define APICTB 0x190820 +#define APIJUNGFRAU 0x190820 #define APIEIGER 0x190820 From 62c4bfab64f90ad999ec1f8837e0b29edf042303 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Wed, 21 Aug 2019 09:23:32 +0200 Subject: [PATCH 105/108] WIP --- slsDetectorSoftware/include/Detector.h | 158 ++++++++-------- .../include/multiSlsDetector.h | 162 ++++++++-------- slsDetectorSoftware/include/slsDetector.h | 34 ++-- slsDetectorSoftware/src/Detector.cpp | 133 ++++++------- slsDetectorSoftware/src/multiSlsDetector.cpp | 178 +++++++++--------- slsDetectorSoftware/src/slsDetector.cpp | 39 ++-- 6 files changed, 339 insertions(+), 365 deletions(-) diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index dfe1451bf..a683f9e37 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -20,8 +20,8 @@ class Detector { public: /** * @param shm_id detector shared memory id - * Default value is 0. Can be set to more values for - * multiple detectors.It is important only if you + * Default value is 0. Can be set to more values for + * multiple detectors.It is important only if you * are controlling multiple detectors from the same pc. */ Detector(int shm_id = 0); @@ -67,7 +67,8 @@ class Detector { Result getModuleSize(Positions pos = {}) const; - /** Gets the actual full detector size. It is the same even if ROI changes */ + /** Gets the actual full detector size. It is the same even if ROI changes + */ defs::xy getDetectorSize() const; /** @@ -82,8 +83,6 @@ class Detector { /** [Jungfrau][Gotthard] */ void setSettings(defs::detectorSettings value, Positions pos = {}); - - /************************************************** * * * Acquisition Parameters * @@ -174,9 +173,7 @@ class Detector { * [Gotthard, Jungfrau, CTB Options: AUTO_TIMING, TRIGGER_EXPOSURE] * [Eiger Options: AUTO_TIMING, TRIGGER_EXPOSURE, GATED, BURST_TRIGGER] */ - void setTimingMode(defs::timingMode value, - Positions pos = {}); - + void setTimingMode(defs::timingMode value, Positions pos = {}); /************************************************** * * @@ -190,16 +187,18 @@ class Detector { */ void acquire(); - /** Non blocking + /** Non blocking * Starts the reciever (if enabled) and then the detector - * You have to check detector status until it is idle before you call stopACquisition - * - */ + * You have to check detector status until it is idle before you call + * stopACquisition + * + */ void startAcquisition(); /** * Stops detector acquisition and then receiver (if enabled) - * If no receiver enabled, you can skip this for normal acquisition (no abort) + * If no receiver enabled, you can skip this for normal acquisition (no + * abort) */ void stopAcquisition(); @@ -224,20 +223,19 @@ class Detector { /** [Eiger] Sends an internal software trigger to the detector */ void sendSoftwareTrigger(Positions pos = {}); - //TODO: remove resetframescaught in receiver - + // TODO: remove resetframescaught in receiver /************************************************** * * * Network Configuration (Detector<->Receiver) * * * * ************************************************/ - - /** Configures the destination for UDP packets in the detector + + /** Configures the destination for UDP packets in the detector * Needed only if you use a custom receiver (not slsReceiver) * as it is already included in setReceiverHostname. - */ - void configureMAC(Positions pos = {});//TODO: find a reasonable name + */ + void configureMAC(Positions pos = {}); // TODO: find a reasonable name /** [Jungfrau] */ Result getNumberofUDPInterfaces(Positions pos = {}) const; @@ -258,12 +256,12 @@ class Detector { Result getSourceUDPIP(Positions pos = {}) const; /* For Eiger 1G, the detector will replace with its own DHCP IP - * 10G Eiger and other detectors, the source UDP IP must be in the + * 10G Eiger and other detectors, the source UDP IP must be in the * same subnet of the destination UDP IP */ void setSourceUDPIP(const std::string &ip, Positions pos = {}); - /** [Jungfrau] bottom half */ + /** [Jungfrau] bottom half */ Result getSourceUDPIP2(Positions pos = {}) const; /** [Jungfrau] bottom half */ @@ -275,7 +273,7 @@ class Detector { * For Eiger 10G, the detector will replace with its own DHCP MAC + 1 * Others can be anything (beware of certain bits) */ - + void setSourceUDPMAC(const std::string &mac, Positions pos = {}); /** [Jungfrau] bottom half */ @@ -294,13 +292,13 @@ class Detector { /** [Jungfrau bottom half] */ void setDestinationUDPIP2(const std::string &ip, Positions pos = {}); - + Result getDestinationUDPMAC(Positions pos = {}) const; - /** MAC of the interface in receiver that the detector sends data to + /** MAC of the interface in receiver that the detector sends data to * Only needed if you use a custom receiver (not slsReceiver) * Must be followed by configuremac. - */ + */ void setDestinationUDPMAC(const std::string &mac, Positions pos = {}); /** [Jungfrau bottom half] */ @@ -311,15 +309,18 @@ class Detector { Result getDestinationUDPPort(Positions pos = {}) const; - /** module_id is -1 for all detectors, ports for each module is calculated (increments) */ - //TODO if Parallel takes a vector, can send multiple vaues to set in slsdetector.cp + /** module_id is -1 for all detectors, ports for each module is calculated + * (increments) */ + // TODO if Parallel takes a vector, can send multiple vaues to set in + // slsdetector.cp void setDestinationUDPPort(int port, int module_id = -1); /** [Eiger right port][Jungfrau bottom half] */ Result getDestinationUDPPort2(Positions pos = {}) const; /** [Eiger right port][Jungfrau bottom half] - * module_id is -1 for all detectors, ports for each module is calculated (increments) + * module_id is -1 for all detectors, ports for each module is calculated + * (increments) */ void setDestinationUDPPort2(int port, int module_id = -1); @@ -342,9 +343,9 @@ class Detector { /** * [Jungfrau]: Sets the transmission delay of the first UDP packet being - * streamed out of the module. Options: 0 - 31, each value represenets 1 ms - * [Eiger]: Sets the transmission delay of entire frame streamed out for both - * left and right UDP ports. Options: //TODO possible values + * streamed out of the module. Options: 0 - 31, each value represenets 1 ms + * [Eiger]: Sets the transmission delay of entire frame streamed out for + * both left and right UDP ports. Options: //TODO possible values */ void setTransmissionDelayFrame(int value, Positions pos = {}); @@ -368,7 +369,6 @@ class Detector { */ void setTransmissionDelayRight(int value, Positions pos = {}); - /************************************************** * * * RECEIVER CONFIG * @@ -412,8 +412,8 @@ class Detector { * discard partial frames is the fastest */ void setRxFrameDiscardPolicy(defs::frameDiscardPolicy f, - Positions pos = {}); - + Positions pos = {}); + Result getPartialFramesPadding(Positions pos = {}) const; /** padding enabled. Disabling padding is the fastest */ @@ -421,12 +421,11 @@ class Detector { Result getRxUDPSocketBufferSize(Positions pos = {}) const; - void setRxUDPSocketBufferSize(int64_t udpsockbufsize, - Positions pos = {}); - /** TODO: - * Linux kernel allocates twice the amount you set for bookkeeping purposes */ - Result - getRxRealUDPSocketBufferSize(Positions pos = {}) const; + void setRxUDPSocketBufferSize(int64_t udpsockbufsize, Positions pos = {}); + /** TODO: + * Linux kernel allocates twice the amount you set for bookkeeping purposes + */ + Result getRxRealUDPSocketBufferSize(Positions pos = {}) const; Result getRxLock(Positions pos = {}); @@ -435,7 +434,6 @@ class Detector { Result getRxLastClientIP(Positions pos = {}) const; - /************************************************** * * * FILE * @@ -453,10 +451,10 @@ class Detector { Result getFileNamePrefix(Positions pos = {}) const; - /** default run - * File Name: [file name prefix]_d[module index]_f[file index]_[acquisition index].[file format] - * eg. run_d0_f0_5.raw - */ + /** default run + * File Name: [file name prefix]_d[module index]_f[file index]_[acquisition + * index].[file format] eg. run_d0_f0_5.raw + */ void setFileNamePrefix(const std::string &fname, Positions pos = {}); Result getAcquisitonIndex(Positions pos = {}) const; @@ -483,13 +481,12 @@ class Detector { /** 0 will set frames per file to unlimited */ void setFramesPerFile(int n, Positions pos = {}); - /************************************************** * * * ZMQ Streaming Parameters (Receiver<->Client)* * * * ************************************************/ - //TODO callback functions + // TODO callback functions Result getRxZmqDataStream(Positions pos = {}) const; @@ -501,7 +498,8 @@ class Detector { * If 0, streaming timer is the timeout, * after which current frame sent out. Default is 0 at 200 ms. * Default is 1: send every frame. - * If you want just to see some frames for gui purposes, set to 0 (200ms default timer). + * If you want just to see some frames for gui purposes, set to 0 (200ms + * default timer). */ void setRxZmqFrequency(int freq, Positions pos = {}); @@ -516,22 +514,22 @@ class Detector { Result getRxZmqPort(Positions pos = {}) const; /** - * module_id is -1 for all detectors, ports for each module is calculated (increments) - * Restarts receiver zmq sockets only if it was already enabled + * module_id is -1 for all detectors, ports for each module is calculated + * (increments) Restarts receiver zmq sockets only if it was already enabled */ void setRxZmqPort(int port, int module_id = -1); Result getRxZmqIP(Positions pos = {}) const; - void setRxZmqIP(const std::string &ip, - Positions pos = {}); + void setRxZmqIP(const std::string &ip, Positions pos = {}); Result getClientZmqPort(Positions pos = {}) const; - + /** - * Needed only when using the client call back to get reconstructed data from multi modules - * module_id is -1 for all detectors, ports for each module is calculated (increments) - * Restarts client zmq sockets oonly if it was already enabled + * Needed only when using the client call back to get reconstructed data + * from multi modules module_id is -1 for all detectors, ports for each + * module is calculated (increments) Restarts client zmq sockets oonly if it + * was already enabled */ void setClientZmqPort(int port, int module_id = -1); @@ -539,7 +537,6 @@ class Detector { void setClientZmqIp(const std::string &ip, Positions pos = {}); - /************************************************** * * * Eiger Specific * @@ -629,7 +626,8 @@ class Detector { /** //TODO: default, get, set * [Eiger] Set Rate correction - * 0 disable correction, < 0: default dead time from trimbit file, > 0 custom deadtime (advanced) + * 0 disable correction, < 0: default dead time from trimbit file, > 0 + * custom deadtime (advanced) */ void setRateCorrection(ns dead_time, Positions pos = {}); @@ -669,15 +667,15 @@ class Detector { /** [Eiger] Advanced */ Result getPartialReset(Positions pos = {}) const; - /** [Eiger] Advanced + /** [Eiger] Advanced * used for pulsing chips */ void setPartialReset(bool enable, Positions pos = {}); - /** [Eiger] Advanced + /** [Eiger] Advanced * Pulse Pixel n times at x and y coordinates */ void pulsePixel(int n, defs::xy pixel, Positions pos = {}); - /** [Eiger] Advanced + /** [Eiger] Advanced * Pulse Pixel n times and move by a relative value of x and y * coordinates */ void pulsePixelNMove(int n, defs::xy pixel, Positions pos = {}); @@ -692,7 +690,6 @@ class Detector { /** [Eiger] with specific quad hardware */ void setQuad(const bool enable); - /************************************************** * * * Jungfrau Specific * @@ -735,10 +732,12 @@ class Detector { /** [Jungfrau] Advanced * //TODO naming - * By default, the on-chip gain switching is active during the entire exposure. - * This mode disables the on-chip gain switching comparator automatically after 93.75% of exposure time (only for longer than 100us). */ + * By default, the on-chip gain switching is active during the entire + * exposure. This mode disables the on-chip gain switching comparator + * automatically after 93.75% of exposure time (only for longer than 100us). + */ void setAutoCompDisable(bool value, Positions pos = {}); - + /** [Jungfrau] Advanced TODO naming */ Result getNumberOfAdditionalStorageCells() const; @@ -748,8 +747,8 @@ class Detector { /** [Jungfrau] Advanced */ Result getStorageCellStart(Positions pos = {}) const; - /** [Jungfrau] Advanced. Sets the storage cell storing the first acquisition of the - * series. Options: 0-15 + /** [Jungfrau] Advanced. Sets the storage cell storing the first acquisition + * of the series. Options: 0-15 */ void setStoragecellStart(int cell, Positions pos = {}); @@ -760,7 +759,6 @@ class Detector { * Options: (0-1638375 ns (resolution of 25ns) */ void setStorageCellDelay(ns value, Positions pos = {}); - /************************************************** * * * Gotthard Specific * @@ -778,7 +776,8 @@ class Detector { */ void setROI(defs::ROI value, int moduleId); - /** [Gotthard] TODO: check with jiaguo if he needs any of these functions // TODO remove */ + /** [Gotthard] TODO: check with jiaguo if he needs any of these functions // + * TODO remove */ Result getExptimeLeft(Positions pos = {}) const; /** [Gotthard] TODO remove */ @@ -795,7 +794,8 @@ class Detector { /** [Gotthard] */ Result getImageTestMode(Positions pos = {}); - /** [Gotthard] If 1, adds channel intensity with precalculated values. Default is 0 */ + /** [Gotthard] If 1, adds channel intensity with precalculated values. + * Default is 0 */ Result setImageTestMode(const int value, Positions pos = {}); /************************************************** @@ -819,8 +819,8 @@ class Detector { /** [CTB] */ Result getReadoutMode(Positions pos = {}) const; - /** [CTB] Options: NORMAL_READOUT = 0, DIGITAL_ONLY = 1, ANALOG_AND_DIGITAL //TODO ANALOG_ONLY, make enum - * = 2 */ + /** [CTB] Options: NORMAL_READOUT = 0, DIGITAL_ONLY = 1, ANALOG_AND_DIGITAL + * //TODO ANALOG_ONLY, make enum = 2 */ void setReadoutMode(int value, Positions pos = {}); /** [CTB] */ @@ -955,7 +955,6 @@ class Detector { /** [CTB] */ void setLEDEnable(bool enable, Positions pos = {}); - /************************************************** * * * PATTERN * @@ -1024,7 +1023,6 @@ class Detector { * * * ************************************************/ - /** [Moench] */ Result getAdditionalJsonHeader(Positions pos = {}) const; @@ -1045,7 +1043,7 @@ class Detector { const std::string &value, Positions pos = {}); - /** [Moench] TODO! How do we do this best??? Can be refactored to something + /** [Moench] TODO! How do we do this best??? Can be refactored to something * else? Use a generic zmq message passing system... * For now limiting to all detectors working the same*/ /** [Moench: -1 if not found or cannot convert to int] */ @@ -1080,7 +1078,7 @@ class Detector { /** [Jungfrau][CTB] */ void resetFPGA(Positions pos = {}); - /** [Jungfrau][Gotthard][CTB] + /** [Jungfrau][Gotthard][CTB] * Copy detector server fname from tftp folder of hostname to detector * Also changes respawn server, which is effective after a reboot. */ @@ -1121,7 +1119,6 @@ class Detector { /** [Gotthard][Jungfrau][CTB] not possible to read back*/ void writeAdcRegister(uint32_t addr, uint32_t value, Positions pos = {}); - /************************************************** * * * Insignificant * @@ -1161,11 +1158,10 @@ class Detector { std::string getUserDetails() const; - Result getRxCurrentFrameIndex(Positions pos = {}) const; - -private: -std::vector getPortNumbers(int start_port); + Result getRxCurrentFrameIndex(Positions pos = {}) const; + private: + std::vector getPortNumbers(int start_port); }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index 07f544700..abe0c2e78 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -1,9 +1,9 @@ #pragma once +#include "Result.h" #include "SharedMemory.h" #include "logger.h" #include "sls_detector_defs.h" -#include "Result.h" class slsDetector; class ZmqSocket; @@ -57,7 +57,7 @@ struct sharedMultiSlsDetector { slsDetectorDefs::xy numberOfDetector; /** max number of channels for complete detector*/ - slsDetectorDefs::xy numberOfChannels; + slsDetectorDefs::xy numberOfChannels; /** flag for acquiring */ bool acquiringFlag; @@ -309,7 +309,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param port starting port number */ void setVirtualDetectorServers(const int numdet, const int port); - + /** * Sets the hostname of all sls detectors in shared memory and updates local * cache @@ -347,7 +347,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns detector type of sls detector in position pos, if -1, returns * the first det type */ - detectorType getDetectorTypeAsEnum(int detPos);// + detectorType getDetectorTypeAsEnum(int detPos); // /** * Concatenates string types of all sls detectors or @@ -356,25 +356,27 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns detector type of sls detector in position pos, if -1, * concatenates */ - std::string getDetectorTypeAsString(int detPos = -1);// + std::string getDetectorTypeAsString(int detPos = -1); // /** * Returns the number of detectors in the multidetector structure * @returns number of detectors */ - size_t size() const;// + size_t size() const; // /** * Returns the number of detectors in each direction */ - slsDetectorDefs::xy getNumberOfDetectors() const;// + slsDetectorDefs::xy getNumberOfDetectors() const; // /** - * Returns the total number of channels of all sls detectors including gap pixels + * Returns the total number of channels of all sls detectors including gap + * pixels * @param detPos -1 for all detectors in list or specific detector position - * @returns the total number of channels of all sls detectors including gap pixels + * @returns the total number of channels of all sls detectors including gap + * pixels */ - slsDetectorDefs::xy getNumberOfChannels(int detPos = -1) const;// + slsDetectorDefs::xy getNumberOfChannels(int detPos = -1) const; // /** * Must be set before setting hostname @@ -382,35 +384,35 @@ class multiSlsDetector : public virtual slsDetectorDefs { * dimension d from shared memory * @param c maximum number of channels of all sls detectors */ - void setNumberOfChannels(const slsDetectorDefs::xy c); // + void setNumberOfChannels(const slsDetectorDefs::xy c); // /** * Get Quad Type (Only for Eiger Quad detector hardware) * @param detPos -1 for all detectors in list or specific detector position * @returns quad type */ - int getQuad(int detPos = -1);// + int getQuad(int detPos = -1); // /** * Set Quad Type (Only for Eiger Quad detector hardware) * @param enable true if quad type set, else false * @param detPos -1 for all detectors in list or specific detector position */ - void setQuad(const bool enable, int detPos = -1);// + void setQuad(const bool enable, int detPos = -1); // /** * Set number of rows to read out (Only for Eiger) * @param value number of lines * @param detPos -1 for all detectors in list or specific detector position */ - void setReadNLines(const int value, int detPos = -1);// + void setReadNLines(const int value, int detPos = -1); // /** * Get number of rows to read out (Only for Eiger) * @param detPos -1 for all detectors in list or specific detector position * @returns number of lines */ - int getReadNLines(int detPos = -1);// + int getReadNLines(int detPos = -1); // /** * Set/Gets TCP Port of the detector @@ -418,7 +420,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns port number */ - int setControlPort(int port_number = -1, int detPos = -1);// + int setControlPort(int port_number = -1, int detPos = -1); // /** * Set/Gets TCP STOP Port of the detector @@ -426,7 +428,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns port number */ - int setStopPort(int port_number = -1, int detPos = -1);// + int setStopPort(int port_number = -1, int detPos = -1); // /** * Set/Gets TCP Port of the receiver @@ -434,14 +436,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns port number */ - int setReceiverPort(int port_number = -1, int detPos = -1);// + int setReceiverPort(int port_number = -1, int detPos = -1); // /** * Get Receiver port * @param detPos -1 for all detectors in list or specific detector position * @returns vector of receiver port */ - int getReceiverPort(int detPos = -1) const;// + int getReceiverPort(int detPos = -1) const; // /** * Lock server for this client IP @@ -449,27 +451,27 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns 1 for locked or 0 for unlocked */ - int lockServer(int p = -1, int detPos = -1);// + int lockServer(int p = -1, int detPos = -1); // /** * Get last client IP saved on detector server * @param detPos -1 for all detectors in list or specific detector position * @returns last client IP saved on detector server */ - std::string getLastClientIP(int detPos = -1);// + std::string getLastClientIP(int detPos = -1); // /** * Exit detector server * @param detPos -1 for all detectors in list or specific detector position */ - void exitServer(int detPos = -1);// + void exitServer(int detPos = -1); // /** * Execute a command on the detector server * @param cmd command * @param detPos -1 for all detectors in list or specific detector position */ - void execCommand(const std::string &cmd, int detPos);// + void execCommand(const std::string &cmd, int detPos); // /** * Load configuration from a configuration File @@ -481,14 +483,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * Write current configuration to a file * @param fname configuration file name */ - void writeConfigurationFile(const std::string &fname);// + void writeConfigurationFile(const std::string &fname); // /** * Get detector settings * @param detPos -1 for all detectors in list or specific detector position * @returns current settings */ - detectorSettings getSettings(int detPos = -1);// + detectorSettings getSettings(int detPos = -1); // /** * Load detector settings from the settings file picked from the @@ -498,14 +500,15 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns current settings */ - detectorSettings setSettings(detectorSettings isettings, int detPos = -1);// + detectorSettings setSettings(detectorSettings isettings, + int detPos = -1); // /** * Get threshold energy (Eiger) * @param detPos -1 for all detectors in list or specific detector position * @returns current threshold value for imod in ev (-1 failed) */ - int getThresholdEnergy(int detPos = -1);// + int getThresholdEnergy(int detPos = -1); // /** * Set threshold energy (Eiger) @@ -516,14 +519,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns current threshold value for imod in ev (-1 failed) */ int setThresholdEnergy(int e_eV, detectorSettings isettings = GET_SETTINGS, - int tb = 1, int detPos = -1);// + int tb = 1, int detPos = -1); // /** * Returns the detector trimbit/settings directory * @param detPos -1 for all detectors in list or specific detector position * @returns the trimbit/settings directory */ - std::string getSettingsDir(int detPos = -1);// + std::string getSettingsDir(int detPos = -1); // /** * Sets the detector trimbit/settings directory @@ -531,7 +534,8 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the trimbit/settings directory */ - std::string setSettingsDir(const std::string &directory, int detPos = -1);// + std::string setSettingsDir(const std::string &directory, + int detPos = -1); // /** * Loads the modules settings/trimbits reading from a specific file @@ -539,7 +543,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param fname specific settings/trimbits file * @param detPos -1 for all detectors in list or specific detector position */ - void loadSettingsFile(const std::string &fname, int detPos = -1);// + void loadSettingsFile(const std::string &fname, int detPos = -1); // /** * Saves the modules settings/trimbits to a specific file @@ -547,34 +551,32 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param fname specific settings/trimbits file * @param detPos -1 for all detectors in list or specific detector position */ - void saveSettingsFile(const std::string &fname, int detPos = -1);// + void saveSettingsFile(const std::string &fname, int detPos = -1); // /** * Get Detector run status * @param detPos -1 for all detectors in list or specific detector position * @returns status */ - runStatus getRunStatus(int detPos = -1);// - - + runStatus getRunStatus(int detPos = -1); // /** * Start detector acquisition (Non blocking) * @param detPos -1 for all detectors in list or specific detector position */ - void startAcquisition(int detPos = -1);// + void startAcquisition(int detPos = -1); // /** * Stop detector acquisition * @param detPos -1 for all detectors in list or specific detector position */ - void stopAcquisition(int detPos = -1);// + void stopAcquisition(int detPos = -1); // /** * Give an internal software trigger to the detector (Eiger only) * @param detPos -1 for all detectors in list or specific detector position */ - void sendSoftwareTrigger(int detPos = -1);// + void sendSoftwareTrigger(int detPos = -1); // /** * Configures in detector the destination for UDP packets @@ -601,7 +603,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param index timer index * @param t time in ns or number of...(e.g. frames, probes) * @param detPos -1 for all detectors in list or specific detector position - * @returns timer set value in ns or number of...(e.g. frames, + * @returns timer set value in ns or number of...(e.g. frames, * probes) */ int64_t setTimer(timerIndex index, int64_t t = -1, int detPos = -1); // @@ -634,7 +636,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns delay after trigger in ns, or s if specified */ double setDelayAfterTrigger(double t = -1, bool inseconds = false, - int detPos = -1);// + int detPos = -1); // /** * (Advanced users) @@ -656,7 +658,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns sub frame dead time in ns, or s if specified */ double setSubFrameExposureDeadTime(double t = -1, bool inseconds = false, - int detPos = -1);// + int detPos = -1); // /** * Set/get number of frames @@ -664,7 +666,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns number of frames */ - int64_t setNumberOfFrames(int64_t t = -1, int detPos = -1);// + int64_t setNumberOfFrames(int64_t t = -1, int detPos = -1); // /** * Set/get number of cycles @@ -672,7 +674,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns number of cycles */ - int64_t setNumberOfCycles(int64_t t = -1, int detPos = -1);// + int64_t setNumberOfCycles(int64_t t = -1, int detPos = -1); // /** * Set/get number of additional storage cells (Jungfrau) @@ -680,7 +682,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns number of additional storage cells */ - int64_t setNumberOfStorageCells(int64_t t = -1, int detPos = -1);// + int64_t setNumberOfStorageCells(int64_t t = -1, int detPos = -1); // /** * Get measured period between previous two frames (EIGER) @@ -689,7 +691,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns sub frame dead time in ns, or s if specified */ - double getMeasuredPeriod(bool inseconds = false, int detPos = -1);// + double getMeasuredPeriod(bool inseconds = false, int detPos = -1); // /** * Get sub period between previous two sub frames in 32 bit mode (EIGER) @@ -698,7 +700,8 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns sub frame dead time in ns, or s if specified */ - double getMeasuredSubFramePeriod(bool inseconds = false, int detPos = -1);// + double getMeasuredSubFramePeriod(bool inseconds = false, + int detPos = -1); // /** * Set/get timer value left in acquisition (not all implemented for all @@ -706,10 +709,10 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param index timer index * @param t time in ns or number of...(e.g. frames, probes) * @param detPos -1 for all detectors in list or specific detector position - * @returns timer set value in ns or number of...(e.g. frames, + * @returns timer set value in ns or number of...(e.g. frames, * probes) */ - int64_t getTimeLeft(timerIndex index, int detPos = -1);// + int64_t getTimeLeft(timerIndex index, int detPos = -1); // /** * Set speed @@ -723,7 +726,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns value of speed set */ int setSpeed(speedVariable index, int value = -1, int mode = 0, - int detPos = -1);// + int detPos = -1); // /** * Set/get dynamic range and updates the number of dataBytes @@ -733,7 +736,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns current dynamic range */ - int setDynamicRange(int dr = -1, int detPos = -1);// + int setDynamicRange(int dr = -1, int detPos = -1); // /** * Set/get dacs value @@ -743,7 +746,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns current DAC value */ - int setDAC(int val, dacIndex index, int mV, int detPos = -1);// + int setDAC(int val, dacIndex index, int mV, int detPos = -1); // /** * Get adc value @@ -752,7 +755,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns current adc value (temperature for eiger and jungfrau in * millidegrees) */ - int getADC(dacIndex index, int detPos = -1);// + int getADC(dacIndex index, int detPos = -1); // /** * Set/get timing mode @@ -760,7 +763,8 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns current timing mode */ - timingMode setTimingMode(timingMode pol = GET_TIMING_MODE, int detPos = -1);// + timingMode setTimingMode(timingMode pol = GET_TIMING_MODE, + int detPos = -1); // /** * Set/get external signal flags (to specify triggerinrising edge etc) @@ -771,7 +775,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ externalSignalFlag setExternalSignalFlags(externalSignalFlag pol = GET_EXTERNAL_SIGNAL_FLAG, - int detPos = -1);// + int detPos = -1); // /** * Set/get readout flags (Eiger, Mythen) @@ -780,7 +784,8 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns readout flag */ - int setReadOutFlags(readOutFlags flag = GET_READOUT_FLAGS, int detPos = -1);// + int setReadOutFlags(readOutFlags flag = GET_READOUT_FLAGS, + int detPos = -1); // /** * Set Interrupt last sub frame (Only for Eiger) @@ -837,7 +842,8 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the detector MAC address */ - std::string setDetectorMAC(const std::string &detectorMAC, int detPos = -1); // + std::string setDetectorMAC(const std::string &detectorMAC, + int detPos = -1); // /** * Returns the detector MAC address @@ -870,7 +876,8 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the detector IP address */ - std::string setDetectorIP(const std::string &detectorIP, int detPos = -1); // + std::string setDetectorIP(const std::string &detectorIP, + int detPos = -1); // /** * Returns the detector IP address @@ -886,7 +893,8 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the detector IP address (bottom half) */ - std::string setDetectorIP2(const std::string &detectorIP, int detPos = -1); // + std::string setDetectorIP2(const std::string &detectorIP, + int detPos = -1); // /** * Returns the detector IP address (bottom half) Jungfrau only @@ -952,14 +960,15 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the receiver UDP MAC address */ - std::string setReceiverUDPMAC(const std::string &udpmac, int detPos = -1);// + std::string setReceiverUDPMAC(const std::string &udpmac, + int detPos = -1); // /** * Returns the receiver UDP MAC address * @param detPos -1 for all detectors in list or specific detector position * @returns the receiver UDP MAC address */ - std::string getReceiverUDPMAC(int detPos = -1) const; // + std::string getReceiverUDPMAC(int detPos = -1) const; // /** * Validates the format of the receiver UDP MAC address (bottom half) and @@ -1127,7 +1136,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @returns transmission delay */ int setDetectorNetworkParameter(networkParameter index, int delay, - int detPos = -1); //maybe not needed in API + int detPos = -1); // maybe not needed in API /** * Sets the additional json header @@ -1311,8 +1320,6 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ int getExternalSamplingSource(int detPos = -1); // - - /** * Set external sampling enable (CTB only) * @param value external sampling source (Option: 0-63) @@ -1414,7 +1421,6 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ int enableGapPixels(int val = -1, int detPos = -1); // - void setGapPixelsEnable(bool enable, sls::Positions pos = {}); /** * Sets the number of trim energies and their value (Eiger) @@ -1450,14 +1456,14 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param y is relative y value * @param detPos -1 for all detectors in list or specific detector position */ - void pulsePixelNMove(int n = 0, int x = 0, int y = 0, int detPos = -1);// + void pulsePixelNMove(int n = 0, int x = 0, int y = 0, int detPos = -1); // /** * Pulse Chip (Eiger) * @param n is number of times to pulse * @param detPos -1 for all detectors in list or specific detector position */ - void pulseChip(int n = 0, int detPos = -1);// + void pulseChip(int n = 0, int detPos = -1); // /** * Set/gets threshold temperature (Jungfrau) @@ -1489,7 +1495,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns the storage cell that stores the first acquisition of the series */ - int setStoragecellStart(int pos = -1, int detPos = -1);// + int setStoragecellStart(int pos = -1, int detPos = -1); // /** * Programs FPGA with pof file (Jungfrau, CTB, Moench) @@ -2066,11 +2072,11 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ void updateUserdetails(); - /** + /** * Prepares detector for acquisition (Eiger) * @param detPos -1 for all detectors in list or specific detector position */ - void prepareAcquisition(int detPos = -1);// + void prepareAcquisition(int detPos = -1); // /** * Check if acquiring flag is set, set error if set @@ -2087,11 +2093,11 @@ class multiSlsDetector : public virtual slsDetectorDefs { /** * Appends detectors to the end of the list in shared memory - * Connects to them + * Connects to them * @param name concatenated hostname of the sls detectors to be appended to * the list */ - void addMultipleDetectors(const char *name);// + void addMultipleDetectors(const char *name); // /** * Add sls detector @@ -2101,11 +2107,11 @@ class multiSlsDetector : public virtual slsDetectorDefs { /** * Updates the channel size in X and Y dimension for all the sls - * detectors + * detectors */ void updateDetectorSize(); - /** + /** * increments file index * @param detPos -1 for all detectors in list or specific detector position * @returns the file index @@ -2168,20 +2174,20 @@ class multiSlsDetector : public virtual slsDetectorDefs { * acquisition) * @param detPos -1 for all detectors in list or specific detector position */ - void startAndReadAll(int detPos = -1);// + void startAndReadAll(int detPos = -1); // - /** + /** * Start readout (without exposure or interrupting exposure) (Eiger store in * ram) * @param detPos -1 for all detectors in list or specific detector position */ - void startReadOut(int detPos = -1);// + void startReadOut(int detPos = -1); // /** * Requests and receives all data from the detector (Eiger store in ram) * @param detPos -1 for all detectors in list or specific detector position */ - void readAll(int detPos = -1);// + void readAll(int detPos = -1); // /** * Check if processing thread is ready to join main thread @@ -2201,8 +2207,6 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ int kbhit(); - - /** * Convert a double holding time in seconds to an int64_t with nano seconds * Used for conversion when sending time to detector diff --git a/slsDetectorSoftware/include/slsDetector.h b/slsDetectorSoftware/include/slsDetector.h index 81b9d6842..1afa9bf99 100755 --- a/slsDetectorSoftware/include/slsDetector.h +++ b/slsDetectorSoftware/include/slsDetector.h @@ -322,7 +322,7 @@ class slsDetector : public virtual slsDetectorDefs { * Returns the total number of channels including gap pixels * @returns the total number of channels including gap pixels */ - slsDetectorDefs::xy getNumberOfChannels() const; + slsDetectorDefs::xy getNumberOfChannels() const; /** * Get Quad Type (Only for Eiger Quad detector hardware) @@ -336,7 +336,7 @@ class slsDetector : public virtual slsDetectorDefs { */ void setQuad(const bool enable); - /** + /** * Set number of rows to read out (Only for Eiger) * @param value number of lines */ @@ -354,7 +354,6 @@ class slsDetector : public virtual slsDetectorDefs { */ void updateMultiSize(slsDetectorDefs::xy det); - int setControlPort(int port_number); /** @@ -557,7 +556,7 @@ class slsDetector : public virtual slsDetectorDefs { * Set/get timer value (not all implemented for all detectors) * @param index timer index * @param t time in ns or number of...(e.g. frames, probes) - * @returns timer set value in ns or number of...(e.g. frames, + * @returns timer set value in ns or number of...(e.g. frames, * probes) */ int64_t setTimer(timerIndex index, int64_t t = -1); @@ -567,7 +566,7 @@ class slsDetector : public virtual slsDetectorDefs { * detectors) * @param index timer index * @param t time in ns or number of...(e.g. frames, probes) - * @returns timer set value in ns or number of...(e.g. frames, + * @returns timer set value in ns or number of...(e.g. frames, * probes) */ int64_t getTimeLeft(timerIndex index) const; @@ -585,7 +584,7 @@ class slsDetector : public virtual slsDetectorDefs { int setSpeed(speedVariable sp, int value = -1, int mode = 0); /** - * Set/get dynamic range + * Set/get dynamic range * (Eiger: If i is 32, also sets clkdivider to 2, if 16, sets clkdivider to * 1) * @param i dynamic range (-1 get) @@ -1007,7 +1006,7 @@ class slsDetector : public virtual slsDetectorDefs { void setROI(slsDetectorDefs::ROI arg); /** - * Send ROI from shared memory to Receiver (Gotthard) + * Send ROI from shared memory to Receiver (Gotthard) */ void sendROItoReceiver(); @@ -1701,31 +1700,30 @@ class slsDetector : public virtual slsDetectorDefs { void sendToDetectorStop(int fnum, const void *args, size_t args_size, void *retval, size_t retval_size); - void sendToDetectorStop(int fnum, const void *args, size_t args_size, + void sendToDetectorStop(int fnum, const void *args, size_t args_size, void *retval, size_t retval_size) const; template void sendToDetectorStop(int fnum, const Arg &args, Ret &retval); - template + template void sendToDetectorStop(int fnum, const Arg &args, Ret &retval) const; template void sendToDetectorStop(int fnum, const Arg &args, std::nullptr_t); - template + template void sendToDetectorStop(int fnum, const Arg &args, std::nullptr_t) const; template void sendToDetectorStop(int fnum, std::nullptr_t, Ret &retval); - template + template void sendToDetectorStop(int fnum, std::nullptr_t, Ret &retval) const; void sendToDetectorStop(int fnum); - void sendToDetectorStop(int fnum) const; - + void sendToDetectorStop(int fnum) const; /** * Send function parameters to receiver @@ -1738,30 +1736,30 @@ class slsDetector : public virtual slsDetectorDefs { void sendToReceiver(int fnum, const void *args, size_t args_size, void *retval, size_t retval_size); - void sendToReceiver(int fnum, const void *args, size_t args_size, + void sendToReceiver(int fnum, const void *args, size_t args_size, void *retval, size_t retval_size) const; template void sendToReceiver(int fnum, const Arg &args, Ret &retval); - template + template void sendToReceiver(int fnum, const Arg &args, Ret &retval) const; template void sendToReceiver(int fnum, const Arg &args, std::nullptr_t); - template + template void sendToReceiver(int fnum, const Arg &args, std::nullptr_t) const; template void sendToReceiver(int fnum, std::nullptr_t, Ret &retval); - template + template void sendToReceiver(int fnum, std::nullptr_t, Ret &retval) const; void sendToReceiver(int fnum); - void sendToReceiver(int fnum) const; + void sendToReceiver(int fnum) const; /** * Get Detector Type from Shared Memory (opening shm without verifying size) diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 395c2e312..f7a500897 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -52,8 +52,7 @@ Result Detector::getReceiverVersion(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverSoftwareVersion, pos); } -Result -Detector::getDetectorType(Positions pos) const { +Result Detector::getDetectorType(Positions pos) const { return pimpl->Parallel(&slsDetector::getDetectorTypeAsEnum, pos); } @@ -83,8 +82,6 @@ void Detector::setSettings(defs::detectorSettings value, Positions pos) { pimpl->Parallel(&slsDetector::setSettings, pos, value); } - - // Acquisition Parameters Result Detector::getNumberOfFrames() const { @@ -103,7 +100,6 @@ void Detector::setNumberOfTriggers(int64_t value) { pimpl->Parallel(&slsDetector::setTimer, {}, defs::CYCLES_NUMBER, value); } - Result Detector::getExptime(Positions pos) const { return pimpl->Parallel(&slsDetector::setTimer, pos, defs::ACQUISITION_TIME, -1); @@ -184,7 +180,8 @@ void Detector::setHighVoltage(int value, Positions pos) { pimpl->Parallel(&slsDetector::setDAC, pos, value, defs::HIGH_VOLTAGE, 0); } -Result Detector::getTemperature(defs::dacIndex index, Positions pos) const { +Result Detector::getTemperature(defs::dacIndex index, + Positions pos) const { switch (index) { case defs::TEMPERATURE_ADC: case defs::TEMPERATURE_FPGA: @@ -232,8 +229,6 @@ void Detector::setTimingMode(defs::timingMode value, Positions pos) { pimpl->Parallel(&slsDetector::setTimingMode, pos, value); } - - // Acquisition void Detector::acquire() { pimpl->acquire(); } @@ -244,15 +239,15 @@ void Detector::startAcquisition() { pimpl->Parallel(&slsDetector::startAcquisition, {}); } -void Detector::stopAcquisition() { +void Detector::stopAcquisition() { pimpl->Parallel(&slsDetector::stopAcquisition, {}); - if (getUseReceiverFlag({}).squash()) //TODO: problem for acquire() + if (getUseReceiverFlag({}).squash()) // TODO: problem for acquire() pimpl->Parallel(&slsDetector::stopReceiver, {}); } void Detector::clearAcquiringFlag() { pimpl->setAcquiringFlag(0); } -Result Detector::getDetectorStatus(Positions pos) const{ +Result Detector::getDetectorStatus(Positions pos) const { return pimpl->Parallel(&slsDetector::getRunStatus, pos); } @@ -276,8 +271,6 @@ void Detector::sendSoftwareTrigger(Positions pos) { pimpl->Parallel(&slsDetector::sendSoftwareTrigger, pos); } - - // Network Configuration (Detector<->Receiver) void Detector::configureMAC(Positions pos) { @@ -383,7 +376,8 @@ void Detector::setDestinationUDPPort(int port, int module_id) { if (module_id == -1) { std::vector port_list = getPortNumbers(port); for (int idet = 0; idet < size(); ++idet) { - pimpl->Parallel(&slsDetector::setReceiverUDPPort, {idet}, port_list[idet]); + pimpl->Parallel(&slsDetector::setReceiverUDPPort, {idet}, + port_list[idet]); } } else { pimpl->Parallel(&slsDetector::setReceiverUDPPort, {module_id}, port); @@ -398,10 +392,11 @@ void Detector::setDestinationUDPPort2(int port, int module_id) { if (module_id == -1) { std::vector port_list = getPortNumbers(port); for (int idet = 0; idet < size(); ++idet) { - pimpl->Parallel(&slsDetector::setReceiverUDPPort2, {idet}, port_list[idet]); + pimpl->Parallel(&slsDetector::setReceiverUDPPort2, {idet}, + port_list[idet]); } } else { - pimpl->Parallel(&slsDetector::setReceiverUDPPort2, {module_id}, port ); + pimpl->Parallel(&slsDetector::setReceiverUDPPort2, {module_id}, port); } } @@ -458,8 +453,6 @@ void Detector::setTransmissionDelayRight(int value, Positions pos) { defs::DETECTOR_TXN_DELAY_RIGHT, value); } - - // Receiver Result Detector::getUseReceiverFlag(Positions pos) const { @@ -506,7 +499,7 @@ Detector::getRxFrameDiscardPolicy(Positions pos) const { } void Detector::setRxFrameDiscardPolicy(defs::frameDiscardPolicy f, - Positions pos) { + Positions pos) { pimpl->Parallel(&slsDetector::setReceiverFramesDiscardPolicy, pos, f); } @@ -522,14 +515,12 @@ Result Detector::getRxUDPSocketBufferSize(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverUDPSocketBufferSize, pos); } -void Detector::setRxUDPSocketBufferSize(int64_t udpsockbufsize, - Positions pos) { +void Detector::setRxUDPSocketBufferSize(int64_t udpsockbufsize, Positions pos) { pimpl->Parallel(&slsDetector::setReceiverUDPSocketBufferSize, pos, udpsockbufsize); } -Result -Detector::getRxRealUDPSocketBufferSize(Positions pos) const { +Result Detector::getRxRealUDPSocketBufferSize(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverRealUDPSocketBufferSize, pos); } @@ -546,8 +537,6 @@ Result Detector::getRxLastClientIP(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverLastClientIP, pos); } - - // File Result Detector::getFileFormat(Positions pos) const { @@ -613,12 +602,11 @@ void Detector::setFramesPerFile(int n, Positions pos) { pimpl->Parallel(&slsDetector::setFramesPerFile, pos, n); } - - // Zmq Streaming (Receiver<->Client) Result Detector::getRxZmqDataStream(Positions pos) const { - return pimpl->Parallel(&slsDetector::enableDataStreamingFromReceiver, pos, -1); + return pimpl->Parallel(&slsDetector::enableDataStreamingFromReceiver, pos, + -1); } void Detector::setRxZmqDataStream(bool enable, Positions pos) { @@ -650,10 +638,12 @@ void Detector::setRxZmqPort(int port, int module_id) { if (module_id == -1) { std::vector port_list = getPortNumbers(port); for (int idet = 0; idet < size(); ++idet) { - pimpl->Parallel(&slsDetector::setReceiverStreamingPort, {idet}, port_list[idet]); + pimpl->Parallel(&slsDetector::setReceiverStreamingPort, {idet}, + port_list[idet]); } } else { - pimpl->Parallel(&slsDetector::setReceiverStreamingPort, {module_id}, port); + pimpl->Parallel(&slsDetector::setReceiverStreamingPort, {module_id}, + port); } } @@ -661,10 +651,8 @@ Result Detector::getRxZmqIP(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverStreamingIP, pos); } -void Detector::setRxZmqIP(const std::string &ip, - Positions pos) { - bool previouslyReceiverStreaming = - getRxZmqDataStream(pos).squash(false); +void Detector::setRxZmqIP(const std::string &ip, Positions pos) { + bool previouslyReceiverStreaming = getRxZmqDataStream(pos).squash(false); pimpl->Parallel(&slsDetector::setReceiverStreamingIP, pos, ip); if (previouslyReceiverStreaming) { setRxZmqDataStream(false, pos); @@ -680,10 +668,12 @@ void Detector::setClientZmqPort(int port, int module_id) { if (module_id == -1) { std::vector port_list = getPortNumbers(port); for (int idet = 0; idet < size(); ++idet) { - pimpl->Parallel(&slsDetector::setClientStreamingPort, {idet}, port_list[idet]); + pimpl->Parallel(&slsDetector::setClientStreamingPort, {idet}, + port_list[idet]); } } else { - pimpl->Parallel(&slsDetector::setClientStreamingPort, {module_id}, port); + pimpl->Parallel(&slsDetector::setClientStreamingPort, {module_id}, + port); } } @@ -691,8 +681,7 @@ Result Detector::getClientZmqIp(Positions pos) const { return pimpl->Parallel(&slsDetector::getClientStreamingIP, pos); } -void Detector::setClientZmqIp(const std::string &ip, - Positions pos) { +void Detector::setClientZmqIp(const std::string &ip, Positions pos) { int previouslyClientStreaming = pimpl->enableDataStreamingToClient(-1); pimpl->Parallel(&slsDetector::setClientStreamingIP, pos, ip); if (previouslyClientStreaming != 0) { @@ -701,8 +690,6 @@ void Detector::setClientZmqIp(const std::string &ip, } } - - // Eiger Specific Result Detector::getDynamicRange(Positions pos) const { @@ -711,7 +698,6 @@ Result Detector::getDynamicRange(Positions pos) const { void Detector::setDynamicRange(int value) { pimpl->setDynamicRange(value); } - Result Detector::getSubExptime(Positions pos) const { return pimpl->Parallel(&slsDetector::setTimer, pos, defs::SUBFRAME_ACQUISITION_TIME, -1); @@ -736,9 +722,11 @@ Result Detector::getThresholdEnergy(Positions pos) const { return pimpl->Parallel(&slsDetector::getThresholdEnergy, pos); } -void Detector::setThresholdEnergy(int threshold_ev, defs::detectorSettings settings, +void Detector::setThresholdEnergy(int threshold_ev, + defs::detectorSettings settings, bool trimbits, Positions pos) { - pimpl->Parallel(&slsDetector::setThresholdEnergy, pos, threshold_ev, settings, static_cast(trimbits)); + pimpl->Parallel(&slsDetector::setThresholdEnergy, pos, threshold_ev, + settings, static_cast(trimbits)); } Result Detector::getSettingsDir(Positions pos) const { @@ -796,7 +784,8 @@ Result Detector::getBottom(Positions pos) const { } void Detector::setBottom(bool value, Positions pos) { - pimpl->Parallel(&slsDetector::setFlippedDataX, pos, static_cast(value)); + pimpl->Parallel(&slsDetector::setFlippedDataX, pos, + static_cast(value)); } Result Detector::getAllTrimbits(Positions pos) const { @@ -874,7 +863,7 @@ void Detector::setPartialReset(bool value, Positions pos) { pimpl->Parallel(&slsDetector::setCounterBit, pos, !value); } -void Detector::pulsePixel(int n,defs::xy pixel, Positions pos) { +void Detector::pulsePixel(int n, defs::xy pixel, Positions pos) { pimpl->Parallel(&slsDetector::pulsePixel, pos, n, pixel.x, pixel.y); } @@ -890,11 +879,7 @@ Result Detector::getQuad(Positions pos) const { return pimpl->Parallel(&slsDetector::getQuad, pos); } -void Detector::setQuad(const bool value) { - pimpl->setQuad(value); -} - - +void Detector::setQuad(const bool value) { pimpl->setQuad(value); } // Jungfrau Specific @@ -979,11 +964,8 @@ void Detector::setStorageCellDelay(ns value, Positions pos) { value.count()); } - - // Gotthard Specific - Result Detector::getROI(Positions pos) const { return pimpl->Parallel(&slsDetector::getROI, pos); } @@ -1016,17 +998,15 @@ void Detector::setExternalSignalFlags(defs::externalSignalFlag value, } Result Detector::getImageTestMode(Positions pos) { - return pimpl->Parallel(&slsDetector::digitalTest, pos, - defs::IMAGE_TEST, -1); + return pimpl->Parallel(&slsDetector::digitalTest, pos, defs::IMAGE_TEST, + -1); } Result Detector::setImageTestMode(int value, Positions pos) { - return pimpl->Parallel(&slsDetector::digitalTest, pos, - defs::IMAGE_TEST, value); + return pimpl->Parallel(&slsDetector::digitalTest, pos, defs::IMAGE_TEST, + value); } - - // CTB Specific Result Detector::getNumberOfAnalogSamples(Positions pos) const { @@ -1083,7 +1063,8 @@ void Detector::setReadoutMode(int value, Positions pos) { } Result Detector::getDBITPhase(Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PHASE, -1, 0); + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PHASE, -1, + 0); } void Detector::setDBITPhase(int value, Positions pos) { @@ -1096,10 +1077,11 @@ Result Detector::getMaxDBITPhaseShift(Positions pos) const { } Result Detector::getDBITPhaseInDegrees(Positions pos) const { - return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PHASE, -1, 1); + return pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PHASE, -1, + 1); } -void Detector::setDBITPhaseInDegrees(int value,Positions pos) { +void Detector::setDBITPhaseInDegrees(int value, Positions pos) { pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PHASE, value, 1); } @@ -1108,7 +1090,8 @@ Result Detector::getADCClock(Positions pos) const { } void Detector::setADCClock(int value_in_MHz, Positions pos) { - pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_CLOCK, value_in_MHz, 0); + pimpl->Parallel(&slsDetector::setSpeed, pos, defs::ADC_CLOCK, value_in_MHz, + 0); } Result Detector::getDBITClock(Positions pos) const { @@ -1117,7 +1100,8 @@ Result Detector::getDBITClock(Positions pos) const { } void Detector::setDBITClock(int value_in_MHz, Positions pos) { - pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_CLOCK, value_in_MHz, 0); + pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_CLOCK, value_in_MHz, + 0); } Result Detector::getRUNClock(Positions pos) const { @@ -1126,7 +1110,8 @@ Result Detector::getRUNClock(Positions pos) const { } void Detector::setRUNClock(int value_in_MHz, Positions pos) { - pimpl->Parallel(&slsDetector::setSpeed, pos, defs::CLOCK_DIVIDER, value_in_MHz, 0); + pimpl->Parallel(&slsDetector::setSpeed, pos, defs::CLOCK_DIVIDER, + value_in_MHz, 0); } Result Detector::getSYNCClock(Positions pos) const { @@ -1152,7 +1137,6 @@ void Detector::setDBITPipeline(int value, Positions pos) { pimpl->Parallel(&slsDetector::setSpeed, pos, defs::DBIT_PIPELINE, value, 0); } - Result Detector::getVrefVoltage(bool mV, Positions pos) const { return pimpl->Parallel(&slsDetector::setDAC, pos, -1, defs::ADC_VPP, mV); } @@ -1291,8 +1275,6 @@ void Detector::setLEDEnable(bool enable, Positions pos) { pimpl->Parallel(&slsDetector::setLEDEnable, pos, static_cast(enable)); } - - // Pattern void Detector::setPattern(const std::string &fname, Positions pos) { @@ -1362,8 +1344,6 @@ void Detector::setPatternBitMask(uint64_t mask, Positions pos) { pimpl->Parallel(&slsDetector::setPatternBitMask, pos, mask); } - - // Moench Result Detector::getAdditionalJsonHeader(Positions pos) const { @@ -1449,12 +1429,11 @@ void Detector::setDetectorMode(defs::detectorModeType value, Positions pos) { "detectorMode", defs::getDetectorModeType(value)); } - - // Advanced void Detector::programFPGA(const std::string &fname, Positions pos) { - FILE_LOG(logINFO) << "Updating Firmware. This can take awhile. Please be patient..."; + FILE_LOG(logINFO) + << "Updating Firmware. This can take awhile. Please be patient..."; std::vector buffer = pimpl->readPofFile(fname); pimpl->Parallel(&slsDetector::programFPGA, pos, buffer); } @@ -1512,11 +1491,8 @@ void Detector::writeAdcRegister(uint32_t addr, uint32_t value, Positions pos) { pimpl->Parallel(&slsDetector::writeAdcRegister, pos, addr, value); } - - // Insignificant - Result Detector::getControlPort(Positions pos) const { return pimpl->Parallel(&slsDetector::getControlPort, pos); } @@ -1565,19 +1541,18 @@ Result Detector::getMeasurementTime(Positions pos) const { std::string Detector::getUserDetails() const { return pimpl->getUserDetails(); } - Result Detector::getRxCurrentFrameIndex(Positions pos) const { return pimpl->Parallel(&slsDetector::getReceiverCurrentFrameIndex, pos); } std::vector Detector::getPortNumbers(int start_port) { - int num_sockets_per_detector = 1; + int num_sockets_per_detector = 1; switch (getDetectorType({}).squash()) { case defs::EIGER: num_sockets_per_detector *= 2; break; case defs::JUNGFRAU: - if(getNumberofUDPInterfaces({}).squash() == 2) { + if (getNumberofUDPInterfaces({}).squash() == 2) { num_sockets_per_detector *= 2; } break; diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index 599321e53..3c3a29377 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -233,17 +233,23 @@ std::string multiSlsDetector::getUserDetails() { std::ostringstream sstream; sstream << "\nHostname: "; for (auto &d : detectors) { - sstream << (d->isFixedPatternSharedMemoryCompatible() ? d->getHostname() : "Unknown") << "+"; + sstream << (d->isFixedPatternSharedMemoryCompatible() ? d->getHostname() + : "Unknown") + << "+"; } sstream << "\nType: "; // get type from multi shm if (multi_shm()->shmversion >= MULTI_SHMAPIVERSION) { - sstream << slsDetectorDefs::detectorTypeToString(getDetectorTypeAsEnum()); - } + sstream << slsDetectorDefs::detectorTypeToString( + getDetectorTypeAsEnum()); + } // get type from slsdet shm else { for (auto &d : detectors) { - sstream << (d->isFixedPatternSharedMemoryCompatible() ? d->getDetectorTypeAsString() : "Unknown") << "+"; + sstream << (d->isFixedPatternSharedMemoryCompatible() + ? d->getDetectorTypeAsString() + : "Unknown") + << "+"; } } @@ -325,7 +331,6 @@ bool multiSlsDetector::isAcquireReady() { return OK != 0u; } - std::string multiSlsDetector::exec(const char *cmd) { int bufsize = 128; char buffer[bufsize]; @@ -349,11 +354,13 @@ std::string multiSlsDetector::exec(const char *cmd) { return result; } -void multiSlsDetector::setVirtualDetectorServers(const int numdet, const int port) { - std::vector hostnames; +void multiSlsDetector::setVirtualDetectorServers(const int numdet, + const int port) { + std::vector hostnames; for (int i = 0; i < numdet; ++i) { // * 2 is for control and stop port - hostnames.push_back(std::string("localhost:") + std::to_string(port + i * 2)); + hostnames.push_back(std::string("localhost:") + + std::to_string(port + i * 2)); } setHostname(hostnames); } @@ -366,7 +373,7 @@ void multiSlsDetector::setHostname(const std::vector &name) { "Freeing Shared memory now."; freeSharedMemory(); setupMultiDetector(); - } + } for (const auto &hostname : name) { addSlsDetector(hostname); } @@ -412,7 +419,7 @@ void multiSlsDetector::addMultipleDetectors(const char *name) { void multiSlsDetector::addSlsDetector(const std::string &hostname) { FILE_LOG(logDEBUG1) << "Adding detector " << hostname; - + int port = DEFAULT_PORTNO; std::string host = hostname; auto res = sls::split(hostname, ':'); @@ -434,8 +441,7 @@ void multiSlsDetector::addSlsDetector(const std::string &hostname) { } // get type by connecting - detectorType type = - slsDetector::getTypeFromDetector(host, port); + detectorType type = slsDetector::getTypeFromDetector(host, port); int pos = (int)detectors.size(); detectors.push_back( sls::make_unique(type, multiId, pos, false)); @@ -443,14 +449,15 @@ void multiSlsDetector::addSlsDetector(const std::string &hostname) { detectors[pos]->setControlPort(port); detectors[pos]->setStopPort(port + 1); detectors[pos]->setHostname(host); - multi_shm()->multiDetectorType = getDetectorTypeAsEnum(-1);// -1 needed here + multi_shm()->multiDetectorType = + getDetectorTypeAsEnum(-1); // -1 needed here } void multiSlsDetector::updateDetectorSize() { FILE_LOG(logDEBUG) << "Updating Multi-Detector Size: " << size(); - + const slsDetectorDefs::xy det_size = detectors[0]->getNumberOfChannels(); - + int maxy = multi_shm()->numberOfChannels.y; if (maxy == 0) { maxy = det_size.y * size(); @@ -465,23 +472,21 @@ void multiSlsDetector::updateDetectorSize() { multi_shm()->numberOfDetector.x = ndetx; multi_shm()->numberOfDetector.y = ndety; multi_shm()->numberOfChannels.x = det_size.x * ndetx; - multi_shm()->numberOfChannels.y = det_size.y * ndety; - - FILE_LOG(logDEBUG) - << "\n\tNumber of Detectors in X direction:" - << multi_shm()->numberOfDetector.x - << "\n\tNumber of Detectors in Y direction:" - << multi_shm()->numberOfDetector.y - << "\n\tNumber of Channels in X direction:" - << multi_shm()->numberOfChannels.x - << "\n\tNumber of Channels in Y direction:" - << multi_shm()->numberOfChannels.y; + multi_shm()->numberOfChannels.y = det_size.y * ndety; + FILE_LOG(logDEBUG) << "\n\tNumber of Detectors in X direction:" + << multi_shm()->numberOfDetector.x + << "\n\tNumber of Detectors in Y direction:" + << multi_shm()->numberOfDetector.y + << "\n\tNumber of Channels in X direction:" + << multi_shm()->numberOfChannels.x + << "\n\tNumber of Channels in Y direction:" + << multi_shm()->numberOfChannels.y; for (auto &d : detectors) { d->updateMultiSize(multi_shm()->numberOfDetector); } - } +} slsDetectorDefs::detectorType multiSlsDetector::getDetectorTypeAsEnum() const { return multi_shm()->multiDetectorType; @@ -528,7 +533,8 @@ slsDetectorDefs::xy multiSlsDetector::getNumberOfChannels(int detPos) const { void multiSlsDetector::setNumberOfChannels(const slsDetectorDefs::xy c) { if (size() > 1) { - throw RuntimeError("Set the number of channels before setting hostname."); + throw RuntimeError( + "Set the number of channels before setting hostname."); } multi_shm()->numberOfChannels = c; } @@ -880,7 +886,7 @@ void multiSlsDetector::readAll(int detPos) { } // multi - parallelCall(&slsDetector::readAll); + parallelCall(&slsDetector::readAll); } void multiSlsDetector::configureMAC(int detPos) { @@ -1058,7 +1064,6 @@ int multiSlsDetector::setDynamicRange(int dr, int detPos) { auto r = parallelCall(&slsDetector::setDynamicRange, dr); int ret = sls::minusOneIfDifferent(r); - // change in dr if (dr != -1 && dr != prevValue) { @@ -1125,7 +1130,8 @@ int multiSlsDetector::getADC(dacIndex index, int detPos) { return sls::minusOneIfDifferent(r); } -slsDetectorDefs::timingMode multiSlsDetector::setTimingMode(timingMode pol, int detPos) { +slsDetectorDefs::timingMode multiSlsDetector::setTimingMode(timingMode pol, + int detPos) { // single if (detPos >= 0) { return detectors[detPos]->setTimingMode(pol); @@ -1712,7 +1718,6 @@ void multiSlsDetector::setReceiverDataStreamingOutIP(const std::string &ip, } } - std::string multiSlsDetector::getReceiverStreamingIP(int detPos) { // single if (detPos >= 0) { @@ -2049,7 +2054,7 @@ int multiSlsDetector::getReceiverDbitOffset(int detPos) { } void multiSlsDetector::writeAdcRegister(uint32_t addr, uint32_t val, - int detPos) { + int detPos) { // single if (detPos >= 0) { detectors[detPos]->writeAdcRegister(addr, val); @@ -2139,7 +2144,8 @@ int multiSlsDetector::enableGapPixels(int val, int detPos) { if (val != -1) { Parallel(&slsDetector::enableGapPixels, {}, val); - Result res = Parallel(&slsDetector::getNumberOfChannels, {}); + Result res = + Parallel(&slsDetector::getNumberOfChannels, {}); multi_shm()->numberOfChannels.x = 0; multi_shm()->numberOfChannels.y = 0; for (auto &it : res) { @@ -2150,9 +2156,10 @@ int multiSlsDetector::enableGapPixels(int val, int detPos) { return ret; } -void multiSlsDetector::setGapPixelsEnable(bool enable, Positions pos){ +void multiSlsDetector::setGapPixelsEnable(bool enable, Positions pos) { Parallel(&slsDetector::enableGapPixels, pos, static_cast(enable)); - Result res = Parallel(&slsDetector::getNumberOfChannels, {}); + Result res = + Parallel(&slsDetector::getNumberOfChannels, {}); multi_shm()->numberOfChannels.x = 0; multi_shm()->numberOfChannels.y = 0; for (auto &it : res) { @@ -2276,14 +2283,14 @@ void multiSlsDetector::resetFPGA(int detPos) { } void multiSlsDetector::copyDetectorServer(const std::string &fname, - const std::string &hostname, - int detPos) { + const std::string &hostname, + int detPos) { // single if (detPos >= 0) { detectors[detPos]->copyDetectorServer(fname, hostname); - detectors[detPos]->rebootController(); + detectors[detPos]->rebootController(); // reboot and copy should be independant for - // update command + // update command } // multi @@ -2302,8 +2309,8 @@ void multiSlsDetector::rebootController(int detPos) { } void multiSlsDetector::update(const std::string &sname, - const std::string &hostname, - const std::string &fname, int detPos) { + const std::string &hostname, + const std::string &fname, int detPos) { FILE_LOG(logINFO) << "This can take awhile. Please be patient..."; // read pof file std::vector buffer = readPofFile(fname); @@ -2829,7 +2836,8 @@ void multiSlsDetector::readFrameFromReceiver() { // updates its header data gappixelsenable = (doc["gappixels"].GetUint() == 0) ? false : true; - quadEnable = (doc["quad"].GetUint() == 0) ? false : true; + quadEnable = + (doc["quad"].GetUint() == 0) ? false : true; FILE_LOG(logDEBUG1) << "One Time Header Info:" "\n\tsize: " @@ -2906,12 +2914,11 @@ void multiSlsDetector::readFrameFromReceiver() { } } } - FILE_LOG(logDEBUG) - << "Call Back Info:" - << "\n\t nDetPixelsX: " << nDetPixelsX - << "\n\t nDetPixelsY: " << nDetPixelsY - << "\n\t databytes: " << multisize - << "\n\t dynamicRange: " << dynamicRange; + FILE_LOG(logDEBUG) << "Call Back Info:" + << "\n\t nDetPixelsX: " << nDetPixelsX + << "\n\t nDetPixelsY: " << nDetPixelsY + << "\n\t databytes: " << multisize + << "\n\t dynamicRange: " << dynamicRange; // send data to callback if (data) { @@ -2919,18 +2926,18 @@ void multiSlsDetector::readFrameFromReceiver() { // 4bit gap pixels if (dynamicRange == 4 && gappixelsenable) { if (quadEnable) { - nDetPixelsX += 2; - nDetPixelsY += 2; - } else { - nDetPixelsX = nX * (nPixelsX + 3); - nDetPixelsY = nY * (nPixelsY + 1); - } - int n = processImageWithGapPixels(multiframe, multigappixels, quadEnable); - FILE_LOG(logDEBUG) - << "Call Back Info Recalculated:" - << "\n\t nDetPixelsX: " << nDetPixelsX - << "\n\t nDetPixelsY: " << nDetPixelsY - << "\n\t databytes: " << n; + nDetPixelsX += 2; + nDetPixelsY += 2; + } else { + nDetPixelsX = nX * (nPixelsX + 3); + nDetPixelsY = nY * (nPixelsY + 1); + } + int n = processImageWithGapPixels(multiframe, multigappixels, + quadEnable); + FILE_LOG(logDEBUG) << "Call Back Info Recalculated:" + << "\n\t nDetPixelsX: " << nDetPixelsX + << "\n\t nDetPixelsY: " << nDetPixelsY + << "\n\t databytes: " << n; thisData = new detectorData( getCurrentProgress(), currentFileName.c_str(), nDetPixelsX, nDetPixelsY, multigappixels, n, dynamicRange, @@ -2986,15 +2993,18 @@ void multiSlsDetector::readFrameFromReceiver() { delete[] multigappixels; } -int multiSlsDetector::processImageWithGapPixels(char *image, char *&gpImage, bool quadEnable) { - // eiger 4 bit mode - int nxb = multi_shm()->numberOfDetector.x * (512 + 3); //(divided by 2 already) +int multiSlsDetector::processImageWithGapPixels(char *image, char *&gpImage, + bool quadEnable) { + // eiger 4 bit mode + int nxb = + multi_shm()->numberOfDetector.x * (512 + 3); //(divided by 2 already) int nyb = multi_shm()->numberOfDetector.y * (256 + 1); int nchipInRow = 4; int nxchip = multi_shm()->numberOfDetector.x * 4; int nychip = multi_shm()->numberOfDetector.y * 1; if (quadEnable) { - nxb = multi_shm()->numberOfDetector.x * (256 + 1); //(divided by 2 already) + nxb = multi_shm()->numberOfDetector.x * + (256 + 1); //(divided by 2 already) nyb = multi_shm()->numberOfDetector.y * (512 + 2); nxchip /= 2; nychip *= 2; @@ -3002,8 +3012,6 @@ int multiSlsDetector::processImageWithGapPixels(char *image, char *&gpImage, boo } int gapdatabytes = nxb * nyb; - - // allocate if (gpImage == nullptr) { gpImage = new char[gapdatabytes]; @@ -3021,8 +3029,8 @@ int multiSlsDetector::processImageWithGapPixels(char *image, char *&gpImage, boo dst = gpImage; for (int row = 0; row < nychip; ++row) { // for each chip row for (int ichipy = 0; ichipy < b1chipy; - ++ichipy) { // for each row in a chip - for (int col = 0; col < nxchip; ++col) {// for each chip in a row + ++ichipy) { // for each row in a chip + for (int col = 0; col < nxchip; ++col) { // for each chip in a row memcpy(dst, src, b1chipx); src += b1chipx; dst += b1chipx; @@ -3043,7 +3051,8 @@ int multiSlsDetector::processImageWithGapPixels(char *image, char *&gpImage, boo for (int row = 0; row < nychip; ++row) { // for each chip row for (int ichipy = 0; ichipy < b1chipy; ++ichipy) { // for each row in a chip - for (int col = 0; col < nxchip; ++col) {// for each chip in a row + for (int col = 0; col < nxchip; + ++col) { // for each chip in a row dst += b1chipx; mod = (col + 1) % nchipInRow; // get gap pixels // copy gap pixel(chip 0, 1, 2) @@ -3394,7 +3403,7 @@ int multiSlsDetector::setLEDEnable(int enable, int detPos) { } void multiSlsDetector::setDigitalIODelay(uint64_t pinMask, int delay, - int detPos) { + int detPos) { // single if (detPos >= 0) { detectors[detPos]->setDigitalIODelay(pinMask, delay); @@ -3618,15 +3627,18 @@ void multiSlsDetector::registerDataCallback( } int multiSlsDetector::setTotalProgress() { - int nf = Parallel(&slsDetector::setTimer, {}, FRAME_NUMBER, -1).tsquash("Inconsistent number of frames"); - int nc = Parallel(&slsDetector::setTimer, {}, CYCLES_NUMBER, -1).tsquash("Inconsistent number of cycles"); + int nf = Parallel(&slsDetector::setTimer, {}, FRAME_NUMBER, -1) + .tsquash("Inconsistent number of frames"); + int nc = Parallel(&slsDetector::setTimer, {}, CYCLES_NUMBER, -1) + .tsquash("Inconsistent number of cycles"); if (nf == 0 || nc == 0) { throw RuntimeError("Number of frames or cycles is 0"); } int ns = 1; if (getDetectorTypeAsEnum() == JUNGFRAU) { - ns = Parallel(&slsDetector::setTimer, {}, STORAGE_CELL_NUMBER, -1).tsquash("Inconsistent number of additional storage cells"); + ns = Parallel(&slsDetector::setTimer, {}, STORAGE_CELL_NUMBER, -1) + .tsquash("Inconsistent number of additional storage cells"); ++ns; } @@ -3707,12 +3719,12 @@ int multiSlsDetector::acquire() { // stop receiver if (receiver) { stopReceiver(); - if (dataReady != nullptr) { - sem_wait(&sem_endRTAcquisition); // waits for receiver's - } - // external process to be - // done sending data to gui - + if (dataReady != nullptr) { + sem_wait(&sem_endRTAcquisition); // waits for receiver's + } + // external process to be + // done sending data to gui + incrementFileIndex(); } @@ -3904,9 +3916,3 @@ std::vector multiSlsDetector::readPofFile(const std::string &fname) { FILE_LOG(logINFO) << "Read file into memory"; return buffer; } - - - - - - diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index 92ed065b8..41c543ee2 100755 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -23,7 +23,6 @@ using namespace sls; - // create shm slsDetector::slsDetector(detectorType type, int multi_id, int det_id, bool verify) @@ -590,8 +589,10 @@ void slsDetector::updateNumberOfChannels() { slsDetectorDefs::xy slsDetector::getNumberOfChannels() const { slsDetectorDefs::xy coord; - coord.x = (shm()->nChan.x * shm()->nChip.x + shm()->gappixels * shm()->nGappixels.x); - coord.y = (shm()->nChan.y * shm()->nChip.y + shm()->gappixels * shm()->nGappixels.y); + coord.x = (shm()->nChan.x * shm()->nChip.x + + shm()->gappixels * shm()->nGappixels.x); + coord.y = (shm()->nChan.y * shm()->nChip.y + + shm()->gappixels * shm()->nGappixels.y); return coord; } @@ -601,7 +602,6 @@ bool slsDetector::getQuad() { sendToDetector(F_GET_QUAD, nullptr, retval); FILE_LOG(logDEBUG1) << "Quad Type :" << retval; return (retval == 0 ? false : true); - } void slsDetector::setQuad(const bool enable) { @@ -617,10 +617,11 @@ void slsDetector::setQuad(const bool enable) { void slsDetector::setReadNLines(const int value) { FILE_LOG(logDEBUG1) << "Setting read n lines to " << value; sendToDetector(F_SET_READ_N_LINES, value, nullptr); - FILE_LOG(logDEBUG1) << "Setting read n lines to " << value << " in Receiver"; + FILE_LOG(logDEBUG1) << "Setting read n lines to " << value + << " in Receiver"; if (shm()->useReceiverFlag) { sendToReceiver(F_SET_RECEIVER_READ_N_LINES, value, nullptr); -} + } } int slsDetector::getReadNLines() { @@ -635,7 +636,6 @@ void slsDetector::updateMultiSize(slsDetectorDefs::xy det) { shm()->multiSize = det; } - int slsDetector::setControlPort(int port_number) { int retval = -1; FILE_LOG(logDEBUG1) << "Setting control port to " << port_number; @@ -736,7 +736,7 @@ void slsDetector::updateCachedDetectorVariables() { // dr n += client.Receive(&i32, sizeof(i32)); - shm()->dynamicRange = i32; + shm()->dynamicRange = i32; // settings if ((shm()->myDetectorType != CHIPTESTBOARD) && @@ -1438,9 +1438,7 @@ int slsDetector::setDynamicRange(int n) { return shm()->dynamicRange; } -int slsDetector::getDynamicRangeFromShm() { - return shm()->dynamicRange; -} +int slsDetector::getDynamicRangeFromShm() { return shm()->dynamicRange; } int slsDetector::setDAC(int val, dacIndex index, int mV) { int args[]{static_cast(index), mV, val}; @@ -2190,7 +2188,8 @@ void slsDetector::setROI(slsDetectorDefs::ROI arg) { arg.xmin = -1; arg.xmax = -1; } - FILE_LOG(logDEBUG) << "Sending ROI to detector [" << arg.xmin << ", " << arg.xmax << "]"; + FILE_LOG(logDEBUG) << "Sending ROI to detector [" << arg.xmin << ", " + << arg.xmax << "]"; auto client = DetectorSocket(shm()->hostname, shm()->controlPort); client.Send(&fnum, sizeof(fnum)); client.Send(&arg.xmin, sizeof(int)); @@ -2203,7 +2202,7 @@ void slsDetector::setROI(slsDetectorDefs::ROI arg) { throw RuntimeError("Detector " + std::to_string(detId) + " returned error: " + std::string(mess)); } else { - memcpy(&shm()->roi, &arg, sizeof(ROI)); + memcpy(&shm()->roi, &arg, sizeof(ROI)); if (ret == FORCE_UPDATE) { updateCachedDetectorVariables(); } @@ -2243,14 +2242,13 @@ slsDetectorDefs::ROI slsDetector::getROI() { client.Receive(&retval.xmin, sizeof(int)); client.Receive(&retval.xmax, sizeof(int)); FILE_LOG(logDEBUG1) - << "ROI retval [" << retval.xmin << "," - << retval.xmax << "]"; + << "ROI retval [" << retval.xmin << "," << retval.xmax << "]"; if (ret == FORCE_UPDATE) { updateCachedDetectorVariables(); } // if different from shm, update and send to receiver if (shm()->roi.xmin != retval.xmin || shm()->roi.xmax != retval.xmax) { - memcpy(&shm()->roi, &retval, sizeof(ROI)); + memcpy(&shm()->roi, &retval, sizeof(ROI)); sendROItoReceiver(); } } @@ -2258,8 +2256,6 @@ slsDetectorDefs::ROI slsDetector::getROI() { return shm()->roi; } - - void slsDetector::setADCEnableMask(uint32_t mask) { uint32_t arg = mask; FILE_LOG(logDEBUG1) << "Setting ADC Enable mask to 0x" << std::hex << arg @@ -2414,9 +2410,7 @@ bool slsDetector::setDeactivatedRxrPaddingMode(int padding) { return shm()->rxPadDeactivatedModules; } -int slsDetector::getFlippedDataX() const { - return shm()->flippedDataX; -} +int slsDetector::getFlippedDataX() const { return shm()->flippedDataX; } int slsDetector::setFlippedDataX(int value) { // replace get with shm value (write to shm right away as it is a det value, @@ -2426,7 +2420,8 @@ int slsDetector::setFlippedDataX(int value) { } int retval = -1; int arg = shm()->flippedDataX; - FILE_LOG(logDEBUG1) << "Setting flipped data across x axis with value: " << arg; + FILE_LOG(logDEBUG1) << "Setting flipped data across x axis with value: " + << arg; if (shm()->useReceiverFlag) { sendToReceiver(F_SET_FLIPPED_DATA_RECEIVER, arg, retval); FILE_LOG(logDEBUG1) << "Flipped data:" << retval; From 4b0fb5029f49756780cc61950a78a30939ba3f4c Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Wed, 21 Aug 2019 12:45:08 +0200 Subject: [PATCH 106/108] WIP --- slsDetectorGui/include/qDrawPlot.h | 1 - slsDetectorGui/src/qDrawPlot.cpp | 7 +---- slsDetectorSoftware/include/Detector.h | 31 +++++++++++++++++++ .../include/multiSlsDetector.h | 10 ------ .../include/slsDetectorUsers.h | 8 ----- slsDetectorSoftware/src/Detector.cpp | 16 ++++++++++ slsDetectorSoftware/src/multiSlsDetector.cpp | 10 ------ slsDetectorSoftware/src/slsDetectorUsers.cpp | 4 --- 8 files changed, 48 insertions(+), 39 deletions(-) diff --git a/slsDetectorGui/include/qDrawPlot.h b/slsDetectorGui/include/qDrawPlot.h index 99898a72b..52ab92a23 100755 --- a/slsDetectorGui/include/qDrawPlot.h +++ b/slsDetectorGui/include/qDrawPlot.h @@ -74,7 +74,6 @@ class qDrawPlot : public QWidget, private Ui::PlotObject { void SetupPlots(); void GetStatistics(double &min, double &max, double &sum); void DetachHists(); - static void GetProgressCallBack(double currentProgress, void *this_pointer); static void GetAcquisitionFinishedCallBack(double currentProgress, int detectorStatus, void *this_pointer); static void GetDataCallBack(detectorData *data, uint64_t frameIndex, uint32_t subFrameIndex, void *this_pointer); std::string AcquireThread(); diff --git a/slsDetectorGui/src/qDrawPlot.cpp b/slsDetectorGui/src/qDrawPlot.cpp index 61972327c..b6b6606b9 100755 --- a/slsDetectorGui/src/qDrawPlot.cpp +++ b/slsDetectorGui/src/qDrawPlot.cpp @@ -64,7 +64,6 @@ void qDrawPlot::SetupWidgetWindow() { SetupPlots(); SetDataCallBack(true); myDet->registerAcquisitionFinishedCallback(&(GetAcquisitionFinishedCallBack), this); - myDet->registerProgressCallback(&(GetProgressCallBack), this); // future watcher to watch result of AcquireThread only because it uses signals/slots to handle acquire exception acqResultWatcher = new QFutureWatcher(); @@ -590,11 +589,6 @@ std::string qDrawPlot::AcquireThread() { return std::string(""); } -void qDrawPlot::GetProgressCallBack(double currentProgress, void *this_pointer) { - ((qDrawPlot *)this_pointer)->progress = currentProgress; - FILE_LOG(logDEBUG) << "Progress Call back successful"; -} - void qDrawPlot::GetAcquisitionFinishedCallBack(double currentProgress, int detectorStatus, void *this_pointer) { ((qDrawPlot *)this_pointer)->AcquisitionFinished(currentProgress, detectorStatus); FILE_LOG(logDEBUG) << "Acquisition Finished Call back successful"; @@ -606,6 +600,7 @@ void qDrawPlot::GetDataCallBack(detectorData *data, uint64_t frameIndex, uint32_ } void qDrawPlot::AcquisitionFinished(double currentProgress, int detectorStatus) { + progress = currentProgress; std::string status = slsDetectorDefs::runStatusType(static_cast(detectorStatus)); if (detectorStatus == slsDetectorDefs::ERROR) { diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index a683f9e37..679646a37 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -6,6 +6,8 @@ #include class multiSlsDetector; +class detectorData; + namespace sls { using ns = std::chrono::nanoseconds; class MacAddr; @@ -83,6 +85,35 @@ class Detector { /** [Jungfrau][Gotthard] */ void setSettings(defs::detectorSettings value, Positions pos = {}); + /************************************************** + * * + * Callbacks * + * * + * ************************************************/ + + /** + * register callback for end of acquisition + * @param func function to be called with parameters: + * current progress in percentage, detector status, pArg pointer + * @param pArg pointer that is returned in call back + */ + void registerAcquisitionFinishedCallback(void (*func)(double, int, void *), + void *pArg); + + /** + * register callback for accessing reconstructed complete images + * Receiver sends out images via zmq, the client reconstructs them into + * complete images. Therefore, it also enables zmq streaming from receiver + * and the client. + * @param func function to be called for each image with parameters: + * detector data structure, frame number, sub frame number (for eiger in 32 + * bit mode), pArg pointer + * @param pArg pointer that is returned in call back + */ + void registerDataCallback(void (*func)(detectorData *, uint64_t, uint32_t, + void *), + void *pArg); + /************************************************** * * * Acquisition Parameters * diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index abe0c2e78..f486d0010 100755 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -1993,13 +1993,6 @@ class multiSlsDetector : public virtual slsDetectorDefs { */ void registerAcquisitionFinishedCallback(void (*func)(double, int, void *), void *pArg); - /** - * register callback for accessing detector progress - * @param func function to be called at the end of the acquisition. - * gets detector status and progress index as arguments - * @param pArg argument - */ - void registerProgressCallback(void (*func)(double, void *), void *pArg); /** * register calbback for accessing detector final data, @@ -2260,9 +2253,6 @@ class multiSlsDetector : public virtual slsDetectorDefs { void (*acquisition_finished)(double, int, void *){nullptr}; void *acqFinished_p{nullptr}; - void (*progress_call)(double, void *){nullptr}; - void *pProgressCallArg{nullptr}; - void (*dataReady)(detectorData *, uint64_t, uint32_t, void *){nullptr}; void *pCallbackArg{nullptr}; }; diff --git a/slsDetectorSoftware/include/slsDetectorUsers.h b/slsDetectorSoftware/include/slsDetectorUsers.h index eacf25992..c0f5ee46f 100755 --- a/slsDetectorSoftware/include/slsDetectorUsers.h +++ b/slsDetectorSoftware/include/slsDetectorUsers.h @@ -775,14 +775,6 @@ public: */ void registerAcquisitionFinishedCallback(void( *func)(double,int, void*), void *pArg); - /** - * register callback for accessing detector progress in client, - * @param func function to be called at the end of the acquisition. - * gets detector status and progress index as arguments - * @param pArg argument - */ - void registerProgressCallback(void( *func)(double,void*), void *pArg); - /** @short [usage strongly discouraged] sets parameters trough command line interface http://www.psi.ch/detectors/UsersSupportEN/slsDetectorClientHowTo.pdf \param command string as it would be written on the command line diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index f7a500897..566b00561 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -4,6 +4,8 @@ #include "multiSlsDetector.h" #include "slsDetector.h" #include "sls_detector_defs.h" +#include "detectorData.h" + namespace sls { using defs = slsDetectorDefs; @@ -82,6 +84,20 @@ void Detector::setSettings(defs::detectorSettings value, Positions pos) { pimpl->Parallel(&slsDetector::setSettings, pos, value); } +// Callback + +void Detector::registerAcquisitionFinishedCallback(void (*func)(double, int, + void *), + void *pArg) { + pimpl->registerAcquisitionFinishedCallback(func, pArg); +} + +void Detector::registerDataCallback(void (*func)(detectorData *, uint64_t, + uint32_t, void *), + void *pArg) { + pimpl->registerDataCallback(func, pArg); +} + // Acquisition Parameters Result Detector::getNumberOfFrames() const { diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index 3c3a29377..2183dcec7 100755 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -3604,12 +3604,6 @@ void multiSlsDetector::registerAcquisitionFinishedCallback( acqFinished_p = pArg; } -void multiSlsDetector::registerProgressCallback(void (*func)(double, void *), - void *pArg) { - progress_call = func; - pProgressCallArg = pArg; -} - void multiSlsDetector::registerDataCallback( void (*userCallback)(detectorData *, uint64_t, uint32_t, void *), void *pArg) { @@ -3733,10 +3727,6 @@ int multiSlsDetector::acquire() { sem_post(&sem_newRTAcquisition); dataProcessingThread.join(); - if (progress_call != nullptr) { - progress_call(getCurrentProgress(), pProgressCallArg); - } - if (acquisition_finished != nullptr) { acquisition_finished(getCurrentProgress(), getRunStatus(), acqFinished_p); diff --git a/slsDetectorSoftware/src/slsDetectorUsers.cpp b/slsDetectorSoftware/src/slsDetectorUsers.cpp index 7dd0069a8..acab7f2a9 100755 --- a/slsDetectorSoftware/src/slsDetectorUsers.cpp +++ b/slsDetectorSoftware/src/slsDetectorUsers.cpp @@ -383,10 +383,6 @@ void slsDetectorUsers::registerAcquisitionFinishedCallback(void( *func)(double,i detector.registerAcquisitionFinishedCallback(func,pArg); } -void slsDetectorUsers::registerProgressCallback(void( *func)(double,void*), void *pArg) { - detector.registerProgressCallback(func,pArg); -} - void slsDetectorUsers::putCommand(const std::string& command){ multiSlsDetectorClient(command, slsDetectorDefs::PUT_ACTION, &detector); } From cf045d8a1d0f916f4acc71b959c6ff7169a8f662 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Wed, 21 Aug 2019 15:18:50 +0200 Subject: [PATCH 107/108] ctb gui fix --- ctbGui/Makefile.root5 | 10 ++-- slsDetectorCalibration/moenchCommonMode.h | 56 +++++++++++------------ 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/ctbGui/Makefile.root5 b/ctbGui/Makefile.root5 index 0617d61dd..698a06e4c 100644 --- a/ctbGui/Makefile.root5 +++ b/ctbGui/Makefile.root5 @@ -1,17 +1,17 @@ INCS=ctbMain.h ctbDacs.h ctbPattern.h ctbSignals.h ctbAdcs.h ctbAcquisition.h ctbPowers.h ctbSlowAdcs.h -SRC= $(SRC:.h=.cpp) ctbDict.cpp +SRC= $(INCS:.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 +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) @@ -30,13 +30,13 @@ ctbDict.cpp: $(INCS) $(LINKDEF) %.o : %.cpp echo $@ - g++ -DMYROOT `source root-config --cflags --glibs` -lMinuit -DCTB $(LDFLAG) -o $@ -c $< $(INCDIR) + 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 `source root-config --cflags --glibs` -lMinuit -DCTB $(LDFLAG) -o ctbGui $(INCDIR) $(OBJS) ../slsDetectorCalibration/tiffIO.cpp + g++ -DMYROOT `root-config --cflags --glibs` -lMinuit -DCTB $(LDFLAG) -o ctbGui $(INCDIR) $(OBJS) ../slsDetectorCalibration/tiffIO.cpp mv ctbGui $(DESTDIR) clean: diff --git a/slsDetectorCalibration/moenchCommonMode.h b/slsDetectorCalibration/moenchCommonMode.h index dba0df2b7..75dcdeed5 100644 --- a/slsDetectorCalibration/moenchCommonMode.h +++ b/slsDetectorCalibration/moenchCommonMode.h @@ -1,7 +1,7 @@ #ifndef MOENCHCOMMONMODE_H #define MOENCHCOMMONMODE_H -#include "commonModeSubtraction.h" +#include "commonModeSubtractionNew.h" class moenchCommonMode : public commonModeSubtraction { /** @short class to calculate the common mode noise for moench02 i.e. on 4 supercolumns separately */ @@ -9,35 +9,35 @@ class moenchCommonMode : public commonModeSubtraction { /** constructor - initalizes a commonModeSubtraction with 4 different regions of interest \param nn number of samples for the moving average */ - moenchCommonMode(int nn=1000) : commonModeSubtraction(nn,4){} ; + moenchCommonMode(int nn=0) : commonModeSubtraction(0){} ; - /** add value to common mode as a function of the pixel value, subdividing the region of interest in the 4 supercolumns of 40 columns each; - \param val value to add to the common mode - \param ix pixel coordinate in the x direction - \param iy pixel coordinate in the y direction - */ - virtual void addToCommonMode(double val, int ix=0, int iy=0) { - (void) iy; - int isc=ix/40; - if (isc>=0 && isc=0 && isc0) return cmPed[isc]/nCm[isc]-cmStat[isc].Mean(); - } - return 0; - }; + /* /\** add value to common mode as a function of the pixel value, subdividing the region of interest in the 4 supercolumns of 40 columns each; */ + /* \param val value to add to the common mode */ + /* \param ix pixel coordinate in the x direction */ + /* \param iy pixel coordinate in the y direction */ + /* *\/ */ + /* virtual void addToCommonMode(double val, int ix=0, int iy=0) { */ + /* (void) iy; */ + /* int isc=ix/40; */ + /* if (isc>=0 && isc=0 && isc0) return cmPed[isc]/nCm[isc]-cmStat[isc].Mean(); */ + /* } */ + /* return 0; */ + /* }; */ }; From e04242c5faf591f6731e6de86ab404c3519b2ed1 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Wed, 21 Aug 2019 15:40:19 +0200 Subject: [PATCH 108/108] ctb gui progress call back fix --- .gitignore | 4 ++++ ctbGui/ctbAcquisition.cpp | 12 ++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index d31ff259f..0a79fe941 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,10 @@ build RELEASE.txt Testing/ +ctbDict.cpp +ctbDict.h + + *.pyc */__pycache__/* diff --git a/ctbGui/ctbAcquisition.cpp b/ctbGui/ctbAcquisition.cpp index 1b385fe3e..8246d6af8 100755 --- a/ctbGui/ctbAcquisition.cpp +++ b/ctbGui/ctbAcquisition.cpp @@ -597,12 +597,12 @@ hframe=new TGHorizontalFrame(this, 800,50); 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 progress callback" << endl; + // try { + // myDet->registerProgressCallback(&progressCallback,(void*)this); + // } catch (...) { + // cout << "Do nothing for this error" << endl; + // } cout <<"Registering data callback" << endl; try{