From 1ff35edb993b05d62032873a27543e21e5c27eb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Fr=C3=B6jdh?= Date: Mon, 28 Mar 2022 14:27:47 +0200 Subject: [PATCH] Setting dac names for CTB (C++ and Python) (#413) # Setting DAC names for CTB * Introduced new shared memory for CTB only * Prepared for additional functionality * Works from C++ and Python Co-authored-by: Dhanya Thattil --- RELEASE.txt | 2 +- python/slsdet/ctb.py | 56 ++++++------- python/slsdet/dacs.py | 80 ++++++++++++++++++- python/slsdet/detector.py | 12 ++- python/src/detector.cpp | 13 +++ slsDetectorSoftware/CMakeLists.txt | 1 + slsDetectorSoftware/include/sls/Detector.h | 8 ++ slsDetectorSoftware/src/CmdProxy.cpp | 58 ++++++++++++-- slsDetectorSoftware/src/CmdProxy.h | 7 +- slsDetectorSoftware/src/CtbConfig.cpp | 72 +++++++++++++++++ slsDetectorSoftware/src/CtbConfig.h | 31 +++++++ slsDetectorSoftware/src/Detector.cpp | 43 ++++++++++ slsDetectorSoftware/src/DetectorImpl.cpp | 37 ++++++++- slsDetectorSoftware/src/DetectorImpl.h | 8 ++ slsDetectorSoftware/src/SharedMemory.h | 30 +++---- slsDetectorSoftware/tests/CMakeLists.txt | 1 + slsDetectorSoftware/tests/test-CmdProxy.cpp | 8 +- slsDetectorSoftware/tests/test-CtbConfig.cpp | 59 ++++++++++++++ .../tests/test-SharedMemory.cpp | 28 +++++++ 19 files changed, 487 insertions(+), 67 deletions(-) create mode 100644 slsDetectorSoftware/src/CtbConfig.cpp create mode 100644 slsDetectorSoftware/src/CtbConfig.h create mode 100644 slsDetectorSoftware/tests/test-CtbConfig.cpp diff --git a/RELEASE.txt b/RELEASE.txt index 5d1bbf6cf..7eff077d3 100755 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -54,7 +54,7 @@ This document describes the differences between v7.0.0 and v6.x.x - added geometry to metadata - 10g eiger nextframenumber get fixed. - stop, able to set nextframenumber to a consistent (max + 1) for all modules if different (eiger/ctb/jungfrau/moench) -- fpga/kernel programming, checks if drive is a special file and not a normal file +- ctb: can set names for all the dacs - fpga/kernel programming, checks if drive is a special file and not a normal file - gotthard 25 um image reconstructed in gui and virtual hdf5 (firmware updated for slave to reverse channels) diff --git a/python/slsdet/ctb.py b/python/slsdet/ctb.py index 10afd3ae3..53ba8e8d7 100644 --- a/python/slsdet/ctb.py +++ b/python/slsdet/ctb.py @@ -1,43 +1,45 @@ # SPDX-License-Identifier: LGPL-3.0-or-other # Copyright (C) 2021 Contributors to the SLS Detector Package -from .detector import Detector +from .detector import Detector, freeze from .utils import element_if_equal -from .dacs import DetectorDacs +from .dacs import DetectorDacs, NamedDacs import _slsdet dacIndex = _slsdet.slsDetectorDefs.dacIndex from .detector_property import DetectorProperty -class CtbDacs(DetectorDacs): - """ - Ctb dacs - """ - _dacs = [('dac0', dacIndex(0), 0, 4000, 1400), - ('dac1', dacIndex(1), 0, 4000, 1200), - ('dac2', dacIndex(2), 0, 4000, 900), - ('dac3', dacIndex(3), 0, 4000, 1050), - ('dac4', dacIndex(4), 0, 4000, 1400), - ('dac5', dacIndex(5), 0, 4000, 655), - ('dac6', dacIndex(6), 0, 4000, 2000), - ('dac7', dacIndex(7), 0, 4000, 1400), - ('dac8', dacIndex(8), 0, 4000, 850), - ('dac9', dacIndex(9), 0, 4000, 2000), - ('dac10', dacIndex(10), 0, 4000, 2294), - ('dac11', dacIndex(11), 0, 4000, 983), - ('dac12', dacIndex(12), 0, 4000, 1475), - ('dac13', dacIndex(13), 0, 4000, 1200), - ('dac14', dacIndex(14), 0, 4000, 1600), - ('dac15', dacIndex(15), 0, 4000, 1455), - ('dac16', dacIndex(16), 0, 4000, 0), - ('dac17', dacIndex(17), 0, 4000, 1000), - ] - _dacnames = [_d[0] for _d in _dacs] +# class CtbDacs(DetectorDacs): +# """ +# Ctb dacs +# """ +# _dacs = [('dac0', dacIndex(0), 0, 4000, 1400), +# ('dac1', dacIndex(1), 0, 4000, 1200), +# ('dac2', dacIndex(2), 0, 4000, 900), +# ('dac3', dacIndex(3), 0, 4000, 1050), +# ('dac4', dacIndex(4), 0, 4000, 1400), +# ('dac5', dacIndex(5), 0, 4000, 655), +# ('dac6', dacIndex(6), 0, 4000, 2000), +# ('dac7', dacIndex(7), 0, 4000, 1400), +# ('dac8', dacIndex(8), 0, 4000, 850), +# ('dac9', dacIndex(9), 0, 4000, 2000), +# ('dac10', dacIndex(10), 0, 4000, 2294), +# ('dac11', dacIndex(11), 0, 4000, 983), +# ('dac12', dacIndex(12), 0, 4000, 1475), +# ('dac13', dacIndex(13), 0, 4000, 1200), +# ('dac14', dacIndex(14), 0, 4000, 1600), +# ('dac15', dacIndex(15), 0, 4000, 1455), +# ('dac16', dacIndex(16), 0, 4000, 0), +# ('dac17', dacIndex(17), 0, 4000, 1000), +# ] +# _dacnames = [_d[0] for _d in _dacs] from .utils import element +@freeze class Ctb(Detector): def __init__(self, id = 0): super().__init__(id) self._frozen = False - self._dacs = CtbDacs(self) + # self._dacs = CtbDacs(self) + self._dacs = NamedDacs(self) @property def dacs(self): diff --git a/python/slsdet/dacs.py b/python/slsdet/dacs.py index 5628eb3a6..0321c24dc 100755 --- a/python/slsdet/dacs.py +++ b/python/slsdet/dacs.py @@ -36,6 +36,79 @@ class Dac(DetectorProperty): dacstr = ''.join([f'{item:5d}' for item in self.get()]) return f'{self.__name__:15s}:{dacstr}' +class NamedDacs: + """ + New implementation of the detector dacs. Used at the momen for + Ctb but should replace the old one for all detectors + """ + _frozen = False + _direct_access = ['_detector', '_current', '_dacnames'] + def __init__(self, detector): + self._detector = detector + self._current = 0 + + self._dacnames = [n.replace(" ", "") for n in detector.getDacNames()] + # # Populate the dacs + for i,name in enumerate(self._dacnames): + #name, enum, low, high, default, detector + setattr(self, name, Dac(name, dacIndex(i), 0, 4000, 1000, detector)) + + self._frozen = True + + # def __getattr__(self, name): + # return self.__getattribute__('_' + name) + + def __setattr__(self, name, value): + if not self._frozen: + #durining init we need to be able to set up the class + super().__setattr__(name, value) + else: + #Later we restrict us to manipulate dacs and a few fields + if name in self._direct_access: + super().__setattr__(name, value) + elif name in self._dacnames: + return self.__getattribute__(name).__setitem__(slice(None, None, None), value) + else: + raise AttributeError(f'Dac not found: {name}') + + def __next__(self): + if self._current >= len(self._dacnames): + self._current = 0 + raise StopIteration + else: + self._current += 1 + return self.__getattribute__(self._dacnames[self._current-1]) + # return self.__getattr__(self._dacnames[self._current-1]) + + def __iter__(self): + return self + + def __repr__(self): + r_str = ['========== DACS ========='] + r_str += [repr(dac) for dac in self] + return '\n'.join(r_str) + def get_asarray(self): + """ + Read the dacs into a numpy array with dimensions [ndacs, nmodules] + """ + dac_array = np.zeros((len(self._dacnames), len(self._detector))) + for i, _d in enumerate(self): + dac_array[i,:] = _d[:] + return dac_array + + def to_array(self): + return self.get_asarray() + + def set_from_array(self, dac_array): + """ + Set the dacs from an numpy array with dac values. [ndacs, nmodules] + """ + dac_array = dac_array.astype(np.int) + for i, _d in enumerate(self): + _d[:] = dac_array[i] + + def from_array(self, dac_array): + self.set_from_array(dac_array) class DetectorDacs: _dacs = [] @@ -50,7 +123,7 @@ class DetectorDacs: # Index to support iteration self._current = 0 - # Populate the dacs + # Name the attributes? for _d in self._dacs: setattr(self, '_'+_d[0], Dac(*_d, detector)) @@ -59,7 +132,10 @@ class DetectorDacs: def __getattr__(self, name): return self.__getattribute__('_' + name) - + @property + def dacnames(self): + return [_d[0] for _d in _dacs] + def __setattr__(self, name, value): if name in self._dacnames: return self.__getattribute__('_' + name).__setitem__(slice(None, None, None), value) diff --git a/python/slsdet/detector.py b/python/slsdet/detector.py index d60dd05e8..d94d82995 100755 --- a/python/slsdet/detector.py +++ b/python/slsdet/detector.py @@ -1571,8 +1571,16 @@ class Detector(CppDetectorApi): @property def daclist(self): - """Gets the list of enums for every dac for this detector.""" - return self.getDacList() + """ + List of enums for every dac for this detector. + :setter: Only implemented for Chiptestboard + + """ + return self.getDacNames() + + @daclist.setter + def daclist(self, value): + self.setDacNames(value) @property def dacvalues(self): diff --git a/python/src/detector.cpp b/python/src/detector.cpp index 024d08ddb..2323a0e1d 100644 --- a/python/src/detector.cpp +++ b/python/src/detector.cpp @@ -1427,6 +1427,19 @@ void init_det(py::module &m) { (void (Detector::*)(bool, sls::Positions)) & Detector::setLEDEnable, py::arg(), py::arg() = Positions{}) + .def("setDacNames", + (void (Detector::*)(const std::vector)) & + Detector::setDacNames, + py::arg()) + .def("getDacNames", (std::vector(Detector::*)() const) & + Detector::getDacNames) + .def("getDacIndex", + (defs::dacIndex(Detector::*)(const std::string &)) & + Detector::getDacIndex, + py::arg()) + .def("getDacName", + (std::string(Detector::*)(defs::dacIndex)) & Detector::getDacName, + py::arg()) .def("setPattern", (void (Detector::*)(const std::string &, sls::Positions)) & Detector::setPattern, diff --git a/slsDetectorSoftware/CMakeLists.txt b/slsDetectorSoftware/CMakeLists.txt index ce88e0ca8..33bfc8432 100755 --- a/slsDetectorSoftware/CMakeLists.txt +++ b/slsDetectorSoftware/CMakeLists.txt @@ -7,6 +7,7 @@ set(SOURCES src/CmdProxy.cpp src/CmdParser.cpp src/Pattern.cpp + src/CtbConfig.cpp ) add_library(slsDetectorObject OBJECT diff --git a/slsDetectorSoftware/include/sls/Detector.h b/slsDetectorSoftware/include/sls/Detector.h index e359d49a5..68ccbd2a9 100644 --- a/slsDetectorSoftware/include/sls/Detector.h +++ b/slsDetectorSoftware/include/sls/Detector.h @@ -1613,6 +1613,14 @@ class Detector { /** [CTB] Default is enabled. */ void setLEDEnable(bool enable, Positions pos = {}); + + + void setDacNames(const std::vector names); + + std::vector getDacNames() const; + + defs::dacIndex getDacIndex(const std::string& name); + std::string getDacName(defs::dacIndex i); ///@} /** @name Pattern */ diff --git a/slsDetectorSoftware/src/CmdProxy.cpp b/slsDetectorSoftware/src/CmdProxy.cpp index ddd2e1d5f..6b84e770d 100644 --- a/slsDetectorSoftware/src/CmdProxy.cpp +++ b/slsDetectorSoftware/src/CmdProxy.cpp @@ -1056,11 +1056,10 @@ std::string CmdProxy::TemperatureValues(int action) { std::string CmdProxy::Dac(int action) { std::ostringstream os; os << cmd << ' '; - + auto type = det->getDetectorType().squash(); // dac indices only for ctb if (args.size() > 0 && action != defs::HELP_ACTION) { - if (is_int(args[0]) && - det->getDetectorType().squash() != defs::CHIPTESTBOARD) { + if (is_int(args[0]) && type != defs::CHIPTESTBOARD) { throw sls::RuntimeError( "Dac indices can only be used for chip test board. Use daclist " "to get list of dac names for current detector."); @@ -1077,7 +1076,14 @@ std::string CmdProxy::Dac(int action) { if (args.empty()) WrongNumberOfParameters(1); // This prints slightly wrong - defs::dacIndex dacIndex = StringTo(args[0]); + defs::dacIndex dacIndex{}; + //TODO! Remove if + if (type == defs::CHIPTESTBOARD && !is_int(args[0])) { + dacIndex = det->getDacIndex(args[0]); + } else { + dacIndex = StringTo(args[0]); + } + bool mV = false; if (args.size() == 2) { @@ -1095,7 +1101,11 @@ std::string CmdProxy::Dac(int action) { if (args.empty()) WrongNumberOfParameters(1); // This prints slightly wrong - defs::dacIndex dacIndex = StringTo(args[0]); + defs::dacIndex dacIndex{}; + if (type == defs::CHIPTESTBOARD && !is_int(args[0])) + dacIndex = det->getDacIndex(args[0]); + else + dacIndex = StringTo(args[0]); bool mV = false; if (args.size() == 3) { if ((args[2] != "mv") && (args[2] != "mV")) { @@ -1115,6 +1125,38 @@ std::string CmdProxy::Dac(int action) { return os.str(); } +std::string CmdProxy::DacList(const int action) { + std::ostringstream os; + os << cmd << ' '; + if (action == slsDetectorDefs::HELP_ACTION) { + os << "\n\t[dacname1 dacname2 .. dacname18] \n\t\t[ChipTestBoard] Set " + "the list of dac names for this detector.\n\t\t[All] Gets the " + "list " + "of " + "dac names for every dac for this detector." + << '\n'; + } else if (action == slsDetectorDefs::GET_ACTION) { + if (!args.empty()) { + WrongNumberOfParameters(0); + } + auto t = det->getDacNames(); + os << sls::ToString(t) << '\n'; + } else if (action == slsDetectorDefs::PUT_ACTION) { + if (det->getDetectorType().squash() != defs::CHIPTESTBOARD) { + throw sls::RuntimeError("This detector already has fixed dac " + "names. Cannot change them."); + } + if (args.size() != 18) { + WrongNumberOfParameters(18); + } + det->setDacNames(args); + os << ToString(args) << '\n'; + } else { + throw sls::RuntimeError("Unknown action"); + } + return os.str(); +} + std::string CmdProxy::DacValues(int action) { std::ostringstream os; os << cmd << ' '; @@ -1134,13 +1176,15 @@ std::string CmdProxy::DacValues(int action) { WrongNumberOfParameters(1); } auto t = det->getDacList(); + auto names = det->getDacNames(); + auto name_it = names.begin(); os << '['; auto it = t.cbegin(); - os << ToString(*it) << ' '; + os << ToString(*name_it++) << ' '; os << OutString(det->getDAC(*it++, mv, std::vector{det_id})) << (!args.empty() ? " mV" : ""); while (it != t.cend()) { - os << ", " << ToString(*it) << ' '; + os << ", " << ToString(*name_it++) << ' '; os << OutString(det->getDAC(*it++, mv, std::vector{det_id})) << (!args.empty() ? " mV" : ""); } diff --git a/slsDetectorSoftware/src/CmdProxy.h b/slsDetectorSoftware/src/CmdProxy.h index 0f8952c91..293bda371 100644 --- a/slsDetectorSoftware/src/CmdProxy.h +++ b/slsDetectorSoftware/src/CmdProxy.h @@ -837,7 +837,7 @@ class CmdProxy { /* dacs */ {"dac", &CmdProxy::Dac}, - {"daclist", &CmdProxy::daclist}, + {"daclist", &CmdProxy::DacList}, {"dacvalues", &CmdProxy::DacValues}, {"resetdacs", &CmdProxy::ResetDacs}, {"defaultdac", &CmdProxy::DefaultDac}, @@ -1124,6 +1124,7 @@ class CmdProxy { std::string TemperatureValues(int action); /* dacs */ std::string Dac(int action); + std::string DacList(int action); std::string DacValues(int action); std::string ResetDacs(int action); std::string DefaultDac(int action); @@ -1465,10 +1466,6 @@ class CmdProxy { /* dacs */ - GET_COMMAND_NOID( - daclist, getDacList, - "\n\tGets the list of commands for every dac for this detector."); - /* on chip dacs */ INTEGER_USER_IND_COMMAND( vchip_comp_fe, getOnChipDAC, setOnChipDAC, StringTo, diff --git a/slsDetectorSoftware/src/CtbConfig.cpp b/slsDetectorSoftware/src/CtbConfig.cpp new file mode 100644 index 000000000..d450ac5e6 --- /dev/null +++ b/slsDetectorSoftware/src/CtbConfig.cpp @@ -0,0 +1,72 @@ + +#include "CtbConfig.h" +#include "SharedMemory.h" +#include "sls/ToString.h" +#include "sls/string_utils.h" + +#include +#include +#include + +namespace sls { + +CtbConfig::CtbConfig(){ + for (size_t i=0; i!=num_dacs; ++i){ + setDacName(i, "dac"+ToString(i)); + } +} + +void CtbConfig::check_index(size_t i) const { + if (!(i < num_dacs)) { + std::ostringstream oss; + oss << "DAC index is too large needs to be below " << num_dacs; + throw RuntimeError(oss.str()); + } +} + +void CtbConfig::check_size(const std::string &name) const { + + if (name.empty()) + throw RuntimeError("Name needs to be at least one character"); + + // dacname_length -1 to account for \0 termination + if (!(name.size() < (name_length - 1))) { + std::ostringstream oss; + oss << "Length of name needs to be less than " << name_length - 1 + << " chars"; + throw RuntimeError(oss.str()); + } +} + +void CtbConfig::setDacName(size_t index, const std::string &name) { + + check_index(index); + check_size(name); + + char *dst = &dacnames[index * name_length]; + memset(dst, '\0', name_length); + memcpy(dst, &name[0], name.size()); +} + +void CtbConfig::setDacNames(const std::vector& names){ + for (size_t i = 0; i!=num_dacs; ++i){ + setDacName(i, names[i]); + } +} + +std::string CtbConfig::getDacName(size_t index) const { + return dacnames + index * name_length; +} + +std::vector CtbConfig::getDacNames() const { + std::vector names; + for (size_t i = 0; i != num_dacs; ++i) + names.push_back(getDacName(i)); + return names; +} + +const char* CtbConfig::shm_tag(){ + return shm_tag_; +} + +} // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/src/CtbConfig.h b/slsDetectorSoftware/src/CtbConfig.h new file mode 100644 index 000000000..6c17fadbf --- /dev/null +++ b/slsDetectorSoftware/src/CtbConfig.h @@ -0,0 +1,31 @@ +#pragma once +#include +#include +namespace sls { + + +class CtbConfig { + static constexpr size_t name_length = 20; + static constexpr size_t num_dacs = 18; + static constexpr const char* shm_tag_ = "ctbdacs"; + char dacnames[name_length * num_dacs]{}; + + void check_index(size_t i) const; + void check_size(const std::string &name) const; + + public: + CtbConfig(); + CtbConfig(const CtbConfig&) = default; + CtbConfig(CtbConfig&&) = default; + CtbConfig& operator=(const CtbConfig&) = default; + ~CtbConfig() = default; + + void setDacNames(const std::vector &names); + void setDacName(size_t index, const std::string &name); + std::string getDacName(size_t index) const; + std::vector getDacNames() const; + static const char* shm_tag(); +}; + + +} // namespace sls diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 98108cf43..74447566d 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -7,6 +7,7 @@ #include "CmdProxy.h" #include "DetectorImpl.h" #include "Module.h" +#include "CtbConfig.h" #include "sls/Pattern.h" #include "sls/container_utils.h" #include "sls/file_utils.h" @@ -21,6 +22,7 @@ namespace sls { void freeSharedMemory(int detectorIndex, int moduleIndex) { + // single module if (moduleIndex >= 0) { SharedMemory moduleShm(detectorIndex, moduleIndex); @@ -44,6 +46,11 @@ void freeSharedMemory(int detectorIndex, int moduleIndex) { SharedMemory moduleShm(detectorIndex, i); moduleShm.RemoveSharedMemory(); } + + // Ctb configuration + SharedMemory ctbShm(detectorIndex, -1, CtbConfig::shm_tag()); + if (ctbShm.IsExisting()) + ctbShm.RemoveSharedMemory(); } using defs = slsDetectorDefs; @@ -2067,6 +2074,42 @@ void Detector::setLEDEnable(bool enable, Positions pos) { pimpl->Parallel(&Module::setLEDEnable, pos, enable); } +void Detector::setDacNames(const std::vector names) { + if (getDetectorType().squash() != defs::CHIPTESTBOARD) + throw RuntimeError("Named dacs only for CTB"); + pimpl->setCtbDacNames(names); +} + +std::vector Detector::getDacNames() const { + std::vector names; + auto type = getDetectorType().squash(); + if (type == defs::CHIPTESTBOARD) + return pimpl->getCtbDacNames(); + + for (const auto &index : getDacList()) + names.push_back(ToString(index)); + return names; +} + +defs::dacIndex Detector::getDacIndex(const std::string &name) { + auto type = getDetectorType().squash(); + if (type == defs::CHIPTESTBOARD) { + auto names = getDacNames(); + auto it = std::find(names.begin(), names.end(), name); + if (it == names.end()) + throw RuntimeError("Dacname not found"); + return static_cast(it - names.begin()); + } + return StringTo(name); +} + +std::string Detector::getDacName(defs::dacIndex i) { + auto type = getDetectorType().squash(); + if (type == defs::CHIPTESTBOARD) + return pimpl->getCtbDacName(i); + return ToString(i); +} + // Pattern void Detector::setPattern(const std::string &fname, Positions pos) { diff --git a/slsDetectorSoftware/src/DetectorImpl.cpp b/slsDetectorSoftware/src/DetectorImpl.cpp index 6b5e84db7..7e8aa1719 100644 --- a/slsDetectorSoftware/src/DetectorImpl.cpp +++ b/slsDetectorSoftware/src/DetectorImpl.cpp @@ -32,7 +32,8 @@ namespace sls { DetectorImpl::DetectorImpl(int detector_index, bool verify, bool update) - : detectorIndex(detector_index), shm(detector_index, -1) { + : detectorIndex(detector_index), shm(detector_index, -1), + ctb_shm(detector_index, -1, CtbConfig::shm_tag()) { setupDetector(verify, update); } @@ -44,6 +45,9 @@ void DetectorImpl::setupDetector(bool verify, bool update) { if (update) { updateUserdetails(); } + + if (ctb_shm.IsExisting()) + ctb_shm.OpenSharedMemory(); } void DetectorImpl::setAcquiringFlag(bool flag) { shm()->acquiringFlag = flag; } @@ -74,6 +78,10 @@ void DetectorImpl::freeSharedMemory(int detectorIndex, int detPos) { SharedMemory moduleShm(detectorIndex, i); moduleShm.RemoveSharedMemory(); } + + SharedMemory ctbShm(detectorIndex, -1, CtbConfig::shm_tag()); + if (ctbShm.IsExisting()) + ctbShm.RemoveSharedMemory(); } void DetectorImpl::freeSharedMemory() { @@ -86,6 +94,9 @@ void DetectorImpl::freeSharedMemory() { // clear detector shm shm.RemoveSharedMemory(); client_downstream = false; + + if (ctb_shm.IsExisting()) + ctb_shm.RemoveSharedMemory(); } std::string DetectorImpl::getUserDetails() { @@ -144,6 +155,8 @@ void DetectorImpl::initSharedMemory(bool verify) { throw SharedMemoryError("Shared memory version mismatch!"); } } + + // std::cout << } void DetectorImpl::initializeDetectorStructure() { @@ -245,6 +258,16 @@ void DetectorImpl::setHostname(const std::vector &name) { addModule(hostname); } updateDetectorSize(); + + // Here we know the detector type and can add ctb shared memory + // if needed, CTB dac names are only on detector level + + if (shm()->detType == defs::CHIPTESTBOARD) { + if (ctb_shm.IsExisting()) + ctb_shm.OpenSharedMemory(); + else + ctb_shm.CreateSharedMemory(); + } } void DetectorImpl::addModule(const std::string &hostname) { @@ -1379,4 +1402,16 @@ void DetectorImpl::setDefaultDac(defs::dacIndex index, int defaultValue, Parallel(&Module::setDefaultDac, pos, index, defaultValue, sett); } +std::vector DetectorImpl::getCtbDacNames() const { + return ctb_shm()->getDacNames(); +} + +void DetectorImpl::setCtbDacNames(const std::vector &names) { + ctb_shm()->setDacNames(names); +} + +std::string DetectorImpl::getCtbDacName(defs::dacIndex i) const { + return ctb_shm()->getDacName(static_cast(i)); +} + } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/src/DetectorImpl.h b/slsDetectorSoftware/src/DetectorImpl.h index e3b0ab985..92d364556 100644 --- a/slsDetectorSoftware/src/DetectorImpl.h +++ b/slsDetectorSoftware/src/DetectorImpl.h @@ -7,6 +7,8 @@ #include "sls/logger.h" #include "sls/sls_detector_defs.h" + +#include "CtbConfig.h" class ZmqSocket; class detectorData; @@ -298,6 +300,11 @@ class DetectorImpl : public virtual slsDetectorDefs { void setDefaultDac(defs::dacIndex index, int defaultValue, defs::detectorSettings sett, Positions pos); + + std::vector getCtbDacNames() const; + std::string getCtbDacName(defs::dacIndex i) const; + void setCtbDacNames(const std::vector& names); + private: /** * Creates/open shared memory, initializes detector structure and members @@ -381,6 +388,7 @@ class DetectorImpl : public virtual slsDetectorDefs { const int detectorIndex{0}; sls::SharedMemory shm{0, -1}; + sls::SharedMemory ctb_shm{0, -1, "a"}; std::vector> modules; /** data streaming (down stream) enabled in client (zmq sckets created) */ diff --git a/slsDetectorSoftware/src/SharedMemory.h b/slsDetectorSoftware/src/SharedMemory.h index e50662487..70be4e741 100644 --- a/slsDetectorSoftware/src/SharedMemory.h +++ b/slsDetectorSoftware/src/SharedMemory.h @@ -19,7 +19,6 @@ #include // O_CREAT, O_TRUNC.. #include #include -// #include // printf #include // shared memory #include // fstat #include @@ -36,11 +35,9 @@ namespace sls { template class SharedMemory { public: - /** - * moduleid of -1 creates a detector only shared memory - */ - SharedMemory(int detectorId, int moduleIndex) { - name = ConstructSharedMemoryName(detectorId, moduleIndex); + //moduleid of -1 creates a detector only shared memory + SharedMemory(int detectorId, int moduleIndex, const std::string& tag = "") { + name = ConstructSharedMemoryName(detectorId, moduleIndex, tag); } /** @@ -103,11 +100,7 @@ template class SharedMemory { return ret; } - /** - * Get shared memory name - */ std::string GetName() const { return name; } - size_t size() const { return shmSize; } /** @@ -133,8 +126,10 @@ template class SharedMemory { RemoveSharedMemory(); throw SharedMemoryError(msg); } + // int *pInt = new (buf) int(3); shared_struct = MapSharedMemory(); + new (shared_struct) T{}; // is this ok? LOG(logINFO) << "Shared memory created " << name; } @@ -211,7 +206,7 @@ template class SharedMemory { * @param moduleIndex module id, -1 if a detector shared memory * @returns shared memory name */ - std::string ConstructSharedMemoryName(int detectorId, int moduleIndex) { + std::string ConstructSharedMemoryName(int detectorId, int moduleIndex, const std::string& tag) { // using environment path std::string sEnvPath; @@ -222,8 +217,12 @@ template class SharedMemory { } std::stringstream ss; - if (moduleIndex < 0) + if (moduleIndex < 0){ ss << SHM_DETECTOR_PREFIX << detectorId << sEnvPath; + if (!tag.empty()) + ss << "_" << tag; + } + else ss << SHM_DETECTOR_PREFIX << detectorId << SHM_MODULE_PREFIX << moduleIndex << sEnvPath; @@ -293,15 +292,10 @@ template class SharedMemory { return 0; } - /** Shared memory name */ + std::string name; - - /** File descriptor */ int fd{-1}; - - /** shm size */ size_t shmSize{0}; - T *shared_struct{nullptr}; }; diff --git a/slsDetectorSoftware/tests/CMakeLists.txt b/slsDetectorSoftware/tests/CMakeLists.txt index bc65a73e9..5a39e615e 100755 --- a/slsDetectorSoftware/tests/CMakeLists.txt +++ b/slsDetectorSoftware/tests/CMakeLists.txt @@ -18,6 +18,7 @@ target_sources(tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/test-CmdParser.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-Module.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-Pattern.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test-CtbConfig.cpp ) target_include_directories(tests PUBLIC "$") \ No newline at end of file diff --git a/slsDetectorSoftware/tests/test-CmdProxy.cpp b/slsDetectorSoftware/tests/test-CmdProxy.cpp index 06b95c48f..ff451bff5 100644 --- a/slsDetectorSoftware/tests/test-CmdProxy.cpp +++ b/slsDetectorSoftware/tests/test-CmdProxy.cpp @@ -590,13 +590,13 @@ TEST_CASE("master", "[.cmd]") { } { std::ostringstream oss1; - proxy.Call("master", {"0"}, 0, PUT, oss3); - REQUIRE(oss3.str() == "master 0\n"); + proxy.Call("master", {"0"}, 0, PUT, oss1); + REQUIRE(oss1.str() == "master 0\n"); } { std::ostringstream oss1; - proxy.Call("master", {"1"}, 0, PUT, oss3); - REQUIRE(oss3.str() == "master 1\n"); + proxy.Call("master", {"1"}, 0, PUT, oss1); + REQUIRE(oss1.str() == "master 1\n"); } REQUIRE_THROWS(proxy.Call("master", {"1"}, -1, PUT)); // set all to slaves, and then master diff --git a/slsDetectorSoftware/tests/test-CtbConfig.cpp b/slsDetectorSoftware/tests/test-CtbConfig.cpp new file mode 100644 index 000000000..15a22e852 --- /dev/null +++ b/slsDetectorSoftware/tests/test-CtbConfig.cpp @@ -0,0 +1,59 @@ +#include "catch.hpp" +#include + +#include + +#include "SharedMemory.h" +#include "CtbConfig.h" +using namespace sls; +#include + + +TEST_CASE("Default construction"){ + static_assert(sizeof(CtbConfig) == 360); // 18*20 + + CtbConfig c; + auto names = c.getDacNames(); + REQUIRE(names.size() == 18); + REQUIRE(names[0] == "dac0"); + REQUIRE(names[1] == "dac1"); + REQUIRE(names[2] == "dac2"); + REQUIRE(names[3] == "dac3"); +} + +TEST_CASE("Set and get a single dac name"){ + CtbConfig c; + c.setDacName(3, "vrf"); + auto names = c.getDacNames(); + + REQUIRE(c.getDacName(3) == "vrf"); + REQUIRE(names[3] == "vrf"); +} + +TEST_CASE("Set a name that is too large throws"){ + CtbConfig c; + REQUIRE_THROWS(c.setDacName(3, "somestringthatisreallytolongforadatac")); +} + +TEST_CASE("Length of dac name cannot be 0"){ + CtbConfig c; + REQUIRE_THROWS(c.setDacName(1, "")); +} + +TEST_CASE("Copy a CTB config"){ + CtbConfig c1; + c1.setDacName(5, "somename"); + + auto c2 = c1; + //change the name on the first object + //to detecto shallow copy + c1.setDacName(5, "someothername"); + REQUIRE(c2.getDacName(5) == "somename"); +} + +TEST_CASE("Move CtbConfig "){ + CtbConfig c1; + c1.setDacName(3, "yetanothername"); + CtbConfig c2(std::move(c1)); + REQUIRE(c2.getDacName(3) == "yetanothername"); +} \ No newline at end of file diff --git a/slsDetectorSoftware/tests/test-SharedMemory.cpp b/slsDetectorSoftware/tests/test-SharedMemory.cpp index fb1248653..f231ad19e 100644 --- a/slsDetectorSoftware/tests/test-SharedMemory.cpp +++ b/slsDetectorSoftware/tests/test-SharedMemory.cpp @@ -134,3 +134,31 @@ TEST_CASE("Create several shared memories", "[detector]") { CHECK(v[i].IsExisting() == false); } } + +TEST_CASE("Create create a shared memory with a tag"){ + SharedMemory shm(0, -1, "ctbdacs"); + REQUIRE(shm.GetName() == "/slsDetectorPackage_detector_0_ctbdacs"); + +} + +TEST_CASE("Create create a shared memory with a tag when SLSDETNAME is set"){ + + // if SLSDETNAME is already set we unset it but + // save the value + std::string old_slsdetname; + if (getenv(SHM_ENV_NAME)) + old_slsdetname = getenv(SHM_ENV_NAME); + unsetenv(SHM_ENV_NAME); + setenv(SHM_ENV_NAME, "myprefix", 1); + + SharedMemory shm(0, -1, "ctbdacs"); + REQUIRE(shm.GetName() == "/slsDetectorPackage_detector_0_myprefix_ctbdacs"); + + // Clean up after us + if (old_slsdetname.empty()) + unsetenv(SHM_ENV_NAME); + else + setenv(SHM_ENV_NAME, old_slsdetname.c_str(), 1); + +} +