From 61c31ed44a5bcebd99c833f7d8cb8d837e1fbea6 Mon Sep 17 00:00:00 2001 From: Dhanya Thattil <33750417+thattil@users.noreply.github.com> Date: Thu, 24 Nov 2022 11:57:26 +0100 Subject: [PATCH] txdelay for all modules (#584) * setting txdelay for all modules for eiger, jungfrau and m3 * added txdelay in python and renamed txndelay_ to txdelay_ * call in parallel --- RELEASE.txt | 1 + python/slsdet/detector.py | 41 +++++++--- python/src/detector.cpp | 6 ++ slsDetectorSoftware/include/sls/Detector.h | 14 ++++ slsDetectorSoftware/src/CmdProxy.cpp | 36 +++++++++ slsDetectorSoftware/src/CmdProxy.h | 19 +++-- slsDetectorSoftware/src/Detector.cpp | 8 ++ slsDetectorSoftware/src/DetectorImpl.cpp | 83 +++++++++++++++++++++ slsDetectorSoftware/src/DetectorImpl.h | 5 +- slsDetectorSoftware/tests/test-CmdProxy.cpp | 58 +++++++++++++- 10 files changed, 250 insertions(+), 21 deletions(-) diff --git a/RELEASE.txt b/RELEASE.txt index f0ad19995..0c59b40bb 100644 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -127,6 +127,7 @@ This document describes the differences between v7.0.0 and v6.x.x - gui nios temperature added - detector header change (bunchid, reserved, debug, roundRnumber) ->detSpec1 - 4 -ctb and moench (allowing all clkdivs (totaldiv was a float instead of int)) + - txndelay_ ->txdelay_ (also for python), txdelay = delay for all with step - hardwareversion - jungfrau connected moduleid to detid_jungfrau.txt on board diff --git a/python/slsdet/detector.py b/python/slsdet/detector.py index aeae768b4..30d60f961 100755 --- a/python/slsdet/detector.py +++ b/python/slsdet/detector.py @@ -627,25 +627,46 @@ class Detector(CppDetectorApi): @property @element - def txndelay_frame(self): + def txdelay(self): + """ + [Eiger][Jungfrau][Mythen3] Set transmission delay for all modules in the detector using the step size provided. + + Note + ---- + Sets up the following for every module:\n + \t\t[Eiger] txdelay_left to (2 * mod_index * n_delay), \n + \t\t[Eiger] txdelay_right to ((2 * mod_index + 1) * n_delay) and \n + \t\t[Eiger] txdelay_frame to (2 *num_modules * n_delay) \n + \t\t[Jungfrau][Mythen3] txdelay_frame to (num_modules * n_delay)\n\n + Please refer txdelay_left, txdelay_right and txdelay_frame for details. + """ + return self.getTransmissionDelay() + + @txdelay.setter + def txdelay(self, args): + ut.set_using_dict(self.setTransmissionDelay, args) + + @property + @element + def txdelay_frame(self): """ [Eiger][Jungfrau][Mythen3] Transmission delay of first udp packet being streamed out of the module.\n Note ---- [Jungfrau] [0-31] Each value represents 1 ms. \n - [Eiger] Additional delay to txndelay_left and txndelay_right. Each value represents 10ns. Typical value is 50000. \n + [Eiger] Additional delay to txdelay_left and txdelay_right. Each value represents 10ns. Typical value is 50000. \n [Mythen3] [0-16777215] Each value represents 8 ns (125 MHz clock), max is 134 ms. """ return self.getTransmissionDelayFrame() - @txndelay_frame.setter - def txndelay_frame(self, args): + @txdelay_frame.setter + def txdelay_frame(self, args): ut.set_using_dict(self.setTransmissionDelayFrame, args) @property @element - def txndelay_left(self): + def txdelay_left(self): """[Eiger] Transmission delay of first packet in an image being streamed out of the module's left UDP port. Note @@ -654,13 +675,13 @@ class Detector(CppDetectorApi): """ return self.getTransmissionDelayLeft() - @txndelay_left.setter - def txndelay_left(self, args): + @txdelay_left.setter + def txdelay_left(self, args): ut.set_using_dict(self.setTransmissionDelayLeft, args) @property @element - def txndelay_right(self): + def txdelay_right(self): """ [Eiger] Transmission delay of first packet in an image being streamed out of the module's right UDP port. @@ -670,8 +691,8 @@ class Detector(CppDetectorApi): """ return self.getTransmissionDelayRight() - @txndelay_right.setter - def txndelay_right(self, args): + @txdelay_right.setter + def txdelay_right(self, args): ut.set_using_dict(self.setTransmissionDelayRight, args) @property diff --git a/python/src/detector.cpp b/python/src/detector.cpp index 587565b99..0df2feaef 100644 --- a/python/src/detector.cpp +++ b/python/src/detector.cpp @@ -783,6 +783,12 @@ void init_det(py::module &m) { (void (Detector::*)(int, sls::Positions)) & Detector::setTransmissionDelayRight, py::arg(), py::arg() = Positions{}); + CppDetectorApi.def("getTransmissionDelay", + (int (Detector::*)() const) & + Detector::getTransmissionDelay); + CppDetectorApi.def( + "setTransmissionDelay", + (void (Detector::*)(int)) & Detector::setTransmissionDelay, py::arg()); CppDetectorApi.def("getUseReceiverFlag", (Result(Detector::*)(sls::Positions) const) & Detector::getUseReceiverFlag, diff --git a/slsDetectorSoftware/include/sls/Detector.h b/slsDetectorSoftware/include/sls/Detector.h index 4aba29d96..d0bb203b0 100644 --- a/slsDetectorSoftware/include/sls/Detector.h +++ b/slsDetectorSoftware/include/sls/Detector.h @@ -835,6 +835,20 @@ class Detector { * port */ void setTransmissionDelayRight(int value, Positions pos = {}); + + /** [Eiger][Jungfrau] */ + int getTransmissionDelay() const; + + /** + * [Eiger][Jungfrau][Mythen3] Set transmission delay for all modules in the + * detector using the step size provided.Sets up \n\t\t[Eiger] txdelay_left + * to (2 * mod_index * n_delay), \n\t\t[Eiger] txdelay_right to ((2 * + * mod_index + 1) * n_delay) and \n\t\t[Eiger] txdelay_frame to (2 + * *num_modules * n_delay) \n\t\t[Jungfrau][Mythen3] txdelay_frame to + * (num_modules * n_delay) \nfor every module. + */ + void setTransmissionDelay(int step); + ///@} /** @name Receiver Configuration */ diff --git a/slsDetectorSoftware/src/CmdProxy.cpp b/slsDetectorSoftware/src/CmdProxy.cpp index 355e673e0..35f3cf777 100644 --- a/slsDetectorSoftware/src/CmdProxy.cpp +++ b/slsDetectorSoftware/src/CmdProxy.cpp @@ -1705,6 +1705,42 @@ std::string CmdProxy::UDPDestinationIP2(int action) { return os.str(); } +std::string CmdProxy::TransmissionDelay(int action) { + std::ostringstream os; + os << cmd << ' '; + if (action == defs::HELP_ACTION) { + os << "[n_delay]\n\t[Eiger][Jungfrau][Mythen3] Set transmission delay " + "for all modules in the detector using the step size " + "provided.Sets up \n\t\t[Eiger] txdelay_left to (2 * mod_index * " + "n_delay), \n\t\t[Eiger] txdelay_right to ((2 * mod_index + 1) * " + "n_delay) and \n\t\t[Eiger] txdelay_frame to (2 *num_modules * " + "n_delay) \n\t\t[Jungfrau][Mythen3] txdelay_frame to " + "(num_modules * n_delay) \nfor every module." + << '\n'; + } else if (action == defs::GET_ACTION) { + if (det_id != -1) { + throw RuntimeError("Cannot execute this at module level"); + } + if (args.size() != 0) { + WrongNumberOfParameters(0); + } + auto t = det->getTransmissionDelay(); + os << OutString(t) << '\n'; + } else if (action == defs::PUT_ACTION) { + if (det_id != -1) { + throw RuntimeError("Cannot execute this at module level"); + } + if (args.size() != 1) { + WrongNumberOfParameters(1); + } + det->setTransmissionDelay(StringTo(args[0])); + os << args.front() << '\n'; + } else { + throw RuntimeError("Unknown action"); + } + return os.str(); +} + /* Receiver Config */ std::string CmdProxy::ReceiverHostname(int action) { std::ostringstream os; diff --git a/slsDetectorSoftware/src/CmdProxy.h b/slsDetectorSoftware/src/CmdProxy.h index 0d8529148..c0983d84a 100644 --- a/slsDetectorSoftware/src/CmdProxy.h +++ b/slsDetectorSoftware/src/CmdProxy.h @@ -697,6 +697,9 @@ class CmdProxy { {"rx_udpport", "udp_dstport"}, {"rx_udpport2", "udp_dstport2"}, {"flowcontrol_10g", "flowcontrol10g"}, + {"txndelay_frame", "txdelay_frame"}, + {"txndelay_left", "txdelay_left"}, + {"txndelay_right", "txdelay_right"}, /* Receiver Config */ {"r_silent", "rx_silent"}, @@ -893,9 +896,10 @@ class CmdProxy { {"rx_printconfig", &CmdProxy::rx_printconfig}, {"tengiga", &CmdProxy::tengiga}, {"flowcontrol10g", &CmdProxy::flowcontrol10g}, - {"txndelay_frame", &CmdProxy::txndelay_frame}, - {"txndelay_left", &CmdProxy::txndelay_left}, - {"txndelay_right", &CmdProxy::txndelay_right}, + {"txdelay_frame", &CmdProxy::txdelay_frame}, + {"txdelay_left", &CmdProxy::txdelay_left}, + {"txdelay_right", &CmdProxy::txdelay_right}, + {"txdelay", &CmdProxy::TransmissionDelay}, /* Receiver Config */ {"rx_hostname", &CmdProxy::ReceiverHostname}, @@ -1158,6 +1162,7 @@ class CmdProxy { std::string UDPSourceIP2(int action); std::string UDPDestinationIP(int action); std::string UDPDestinationIP2(int action); + std::string TransmissionDelay(int action); /* Receiver Config */ std::string ReceiverHostname(int action); std::string Rx_ROI(int action); @@ -1689,24 +1694,24 @@ class CmdProxy { "[0, 1]\n\t[Eiger][Jungfrau] 10GbE Flow Control."); INTEGER_COMMAND_VEC_ID( - txndelay_frame, getTransmissionDelayFrame, setTransmissionDelayFrame, + txdelay_frame, getTransmissionDelayFrame, setTransmissionDelayFrame, StringTo, "[n_delay]\n\t[Eiger][Jungfrau][Mythen3] Transmission delay of first " "udp packet being streamed out of the module.\n\t[Jungfrau] [0-31] " "Each value represents 1 ms\n\t[Eiger] Additional delay to " - "txndelay_left and txndelay_right. Each value represents 10ns. Typical " + "txdelay_left and txdelay_right. Each value represents 10ns. Typical " "value is 50000.\n\t[Mythen3] [0-16777215] Each value represents 8 ns " "(125 MHz clock), max is 134 ms."); INTEGER_COMMAND_VEC_ID( - txndelay_left, getTransmissionDelayLeft, setTransmissionDelayLeft, + txdelay_left, getTransmissionDelayLeft, setTransmissionDelayLeft, StringTo, "[n_delay]\n\t[Eiger] Transmission delay of first packet in an image " "being streamed out of the module's left UDP port. Each value " "represents 10ns. Typical value is 50000."); INTEGER_COMMAND_VEC_ID( - txndelay_right, getTransmissionDelayRight, setTransmissionDelayRight, + txdelay_right, getTransmissionDelayRight, setTransmissionDelayRight, StringTo, "[n_delay]\n\t[Eiger] Transmission delay of first packet in an image " "being streamed out of the module's right UDP port. Each value " diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index a12489d11..6f73483c6 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -1120,6 +1120,14 @@ void Detector::setTransmissionDelayRight(int value, Positions pos) { pimpl->Parallel(&Module::setTransmissionDelayRight, pos, value); } +int Detector::getTransmissionDelay() const { + return pimpl->getTransmissionDelay(); +} + +void Detector::setTransmissionDelay(int step) { + pimpl->setTransmissionDelay(step); +} + // Receiver Result Detector::getUseReceiverFlag(Positions pos) const { diff --git a/slsDetectorSoftware/src/DetectorImpl.cpp b/slsDetectorSoftware/src/DetectorImpl.cpp index 7688d5708..7e7fb2e4f 100644 --- a/slsDetectorSoftware/src/DetectorImpl.cpp +++ b/slsDetectorSoftware/src/DetectorImpl.cpp @@ -431,6 +431,89 @@ void DetectorImpl::setGapPixelsinCallback(const bool enable) { shm()->gapPixels = enable; } +int DetectorImpl::getTransmissionDelay() const { + bool eiger = false; + switch (shm()->detType) { + case JUNGFRAU: + case MYTHEN3: + break; + case EIGER: + eiger = true; + break; + default: + throw RuntimeError( + "Transmission delay is not implemented for the this detector."); + } + if (!eiger && size() <= 1) { + throw RuntimeError( + "Cannot get intermodule transmission delays with just one module"); + } + int step = 0; + if (eiger) { + // between left and right + step = modules[0]->getTransmissionDelayRight(); + } else { + // between first and second + step = modules[1]->getTransmissionDelayFrame(); + } + for (int i = 0; i != size(); ++i) { + if (eiger) { + if ((modules[i]->getTransmissionDelayLeft() != (2 * i * step)) || + (modules[i]->getTransmissionDelayRight() != + ((2 * i + 1) * step)) || + (modules[i]->getTransmissionDelayFrame() != + (2 * size() * step))) { + return -1; + } + } else { + if (modules[i]->getTransmissionDelayFrame() != (i * step)) { + return -1; + } + } + } + return step; +} + +void DetectorImpl::setTransmissionDelay(int step) { + bool eiger = false; + switch (shm()->detType) { + case JUNGFRAU: + case MYTHEN3: + break; + case EIGER: + eiger = true; + break; + default: + throw RuntimeError( + "Transmission delay is not implemented for the this detector."); + } + + //using a asyc+future directly (instead of Parallel) to pass different values + std::vector> futures; + for (int i = 0; i != size(); ++i) { + if (eiger) { + futures.push_back(std::async(std::launch::async, + &Module::setTransmissionDelayLeft, + modules[i].get(), 2 * i * step)); + futures.push_back(std::async(std::launch::async, + &Module::setTransmissionDelayRight, + modules[i].get(), (2 * i + 1) * step)); + futures.push_back(std::async(std::launch::async, + &Module::setTransmissionDelayFrame, + modules[i].get(), 2 * size() * step)); + + } else { + futures.push_back(std::async(std::launch::async, + &Module::setTransmissionDelayFrame, + modules[i].get(), i * step)); + } + } + + //wait for calls to complete + for (auto &f : futures) + f.get(); +} + int DetectorImpl::destroyReceivingDataSockets() { LOG(logINFO) << "Going to destroy data sockets"; // close socket diff --git a/slsDetectorSoftware/src/DetectorImpl.h b/slsDetectorSoftware/src/DetectorImpl.h index b40ee1d7b..01360096c 100644 --- a/slsDetectorSoftware/src/DetectorImpl.h +++ b/slsDetectorSoftware/src/DetectorImpl.h @@ -237,11 +237,10 @@ class DetectorImpl : public virtual slsDetectorDefs { * Sets maximum number of channels of all sls modules */ void setNumberOfChannels(const slsDetectorDefs::xy c); - /** [Eiger][Jungfrau] */ bool getGapPixelsinCallback() const; - /** [Eiger][Jungfrau] */ void setGapPixelsinCallback(const bool enable); - + int getTransmissionDelay() const; + void setTransmissionDelay(int step); bool getDataStreamingToClient(); void setDataStreamingToClient(bool enable); int getClientStreamingHwm() const; diff --git a/slsDetectorSoftware/tests/test-CmdProxy.cpp b/slsDetectorSoftware/tests/test-CmdProxy.cpp index 91b043d56..f57a0bf71 100644 --- a/slsDetectorSoftware/tests/test-CmdProxy.cpp +++ b/slsDetectorSoftware/tests/test-CmdProxy.cpp @@ -2672,7 +2672,7 @@ TEST_CASE("txndelay_frame", "[.cmd]") { det_type == defs::MYTHEN3) { auto prev_val = det.getTransmissionDelayFrame(); auto val = 5000; - if (det_type == defs::JUNGFRAU) { + if (det_type == defs::JUNGFRAU || det_type == defs::MYTHEN3) { val = 5; } std::string sval = std::to_string(val); @@ -2691,6 +2691,62 @@ TEST_CASE("txndelay_frame", "[.cmd]") { } } +TEST_CASE("txdelay", "[.cmd]") { + Detector det; + CmdProxy proxy(&det); + auto det_type = det.getDetectorType().squash(); + if (det_type == defs::EIGER || det_type == defs::JUNGFRAU || + det_type == defs::MYTHEN3) { + Result prev_left, prev_right; + bool eiger = false; + if (det_type == defs::EIGER) { + eiger = true; + prev_left = det.getTransmissionDelayLeft(); + prev_right = det.getTransmissionDelayRight(); + } + auto prev_frame = det.getTransmissionDelayFrame(); + auto val = 5000; + if (det_type == defs::JUNGFRAU || det_type == defs::MYTHEN3) { + val = 5; + } + std::string sval = std::to_string(val); + { + std::ostringstream oss1, oss2; + proxy.Call("txdelay", {sval}, -1, PUT, oss1); + REQUIRE(oss1.str() == "txdelay " + sval + "\n"); + proxy.Call("txdelay", {}, -1, GET, oss2); + REQUIRE(oss2.str() == "txdelay " + sval + "\n"); + } + // test other mods + for (int i = 0; i != det.size(); ++i) { + if (eiger) { + REQUIRE(det.getTransmissionDelayLeft({i}).squash(-1) == + (3 * i * val)); + REQUIRE(det.getTransmissionDelayRight({i}).squash(-1) == + ((3 * i + 1) * val)); + REQUIRE(det.getTransmissionDelayFrame({i}).squash(-1) == + ((3 * i + 2) * val)); + } else { + REQUIRE(det.getTransmissionDelayFrame({i}).squash(-1) == + (i * val)); + } + } + // not a module level command + REQUIRE_THROWS(proxy.Call("txdelay", {"5"}, 0, PUT)); + REQUIRE_THROWS(proxy.Call("txdelay", {}, 0, GET)); + + for (int i = 0; i != det.size(); ++i) { + if (eiger) { + det.setTransmissionDelayLeft(prev_left[i]); + det.setTransmissionDelayRight(prev_right[i]); + } + det.setTransmissionDelayFrame(prev_frame[i]); + } + } else { + REQUIRE_THROWS(proxy.Call("txdelay", {}, -1, GET)); + } +} + /* ZMQ Streaming Parameters (Receiver<->Client) */ TEST_CASE("zmqport", "[.cmd]") {