mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-04-25 07:40:03 +02:00
3961 lines
116 KiB
C++
Executable File
3961 lines
116 KiB
C++
Executable File
#include "multiSlsDetector.h"
|
|
#include "SharedMemory.h"
|
|
#include "ZmqSocket.h"
|
|
#include "detectorData.h"
|
|
#include "file_utils.h"
|
|
#include "logger.h"
|
|
#include "multiSlsDetectorClient.h"
|
|
#include "slsDetector.h"
|
|
#include "slsDetectorCommand.h"
|
|
#include "sls_detector_exceptions.h"
|
|
#include "versionAPI.h"
|
|
|
|
#include "container_utils.h"
|
|
#include "network_utils.h"
|
|
#include "string_utils.h"
|
|
|
|
#include <cstring>
|
|
#include <iomanip>
|
|
#include <iostream>
|
|
#include <rapidjson/document.h> //json header in zmq stream
|
|
#include <sstream>
|
|
#include <sys/ipc.h>
|
|
#include <sys/shm.h>
|
|
#include <sys/types.h>
|
|
|
|
#include <chrono>
|
|
#include <future>
|
|
#include <vector>
|
|
|
|
using namespace sls;
|
|
|
|
multiSlsDetector::multiSlsDetector(int multi_id, bool verify, bool update)
|
|
: multiId(multi_id), multi_shm(multi_id, -1) {
|
|
setupMultiDetector(verify, update);
|
|
}
|
|
|
|
multiSlsDetector::~multiSlsDetector() = default;
|
|
|
|
void multiSlsDetector::setupMultiDetector(bool verify, bool update) {
|
|
initSharedMemory(verify);
|
|
initializeMembers(verify);
|
|
if (update) {
|
|
updateUserdetails();
|
|
}
|
|
}
|
|
|
|
template <typename RT, typename... CT>
|
|
std::vector<RT>
|
|
multiSlsDetector::serialCall(RT (slsDetector::*somefunc)(CT...),
|
|
typename NonDeduced<CT>::type... Args) {
|
|
std::vector<RT> result;
|
|
result.reserve(detectors.size());
|
|
for (auto &d : detectors) {
|
|
result.push_back((d.get()->*somefunc)(Args...));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
template <typename RT, typename... CT>
|
|
std::vector<RT>
|
|
multiSlsDetector::serialCall(RT (slsDetector::*somefunc)(CT...) const,
|
|
typename NonDeduced<CT>::type... Args) const {
|
|
std::vector<RT> result;
|
|
result.reserve(detectors.size());
|
|
for (auto &d : detectors) {
|
|
result.push_back((d.get()->*somefunc)(Args...));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
template <typename RT, typename... CT>
|
|
std::vector<RT>
|
|
multiSlsDetector::parallelCall(RT (slsDetector::*somefunc)(CT...),
|
|
typename NonDeduced<CT>::type... Args) {
|
|
std::vector<std::future<RT>> futures;
|
|
for (auto &d : detectors) {
|
|
futures.push_back(
|
|
std::async(std::launch::async, somefunc, d.get(), Args...));
|
|
}
|
|
std::vector<RT> result;
|
|
result.reserve(detectors.size());
|
|
for (auto &i : futures) {
|
|
result.push_back(i.get());
|
|
}
|
|
return result;
|
|
}
|
|
|
|
template <typename RT, typename... CT>
|
|
std::vector<RT>
|
|
multiSlsDetector::parallelCall(RT (slsDetector::*somefunc)(CT...) const,
|
|
typename NonDeduced<CT>::type... Args) const {
|
|
std::vector<std::future<RT>> futures;
|
|
for (auto &d : detectors) {
|
|
futures.push_back(
|
|
std::async(std::launch::async, somefunc, d.get(), Args...));
|
|
}
|
|
std::vector<RT> result;
|
|
result.reserve(detectors.size());
|
|
for (auto &i : futures) {
|
|
result.push_back(i.get());
|
|
}
|
|
return result;
|
|
}
|
|
|
|
template <typename... CT>
|
|
void multiSlsDetector::parallelCall(void (slsDetector::*somefunc)(CT...),
|
|
typename NonDeduced<CT>::type... Args) {
|
|
std::vector<std::future<void>> futures;
|
|
for (auto &d : detectors) {
|
|
futures.push_back(
|
|
std::async(std::launch::async, somefunc, d.get(), Args...));
|
|
}
|
|
for (auto &i : futures) {
|
|
i.get();
|
|
}
|
|
return;
|
|
}
|
|
|
|
template <typename... CT>
|
|
void multiSlsDetector::parallelCall(
|
|
void (slsDetector::*somefunc)(CT...) const,
|
|
typename NonDeduced<CT>::type... Args) const {
|
|
std::vector<std::future<void>> futures;
|
|
for (auto &d : detectors) {
|
|
futures.push_back(
|
|
std::async(std::launch::async, somefunc, d.get(), Args...));
|
|
}
|
|
for (auto &i : futures) {
|
|
i.get();
|
|
}
|
|
return;
|
|
}
|
|
|
|
void multiSlsDetector::setAcquiringFlag(bool flag) {
|
|
multi_shm()->acquiringFlag = flag;
|
|
}
|
|
|
|
bool multiSlsDetector::getAcquiringFlag() const {
|
|
return multi_shm()->acquiringFlag;
|
|
}
|
|
|
|
void multiSlsDetector::checkDetectorVersionCompatibility(int detPos) {
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->checkDetectorVersionCompatibility();
|
|
}
|
|
|
|
parallelCall(&slsDetector::checkDetectorVersionCompatibility);
|
|
}
|
|
|
|
void multiSlsDetector::checkReceiverVersionCompatibility(int detPos) {
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->checkReceiverVersionCompatibility();
|
|
}
|
|
|
|
parallelCall(&slsDetector::checkReceiverVersionCompatibility);
|
|
}
|
|
|
|
int64_t multiSlsDetector::getId(idMode mode, int detPos) {
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getId(mode);
|
|
}
|
|
|
|
auto r = parallelCall(&slsDetector::getId, mode);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int64_t multiSlsDetector::getClientSoftwareVersion() const { return APILIB; }
|
|
|
|
int64_t multiSlsDetector::getReceiverSoftwareVersion(int detPos) {
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getReceiverSoftwareVersion();
|
|
}
|
|
|
|
auto r = parallelCall(&slsDetector::getReceiverSoftwareVersion);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
std::vector<int64_t> multiSlsDetector::getDetectorNumber() {
|
|
return parallelCall(&slsDetector::getId,
|
|
slsDetectorDefs::DETECTOR_SERIAL_NUMBER);
|
|
}
|
|
|
|
void multiSlsDetector::freeSharedMemory(int multiId, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
SharedMemory<sharedSlsDetector> temp_shm(multiId, detPos);
|
|
if (temp_shm.IsExisting()) {
|
|
temp_shm.RemoveSharedMemory();
|
|
}
|
|
return;
|
|
}
|
|
|
|
// multi - get number of detectors from shm
|
|
SharedMemory<sharedMultiSlsDetector> multiShm(multiId, -1);
|
|
int numDetectors = 0;
|
|
|
|
if (multiShm.IsExisting()) {
|
|
multiShm.OpenSharedMemory();
|
|
numDetectors = multiShm()->numberOfDetectors;
|
|
multiShm.RemoveSharedMemory();
|
|
}
|
|
|
|
for (int i = 0; i < numDetectors; ++i) {
|
|
SharedMemory<sharedSlsDetector> shm(multiId, i);
|
|
shm.RemoveSharedMemory();
|
|
}
|
|
}
|
|
|
|
void multiSlsDetector::freeSharedMemory(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->freeSharedMemory();
|
|
return;
|
|
}
|
|
|
|
// multi
|
|
zmqSocket.clear();
|
|
for (auto &d : detectors) {
|
|
d->freeSharedMemory();
|
|
}
|
|
detectors.clear();
|
|
|
|
// clear multi detector shm
|
|
multi_shm.RemoveSharedMemory();
|
|
client_downstream = false;
|
|
}
|
|
|
|
std::string multiSlsDetector::getUserDetails() {
|
|
if (detectors.empty()) {
|
|
return std::string("none");
|
|
}
|
|
|
|
std::ostringstream sstream;
|
|
sstream << "\nHostname: ";
|
|
for (auto &d : detectors) {
|
|
sstream << (d->isFixedPatternSharedMemoryCompatible() ? d->getHostname()
|
|
: "Unknown")
|
|
<< "+";
|
|
}
|
|
sstream << "\nType: ";
|
|
// 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
|
|
<< "\nUser: " << multi_shm()->lastUser
|
|
<< "\nDate: " << multi_shm()->lastDate << std::endl;
|
|
|
|
return sstream.str();
|
|
}
|
|
|
|
void multiSlsDetector::initSharedMemory(bool verify) {
|
|
if (!multi_shm.IsExisting()) {
|
|
multi_shm.CreateSharedMemory();
|
|
initializeDetectorStructure();
|
|
} else {
|
|
multi_shm.OpenSharedMemory();
|
|
if (verify && multi_shm()->shmversion != MULTI_SHMVERSION) {
|
|
FILE_LOG(logERROR) << "Multi shared memory (" << multiId
|
|
<< ") version mismatch "
|
|
"(expected 0x"
|
|
<< std::hex << MULTI_SHMVERSION << " but got 0x"
|
|
<< multi_shm()->shmversion << std::dec
|
|
<< ". Clear Shared memory to continue.";
|
|
throw SharedMemoryError("Shared memory version mismatch!");
|
|
}
|
|
}
|
|
}
|
|
|
|
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()->acquiringFlag = false;
|
|
multi_shm()->receiver_upstream = false;
|
|
}
|
|
|
|
void multiSlsDetector::initializeMembers(bool verify) {
|
|
// multiSlsDetector
|
|
zmqSocket.clear();
|
|
|
|
// get objects from single det shared memory (open)
|
|
for (int i = 0; i < multi_shm()->numberOfDetectors; i++) {
|
|
try {
|
|
detectors.push_back(
|
|
sls::make_unique<slsDetector>(multiId, i, verify));
|
|
} catch (...) {
|
|
detectors.clear();
|
|
throw;
|
|
}
|
|
}
|
|
}
|
|
|
|
void multiSlsDetector::updateUserdetails() {
|
|
multi_shm()->lastPID = getpid();
|
|
memset(multi_shm()->lastUser, 0, SHORT_STRING_LENGTH);
|
|
memset(multi_shm()->lastDate, 0, SHORT_STRING_LENGTH);
|
|
try {
|
|
sls::strcpy_safe(multi_shm()->lastUser, exec("whoami").c_str());
|
|
sls::strcpy_safe(multi_shm()->lastDate, exec("date").c_str());
|
|
} catch (...) {
|
|
sls::strcpy_safe(multi_shm()->lastUser, "errorreading");
|
|
sls::strcpy_safe(multi_shm()->lastDate, "errorreading");
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
std::string multiSlsDetector::exec(const char *cmd) {
|
|
int bufsize = 128;
|
|
char buffer[bufsize];
|
|
std::string result = "";
|
|
FILE *pipe = popen(cmd, "r");
|
|
if (pipe == nullptr) {
|
|
throw RuntimeError("Could not open pipe");
|
|
}
|
|
try {
|
|
while (feof(pipe) == 0) {
|
|
if (fgets(buffer, bufsize, pipe) != nullptr) {
|
|
result += buffer;
|
|
}
|
|
}
|
|
} catch (...) {
|
|
pclose(pipe);
|
|
throw;
|
|
}
|
|
pclose(pipe);
|
|
result.erase(result.find_last_not_of(" \t\n\r") + 1);
|
|
return result;
|
|
}
|
|
|
|
void multiSlsDetector::setVirtualDetectorServers(const int numdet,
|
|
const int port) {
|
|
std::vector<std::string> 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<std::string> &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);
|
|
}
|
|
updateDetectorSize();
|
|
}
|
|
|
|
void multiSlsDetector::setHostname(const char *name, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->setHostname(name);
|
|
return;
|
|
}
|
|
|
|
// multi
|
|
// 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();
|
|
}
|
|
addMultipleDetectors(name);
|
|
}
|
|
|
|
std::string multiSlsDetector::getHostname(int detPos) const {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getHostname();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getHostname);
|
|
return sls::concatenateNonEmptyStrings(r);
|
|
}
|
|
|
|
void multiSlsDetector::addMultipleDetectors(const char *name) {
|
|
for (const auto &hostname : sls::split(name, '+')) {
|
|
addSlsDetector(hostname);
|
|
}
|
|
updateDetectorSize();
|
|
}
|
|
|
|
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]);
|
|
}
|
|
|
|
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(host, port);
|
|
int pos = (int)detectors.size();
|
|
detectors.push_back(
|
|
sls::make_unique<slsDetector>(type, multiId, pos, false));
|
|
multi_shm()->numberOfDetectors = detectors.size();
|
|
detectors[pos]->setControlPort(port);
|
|
detectors[pos]->setStopPort(port + 1);
|
|
detectors[pos]->setHostname(host);
|
|
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();
|
|
}
|
|
|
|
int ndety = maxy / det_size.y;
|
|
int ndetx = size() / ndety;
|
|
if ((maxy % det_size.y) > 0) {
|
|
++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;
|
|
|
|
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;
|
|
}
|
|
|
|
slsDetectorDefs::detectorType
|
|
multiSlsDetector::getDetectorTypeAsEnum(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getDetectorTypeAsEnum();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getDetectorTypeAsEnum);
|
|
return (detectorType)sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::getDetectorTypeAsString(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getDetectorTypeAsString();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getDetectorTypeAsString);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
size_t multiSlsDetector::size() const { return detectors.size(); }
|
|
|
|
slsDetectorDefs::xy multiSlsDetector::getNumberOfDetectors() const {
|
|
return multi_shm()->numberOfDetector;
|
|
}
|
|
|
|
slsDetectorDefs::xy multiSlsDetector::getNumberOfChannels(int detPos) const {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getNumberOfChannels();
|
|
}
|
|
|
|
// multi
|
|
return multi_shm()->numberOfChannels;
|
|
}
|
|
|
|
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) {
|
|
int retval = detectors[0]->getQuad();
|
|
if (retval && size() > 1) {
|
|
throw RuntimeError("Quad type is available only for 1 Eiger Quad Half "
|
|
"module, but Quad is enabled for 1st readout");
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
void multiSlsDetector::setQuad(const bool enable, int detPos) {
|
|
if (enable && size() > 1) {
|
|
throw RuntimeError("Cannot set Quad type as it is available only for 1 "
|
|
"Eiger Quad Half module.");
|
|
}
|
|
|
|
detectors[0]->setQuad(enable);
|
|
}
|
|
|
|
void multiSlsDetector::setReadNLines(const int value, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->setReadNLines(value);
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::setReadNLines, value);
|
|
}
|
|
|
|
int multiSlsDetector::getReadNLines(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getReadNLines();
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::getReadNLines);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setControlPort(int port_number, int detPos) {
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setControlPort(port_number);
|
|
}
|
|
|
|
auto r = serialCall(&slsDetector::setControlPort, port_number);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setStopPort(int port_number, int detPos) {
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setStopPort(port_number);
|
|
}
|
|
|
|
auto r = serialCall(&slsDetector::setStopPort, port_number);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setReceiverPort(int port_number, int detPos) {
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setReceiverPort(port_number);
|
|
}
|
|
|
|
auto r = serialCall(&slsDetector::setReceiverPort, port_number);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::getReceiverPort(int detPos) const {
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getReceiverPort();
|
|
}
|
|
|
|
auto r = serialCall(&slsDetector::getReceiverPort);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::lockServer(int p, int detPos) {
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->lockServer(p);
|
|
}
|
|
auto r = parallelCall(&slsDetector::lockServer, p);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::getLastClientIP(int detPos) {
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getLastClientIP();
|
|
}
|
|
auto r = parallelCall(&slsDetector::getLastClientIP);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
void multiSlsDetector::exitServer(int detPos) {
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->exitServer();
|
|
}
|
|
parallelCall(&slsDetector::exitServer);
|
|
}
|
|
|
|
void multiSlsDetector::execCommand(const std::string &cmd, int detPos) {
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->execCommand(cmd);
|
|
}
|
|
parallelCall(&slsDetector::execCommand, cmd);
|
|
}
|
|
|
|
void multiSlsDetector::readConfigurationFile(const std::string &fname) {
|
|
freeSharedMemory();
|
|
setupMultiDetector();
|
|
FILE_LOG(logINFO) << "Loading configuration file: " << fname;
|
|
|
|
std::ifstream input_file;
|
|
input_file.open(fname, std::ios_base::in);
|
|
if (!input_file.is_open()) {
|
|
throw RuntimeError("Could not open configuration file " + fname +
|
|
" for reading");
|
|
}
|
|
std::string current_line;
|
|
while (input_file.good()) {
|
|
getline(input_file, current_line);
|
|
if (current_line.find('#') != std::string::npos) {
|
|
current_line.erase(current_line.find('#'));
|
|
}
|
|
FILE_LOG(logDEBUG1)
|
|
<< "current_line after removing comments:\n\t" << current_line;
|
|
if (current_line.length() > 1) {
|
|
multiSlsDetectorClient(current_line, PUT_ACTION, this);
|
|
}
|
|
}
|
|
input_file.close();
|
|
}
|
|
|
|
void multiSlsDetector::writeConfigurationFile(const std::string &fname) {
|
|
// TODO! make exception safe!
|
|
const std::vector<std::string> header{"detsizechan", "hostname"};
|
|
std::ofstream outfile;
|
|
|
|
outfile.open(fname.c_str(), std::ios_base::out);
|
|
if (outfile.is_open()) {
|
|
for (const auto &cmd : header)
|
|
multiSlsDetectorClient(cmd, GET_ACTION, this, outfile);
|
|
|
|
// single detector configuration
|
|
for (auto &detector : detectors) {
|
|
outfile << '\n';
|
|
auto det_commands = detector->getConfigFileCommands();
|
|
for (const auto &cmd : det_commands)
|
|
multiSlsDetectorClient(cmd, GET_ACTION, this, outfile);
|
|
}
|
|
} else {
|
|
throw RuntimeError("Could not open configuration file " + fname +
|
|
" for writing");
|
|
}
|
|
}
|
|
|
|
slsDetectorDefs::detectorSettings multiSlsDetector::getSettings(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getSettings();
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::getSettings);
|
|
return (detectorSettings)sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
slsDetectorDefs::detectorSettings
|
|
multiSlsDetector::setSettings(detectorSettings isettings, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setSettings(isettings);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setSettings, isettings);
|
|
return (detectorSettings)sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::getThresholdEnergy(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getThresholdEnergy();
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::getThresholdEnergy);
|
|
if (sls::allEqualWithTol(r, 200)) {
|
|
return r.front();
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int multiSlsDetector::setThresholdEnergy(int e_eV, detectorSettings isettings,
|
|
int tb, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setThresholdEnergy(e_eV, isettings, tb);
|
|
}
|
|
|
|
// multi
|
|
auto r =
|
|
parallelCall(&slsDetector::setThresholdEnergy, e_eV, isettings, tb);
|
|
if (sls::allEqualWithTol(r, 200)) {
|
|
return r.front();
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
std::string multiSlsDetector::getSettingsDir(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getSettingsDir();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getSettingsDir);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::setSettingsDir(const std::string &directory,
|
|
int detPos) {
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setSettingsDir(directory);
|
|
}
|
|
|
|
auto r = parallelCall(&slsDetector::setSettingsDir, directory);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
void multiSlsDetector::loadSettingsFile(const std::string &fname, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->loadSettingsFile(fname);
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::loadSettingsFile, fname);
|
|
}
|
|
|
|
void multiSlsDetector::saveSettingsFile(const std::string &fname, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->saveSettingsFile(fname);
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::saveSettingsFile, fname);
|
|
}
|
|
|
|
slsDetectorDefs::runStatus multiSlsDetector::getRunStatus(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getRunStatus();
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::getRunStatus);
|
|
if (sls::allEqual(r)) {
|
|
return r.front();
|
|
}
|
|
if (sls::anyEqualTo(r, ERROR)) {
|
|
return ERROR;
|
|
}
|
|
for (const auto &value : r) {
|
|
if (value != IDLE) {
|
|
return value;
|
|
}
|
|
}
|
|
return IDLE;
|
|
}
|
|
|
|
void multiSlsDetector::prepareAcquisition(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->prepareAcquisition();
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::prepareAcquisition);
|
|
}
|
|
|
|
void multiSlsDetector::startAcquisition(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
if (detectors[detPos]->getDetectorTypeAsEnum() == EIGER) {
|
|
detectors[detPos]->prepareAcquisition();
|
|
}
|
|
detectors[detPos]->startAcquisition();
|
|
}
|
|
|
|
// multi
|
|
if (getDetectorTypeAsEnum() == EIGER) {
|
|
prepareAcquisition();
|
|
}
|
|
parallelCall(&slsDetector::startAcquisition);
|
|
}
|
|
|
|
void multiSlsDetector::stopAcquisition(int detPos) {
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->stopAcquisition();
|
|
} else {
|
|
parallelCall(&slsDetector::stopAcquisition);
|
|
}
|
|
}
|
|
|
|
void multiSlsDetector::sendSoftwareTrigger(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->sendSoftwareTrigger();
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::sendSoftwareTrigger);
|
|
}
|
|
|
|
void multiSlsDetector::startAndReadAll(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
if (detectors[detPos]->getDetectorTypeAsEnum() == EIGER) {
|
|
detectors[detPos]->prepareAcquisition();
|
|
}
|
|
detectors[detPos]->startAndReadAll();
|
|
}
|
|
|
|
// multi
|
|
if (getDetectorTypeAsEnum() == EIGER) {
|
|
prepareAcquisition();
|
|
}
|
|
parallelCall(&slsDetector::startAndReadAll);
|
|
}
|
|
|
|
void multiSlsDetector::startReadOut(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->startReadOut();
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::startReadOut);
|
|
}
|
|
|
|
void multiSlsDetector::readAll(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->readAll();
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::readAll);
|
|
}
|
|
|
|
void multiSlsDetector::configureMAC(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->configureMAC();
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::configureMAC);
|
|
}
|
|
|
|
void multiSlsDetector::setStartingFrameNumber(const uint64_t value,
|
|
int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setStartingFrameNumber(value);
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::setStartingFrameNumber, value);
|
|
}
|
|
|
|
uint64_t multiSlsDetector::getStartingFrameNumber(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getStartingFrameNumber();
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::getStartingFrameNumber);
|
|
if (sls::allEqual(r)) {
|
|
return r.front();
|
|
}
|
|
|
|
// can't have different values for next acquisition
|
|
std::ostringstream ss;
|
|
ss << "Error: Different Values for starting frame number";
|
|
throw RuntimeError(ss.str());
|
|
}
|
|
|
|
int64_t multiSlsDetector::setTimer(timerIndex index, int64_t t, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setTimer(index, t);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setTimer, index, t);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int64_t multiSlsDetector::secondsToNanoSeconds(double t) {
|
|
int64_t ns = lround(t * 1E9);
|
|
return (ns < 0) ? -1 : ns;
|
|
}
|
|
|
|
double multiSlsDetector::setExposureTime(double t, bool inseconds, int detPos) {
|
|
if (!inseconds) {
|
|
return setTimer(ACQUISITION_TIME, (int64_t)t, detPos);
|
|
}
|
|
auto t_ns = setTimer(ACQUISITION_TIME, secondsToNanoSeconds(t), detPos);
|
|
return (t_ns < 0) ? -1 : 1E-9 * t_ns;
|
|
}
|
|
|
|
double multiSlsDetector::setExposurePeriod(double t, bool inseconds,
|
|
int detPos) {
|
|
if (!inseconds) {
|
|
return setTimer(FRAME_PERIOD, (int64_t)t, detPos);
|
|
}
|
|
auto t_ns = setTimer(FRAME_PERIOD, secondsToNanoSeconds(t), detPos);
|
|
return (t_ns < 0) ? -1 : 1E-9 * t_ns;
|
|
}
|
|
|
|
double multiSlsDetector::setDelayAfterTrigger(double t, bool inseconds,
|
|
int detPos) {
|
|
if (!inseconds) {
|
|
return setTimer(DELAY_AFTER_TRIGGER, (int64_t)t, detPos);
|
|
}
|
|
auto t_ns = setTimer(DELAY_AFTER_TRIGGER, secondsToNanoSeconds(t), detPos);
|
|
return (t_ns < 0) ? -1 : 1E-9 * t_ns;
|
|
}
|
|
|
|
double multiSlsDetector::setSubFrameExposureTime(double t, bool inseconds,
|
|
int detPos) {
|
|
if (!inseconds) {
|
|
return setTimer(SUBFRAME_ACQUISITION_TIME, (int64_t)t, detPos);
|
|
}
|
|
auto t_ns =
|
|
setTimer(SUBFRAME_ACQUISITION_TIME, secondsToNanoSeconds(t), detPos);
|
|
return (t_ns < 0) ? -1 : 1E-9 * t_ns;
|
|
}
|
|
|
|
double multiSlsDetector::setSubFrameExposureDeadTime(double t, bool inseconds,
|
|
int detPos) {
|
|
if (!inseconds) {
|
|
return setTimer(SUBFRAME_DEADTIME, (int64_t)t, detPos);
|
|
}
|
|
auto t_ns = setTimer(SUBFRAME_DEADTIME, secondsToNanoSeconds(t), detPos);
|
|
return (t_ns < 0) ? -1 : 1E-9 * t_ns;
|
|
}
|
|
|
|
int64_t multiSlsDetector::setNumberOfFrames(int64_t t, int detPos) {
|
|
return setTimer(FRAME_NUMBER, t, detPos);
|
|
}
|
|
|
|
int64_t multiSlsDetector::setNumberOfCycles(int64_t t, int detPos) {
|
|
return setTimer(CYCLES_NUMBER, t, detPos);
|
|
}
|
|
|
|
int64_t multiSlsDetector::setNumberOfStorageCells(int64_t t, int detPos) {
|
|
return setTimer(STORAGE_CELL_NUMBER, t, detPos);
|
|
}
|
|
|
|
double multiSlsDetector::getMeasuredPeriod(bool inseconds, int detPos) {
|
|
if (!inseconds) {
|
|
return getTimeLeft(MEASURED_PERIOD, detPos);
|
|
} else {
|
|
int64_t tms = getTimeLeft(MEASURED_PERIOD, detPos);
|
|
if (tms < 0) {
|
|
return -1;
|
|
}
|
|
return ((1E-9) * (double)tms);
|
|
}
|
|
}
|
|
|
|
double multiSlsDetector::getMeasuredSubFramePeriod(bool inseconds, int detPos) {
|
|
if (!inseconds) {
|
|
return getTimeLeft(MEASURED_SUBPERIOD, detPos);
|
|
} else {
|
|
int64_t tms = getTimeLeft(MEASURED_SUBPERIOD, detPos);
|
|
if (tms < 0) {
|
|
return -1;
|
|
}
|
|
return ((1E-9) * (double)tms);
|
|
}
|
|
}
|
|
|
|
int64_t multiSlsDetector::getTimeLeft(timerIndex index, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getTimeLeft(index);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::getTimeLeft, index);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setSpeed(speedVariable index, int value, int mode,
|
|
int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setSpeed(index, value, mode);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setSpeed, index, value, mode);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setDynamicRange(int dr, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
throw RuntimeError("Dynamic Range cannot be set individually");
|
|
}
|
|
|
|
// 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);
|
|
|
|
// change in dr
|
|
if (dr != -1 && dr != prevValue) {
|
|
|
|
// update speed, check ratecorrection
|
|
if (getDetectorTypeAsEnum() == EIGER) {
|
|
|
|
// rate correction before speed for consistency
|
|
// (else exception at speed makes ratecorr inconsistent)
|
|
parallelCall(&slsDetector::updateRateCorrection);
|
|
|
|
// speed(usability)
|
|
switch (dr) {
|
|
case 32:
|
|
FILE_LOG(logINFO)
|
|
<< "Setting Clock to Quarter Speed to cope with "
|
|
"Dynamic Range of 32";
|
|
setSpeed(CLOCK_DIVIDER, 2);
|
|
break;
|
|
case 16:
|
|
FILE_LOG(logINFO)
|
|
<< "Setting Clock to Half Speed for Dynamic Range of 16";
|
|
setSpeed(CLOCK_DIVIDER, 1);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int multiSlsDetector::setDAC(int val, dacIndex index, int mV, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setDAC(val, index, mV);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setDAC, val, index, mV);
|
|
if (getDetectorTypeAsEnum() != EIGER && index != HIGH_VOLTAGE) {
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
// ignore slave values for hv (-999)
|
|
int firstValue = r.front();
|
|
for (const auto &value : r) {
|
|
if ((value != -999) && (value != firstValue)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return firstValue;
|
|
}
|
|
|
|
int multiSlsDetector::getADC(dacIndex index, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getADC(index);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::getADC, index);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
slsDetectorDefs::timingMode multiSlsDetector::setTimingMode(timingMode pol,
|
|
int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setTimingMode(pol);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setTimingMode, pol);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
slsDetectorDefs::externalSignalFlag
|
|
multiSlsDetector::setExternalSignalFlags(externalSignalFlag pol, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setExternalSignalFlags(pol);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setExternalSignalFlags, pol);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setReadOutFlags(readOutFlags flag, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setReadOutFlags(flag);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setReadOutFlags, flag);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
void multiSlsDetector::setInterruptSubframe(const bool enable, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->setInterruptSubframe(enable);
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::setInterruptSubframe, enable);
|
|
}
|
|
|
|
int multiSlsDetector::getInterruptSubframe(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return static_cast<int>(detectors[detPos]->getInterruptSubframe());
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::getInterruptSubframe);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
uint32_t multiSlsDetector::writeRegister(uint32_t addr, uint32_t val,
|
|
int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->writeRegister(addr, val);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::writeRegister, addr, val);
|
|
if (sls::allEqual(r)) {
|
|
return r.front();
|
|
}
|
|
|
|
// can't have different values
|
|
std::ostringstream ss;
|
|
ss << "Error: Different Values for function writeRegister (write 0x"
|
|
<< std::hex << val << " to addr 0x" << std::hex << addr << std::dec
|
|
<< ")";
|
|
throw RuntimeError(ss.str());
|
|
}
|
|
|
|
uint32_t multiSlsDetector::readRegister(uint32_t addr, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->readRegister(addr);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::readRegister, addr);
|
|
if (sls::allEqual(r)) {
|
|
return r.front();
|
|
}
|
|
|
|
// can't have different values
|
|
std::ostringstream ss;
|
|
ss << "Error: Different Values for function readRegister (read from 0x"
|
|
<< std::hex << addr << std::dec << ")";
|
|
throw RuntimeError(ss.str());
|
|
}
|
|
|
|
uint32_t multiSlsDetector::setBit(uint32_t addr, int n, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setBit(addr, n);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setBit, addr, n);
|
|
if (sls::allEqual(r)) {
|
|
return r.front();
|
|
}
|
|
|
|
// can't have different values
|
|
std::ostringstream ss;
|
|
ss << "Error: Different Values for function setBit "
|
|
"(set bit "
|
|
<< n << " to addr 0x" << std::hex << addr << std::dec << ")";
|
|
throw RuntimeError(ss.str());
|
|
}
|
|
|
|
uint32_t multiSlsDetector::clearBit(uint32_t addr, int n, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->clearBit(addr, n);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::clearBit, addr, n);
|
|
if (sls::allEqual(r)) {
|
|
return r.front();
|
|
}
|
|
|
|
// can't have different values
|
|
std::ostringstream ss;
|
|
ss << "Error: Different Values for function clearBit (clear bit " << n
|
|
<< " to addr 0x" << std::hex << addr << std::dec << ")";
|
|
throw RuntimeError(ss.str());
|
|
}
|
|
|
|
std::string multiSlsDetector::setDetectorMAC(const std::string &detectorMAC,
|
|
int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setDetectorMAC(detectorMAC);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setDetectorMAC, detectorMAC);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::getDetectorMAC(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getDetectorMAC().str();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getDetectorMAC);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::setDetectorMAC2(const std::string &detectorMAC,
|
|
int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setDetectorMAC2(detectorMAC);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setDetectorMAC2, detectorMAC);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::getDetectorMAC2(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getDetectorMAC2().str();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getDetectorMAC2);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::setDetectorIP(const std::string &detectorIP,
|
|
int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setDetectorIP(detectorIP);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setDetectorIP, detectorIP);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::getDetectorIP(int detPos) const {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getDetectorIP().str();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getDetectorIP);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::setDetectorIP2(const std::string &detectorIP,
|
|
int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setDetectorIP2(detectorIP);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setDetectorIP2, detectorIP);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::getDetectorIP2(int detPos) const {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getDetectorIP2().str();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getDetectorIP2);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::setReceiverHostname(const std::string &receiver,
|
|
int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setReceiverHostname(receiver);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setReceiverHostname, receiver);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::getReceiverHostname(int detPos) const {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getReceiverHostname();
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::getReceiverHostname);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::setReceiverUDPIP(const std::string &udpip,
|
|
int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setReceiverUDPIP(udpip);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setReceiverUDPIP, udpip);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::getReceiverUDPIP(int detPos) const {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getReceiverUDPIP().str();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getReceiverUDPIP);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::setReceiverUDPIP2(const std::string &udpip,
|
|
int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setReceiverUDPIP2(udpip);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setReceiverUDPIP2, udpip);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::getReceiverUDPIP2(int detPos) const {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getReceiverUDPIP2().str();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getReceiverUDPIP2);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::setReceiverUDPMAC(const std::string &udpmac,
|
|
int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setReceiverUDPMAC(udpmac);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setReceiverUDPMAC, udpmac);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::getReceiverUDPMAC(int detPos) const {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getReceiverUDPMAC().str();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getReceiverUDPMAC);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::setReceiverUDPMAC2(const std::string &udpmac,
|
|
int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setReceiverUDPMAC2(udpmac);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setReceiverUDPMAC2, udpmac);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::getReceiverUDPMAC2(int detPos) const {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getReceiverUDPMAC2().str();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getReceiverUDPMAC2);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setReceiverUDPPort(int udpport, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setReceiverUDPPort(udpport);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setReceiverUDPPort, udpport);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::getReceiverUDPPort(int detPos) const {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getReceiverUDPPort();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getReceiverUDPPort);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setReceiverUDPPort2(int udpport, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setReceiverUDPPort2(udpport);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setReceiverUDPPort2, udpport);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::getReceiverUDPPort2(int detPos) const {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getReceiverUDPPort2();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getReceiverUDPPort2);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setNumberofUDPInterfaces(int n, int detPos) {
|
|
|
|
bool previouslyClientStreaming = enableDataStreamingToClient();
|
|
int previouslyReceiverStreaming = enableDataStreamingFromReceiver();
|
|
|
|
// single
|
|
int ret = OK;
|
|
if (detPos >= 0) {
|
|
ret = detectors[detPos]->setNumberofUDPInterfaces(n);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setNumberofUDPInterfaces, n);
|
|
|
|
// redo the zmq sockets
|
|
if (previouslyClientStreaming) {
|
|
enableDataStreamingToClient(0);
|
|
enableDataStreamingToClient(1);
|
|
}
|
|
if (previouslyReceiverStreaming != 0) {
|
|
enableDataStreamingFromReceiver(0);
|
|
enableDataStreamingFromReceiver(1);
|
|
}
|
|
|
|
// return single
|
|
if (detPos >= 0)
|
|
return ret;
|
|
|
|
// return multi
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::getNumberofUDPInterfaces(int detPos) const {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getNumberofUDPInterfaces();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getNumberofUDPInterfaces);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::selectUDPInterface(int n, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->selectUDPInterface(n);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::selectUDPInterface, n);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::getSelectedUDPInterface(int detPos) const {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getSelectedUDPInterface();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getSelectedUDPInterface);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
void multiSlsDetector::setClientDataStreamingInPort(int i, int detPos) {
|
|
if (i >= 0) {
|
|
bool prev_streaming = enableDataStreamingToClient();
|
|
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->setClientStreamingPort(i);
|
|
}
|
|
// multi
|
|
else {
|
|
// calculate ports individually
|
|
int firstPort = i;
|
|
int numSockets = (getDetectorTypeAsEnum() == EIGER) ? 2 : 1;
|
|
if (getNumberofUDPInterfaces() == 2)
|
|
numSockets *= 2;
|
|
|
|
for (size_t idet = 0; idet < detectors.size(); ++idet) {
|
|
auto port = firstPort + (idet * numSockets);
|
|
detectors[idet]->setClientStreamingPort(port);
|
|
}
|
|
}
|
|
|
|
if (prev_streaming) {
|
|
enableDataStreamingToClient(0);
|
|
enableDataStreamingToClient(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
int multiSlsDetector::getClientStreamingPort(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getClientStreamingPort();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getClientStreamingPort);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
void multiSlsDetector::setReceiverDataStreamingOutPort(int i, int detPos) {
|
|
if (i >= 0) {
|
|
int prev_streaming = enableDataStreamingFromReceiver(-1, detPos);
|
|
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->setReceiverStreamingPort(i);
|
|
}
|
|
// multi
|
|
else {
|
|
// calculate ports individually
|
|
int firstPort = i;
|
|
int numSockets = (getDetectorTypeAsEnum() == EIGER) ? 2 : 1;
|
|
if (getNumberofUDPInterfaces() == 2)
|
|
numSockets *= 2;
|
|
|
|
for (size_t idet = 0; idet < detectors.size(); ++idet) {
|
|
auto port = firstPort + (idet * numSockets);
|
|
detectors[idet]->setReceiverStreamingPort(port);
|
|
}
|
|
}
|
|
|
|
if (prev_streaming != 0) {
|
|
enableDataStreamingFromReceiver(0, detPos);
|
|
enableDataStreamingFromReceiver(1, detPos);
|
|
}
|
|
}
|
|
}
|
|
|
|
int multiSlsDetector::getReceiverStreamingPort(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getReceiverStreamingPort();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getReceiverStreamingPort);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
void multiSlsDetector::setClientDataStreamingInIP(const std::string &ip,
|
|
int detPos) {
|
|
if (ip.length() != 0u) {
|
|
bool prev_streaming = enableDataStreamingToClient(-1);
|
|
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->setClientStreamingIP(ip);
|
|
}
|
|
// multi
|
|
else {
|
|
for (auto &d : detectors) {
|
|
d->setClientStreamingIP(ip);
|
|
}
|
|
}
|
|
|
|
if (prev_streaming) {
|
|
enableDataStreamingToClient(0);
|
|
enableDataStreamingToClient(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
std::string multiSlsDetector::getClientStreamingIP(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getClientStreamingIP();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getClientStreamingIP);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
void multiSlsDetector::setReceiverDataStreamingOutIP(const std::string &ip,
|
|
int detPos) {
|
|
if (ip.length() != 0u) {
|
|
int prev_streaming = enableDataStreamingFromReceiver(-1, detPos);
|
|
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->setReceiverStreamingIP(ip);
|
|
}
|
|
// multi
|
|
else {
|
|
for (auto &d : detectors) {
|
|
d->setReceiverStreamingIP(ip);
|
|
}
|
|
}
|
|
|
|
if (prev_streaming != 0) {
|
|
enableDataStreamingFromReceiver(0, detPos);
|
|
enableDataStreamingFromReceiver(1, detPos);
|
|
}
|
|
}
|
|
}
|
|
|
|
std::string multiSlsDetector::getReceiverStreamingIP(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getReceiverStreamingIP();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getReceiverStreamingIP);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setDetectorNetworkParameter(networkParameter index,
|
|
int value, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setDetectorNetworkParameter(index, value);
|
|
}
|
|
|
|
// multi
|
|
auto r =
|
|
parallelCall(&slsDetector::setDetectorNetworkParameter, index, value);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
std::string
|
|
multiSlsDetector::setAdditionalJsonHeader(const std::string &jsonheader,
|
|
int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setAdditionalJsonHeader(jsonheader);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setAdditionalJsonHeader, jsonheader);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::getAdditionalJsonHeader(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getAdditionalJsonHeader();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getAdditionalJsonHeader);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::setAdditionalJsonParameter(
|
|
const std::string &key, const std::string &value, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setAdditionalJsonParameter(key, value);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setAdditionalJsonParameter, key, value);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::getAdditionalJsonParameter(const std::string &key,
|
|
int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getAdditionalJsonParameter(key);
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getAdditionalJsonParameter, key);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setDetectorMinMaxEnergyThreshold(const int index,
|
|
int value, int detPos) {
|
|
std::string parameter = (index != 0 ? "emax" : "emin");
|
|
|
|
std::string result;
|
|
if (value < 0) {
|
|
result = getAdditionalJsonParameter(parameter, detPos);
|
|
} else {
|
|
result = setAdditionalJsonParameter(parameter, std::to_string(value),
|
|
detPos);
|
|
}
|
|
|
|
// convert to integer
|
|
try {
|
|
return stoi(result);
|
|
}
|
|
// not found or cannot scan integer
|
|
catch (...) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int multiSlsDetector::setFrameMode(frameModeType value, int detPos) {
|
|
std::string parameter = "frameMode";
|
|
std::string result;
|
|
|
|
if (value == GET_FRAME_MODE) {
|
|
result = getAdditionalJsonParameter(parameter, detPos);
|
|
} else {
|
|
result = setAdditionalJsonParameter(parameter, getFrameModeType(value),
|
|
detPos);
|
|
}
|
|
|
|
return getFrameModeType(result);
|
|
}
|
|
|
|
int multiSlsDetector::setDetectorMode(detectorModeType value, int detPos) {
|
|
std::string parameter = "detectorMode";
|
|
std::string result;
|
|
|
|
if (value == GET_DETECTOR_MODE) {
|
|
result = getAdditionalJsonParameter(parameter, detPos);
|
|
} else {
|
|
result = setAdditionalJsonParameter(parameter,
|
|
getDetectorModeType(value), detPos);
|
|
}
|
|
|
|
return getDetectorModeType(result);
|
|
}
|
|
|
|
int64_t multiSlsDetector::setReceiverUDPSocketBufferSize(int64_t udpsockbufsize,
|
|
int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setReceiverUDPSocketBufferSize(
|
|
udpsockbufsize);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setReceiverUDPSocketBufferSize,
|
|
udpsockbufsize);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int64_t multiSlsDetector::getReceiverUDPSocketBufferSize(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getReceiverUDPSocketBufferSize();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getReceiverUDPSocketBufferSize);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int64_t multiSlsDetector::getReceiverRealUDPSocketBufferSize(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getReceiverRealUDPSocketBufferSize();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getReceiverRealUDPSocketBufferSize);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setFlowControl10G(int enable, int detPos) {
|
|
if (enable != -1) {
|
|
enable = ((enable >= 1) ? 1 : 0);
|
|
}
|
|
return setDetectorNetworkParameter(FLOW_CONTROL_10G, enable, detPos);
|
|
}
|
|
|
|
int multiSlsDetector::digitalTest(digitalTestMode mode, int ival, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->digitalTest(mode, ival);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::digitalTest, mode, ival);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setCounterBit(int i, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setCounterBit(i);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setCounterBit, i);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
void multiSlsDetector::clearROI(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->clearROI();
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::clearROI);
|
|
}
|
|
|
|
void multiSlsDetector::setROI(slsDetectorDefs::ROI arg, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->setROI(arg);
|
|
}
|
|
|
|
// multi
|
|
if (detPos < 0 && size() > 1) {
|
|
throw RuntimeError("Cannot set ROI for all modules simultaneously");
|
|
}
|
|
detectors[0]->setROI(arg);
|
|
}
|
|
|
|
slsDetectorDefs::ROI multiSlsDetector::getROI(int detPos) const {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getROI();
|
|
}
|
|
|
|
// multi
|
|
if (detPos < 0 && size() > 1) {
|
|
throw RuntimeError("Cannot get ROI for all modules simultaneously");
|
|
}
|
|
return detectors[0]->getROI();
|
|
}
|
|
|
|
void multiSlsDetector::setADCEnableMask(uint32_t mask, int detPos) {
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->setADCEnableMask(mask);
|
|
}
|
|
|
|
parallelCall(&slsDetector::setADCEnableMask, mask);
|
|
}
|
|
|
|
uint32_t multiSlsDetector::getADCEnableMask(int detPos) {
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getADCEnableMask();
|
|
}
|
|
|
|
auto r = parallelCall(&slsDetector::getADCEnableMask);
|
|
if (sls::allEqual(r)) {
|
|
return r.front();
|
|
}
|
|
|
|
// can't have different values
|
|
throw RuntimeError("Error: Different Values for function getADCEnableMask");
|
|
}
|
|
|
|
void multiSlsDetector::setADCInvert(uint32_t value, int detPos) {
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->setADCInvert(value);
|
|
}
|
|
|
|
parallelCall(&slsDetector::setADCInvert, value);
|
|
}
|
|
|
|
uint32_t multiSlsDetector::getADCInvert(int detPos) {
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getADCInvert();
|
|
}
|
|
|
|
auto r = parallelCall(&slsDetector::getADCInvert);
|
|
if (sls::allEqual(r)) {
|
|
return r.front();
|
|
}
|
|
|
|
// can't have different values
|
|
throw RuntimeError("Error: Different Values for function getADCInvert");
|
|
}
|
|
|
|
void multiSlsDetector::setExternalSamplingSource(int value, int detPos) {
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->setExternalSamplingSource(value);
|
|
}
|
|
|
|
parallelCall(&slsDetector::setExternalSamplingSource, value);
|
|
}
|
|
|
|
int multiSlsDetector::getExternalSamplingSource(int detPos) {
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getExternalSamplingSource();
|
|
}
|
|
|
|
auto r = parallelCall(&slsDetector::getExternalSamplingSource);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
void multiSlsDetector::setExternalSampling(bool value, int detPos) {
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->setExternalSampling(static_cast<int>(value));
|
|
}
|
|
|
|
parallelCall(&slsDetector::setExternalSampling, static_cast<int>(value));
|
|
}
|
|
|
|
int multiSlsDetector::getExternalSampling(int detPos) {
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getExternalSampling();
|
|
}
|
|
|
|
auto r = parallelCall(&slsDetector::getExternalSampling);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
void multiSlsDetector::setReceiverDbitList(std::vector<int> list, int detPos) {
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->setReceiverDbitList(list);
|
|
}
|
|
|
|
parallelCall(&slsDetector::setReceiverDbitList, list);
|
|
}
|
|
|
|
std::vector<int> multiSlsDetector::getReceiverDbitList(int detPos) {
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getReceiverDbitList();
|
|
}
|
|
|
|
auto r = parallelCall(&slsDetector::getReceiverDbitList);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
void multiSlsDetector::setReceiverDbitOffset(int value, int detPos) {
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->setReceiverDbitOffset(value);
|
|
}
|
|
|
|
parallelCall(&slsDetector::setReceiverDbitOffset, value);
|
|
}
|
|
|
|
int multiSlsDetector::getReceiverDbitOffset(int detPos) {
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getReceiverDbitOffset();
|
|
}
|
|
|
|
auto r = parallelCall(&slsDetector::getReceiverDbitOffset);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
void multiSlsDetector::writeAdcRegister(uint32_t addr, uint32_t val,
|
|
int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->writeAdcRegister(addr, val);
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::writeAdcRegister, addr, val);
|
|
}
|
|
|
|
int multiSlsDetector::activate(int const enable, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->activate(enable);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::activate, enable);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setDeactivatedRxrPaddingMode(int padding, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return static_cast<int>(
|
|
detectors[detPos]->setDeactivatedRxrPaddingMode(padding));
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setDeactivatedRxrPaddingMode, padding);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::getFlippedDataX(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getFlippedDataX();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getFlippedDataX);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setFlippedDataX(int value, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setFlippedDataX(value);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setFlippedDataX, value);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setAllTrimbits(int val, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setAllTrimbits(val);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setAllTrimbits, val);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::enableGapPixels(int val, int detPos) {
|
|
if (getDetectorTypeAsEnum() != EIGER) {
|
|
if (val >= 0) {
|
|
throw NotImplementedError(
|
|
"Function (enableGapPixels) not implemented for this detector");
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// single
|
|
if (detPos >= 0) {
|
|
if (val >= 0) {
|
|
throw RuntimeError("Function (enableGapPixels) must be called from "
|
|
"a multi detector level.");
|
|
}
|
|
return detectors[detPos]->enableGapPixels(val);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::enableGapPixels, val);
|
|
int ret = sls::minusOneIfDifferent(r);
|
|
|
|
if (val != -1) {
|
|
Parallel(&slsDetector::enableGapPixels, {}, val);
|
|
Result<slsDetectorDefs::xy> 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<int>(enable));
|
|
Result<slsDetectorDefs::xy> 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<int> energies, int detPos) {
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setTrimEn(energies);
|
|
}
|
|
auto r = parallelCall(&slsDetector::setTrimEn, energies);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
std::vector<int> multiSlsDetector::getTrimEn(int detPos) {
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getTrimEn();
|
|
}
|
|
auto r = parallelCall(&slsDetector::getTrimEn);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
void multiSlsDetector::pulsePixel(int n, int x, int y, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->pulsePixel(n, x, y);
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::pulsePixel, n, x, y);
|
|
}
|
|
|
|
void multiSlsDetector::pulsePixelNMove(int n, int x, int y, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->pulsePixelNMove(n, x, y);
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::pulsePixelNMove, n, x, y);
|
|
}
|
|
|
|
void multiSlsDetector::pulseChip(int n, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->pulseChip(n);
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::pulseChip, n);
|
|
}
|
|
|
|
int multiSlsDetector::setThresholdTemperature(int val, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setThresholdTemperature(val);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setThresholdTemperature, val);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setTemperatureControl(int val, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setTemperatureControl(val);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setTemperatureControl, val);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setTemperatureEvent(int val, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setTemperatureEvent(val);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setTemperatureEvent, val);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setStoragecellStart(int pos, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setStoragecellStart(pos);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setStoragecellStart, pos);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
void multiSlsDetector::programFPGA(const std::string &fname, int detPos) {
|
|
FILE_LOG(logINFO) << "This can take awhile. Please be patient...";
|
|
// read pof file
|
|
std::vector<char> buffer = readPofFile(fname);
|
|
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->programFPGA(buffer);
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::programFPGA, buffer);
|
|
}
|
|
|
|
void multiSlsDetector::resetFPGA(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->resetFPGA();
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::resetFPGA);
|
|
}
|
|
|
|
void multiSlsDetector::copyDetectorServer(const std::string &fname,
|
|
const std::string &hostname,
|
|
int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->copyDetectorServer(fname, hostname);
|
|
detectors[detPos]->rebootController();
|
|
// reboot and copy should be independant for
|
|
// update command
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::copyDetectorServer, fname, hostname);
|
|
parallelCall(&slsDetector::rebootController);
|
|
}
|
|
|
|
void multiSlsDetector::rebootController(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->rebootController();
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::rebootController);
|
|
}
|
|
|
|
void multiSlsDetector::update(const std::string &sname,
|
|
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<char> buffer = readPofFile(fname);
|
|
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->copyDetectorServer(sname, hostname);
|
|
detectors[detPos]->programFPGA(buffer);
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::copyDetectorServer, sname, hostname);
|
|
parallelCall(&slsDetector::programFPGA, buffer);
|
|
}
|
|
|
|
int multiSlsDetector::powerChip(int ival, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->powerChip(ival);
|
|
}
|
|
|
|
// multi delayed call for safety
|
|
if (ival >= 0 && size() > 3) {
|
|
std::vector<int> r;
|
|
r.reserve(detectors.size());
|
|
for (auto &d : detectors) {
|
|
r.push_back(d->powerChip(ival));
|
|
usleep(1000 * 1000);
|
|
}
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
// multi parallel
|
|
auto r = parallelCall(&slsDetector::powerChip, ival);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setAutoComparatorDisableMode(int ival, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setAutoComparatorDisableMode(ival);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setAutoComparatorDisableMode, ival);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
void multiSlsDetector::setDefaultRateCorrection(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->setDefaultRateCorrection();
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::setDefaultRateCorrection);
|
|
}
|
|
|
|
void multiSlsDetector::setRateCorrection(int64_t t, int detPos) {
|
|
if (t < 0) {
|
|
throw sls::RuntimeError("Dead time has to be greater or equal to 0");
|
|
}
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->setRateCorrection(t);
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::setRateCorrection, t);
|
|
}
|
|
|
|
int64_t multiSlsDetector::getRateCorrection(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getRateCorrection();
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::getRateCorrection);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::printReceiverConfiguration(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->printReceiverConfiguration();
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::printReceiverConfiguration);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
bool multiSlsDetector::getUseReceiverFlag(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getUseReceiverFlag();
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::getUseReceiverFlag);
|
|
if (sls::allEqual(r)) {
|
|
return r.front();
|
|
} else {
|
|
throw RuntimeError("Inconsistent Use receiver flags");
|
|
}
|
|
}
|
|
|
|
int multiSlsDetector::lockReceiver(int lock, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->lockReceiver(lock);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::lockReceiver, lock);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::getReceiverLastClientIP(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getReceiverLastClientIP();
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::getReceiverLastClientIP);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
void multiSlsDetector::exitReceiver(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->exitReceiver();
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::exitReceiver);
|
|
}
|
|
|
|
void multiSlsDetector::execReceiverCommand(const std::string &cmd, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->execReceiverCommand(cmd);
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::execReceiverCommand, cmd);
|
|
}
|
|
|
|
std::string multiSlsDetector::getFilePath(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getFilePath();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getFilePath);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::setFilePath(const std::string &path, int detPos) {
|
|
if (path.empty()) {
|
|
return getFilePath(detPos);
|
|
}
|
|
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setFilePath(path);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setFilePath, path);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::getFileName(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getFileName();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getFileName);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
std::string multiSlsDetector::setFileName(const std::string &fname,
|
|
int detPos) {
|
|
if (fname.empty()) {
|
|
return getFileName(detPos);
|
|
}
|
|
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setFileName(fname);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setFileName, fname);
|
|
return sls::concatenateIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setFramesPerFile(int f, int detPos) {
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setFramesPerFile(f);
|
|
}
|
|
auto r = parallelCall(&slsDetector::setFramesPerFile, f);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::getFramesPerFile(int detPos) const {
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getFramesPerFile();
|
|
}
|
|
auto r = parallelCall(&slsDetector::getFramesPerFile);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
slsDetectorDefs::frameDiscardPolicy
|
|
multiSlsDetector::setReceiverFramesDiscardPolicy(frameDiscardPolicy f,
|
|
int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setReceiverFramesDiscardPolicy(f);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setReceiverFramesDiscardPolicy, f);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setPartialFramesPadding(bool padding, int detPos) {
|
|
if (detPos >= 0)
|
|
return static_cast<int>(
|
|
detectors[detPos]->setPartialFramesPadding(padding));
|
|
auto r = parallelCall(&slsDetector::setPartialFramesPadding, padding);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::getPartialFramesPadding(int detPos) const {
|
|
if (detPos >= 0)
|
|
return static_cast<int>(detectors[detPos]->getPartialFramesPadding());
|
|
auto r = parallelCall(&slsDetector::getPartialFramesPadding);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
slsDetectorDefs::fileFormat multiSlsDetector::getFileFormat(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getFileFormat();
|
|
}
|
|
|
|
// multi
|
|
auto r = serialCall(&slsDetector::getFileFormat);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
slsDetectorDefs::fileFormat multiSlsDetector::setFileFormat(fileFormat f,
|
|
int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setFileFormat(f);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setFileFormat, f);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::incrementFileIndex(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->incrementFileIndex();
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::incrementFileIndex);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setFileIndex(int i, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setFileIndex(i);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setFileIndex, i);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::getFileIndex(int detPos) const {
|
|
if (detPos >= 0)
|
|
return detectors[detPos]->getFileIndex();
|
|
auto r = parallelCall(&slsDetector::getFileIndex);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
void multiSlsDetector::startReceiver(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->startReceiver();
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::startReceiver);
|
|
}
|
|
|
|
void multiSlsDetector::stopReceiver(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->stopReceiver();
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::stopReceiver);
|
|
}
|
|
|
|
slsDetectorDefs::runStatus multiSlsDetector::getReceiverStatus(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getReceiverStatus();
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::getReceiverStatus);
|
|
if (sls::allEqual(r)) {
|
|
return r.front();
|
|
}
|
|
if (sls::anyEqualTo(r, ERROR)) {
|
|
return ERROR;
|
|
}
|
|
for (const auto &value : r) {
|
|
if (value != IDLE) {
|
|
return value;
|
|
}
|
|
}
|
|
return IDLE;
|
|
}
|
|
|
|
int multiSlsDetector::getFramesCaughtByReceiver(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getFramesCaughtByReceiver();
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::getFramesCaughtByReceiver);
|
|
|
|
// prevent divide by all or do not take avg when -1 for "did not connect"
|
|
if ((detectors.empty()) || (sls::anyEqualTo(r, -1))) {
|
|
return -1;
|
|
}
|
|
|
|
// return average
|
|
return ((sls::sum(r)) / (int)detectors.size());
|
|
}
|
|
|
|
uint64_t multiSlsDetector::getReceiverCurrentFrameIndex(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getReceiverCurrentFrameIndex();
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::getReceiverCurrentFrameIndex);
|
|
|
|
// prevent divide by all or do not take avg when -1 for "did not connect"
|
|
if ((detectors.empty()) ||
|
|
(sls::anyEqualTo(r, static_cast<uint64_t>(-1)))) {
|
|
return -1;
|
|
}
|
|
|
|
// return average
|
|
return ((sls::sum(r)) / (int)detectors.size());
|
|
}
|
|
|
|
void multiSlsDetector::resetFramesCaught(int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->resetFramesCaught();
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::resetFramesCaught);
|
|
}
|
|
|
|
int multiSlsDetector::createReceivingDataSockets(const bool destroy) {
|
|
if (destroy) {
|
|
FILE_LOG(logINFO) << "Going to destroy data sockets";
|
|
// close socket
|
|
zmqSocket.clear();
|
|
|
|
client_downstream = false;
|
|
FILE_LOG(logINFO) << "Destroyed Receiving Data Socket(s)";
|
|
return OK;
|
|
}
|
|
|
|
FILE_LOG(logINFO) << "Going to create data sockets";
|
|
|
|
size_t numSockets = detectors.size();
|
|
size_t numSocketsPerDetector = 1;
|
|
if (getDetectorTypeAsEnum() == EIGER) {
|
|
numSocketsPerDetector = 2;
|
|
}
|
|
if (getNumberofUDPInterfaces() == 2) {
|
|
numSocketsPerDetector = 2;
|
|
}
|
|
numSockets *= numSocketsPerDetector;
|
|
|
|
for (size_t iSocket = 0; iSocket < numSockets; ++iSocket) {
|
|
uint32_t portnum = (detectors[iSocket / numSocketsPerDetector]
|
|
->getClientStreamingPort());
|
|
portnum += (iSocket % numSocketsPerDetector);
|
|
try {
|
|
zmqSocket.push_back(sls::make_unique<ZmqSocket>(
|
|
detectors[iSocket / numSocketsPerDetector]
|
|
->getClientStreamingIP()
|
|
.c_str(),
|
|
portnum));
|
|
FILE_LOG(logINFO) << "Zmq Client[" << iSocket << "] at "
|
|
<< zmqSocket.back()->GetZmqServerAddress();
|
|
} catch (...) {
|
|
FILE_LOG(logERROR)
|
|
<< "Could not create Zmq socket on port " << portnum;
|
|
createReceivingDataSockets(true);
|
|
return FAIL;
|
|
}
|
|
}
|
|
|
|
client_downstream = true;
|
|
FILE_LOG(logINFO) << "Receiving Data Socket(s) created";
|
|
return OK;
|
|
}
|
|
|
|
void multiSlsDetector::readFrameFromReceiver() {
|
|
|
|
int nX = 0;
|
|
int nY = 0;
|
|
int nDetPixelsX = 0;
|
|
int nDetPixelsY = 0;
|
|
bool gappixelsenable = false;
|
|
bool quadEnable = false;
|
|
bool eiger = false;
|
|
bool numInterfaces = getNumberofUDPInterfaces(); // cannot pick up from zmq
|
|
|
|
bool runningList[zmqSocket.size()], connectList[zmqSocket.size()];
|
|
int numRunning = 0;
|
|
for (size_t i = 0; i < zmqSocket.size(); ++i) {
|
|
if (zmqSocket[i]->Connect() == 0) {
|
|
connectList[i] = true;
|
|
runningList[i] = true;
|
|
++numRunning;
|
|
} else {
|
|
// to remember the list it connected to, to disconnect later
|
|
connectList[i] = false;
|
|
FILE_LOG(logERROR) << "Could not connect to socket "
|
|
<< zmqSocket[i]->GetZmqServerAddress();
|
|
runningList[i] = false;
|
|
}
|
|
}
|
|
int numConnected = numRunning;
|
|
bool data = false;
|
|
char *image = nullptr;
|
|
char *multiframe = nullptr;
|
|
char *multigappixels = nullptr;
|
|
int multisize = 0;
|
|
// only first message header
|
|
uint32_t size = 0, nPixelsX = 0, nPixelsY = 0, dynamicRange = 0;
|
|
float bytesPerPixel = 0;
|
|
// header info every header
|
|
std::string currentFileName = "";
|
|
uint64_t currentAcquisitionIndex = -1, currentFrameIndex = -1,
|
|
currentFileIndex = -1;
|
|
uint32_t currentSubFrameIndex = -1, coordX = -1, coordY = -1,
|
|
flippedDataX = -1;
|
|
|
|
// wait for real time acquisition to start
|
|
bool running = true;
|
|
sem_wait(&sem_newRTAcquisition);
|
|
if (getJoinThreadFlag()) {
|
|
running = false;
|
|
}
|
|
|
|
while (running) {
|
|
// reset data
|
|
data = false;
|
|
if (multiframe != nullptr) {
|
|
memset(multiframe, 0xFF, multisize);
|
|
}
|
|
|
|
// get each frame
|
|
for (unsigned int isocket = 0; isocket < zmqSocket.size(); ++isocket) {
|
|
|
|
// if running
|
|
if (runningList[isocket]) {
|
|
|
|
// HEADER
|
|
{
|
|
rapidjson::Document doc;
|
|
if (zmqSocket[isocket]->ReceiveHeader(
|
|
isocket, doc, SLS_DETECTOR_JSON_HEADER_VERSION) ==
|
|
0) {
|
|
// parse error, version error or end of acquisition for
|
|
// socket
|
|
runningList[isocket] = false;
|
|
--numRunning;
|
|
continue;
|
|
}
|
|
|
|
// if first message, allocate (all one time stuff)
|
|
if (image == nullptr) {
|
|
// allocate
|
|
size = doc["size"].GetUint();
|
|
multisize = size * zmqSocket.size();
|
|
image = new char[size];
|
|
multiframe = new char[multisize];
|
|
memset(multiframe, 0xFF, multisize);
|
|
// dynamic range
|
|
dynamicRange = doc["bitmode"].GetUint();
|
|
bytesPerPixel = (float)dynamicRange / 8;
|
|
// shape
|
|
nPixelsX = doc["shape"][0].GetUint();
|
|
nPixelsY = doc["shape"][1].GetUint();
|
|
// detector shape
|
|
nX = doc["detshape"][0].GetUint();
|
|
nY = doc["detshape"][1].GetUint();
|
|
nY *= numInterfaces;
|
|
nDetPixelsX = nX * nPixelsX;
|
|
nDetPixelsY = nY * nPixelsY;
|
|
// det type
|
|
eiger =
|
|
(doc["detType"].GetUint() == static_cast<int>(3))
|
|
? true
|
|
: false; // to be changed to EIGER when firmware
|
|
// updates its header data
|
|
gappixelsenable =
|
|
(doc["gappixels"].GetUint() == 0) ? false : true;
|
|
quadEnable =
|
|
(doc["quad"].GetUint() == 0) ? false : true;
|
|
FILE_LOG(logDEBUG1)
|
|
<< "One Time Header Info:"
|
|
"\n\tsize: "
|
|
<< size << "\n\tmultisize: " << multisize
|
|
<< "\n\tdynamicRange: " << dynamicRange
|
|
<< "\n\tbytesPerPixel: " << bytesPerPixel
|
|
<< "\n\tnPixelsX: " << nPixelsX
|
|
<< "\n\tnPixelsY: " << nPixelsY << "\n\tnX: " << nX
|
|
<< "\n\tnY: " << nY << "\n\teiger: " << eiger
|
|
<< "\n\tgappixelsenable: " << gappixelsenable
|
|
<< "\n\tquadEnable: " << quadEnable;
|
|
}
|
|
// each time, parse rest of header
|
|
currentFileName = doc["fname"].GetString();
|
|
currentAcquisitionIndex = doc["acqIndex"].GetUint64();
|
|
currentFrameIndex = doc["fIndex"].GetUint64();
|
|
currentFileIndex = doc["fileIndex"].GetUint64();
|
|
currentSubFrameIndex = doc["expLength"].GetUint();
|
|
coordY = doc["row"].GetUint();
|
|
coordX = doc["column"].GetUint();
|
|
if (eiger) {
|
|
coordY = (nY - 1) - coordY;
|
|
}
|
|
flippedDataX = doc["flippedDataX"].GetUint();
|
|
FILE_LOG(logDEBUG1)
|
|
<< "Header Info:"
|
|
"\n\tcurrentFileName: "
|
|
<< currentFileName << "\n\tcurrentAcquisitionIndex: "
|
|
<< currentAcquisitionIndex
|
|
<< "\n\tcurrentFrameIndex: " << currentFrameIndex
|
|
<< "\n\tcurrentFileIndex: " << currentFileIndex
|
|
<< "\n\tcurrentSubFrameIndex: " << currentSubFrameIndex
|
|
<< "\n\tcoordX: " << coordX << "\n\tcoordY: " << coordY
|
|
<< "\n\tflippedDataX: " << flippedDataX;
|
|
}
|
|
|
|
// DATA
|
|
data = true;
|
|
zmqSocket[isocket]->ReceiveData(isocket, image, size);
|
|
|
|
// creating multi image
|
|
{
|
|
uint32_t xoffset = coordX * nPixelsX * bytesPerPixel;
|
|
uint32_t yoffset = coordY * nPixelsY;
|
|
uint32_t singledetrowoffset = nPixelsX * bytesPerPixel;
|
|
uint32_t rowoffset = nX * singledetrowoffset;
|
|
if (getDetectorTypeAsEnum() == CHIPTESTBOARD) {
|
|
singledetrowoffset = size;
|
|
}
|
|
FILE_LOG(logDEBUG1)
|
|
<< "Multi Image Info:"
|
|
"\n\txoffset: "
|
|
<< xoffset << "\n\tyoffset: " << yoffset
|
|
<< "\n\tsingledetrowoffset: " << singledetrowoffset
|
|
<< "\n\trowoffset: " << rowoffset;
|
|
|
|
if (eiger && (flippedDataX != 0u)) {
|
|
for (uint32_t i = 0; i < nPixelsY; ++i) {
|
|
memcpy(((char *)multiframe) +
|
|
((yoffset + (nPixelsY - 1 - i)) *
|
|
rowoffset) +
|
|
xoffset,
|
|
(char *)image + (i * singledetrowoffset),
|
|
singledetrowoffset);
|
|
}
|
|
} else {
|
|
for (uint32_t i = 0; i < nPixelsY; ++i) {
|
|
memcpy(((char *)multiframe) +
|
|
((yoffset + i) * rowoffset) + xoffset,
|
|
(char *)image + (i * singledetrowoffset),
|
|
singledetrowoffset);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
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) {
|
|
setCurrentProgress(currentAcquisitionIndex + 1);
|
|
// 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;
|
|
thisData = new detectorData(
|
|
getCurrentProgress(), currentFileName.c_str(), nDetPixelsX,
|
|
nDetPixelsY, multigappixels, n, dynamicRange,
|
|
currentFileIndex);
|
|
}
|
|
// normal pixels
|
|
else {
|
|
thisData = new detectorData(
|
|
getCurrentProgress(), currentFileName.c_str(), nDetPixelsX,
|
|
nDetPixelsY, multiframe, multisize, dynamicRange,
|
|
currentFileIndex);
|
|
}
|
|
dataReady(thisData, currentFrameIndex,
|
|
((dynamicRange == 32) ? currentSubFrameIndex : -1),
|
|
pCallbackArg);
|
|
delete thisData;
|
|
}
|
|
|
|
// all done
|
|
if (numRunning == 0) {
|
|
// let main thread know that all dummy packets have been received
|
|
//(also from external process),
|
|
// main thread can now proceed to measurement finished call back
|
|
sem_post(&sem_endRTAcquisition);
|
|
// wait for next scan/measurement, else join thread
|
|
sem_wait(&sem_newRTAcquisition);
|
|
// done with complete acquisition
|
|
if (getJoinThreadFlag()) {
|
|
running = false;
|
|
} else {
|
|
// starting a new scan/measurement (got dummy data)
|
|
for (size_t i = 0; i < zmqSocket.size(); ++i) {
|
|
runningList[i] = connectList[i];
|
|
}
|
|
numRunning = numConnected;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Disconnect resources
|
|
for (size_t i = 0; i < zmqSocket.size(); ++i) {
|
|
if (connectList[i]) {
|
|
zmqSocket[i]->Disconnect();
|
|
}
|
|
}
|
|
|
|
// free resources
|
|
if (image != nullptr)
|
|
delete[] image;
|
|
if (multiframe)
|
|
delete[] multiframe;
|
|
if (multigappixels)
|
|
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 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)
|
|
nyb = multi_shm()->numberOfDetector.y * (512 + 2);
|
|
nxchip /= 2;
|
|
nychip *= 2;
|
|
nchipInRow /= 2;
|
|
}
|
|
int gapdatabytes = nxb * nyb;
|
|
|
|
// allocate
|
|
if (gpImage == nullptr) {
|
|
gpImage = new char[gapdatabytes];
|
|
}
|
|
// fill value
|
|
memset(gpImage, 0xFF, gapdatabytes);
|
|
|
|
const int b1chipx = 128;
|
|
const int b1chipy = 256;
|
|
char *src = nullptr;
|
|
char *dst = nullptr;
|
|
|
|
// copying line by line
|
|
src = image;
|
|
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
|
|
memcpy(dst, src, b1chipx);
|
|
src += b1chipx;
|
|
dst += b1chipx;
|
|
if (((col + 1) % nchipInRow) != 0) { // skip gap pixels
|
|
++dst;
|
|
}
|
|
}
|
|
}
|
|
|
|
dst += (2 * nxb);
|
|
}
|
|
|
|
// vertical filling of values
|
|
{
|
|
uint8_t temp, g1, g2;
|
|
int mod;
|
|
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
|
|
dst += b1chipx;
|
|
mod = (col + 1) % nchipInRow; // get gap pixels
|
|
// copy gap pixel(chip 0, 1, 2)
|
|
if (mod != 0) {
|
|
// neighbouring gap pixels to left
|
|
temp = (*((uint8_t *)(dst - 1)));
|
|
g1 = ((temp & 0xF) / 2);
|
|
(*((uint8_t *)(dst - 1))) = (temp & 0xF0) + g1;
|
|
|
|
// neighbouring gap pixels to right
|
|
temp = (*((uint8_t *)(dst + 1)));
|
|
g2 = ((temp >> 4) / 2);
|
|
(*((uint8_t *)(dst + 1))) = (g2 << 4) + (temp & 0x0F);
|
|
|
|
// gap pixels
|
|
(*((uint8_t *)dst)) = (g1 << 4) + g2;
|
|
|
|
// increment to point to proper chip destination
|
|
++dst;
|
|
}
|
|
}
|
|
}
|
|
|
|
dst += (2 * nxb);
|
|
}
|
|
}
|
|
|
|
// return gapdatabytes;
|
|
// horizontal filling
|
|
{
|
|
uint8_t temp, g1, g2;
|
|
char *dst_prevline = nullptr;
|
|
dst = gpImage;
|
|
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)
|
|
if (row < nychip - 1) {
|
|
dst_prevline = dst - nxb;
|
|
for (int gapline = 0; gapline < nxb; ++gapline) {
|
|
temp = (*((uint8_t *)dst_prevline));
|
|
g1 = ((temp >> 4) / 2);
|
|
g2 = ((temp & 0xF) / 2);
|
|
(*((uint8_t *)dst_prevline)) = (g1 << 4) + g2;
|
|
(*((uint8_t *)dst)) = (*((uint8_t *)dst_prevline));
|
|
++dst;
|
|
++dst_prevline;
|
|
}
|
|
}
|
|
|
|
// horizontal copying of gap pixels from neihboring future line (top
|
|
// part)
|
|
if (row > 0) {
|
|
dst -= ((b1chipy + 1) * nxb);
|
|
dst_prevline = dst + nxb;
|
|
for (int gapline = 0; gapline < nxb; ++gapline) {
|
|
temp = (*((uint8_t *)dst_prevline));
|
|
g1 = ((temp >> 4) / 2);
|
|
g2 = ((temp & 0xF) / 2);
|
|
temp = (g1 << 4) + g2;
|
|
(*((uint8_t *)dst_prevline)) = temp;
|
|
(*((uint8_t *)dst)) = temp;
|
|
++dst;
|
|
++dst_prevline;
|
|
}
|
|
dst += ((b1chipy + 1) * nxb);
|
|
}
|
|
|
|
dst += nxb;
|
|
}
|
|
}
|
|
|
|
return gapdatabytes;
|
|
}
|
|
|
|
int multiSlsDetector::setFileWrite(bool value, int detPos) {
|
|
if (detPos >= 0) {
|
|
return static_cast<int>(detectors[detPos]->setFileWrite(value));
|
|
}
|
|
auto r = parallelCall(&slsDetector::setFileWrite, value);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::getFileWrite(int detPos) const {
|
|
if (detPos >= 0) {
|
|
return static_cast<int>(detectors[detPos]->getFileWrite());
|
|
}
|
|
auto r = parallelCall(&slsDetector::getFileWrite);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setMasterFileWrite(bool value, int detPos) {
|
|
if (detPos >= 0) {
|
|
return static_cast<int>(detectors[detPos]->setMasterFileWrite(value));
|
|
}
|
|
auto r = parallelCall(&slsDetector::setMasterFileWrite, value);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::getMasterFileWrite(int detPos) const {
|
|
if (detPos >= 0) {
|
|
return static_cast<int>(detectors[detPos]->getMasterFileWrite());
|
|
}
|
|
auto r = parallelCall(&slsDetector::getMasterFileWrite);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setFileOverWrite(bool enable, int detPos) {
|
|
if (detPos >= 0) {
|
|
return static_cast<int>(detectors[detPos]->setFileOverWrite(enable));
|
|
}
|
|
auto r = parallelCall(&slsDetector::setFileOverWrite, enable);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::getFileOverWrite(int detPos) const {
|
|
if (detPos >= 0) {
|
|
return static_cast<int>(detectors[detPos]->getFileOverWrite());
|
|
}
|
|
auto r = parallelCall(&slsDetector::getFileOverWrite);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setReceiverStreamingFrequency(int freq, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setReceiverStreamingFrequency(freq);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setReceiverStreamingFrequency, freq);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setReceiverStreamingTimer(int time_in_ms, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setReceiverStreamingTimer(time_in_ms);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setReceiverStreamingTimer, time_in_ms);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
bool multiSlsDetector::enableDataStreamingToClient(int enable) {
|
|
if (enable >= 0) {
|
|
// destroy data threads
|
|
if (enable == 0) {
|
|
createReceivingDataSockets(true);
|
|
// create data threads
|
|
} else {
|
|
if (createReceivingDataSockets() == FAIL) {
|
|
throw RuntimeError("Could not create data threads in client.");
|
|
}
|
|
}
|
|
}
|
|
return client_downstream;
|
|
}
|
|
|
|
int multiSlsDetector::enableDataStreamingFromReceiver(int enable, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return static_cast<int>(
|
|
detectors[detPos]->enableDataStreamingFromReceiver(enable));
|
|
}
|
|
|
|
// multi
|
|
auto r =
|
|
parallelCall(&slsDetector::enableDataStreamingFromReceiver, enable);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::enableTenGigabitEthernet(int i, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->enableTenGigabitEthernet(i);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::enableTenGigabitEthernet, i);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setReceiverFifoDepth(int i, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setReceiverFifoDepth(i);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setReceiverFifoDepth, i);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setReceiverSilentMode(int i, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return static_cast<int>(detectors[detPos]->setReceiverSilentMode(i));
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setReceiverSilentMode, i);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
void multiSlsDetector::setPattern(const std::string &fname, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->setPattern(fname);
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::setPattern, fname);
|
|
}
|
|
|
|
void multiSlsDetector::savePattern(const std::string &fname) {
|
|
std::ofstream outfile;
|
|
outfile.open(fname.c_str(), std::ios_base::out);
|
|
if (!outfile.is_open()) {
|
|
throw RuntimeError("Could not create file to save pattern");
|
|
}
|
|
// get pattern limits
|
|
auto r = getPatternLoops(-1);
|
|
// pattern words
|
|
for (int i = r[0]; i <= r[1]; ++i) {
|
|
std::ostringstream os;
|
|
os << "patword 0x" << std::hex << i;
|
|
std::string cmd = os.str();
|
|
multiSlsDetectorClient(cmd, GET_ACTION, this, outfile);
|
|
}
|
|
// rest of pattern file
|
|
const std::vector<std::string> commands{
|
|
"patioctrl",
|
|
"patclkctrl",
|
|
"patlimits",
|
|
"patloop0",
|
|
"patnloop0",
|
|
"patloop1",
|
|
"patnloop1",
|
|
"patloop2",
|
|
"patnloop2",
|
|
"patwait0",
|
|
"patwaittime0",
|
|
"patwait1",
|
|
"patwaittime1",
|
|
"patwait2",
|
|
"patwaittime2",
|
|
"patmask",
|
|
"patsetbit",
|
|
};
|
|
for (const auto &cmd : commands)
|
|
multiSlsDetectorClient(cmd, GET_ACTION, this, outfile);
|
|
}
|
|
|
|
uint64_t multiSlsDetector::setPatternIOControl(uint64_t word, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setPatternIOControl(word);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setPatternIOControl, word);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
uint64_t multiSlsDetector::setPatternClockControl(uint64_t word, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setPatternClockControl(word);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setPatternClockControl, word);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
uint64_t multiSlsDetector::setPatternWord(int addr, uint64_t word, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setPatternWord(addr, word);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setPatternWord, addr, word);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
void multiSlsDetector::setPatternLoops(int level, int start, int stop, int n,
|
|
int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->setPatternLoops(level, start, stop, n);
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::setPatternLoops, level, start, stop, n);
|
|
}
|
|
|
|
std::array<int, 3> multiSlsDetector::getPatternLoops(int level, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setPatternLoops(level, -1, -1, -1);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setPatternLoops, level, -1, -1, -1);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
int multiSlsDetector::setPatternWaitAddr(int level, int addr, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setPatternWaitAddr(level, addr);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setPatternWaitAddr, level, addr);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
uint64_t multiSlsDetector::setPatternWaitTime(int level, uint64_t t,
|
|
int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setPatternWaitTime(level, t);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setPatternWaitTime, level, t);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
void multiSlsDetector::setPatternMask(uint64_t mask, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->setPatternMask(mask);
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::setPatternMask, mask);
|
|
}
|
|
|
|
uint64_t multiSlsDetector::getPatternMask(int detPos) {
|
|
if (detPos >= 0)
|
|
return detectors[detPos]->getPatternMask();
|
|
auto r = parallelCall(&slsDetector::getPatternMask);
|
|
if (sls::allEqual(r)) {
|
|
return r.front();
|
|
} else {
|
|
|
|
throw RuntimeError("multiSlsDetector::getPatternMask: Error: Different "
|
|
"Values returned)");
|
|
}
|
|
}
|
|
|
|
void multiSlsDetector::setPatternBitMask(uint64_t mask, int detPos) {
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->setPatternBitMask(mask);
|
|
}
|
|
parallelCall(&slsDetector::setPatternBitMask, mask);
|
|
}
|
|
|
|
uint64_t multiSlsDetector::getPatternBitMask(int detPos) {
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->getPatternBitMask();
|
|
}
|
|
auto r = parallelCall(&slsDetector::getPatternBitMask);
|
|
if (sls::allEqual(r)) {
|
|
return r.front();
|
|
}
|
|
|
|
// should not have different values
|
|
throw RuntimeError(
|
|
"multiSlsDetector::getPatternBitMask Different Values returned)");
|
|
}
|
|
|
|
int multiSlsDetector::setLEDEnable(int enable, int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
return detectors[detPos]->setLEDEnable(enable);
|
|
}
|
|
|
|
// multi
|
|
auto r = parallelCall(&slsDetector::setLEDEnable, enable);
|
|
return sls::minusOneIfDifferent(r);
|
|
}
|
|
|
|
void multiSlsDetector::setDigitalIODelay(uint64_t pinMask, int delay,
|
|
int detPos) {
|
|
// single
|
|
if (detPos >= 0) {
|
|
detectors[detPos]->setDigitalIODelay(pinMask, delay);
|
|
}
|
|
|
|
// multi
|
|
parallelCall(&slsDetector::setDigitalIODelay, pinMask, delay);
|
|
}
|
|
|
|
int multiSlsDetector::retrieveDetectorSetup(const std::string &fname1,
|
|
int level) {
|
|
|
|
int skip = 0;
|
|
std::string fname;
|
|
std::string str;
|
|
std::ifstream infile;
|
|
int iargval;
|
|
int interrupt = 0;
|
|
char *args[10];
|
|
|
|
char myargs[10][1000];
|
|
|
|
std::string sargname, sargval;
|
|
int iline = 0;
|
|
|
|
if (level == 2) {
|
|
FILE_LOG(logDEBUG1) << "config file read";
|
|
fname = fname1 + std::string(".det");
|
|
} else {
|
|
fname = fname1;
|
|
}
|
|
|
|
infile.open(fname.c_str(), std::ios_base::in);
|
|
if (infile.is_open()) {
|
|
auto cmd = slsDetectorCommand(this);
|
|
while (infile.good() and interrupt == 0) {
|
|
sargname = "none";
|
|
sargval = "0";
|
|
getline(infile, str);
|
|
iline++;
|
|
FILE_LOG(logDEBUG1) << str;
|
|
if (str.find('#') != std::string::npos) {
|
|
FILE_LOG(logDEBUG1) << "Line is a comment \n" << str;
|
|
continue;
|
|
} else {
|
|
std::istringstream ssstr(str);
|
|
iargval = 0;
|
|
while (ssstr.good()) {
|
|
ssstr >> sargname;
|
|
// if (ssstr.good()) {
|
|
sls::strcpy_safe(myargs[iargval], sargname.c_str());
|
|
args[iargval] = myargs[iargval];
|
|
FILE_LOG(logDEBUG1) << args[iargval];
|
|
iargval++;
|
|
// }
|
|
skip = 0;
|
|
}
|
|
if (level != 2) {
|
|
if (std::string(args[0]) == std::string("trimbits")) {
|
|
skip = 1;
|
|
}
|
|
}
|
|
if (skip == 0) {
|
|
cmd.executeLine(iargval, args, PUT_ACTION);
|
|
}
|
|
}
|
|
iline++;
|
|
}
|
|
infile.close();
|
|
|
|
} else {
|
|
throw RuntimeError("Error opening " + fname + " for reading");
|
|
}
|
|
FILE_LOG(logDEBUG1) << "Read " << iline << " lines";
|
|
return OK;
|
|
}
|
|
|
|
int multiSlsDetector::dumpDetectorSetup(const std::string &fname, int level) {
|
|
detectorType type = getDetectorTypeAsEnum();
|
|
std::vector<std::string> names;
|
|
// common config
|
|
names.emplace_back("fname");
|
|
names.emplace_back("index");
|
|
names.emplace_back("enablefwrite");
|
|
names.emplace_back("overwrite");
|
|
names.emplace_back("dr");
|
|
names.emplace_back("settings");
|
|
names.emplace_back("exptime");
|
|
names.emplace_back("period");
|
|
names.emplace_back("frames");
|
|
names.emplace_back("cycles");
|
|
names.emplace_back("timing");
|
|
|
|
switch (type) {
|
|
case EIGER:
|
|
names.emplace_back("flags");
|
|
names.emplace_back("clkdivider");
|
|
names.emplace_back("threshold");
|
|
names.emplace_back("ratecorr");
|
|
names.emplace_back("trimbits");
|
|
break;
|
|
case GOTTHARD:
|
|
names.emplace_back("delay");
|
|
break;
|
|
case JUNGFRAU:
|
|
names.emplace_back("delay");
|
|
names.emplace_back("clkdivider");
|
|
break;
|
|
case CHIPTESTBOARD:
|
|
names.emplace_back("dac:0");
|
|
names.emplace_back("dac:1");
|
|
names.emplace_back("dac:2");
|
|
names.emplace_back("dac:3");
|
|
names.emplace_back("dac:4");
|
|
names.emplace_back("dac:5");
|
|
names.emplace_back("dac:6");
|
|
names.emplace_back("dac:7");
|
|
names.emplace_back("dac:8");
|
|
names.emplace_back("dac:9");
|
|
names.emplace_back("dac:10");
|
|
names.emplace_back("dac:11");
|
|
names.emplace_back("dac:12");
|
|
names.emplace_back("dac:13");
|
|
names.emplace_back("dac:14");
|
|
names.emplace_back("dac:15");
|
|
names.emplace_back("dac:16");
|
|
names.emplace_back("dac:17");
|
|
names.emplace_back("dac:18");
|
|
names.emplace_back("dac:19");
|
|
names.emplace_back("dac:20");
|
|
names.emplace_back("dac:21");
|
|
names.emplace_back("dac:22");
|
|
names.emplace_back("dac:23");
|
|
names.emplace_back("adcvpp");
|
|
names.emplace_back("adcclk");
|
|
names.emplace_back("clkdivider");
|
|
names.emplace_back("adcphase");
|
|
names.emplace_back("adcpipeline");
|
|
names.emplace_back("adcinvert"); //
|
|
names.emplace_back("adcdisable");
|
|
names.emplace_back("patioctrl");
|
|
names.emplace_back("patclkctrl");
|
|
names.emplace_back("patlimits");
|
|
names.emplace_back("patloop0");
|
|
names.emplace_back("patnloop0");
|
|
names.emplace_back("patwait0");
|
|
names.emplace_back("patwaittime0");
|
|
names.emplace_back("patloop1");
|
|
names.emplace_back("patnloop1");
|
|
names.emplace_back("patwait1");
|
|
names.emplace_back("patwaittime1");
|
|
names.emplace_back("patloop2");
|
|
names.emplace_back("patnloop2");
|
|
names.emplace_back("patwait2");
|
|
names.emplace_back("patwaittime2");
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// Workaround to bo able to suplly ecexuteLine with char**
|
|
const int n_arguments = 1;
|
|
char buffer[1000]; // TODO! this should not be hardcoded!
|
|
char *args[n_arguments] = {buffer};
|
|
|
|
std::string outfname;
|
|
if (level == 2) {
|
|
writeConfigurationFile(fname + ".config");
|
|
outfname = fname + ".det";
|
|
} else {
|
|
outfname = fname;
|
|
}
|
|
|
|
std::ofstream outfile;
|
|
outfile.open(outfname.c_str(), std::ios_base::out);
|
|
if (outfile.is_open()) {
|
|
auto cmd = slsDetectorCommand(this);
|
|
for (auto &name : names) {
|
|
sls::strcpy_safe(buffer, name.c_str()); // this is...
|
|
outfile << name << " "
|
|
<< cmd.executeLine(n_arguments, args, GET_ACTION)
|
|
<< std::endl;
|
|
}
|
|
outfile.close();
|
|
} else {
|
|
throw RuntimeError("Error opening parameters file " + fname +
|
|
" for writing");
|
|
}
|
|
|
|
FILE_LOG(logDEBUG1) << "wrote " << names.size() << " lines to "
|
|
<< outfname;
|
|
return OK;
|
|
}
|
|
|
|
void multiSlsDetector::registerAcquisitionFinishedCallback(
|
|
void (*func)(double, int, void *), void *pArg) {
|
|
acquisition_finished = func;
|
|
acqFinished_p = pArg;
|
|
}
|
|
|
|
void multiSlsDetector::registerDataCallback(
|
|
void (*userCallback)(detectorData *, uint64_t, uint32_t, void *),
|
|
void *pArg) {
|
|
dataReady = userCallback;
|
|
pCallbackArg = pArg;
|
|
if (getUseReceiverFlag()) {
|
|
if (dataReady == nullptr) {
|
|
enableDataStreamingToClient(0);
|
|
enableDataStreamingFromReceiver(0);
|
|
} else {
|
|
enableDataStreamingToClient(1);
|
|
enableDataStreamingFromReceiver(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
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");
|
|
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;
|
|
}
|
|
|
|
totalProgress = nf * nc * ns;
|
|
FILE_LOG(logDEBUG1) << "nf " << nf << " nc " << nc << " ns " << ns;
|
|
FILE_LOG(logDEBUG1) << "Set total progress " << totalProgress << std::endl;
|
|
return totalProgress;
|
|
}
|
|
|
|
double multiSlsDetector::getCurrentProgress() {
|
|
std::lock_guard<std::mutex> lock(mp);
|
|
return 100. * ((double)progressIndex) / ((double)totalProgress);
|
|
}
|
|
|
|
void multiSlsDetector::incrementProgress() {
|
|
std::lock_guard<std::mutex> lock(mp);
|
|
progressIndex++;
|
|
std::cout << std::fixed << std::setprecision(2) << std::setw(6)
|
|
<< 100. * ((double)progressIndex) / ((double)totalProgress)
|
|
<< " \%";
|
|
std::cout << '\r' << std::flush;
|
|
}
|
|
|
|
void multiSlsDetector::setCurrentProgress(int i) {
|
|
std::lock_guard<std::mutex> lock(mp);
|
|
progressIndex = i;
|
|
std::cout << std::fixed << std::setprecision(2) << std::setw(6)
|
|
<< 100. * ((double)progressIndex) / ((double)totalProgress)
|
|
<< " \%";
|
|
std::cout << '\r' << std::flush;
|
|
}
|
|
|
|
int multiSlsDetector::acquire() {
|
|
// ensure acquire isnt started multiple times by same client
|
|
if (static_cast<int>(isAcquireReady()) == FAIL) {
|
|
return FAIL;
|
|
}
|
|
|
|
struct timespec begin, end;
|
|
clock_gettime(CLOCK_REALTIME, &begin);
|
|
|
|
// in the real time acquisition loop, processing thread will wait for a post
|
|
// each time
|
|
sem_init(&sem_newRTAcquisition, 1, 0);
|
|
// in the real time acquistion loop, main thread will wait for processing
|
|
// thread to be done each time (which in turn waits for receiver/ext
|
|
// process)
|
|
sem_init(&sem_endRTAcquisition, 1, 0);
|
|
|
|
bool receiver = getUseReceiverFlag();
|
|
progressIndex = 0;
|
|
setJoinThreadFlag(false);
|
|
|
|
// verify receiver is idle
|
|
if (receiver) {
|
|
if (getReceiverStatus() != IDLE) {
|
|
stopReceiver();
|
|
}
|
|
}
|
|
setTotalProgress();
|
|
|
|
startProcessingThread();
|
|
|
|
// resets frames caught in receiver
|
|
if (receiver) {
|
|
resetFramesCaught();
|
|
}
|
|
|
|
// start receiver
|
|
if (receiver) {
|
|
startReceiver();
|
|
// let processing thread listen to these packets
|
|
sem_post(&sem_newRTAcquisition);
|
|
}
|
|
|
|
startAndReadAll();
|
|
|
|
// 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
|
|
|
|
incrementFileIndex();
|
|
}
|
|
|
|
// waiting for the data processing thread to finish!
|
|
setJoinThreadFlag(true);
|
|
sem_post(&sem_newRTAcquisition);
|
|
dataProcessingThread.join();
|
|
|
|
if (acquisition_finished != nullptr) {
|
|
acquisition_finished(getCurrentProgress(), getRunStatus(),
|
|
acqFinished_p);
|
|
}
|
|
|
|
sem_destroy(&sem_newRTAcquisition);
|
|
sem_destroy(&sem_endRTAcquisition);
|
|
|
|
clock_gettime(CLOCK_REALTIME, &end);
|
|
FILE_LOG(logDEBUG1) << "Elapsed time for acquisition:"
|
|
<< ((end.tv_sec - begin.tv_sec) +
|
|
(end.tv_nsec - begin.tv_nsec) / 1000000000.0)
|
|
<< " seconds";
|
|
|
|
setAcquiringFlag(false);
|
|
|
|
return OK;
|
|
}
|
|
|
|
void multiSlsDetector::startProcessingThread() {
|
|
setTotalProgress();
|
|
dataProcessingThread = std::thread(&multiSlsDetector::processData, this);
|
|
}
|
|
|
|
void multiSlsDetector::processData() {
|
|
if (getUseReceiverFlag()) {
|
|
if (dataReady != nullptr) {
|
|
readFrameFromReceiver();
|
|
}
|
|
// only update progress
|
|
else {
|
|
int caught = -1;
|
|
while (true) {
|
|
// to exit acquire by typing q
|
|
if (kbhit() != 0) {
|
|
if (fgetc(stdin) == 'q') {
|
|
FILE_LOG(logINFO)
|
|
<< "Caught the command to stop acquisition";
|
|
stopAcquisition();
|
|
}
|
|
}
|
|
// get progress
|
|
caught = getFramesCaughtByReceiver(0);
|
|
|
|
// updating progress
|
|
if (caught != -1) {
|
|
setCurrentProgress(caught);
|
|
}
|
|
// exiting loop
|
|
if (getJoinThreadFlag()) {
|
|
break;
|
|
}
|
|
// otherwise error when connecting to the receiver too fast
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool multiSlsDetector::getJoinThreadFlag() const {
|
|
std::lock_guard<std::mutex> lock(mp);
|
|
return jointhread;
|
|
}
|
|
|
|
void multiSlsDetector::setJoinThreadFlag(bool value) {
|
|
std::lock_guard<std::mutex> lock(mp);
|
|
jointhread = value;
|
|
}
|
|
|
|
int multiSlsDetector::kbhit() {
|
|
struct timeval tv;
|
|
fd_set fds;
|
|
tv.tv_sec = 0;
|
|
tv.tv_usec = 0;
|
|
FD_ZERO(&fds);
|
|
FD_SET(STDIN_FILENO, &fds); // STDIN_FILENO is 0
|
|
select(STDIN_FILENO + 1, &fds, nullptr, nullptr, &tv);
|
|
return FD_ISSET(STDIN_FILENO, &fds);
|
|
}
|
|
|
|
std::vector<char> multiSlsDetector::readPofFile(const std::string &fname) {
|
|
FILE_LOG(logDEBUG1) << "Programming FPGA with file name:" << fname;
|
|
size_t filesize = 0;
|
|
// check if it exists
|
|
|
|
struct stat st;
|
|
if (stat(fname.c_str(), &st) != 0) {
|
|
throw RuntimeError("Program FPGA: Programming file does not exist");
|
|
}
|
|
|
|
// open src
|
|
FILE *src = fopen(fname.c_str(), "rb");
|
|
if (src == nullptr) {
|
|
throw RuntimeError(
|
|
"Program FPGA: Could not open source file for programming: " +
|
|
fname);
|
|
}
|
|
|
|
// create temp destination file
|
|
char destfname[] = "/tmp/SLS_DET_MCB.XXXXXX";
|
|
int dst = mkstemp(destfname); // create temporary file and open it in r/w
|
|
if (dst == -1) {
|
|
fclose(src);
|
|
throw RuntimeError(
|
|
std::string(
|
|
"Could not create destination file in /tmp for programming: ") +
|
|
destfname);
|
|
}
|
|
|
|
// convert src to dst rawbin
|
|
FILE_LOG(logDEBUG1) << "Converting " << fname << " to " << destfname;
|
|
{
|
|
int filepos, x, y, i;
|
|
// Remove header (0...11C)
|
|
for (filepos = 0; filepos < 0x11C; ++filepos) {
|
|
fgetc(src);
|
|
}
|
|
// Write 0x80 times 0xFF (0...7F)
|
|
{
|
|
char c = 0xFF;
|
|
for (filepos = 0; filepos < 0x80; ++filepos) {
|
|
write(dst, &c, 1);
|
|
}
|
|
}
|
|
// Swap bits and write to file
|
|
for (filepos = 0x80; filepos < 0x1000000; ++filepos) {
|
|
x = fgetc(src);
|
|
if (x < 0) {
|
|
break;
|
|
}
|
|
y = 0;
|
|
for (i = 0; i < 8; ++i) {
|
|
y = y |
|
|
(((x & (1 << i)) >> i) << (7 - i)); // This swaps the bits
|
|
}
|
|
write(dst, &y, 1);
|
|
}
|
|
if (filepos < 0x1000000) {
|
|
throw RuntimeError(
|
|
"Could not convert programming file. EOF before end of flash");
|
|
}
|
|
}
|
|
if (fclose(src) != 0) {
|
|
throw RuntimeError("Program FPGA: Could not close source file");
|
|
}
|
|
if (close(dst) != 0) {
|
|
throw RuntimeError("Program FPGA: Could not close destination file");
|
|
}
|
|
FILE_LOG(logDEBUG1) << "File has been converted to " << destfname;
|
|
|
|
// loading dst file to memory
|
|
FILE *fp = fopen(destfname, "r");
|
|
if (fp == nullptr) {
|
|
throw RuntimeError("Program FPGA: Could not open rawbin file");
|
|
}
|
|
if (fseek(fp, 0, SEEK_END) != 0) {
|
|
throw RuntimeError("Program FPGA: Seek error in rawbin file");
|
|
}
|
|
filesize = ftell(fp);
|
|
if (filesize <= 0) {
|
|
throw RuntimeError("Program FPGA: Could not get length of rawbin file");
|
|
}
|
|
rewind(fp);
|
|
|
|
std::vector<char> buffer(filesize, 0);
|
|
if (fread(buffer.data(), sizeof(char), filesize, fp) != filesize) {
|
|
throw RuntimeError("Program FPGA: Could not read rawbin file");
|
|
}
|
|
|
|
if (fclose(fp) != 0) {
|
|
throw RuntimeError(
|
|
"Program FPGA: Could not close destination file after converting");
|
|
}
|
|
unlink(destfname); // delete temporary file
|
|
FILE_LOG(logDEBUG1)
|
|
<< "Successfully loaded the rawbin file to program memory";
|
|
FILE_LOG(logINFO) << "Read file into memory";
|
|
return buffer;
|
|
}
|