mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-04-21 03:10:02 +02:00
3619 lines
120 KiB
C++
3619 lines
120 KiB
C++
// SPDX-License-Identifier: LGPL-3.0-or-other
|
|
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
|
#include "Module.h"
|
|
#include "SharedMemory.h"
|
|
#include "sls/ClientSocket.h"
|
|
#include "sls/ToString.h"
|
|
#include "sls/bit_utils.h"
|
|
#include "sls/container_utils.h"
|
|
#include "sls/file_utils.h"
|
|
#include "sls/md5_helper.h"
|
|
#include "sls/network_utils.h"
|
|
#include "sls/sls_detector_exceptions.h"
|
|
#include "sls/sls_detector_funcs.h"
|
|
#include "sls/string_utils.h"
|
|
#include "sls/versionAPI.h"
|
|
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include <bitset>
|
|
#include <cassert>
|
|
#include <chrono>
|
|
#include <cmath>
|
|
#include <cstdlib>
|
|
#include <iomanip>
|
|
#include <iterator>
|
|
#include <sstream>
|
|
#include <thread>
|
|
|
|
namespace sls {
|
|
|
|
// creating new shm
|
|
Module::Module(detectorType type, int det_id, int module_index, bool verify)
|
|
: moduleIndex(module_index), shm(det_id, module_index) {
|
|
|
|
// ensure shared memory was not created before
|
|
if (shm.IsExisting()) {
|
|
LOG(logWARNING) << "This shared memory should have been "
|
|
"deleted before! "
|
|
<< shm.GetName() << ". Freeing it again";
|
|
shm.RemoveSharedMemory();
|
|
}
|
|
|
|
initSharedMemory(type, det_id, verify);
|
|
}
|
|
|
|
// opening existing shm
|
|
Module::Module(int det_id, int module_index, bool verify)
|
|
: moduleIndex(module_index), shm(det_id, module_index) {
|
|
|
|
// getDetectorType From shm will check if existing
|
|
detectorType type = getDetectorTypeFromShm(det_id, verify);
|
|
initSharedMemory(type, det_id, verify);
|
|
}
|
|
|
|
Module::~Module() = default;
|
|
|
|
void Module::freeSharedMemory() {
|
|
if (shm.IsExisting()) {
|
|
shm.RemoveSharedMemory();
|
|
}
|
|
}
|
|
|
|
bool Module::isFixedPatternSharedMemoryCompatible() const {
|
|
return (shm()->shmversion >= MODULE_SHMAPIVERSION);
|
|
}
|
|
|
|
std::string Module::getHostname() const { return shm()->hostname; }
|
|
|
|
void Module::setHostname(const std::string &hostname,
|
|
const bool initialChecks) {
|
|
sls::strcpy_safe(shm()->hostname, hostname.c_str());
|
|
auto client = DetectorSocket(shm()->hostname, shm()->controlPort);
|
|
client.close();
|
|
try {
|
|
checkDetectorVersionCompatibility();
|
|
LOG(logINFO) << "Module Version Compatibility - Success";
|
|
} catch (const DetectorError &e) {
|
|
if (!initialChecks) {
|
|
LOG(logWARNING) << "Bypassing Initial Checks at your own risk!";
|
|
} else {
|
|
throw;
|
|
}
|
|
}
|
|
if (shm()->detType == EIGER) {
|
|
setActivate(true);
|
|
}
|
|
}
|
|
|
|
int64_t Module::getFirmwareVersion() const {
|
|
return sendToDetector<int64_t>(F_GET_FIRMWARE_VERSION);
|
|
}
|
|
|
|
int64_t Module::getDetectorServerVersion() const {
|
|
return sendToDetector<int64_t>(F_GET_SERVER_VERSION);
|
|
}
|
|
|
|
std::string Module::getKernelVersion() const {
|
|
char retval[MAX_STR_LENGTH]{};
|
|
sendToDetector(F_GET_KERNEL_VERSION, nullptr, retval);
|
|
return retval;
|
|
}
|
|
|
|
int64_t Module::getSerialNumber() const {
|
|
return sendToDetector<int64_t>(F_GET_SERIAL_NUMBER);
|
|
}
|
|
|
|
int Module::getModuleId() const { return sendToDetector<int>(F_GET_MODULE_ID); }
|
|
|
|
int64_t Module::getReceiverSoftwareVersion() const {
|
|
if (shm()->useReceiverFlag) {
|
|
return sendToReceiver<int64_t>(F_GET_RECEIVER_VERSION);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
// static function
|
|
slsDetectorDefs::detectorType
|
|
Module::getTypeFromDetector(const std::string &hostname, int cport) {
|
|
LOG(logDEBUG1) << "Getting Module type ";
|
|
sls::ClientSocket socket("Detector", hostname, cport);
|
|
socket.Send(F_GET_DETECTOR_TYPE);
|
|
socket.Receive<int>(); // TODO! Should we look at this OK/FAIL?
|
|
auto retval = socket.Receive<detectorType>();
|
|
LOG(logDEBUG1) << "Module type is " << retval;
|
|
return retval;
|
|
}
|
|
|
|
slsDetectorDefs::detectorType Module::getDetectorType() const {
|
|
return shm()->detType;
|
|
}
|
|
|
|
void Module::updateNumberOfChannels() {
|
|
if (shm()->detType == CHIPTESTBOARD || shm()->detType == MOENCH) {
|
|
std::array<int, 2> retvals{};
|
|
sendToDetector(F_GET_NUM_CHANNELS, nullptr, retvals);
|
|
shm()->nChan.x = retvals[0];
|
|
shm()->nChan.y = retvals[1];
|
|
}
|
|
}
|
|
|
|
slsDetectorDefs::xy Module::getNumberOfChannels() const {
|
|
slsDetectorDefs::xy coord{};
|
|
coord.x = (shm()->nChan.x * shm()->nChip.x);
|
|
coord.y = (shm()->nChan.y * shm()->nChip.y);
|
|
return coord;
|
|
}
|
|
|
|
void Module::updateNumberOfModule(slsDetectorDefs::xy det) {
|
|
shm()->numberOfModule = det;
|
|
int args[2] = {shm()->numberOfModule.y, moduleIndex};
|
|
sendToDetector(F_SET_POSITION, args, nullptr);
|
|
}
|
|
|
|
slsDetectorDefs::detectorSettings Module::getSettings() const {
|
|
return sendToDetector<detectorSettings>(F_SET_SETTINGS, GET_FLAG);
|
|
}
|
|
|
|
void Module::setSettings(detectorSettings isettings) {
|
|
if (shm()->detType == EIGER) {
|
|
throw RuntimeError(
|
|
"Cannot set settings for Eiger. Use threshold energy.");
|
|
}
|
|
sendToDetector<int>(F_SET_SETTINGS, isettings);
|
|
}
|
|
|
|
int Module::getThresholdEnergy() const {
|
|
return sendToDetector<int>(F_GET_THRESHOLD_ENERGY);
|
|
}
|
|
|
|
std::array<int, 3> Module::getAllThresholdEnergy() const {
|
|
return sendToDetector<std::array<int, 3>>(F_GET_ALL_THRESHOLD_ENERGY);
|
|
}
|
|
|
|
void Module::setThresholdEnergy(int e_eV, detectorSettings isettings,
|
|
bool trimbits) {
|
|
|
|
// verify e_eV exists in trimEneregies[]
|
|
if (shm()->trimEnergies.empty() || (e_eV < shm()->trimEnergies.front()) ||
|
|
(e_eV > shm()->trimEnergies.back())) {
|
|
throw RuntimeError("This energy " + std::to_string(e_eV) +
|
|
" not defined for this module!");
|
|
}
|
|
bool interpolate =
|
|
std::all_of(shm()->trimEnergies.begin(), shm()->trimEnergies.end(),
|
|
[e_eV](const int &e) { return e != e_eV; });
|
|
|
|
sls_detector_module myMod{shm()->detType};
|
|
|
|
if (!interpolate) {
|
|
std::string settingsfname = getTrimbitFilename(isettings, e_eV);
|
|
LOG(logDEBUG1) << "Settings File is " << settingsfname;
|
|
myMod = readSettingsFile(settingsfname, trimbits);
|
|
} else {
|
|
// find the trim values
|
|
int trim1 = -1, trim2 = -1;
|
|
for (size_t i = 0; i < shm()->trimEnergies.size(); ++i) {
|
|
if (e_eV < shm()->trimEnergies[i]) {
|
|
trim2 = shm()->trimEnergies[i];
|
|
trim1 = shm()->trimEnergies[i - 1];
|
|
break;
|
|
}
|
|
}
|
|
std::string settingsfname1 = getTrimbitFilename(isettings, trim1);
|
|
std::string settingsfname2 = getTrimbitFilename(isettings, trim2);
|
|
LOG(logDEBUG1) << "Settings Files are " << settingsfname1 << " and "
|
|
<< settingsfname2;
|
|
auto myMod1 = readSettingsFile(settingsfname1, trimbits);
|
|
auto myMod2 = readSettingsFile(settingsfname2, trimbits);
|
|
if (myMod1.iodelay != myMod2.iodelay) {
|
|
throw RuntimeError("setThresholdEnergyAndSettings: Iodelays do not "
|
|
"match between files");
|
|
}
|
|
myMod = interpolateTrim(&myMod1, &myMod2, e_eV, trim1, trim2, trimbits);
|
|
myMod.iodelay = myMod1.iodelay;
|
|
myMod.tau =
|
|
linearInterpolation(e_eV, trim1, trim2, myMod1.tau, myMod2.tau);
|
|
}
|
|
|
|
myMod.reg = isettings;
|
|
myMod.eV[0] = e_eV;
|
|
setModule(myMod, trimbits);
|
|
if (getSettings() != isettings) {
|
|
throw RuntimeError("setThresholdEnergyAndSettings: Could not set "
|
|
"settings in Module");
|
|
}
|
|
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver(F_RECEIVER_SET_THRESHOLD, e_eV, nullptr);
|
|
}
|
|
}
|
|
|
|
void Module::setAllThresholdEnergy(std::array<int, 3> e_eV,
|
|
detectorSettings isettings, bool trimbits) {
|
|
if (shm()->trimEnergies.empty()) {
|
|
throw RuntimeError(
|
|
"Trim energies have not been defined for this module yet!");
|
|
}
|
|
|
|
auto counters = getSetBits(getCounterMask());
|
|
enum mythen3_DacIndex {
|
|
M_VCASSH,
|
|
M_VTH2,
|
|
M_VRSHAPER,
|
|
M_VRSHAPER_N,
|
|
M_VIPRE_OUT,
|
|
M_VTH3,
|
|
M_VTH1,
|
|
M_VICIN,
|
|
M_VCAS,
|
|
M_VRPREAMP,
|
|
M_VCAL_N,
|
|
M_VIPRE,
|
|
M_VISHAPER,
|
|
M_VCAL_P,
|
|
M_VTRIM,
|
|
M_VDCSH
|
|
};
|
|
|
|
std::vector<sls_detector_module> myMods{shm()->detType};
|
|
std::vector<int> energy(e_eV.begin(), e_eV.end());
|
|
// if all energies are same
|
|
if (allEqualTo(energy, energy[0])) {
|
|
energy.resize(1);
|
|
}
|
|
myMods.resize(energy.size());
|
|
|
|
// for each threshold
|
|
for (size_t i = 0; i < energy.size(); ++i) {
|
|
// don't interpolate
|
|
if (shm()->trimEnergies.anyEqualTo(energy[i])) {
|
|
std::string settingsfname =
|
|
getTrimbitFilename(isettings, energy[i]);
|
|
LOG(logDEBUG1) << "Settings File is " << settingsfname;
|
|
myMods[i] = readSettingsFile(settingsfname, trimbits);
|
|
}
|
|
// interpolate
|
|
else {
|
|
if (shm()->trimEnergies.size() < 2) {
|
|
throw RuntimeError(
|
|
"Cannot interpolate with less than 2 trim energies");
|
|
}
|
|
// find the trim values
|
|
int trim1 = -1, trim2 = -1;
|
|
if (energy[i] < shm()->trimEnergies[0]) {
|
|
trim1 = shm()->trimEnergies[0];
|
|
trim2 = shm()->trimEnergies[1];
|
|
} else if (energy[i] >
|
|
shm()->trimEnergies[shm()->trimEnergies.size() - 1]) {
|
|
trim1 = shm()->trimEnergies[shm()->trimEnergies.size() - 2];
|
|
trim2 = shm()->trimEnergies[shm()->trimEnergies.size() - 1];
|
|
} else {
|
|
for (size_t j = 0; j < shm()->trimEnergies.size(); ++j) {
|
|
// std::cout << "checking " << energy[i] << " and "
|
|
// << shm()->trimEnergies[j] << std::endl;
|
|
if (energy[i] < shm()->trimEnergies[j]) {
|
|
trim1 = shm()->trimEnergies[j - 1];
|
|
trim2 = shm()->trimEnergies[j];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
LOG(logINFO) << "e_eV:" << energy[i] << " [" << trim1 << ", "
|
|
<< trim2 << "]";
|
|
|
|
std::string settingsfname1 = getTrimbitFilename(isettings, trim1);
|
|
std::string settingsfname2 = getTrimbitFilename(isettings, trim2);
|
|
LOG(logDEBUG1) << "Settings Files are " << settingsfname1 << " and "
|
|
<< settingsfname2;
|
|
auto myMod1 = readSettingsFile(settingsfname1, trimbits);
|
|
auto myMod2 = readSettingsFile(settingsfname2, trimbits);
|
|
|
|
myMods[i] = interpolateTrim(&myMod1, &myMod2, energy[i], trim1,
|
|
trim2, trimbits);
|
|
}
|
|
}
|
|
|
|
sls_detector_module myMod{shm()->detType};
|
|
myMod = myMods[0];
|
|
|
|
// if multiple thresholds, combine
|
|
if (myMods.size() > 1) {
|
|
|
|
// average vtrim of enabled counters
|
|
int sum = 0;
|
|
for (size_t i = 0; i < counters.size(); ++i) {
|
|
sum += myMods[counters[i]].dacs[M_VTRIM];
|
|
}
|
|
myMod.dacs[M_VTRIM] = sum / counters.size();
|
|
|
|
// copy vth1, vth2 and vth3 from the correct threshold mods
|
|
myMod.dacs[M_VTH1] = myMods[0].dacs[M_VTH1];
|
|
myMod.dacs[M_VTH2] = myMods[1].dacs[M_VTH2];
|
|
myMod.dacs[M_VTH3] = myMods[2].dacs[M_VTH3];
|
|
|
|
// check if dacs are different
|
|
for (size_t j = 0; j < 16; ++j) {
|
|
if (j == M_VTRIM || j == M_VTH1 || j == M_VTH2 || j == M_VTH3)
|
|
continue;
|
|
|
|
if (myMods[0].dacs[j] != myMods[1].dacs[j]) {
|
|
throw RuntimeError("Dac Index " + std::to_string(j) +
|
|
" differs for threshold[0]:[" +
|
|
std::to_string(myMods[0].dacs[j]) +
|
|
"] and threshold[1]:" +
|
|
std::to_string(myMods[1].dacs[j]) + "]");
|
|
}
|
|
if (myMods[1].dacs[j] != myMods[2].dacs[j]) {
|
|
throw RuntimeError("Dac Index " + std::to_string(j) +
|
|
" differs for threshold[1]:[" +
|
|
std::to_string(myMods[1].dacs[j]) +
|
|
"] and threshold[2]:" +
|
|
std::to_string(myMods[2].dacs[j]) + "]");
|
|
}
|
|
}
|
|
|
|
// replace correct trim values (interleaved)
|
|
for (int i = 0; i < myMod.nchan; ++i) {
|
|
myMod.chanregs[i] = myMods[i % 3].chanregs[i];
|
|
}
|
|
}
|
|
|
|
myMod.reg = isettings;
|
|
std::copy(e_eV.begin(), e_eV.end(), myMod.eV);
|
|
LOG(logDEBUG) << "ev:" << ToString(myMod.eV);
|
|
|
|
// check for trimbits that are out of range
|
|
bool out_of_range = false;
|
|
for (int i = 0; i != myMod.nchan; ++i) {
|
|
if (myMod.chanregs[i] < 0) {
|
|
myMod.chanregs[i] = 0;
|
|
out_of_range = true;
|
|
} else if (myMod.chanregs[i] > 63) {
|
|
myMod.chanregs[i] = 63;
|
|
out_of_range = true;
|
|
}
|
|
}
|
|
if (out_of_range) {
|
|
LOG(logWARNING)
|
|
<< "Some trimbits were out of range after interpolation, these "
|
|
"have been replaced with 0 or 63.";
|
|
}
|
|
|
|
// check dacs
|
|
out_of_range = false;
|
|
for (auto dac : {M_VTRIM, M_VTH1, M_VTH2, M_VTH3}) {
|
|
if (myMod.dacs[dac] < 600) {
|
|
myMod.dacs[dac] = 600;
|
|
out_of_range = true;
|
|
} else if (myMod.dacs[dac] > 2400) {
|
|
myMod.dacs[dac] = 2400;
|
|
out_of_range = true;
|
|
}
|
|
}
|
|
if (out_of_range) {
|
|
LOG(logWARNING) << "Some dacs were out of range after interpolation, "
|
|
"these have been replaced with 600 or 2400.";
|
|
}
|
|
|
|
setModule(myMod, trimbits);
|
|
if (getSettings() != isettings) {
|
|
throw RuntimeError("setThresholdEnergyAndSettings: Could not set "
|
|
"settings in Module");
|
|
}
|
|
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver(F_RECEIVER_SET_ALL_THRESHOLD, e_eV, nullptr);
|
|
}
|
|
}
|
|
|
|
std::string Module::getSettingsDir() const {
|
|
return std::string(shm()->settingsDir);
|
|
}
|
|
|
|
std::string Module::setSettingsDir(const std::string &dir) {
|
|
sls::strcpy_safe(shm()->settingsDir, dir.c_str());
|
|
return shm()->settingsDir;
|
|
}
|
|
|
|
void Module::loadTrimbits(const std::string &fname) {
|
|
// find specific file if it has detid in file name (.snxxx)
|
|
if (shm()->detType == EIGER || shm()->detType == MYTHEN3) {
|
|
std::ostringstream ostfn;
|
|
ostfn << fname;
|
|
int moduleIdWidth = 3;
|
|
if (shm()->detType == MYTHEN3) {
|
|
moduleIdWidth = 4;
|
|
}
|
|
if ((fname.find(".sn") == std::string::npos) &&
|
|
(fname.find(".trim") == std::string::npos)) {
|
|
ostfn << ".sn" << std::setfill('0') << std::setw(moduleIdWidth)
|
|
<< std::dec << getModuleId();
|
|
}
|
|
auto myMod = readSettingsFile(ostfn.str());
|
|
setModule(myMod);
|
|
} else {
|
|
throw RuntimeError("not implemented for this detector");
|
|
}
|
|
}
|
|
|
|
int Module::getAllTrimbits() const {
|
|
return sendToDetector<int>(F_SET_ALL_TRIMBITS, GET_FLAG);
|
|
}
|
|
|
|
void Module::setAllTrimbits(int val) {
|
|
sendToDetector<int>(F_SET_ALL_TRIMBITS, val);
|
|
}
|
|
|
|
std::vector<int> Module::getTrimEn() const {
|
|
if (shm()->detType != EIGER && shm()->detType != MYTHEN3) {
|
|
throw RuntimeError("getTrimEn not implemented for this detector.");
|
|
}
|
|
return std::vector<int>(shm()->trimEnergies.begin(),
|
|
shm()->trimEnergies.end());
|
|
}
|
|
|
|
int Module::setTrimEn(const std::vector<int> &energies) {
|
|
if (shm()->detType != EIGER && shm()->detType != MYTHEN3) {
|
|
throw RuntimeError("setTrimEn not implemented for this detector.");
|
|
}
|
|
if (energies.size() > MAX_TRIMEN) {
|
|
std::ostringstream os;
|
|
os << "Size of trim energies: " << energies.size()
|
|
<< " exceeds what can be stored in shared memory: " << MAX_TRIMEN
|
|
<< "\n";
|
|
throw RuntimeError(os.str());
|
|
}
|
|
shm()->trimEnergies = energies;
|
|
std::sort(shm()->trimEnergies.begin(), shm()->trimEnergies.end());
|
|
return shm()->trimEnergies.size();
|
|
}
|
|
|
|
bool Module::getFlipRows() const {
|
|
if (shm()->detType == EIGER) {
|
|
return sendToReceiver<int>(F_GET_FLIP_ROWS_RECEIVER);
|
|
}
|
|
return sendToDetector<int>(F_GET_FLIP_ROWS);
|
|
}
|
|
|
|
void Module::setFlipRows(bool value) {
|
|
if (shm()->detType == EIGER) {
|
|
sendToReceiver<int>(F_SET_FLIP_ROWS_RECEIVER, static_cast<int>(value));
|
|
} else {
|
|
sendToDetector(F_SET_FLIP_ROWS, static_cast<int>(value), nullptr);
|
|
}
|
|
}
|
|
|
|
bool Module::isVirtualDetectorServer() const {
|
|
return sendToDetector<int>(F_IS_VIRTUAL);
|
|
}
|
|
|
|
int64_t Module::getNumberOfFrames() const {
|
|
return sendToDetector<int64_t>(F_GET_NUM_FRAMES);
|
|
}
|
|
|
|
void Module::setNumberOfFrames(int64_t value) {
|
|
sendToDetector(F_SET_NUM_FRAMES, value, nullptr);
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver(F_RECEIVER_SET_NUM_FRAMES, value, nullptr);
|
|
}
|
|
}
|
|
|
|
int64_t Module::getNumberOfTriggers() const {
|
|
return sendToDetector<int64_t>(F_GET_NUM_TRIGGERS);
|
|
}
|
|
|
|
void Module::setNumberOfTriggers(int64_t value) {
|
|
sendToDetector(F_SET_NUM_TRIGGERS, value, nullptr);
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver(F_SET_RECEIVER_NUM_TRIGGERS, value, nullptr);
|
|
}
|
|
}
|
|
|
|
int64_t Module::getExptime(int gateIndex) const {
|
|
return sendToDetector<int64_t>(F_GET_EXPTIME, gateIndex);
|
|
}
|
|
|
|
void Module::setExptime(int gateIndex, int64_t value) {
|
|
int64_t prevVal = value;
|
|
if (shm()->detType == EIGER) {
|
|
prevVal = getExptime(-1);
|
|
}
|
|
int64_t args[]{static_cast<int64_t>(gateIndex), value};
|
|
sendToDetector(F_SET_EXPTIME, args, nullptr);
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver(F_RECEIVER_SET_EXPTIME, args, nullptr);
|
|
}
|
|
if (prevVal != value) {
|
|
updateRateCorrection();
|
|
}
|
|
}
|
|
|
|
int64_t Module::getPeriod() const {
|
|
return sendToDetector<int64_t>(F_GET_PERIOD);
|
|
}
|
|
|
|
void Module::setPeriod(int64_t value) {
|
|
sendToDetector(F_SET_PERIOD, value, nullptr);
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver(F_RECEIVER_SET_PERIOD, value, nullptr);
|
|
}
|
|
}
|
|
|
|
int64_t Module::getDelayAfterTrigger() const {
|
|
return sendToDetector<int64_t>(F_GET_DELAY_AFTER_TRIGGER);
|
|
}
|
|
|
|
void Module::setDelayAfterTrigger(int64_t value) {
|
|
sendToDetector(F_SET_DELAY_AFTER_TRIGGER, value, nullptr);
|
|
}
|
|
|
|
int64_t Module::getNumberOfFramesLeft() const {
|
|
return sendToDetectorStop<int64_t>(F_GET_FRAMES_LEFT);
|
|
}
|
|
|
|
int64_t Module::getNumberOfTriggersLeft() const {
|
|
return sendToDetectorStop<int64_t>(F_GET_TRIGGERS_LEFT);
|
|
}
|
|
|
|
int64_t Module::getDelayAfterTriggerLeft() const {
|
|
return sendToDetectorStop<int64_t>(F_GET_DELAY_AFTER_TRIGGER_LEFT);
|
|
}
|
|
|
|
int64_t Module::getPeriodLeft() const {
|
|
return sendToDetectorStop<int64_t>(F_GET_PERIOD_LEFT);
|
|
}
|
|
|
|
int Module::getDynamicRange() const {
|
|
return sendToDetector<int>(F_SET_DYNAMIC_RANGE, GET_FLAG);
|
|
}
|
|
|
|
void Module::setDynamicRange(int dr) {
|
|
int prev_val = dr;
|
|
if (shm()->detType == EIGER) {
|
|
prev_val = getDynamicRange();
|
|
}
|
|
|
|
auto retval = sendToDetector<int>(F_SET_DYNAMIC_RANGE, dr);
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver<int>(F_SET_RECEIVER_DYNAMIC_RANGE, retval);
|
|
}
|
|
|
|
// update speed
|
|
if (shm()->detType == EIGER) {
|
|
if (dr == 32) {
|
|
LOG(logINFO) << "Setting Clock to Quarter Speed to cope with "
|
|
"Dynamic Range of 32";
|
|
setReadoutSpeed(defs::QUARTER_SPEED);
|
|
} else {
|
|
LOG(logINFO) << "Setting Clock to Full Speed for Dynamic Range of "
|
|
<< dr;
|
|
setReadoutSpeed(defs::FULL_SPEED);
|
|
}
|
|
// EIGER only, update speed and rate correction when dr changes
|
|
if (dr != prev_val) {
|
|
updateRateCorrection();
|
|
}
|
|
}
|
|
}
|
|
|
|
slsDetectorDefs::timingMode Module::getTimingMode() const {
|
|
return sendToDetector<timingMode>(F_SET_TIMING_MODE, GET_FLAG);
|
|
}
|
|
|
|
void Module::setTimingMode(timingMode value) {
|
|
sendToDetector<int>(F_SET_TIMING_MODE, value);
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver(F_SET_RECEIVER_TIMING_MODE, value, nullptr);
|
|
}
|
|
}
|
|
|
|
slsDetectorDefs::speedLevel Module::getReadoutSpeed() const {
|
|
return sendToDetector<speedLevel>(F_GET_READOUT_SPEED);
|
|
}
|
|
|
|
void Module::setReadoutSpeed(speedLevel value) {
|
|
sendToDetector(F_SET_READOUT_SPEED, value, nullptr);
|
|
}
|
|
|
|
int Module::getClockDivider(int clkIndex) const {
|
|
return sendToDetector<int>(F_GET_CLOCK_DIVIDER, clkIndex);
|
|
}
|
|
|
|
void Module::setClockDivider(int clkIndex, int value) {
|
|
int args[]{clkIndex, value};
|
|
sendToDetector(F_SET_CLOCK_DIVIDER, args, nullptr);
|
|
}
|
|
|
|
int Module::getClockPhase(int clkIndex, bool inDegrees) const {
|
|
int args[]{clkIndex, static_cast<int>(inDegrees)};
|
|
return sendToDetector<int>(F_GET_CLOCK_PHASE, args);
|
|
}
|
|
|
|
void Module::setClockPhase(int clkIndex, int value, bool inDegrees) {
|
|
int args[]{clkIndex, value, static_cast<int>(inDegrees)};
|
|
sendToDetector(F_SET_CLOCK_PHASE, args, nullptr);
|
|
}
|
|
|
|
int Module::getMaxClockPhaseShift(int clkIndex) const {
|
|
return sendToDetector<int>(F_GET_MAX_CLOCK_PHASE_SHIFT, clkIndex);
|
|
}
|
|
|
|
int Module::getClockFrequency(int clkIndex) const {
|
|
return sendToDetector<int>(F_GET_CLOCK_FREQUENCY, clkIndex);
|
|
}
|
|
|
|
void Module::setClockFrequency(int clkIndex, int value) {
|
|
int args[]{clkIndex, value};
|
|
sendToDetector(F_SET_CLOCK_FREQUENCY, args, nullptr);
|
|
}
|
|
|
|
int Module::getDAC(dacIndex index, bool mV) const {
|
|
int args[]{static_cast<int>(index), static_cast<int>(mV), GET_FLAG};
|
|
return sendToDetector<int>(F_SET_DAC, args);
|
|
}
|
|
int Module::getDefaultDac(slsDetectorDefs::dacIndex index,
|
|
slsDetectorDefs::detectorSettings sett) {
|
|
int args[]{static_cast<int>(index), static_cast<int>(sett)};
|
|
return sendToDetector<int>(F_GET_DEFAULT_DAC, args);
|
|
}
|
|
void Module::setDefaultDac(slsDetectorDefs::dacIndex index, int defaultValue,
|
|
defs::detectorSettings sett) {
|
|
int args[]{static_cast<int>(index), static_cast<int>(sett), defaultValue};
|
|
return sendToDetector(F_SET_DEFAULT_DAC, args, nullptr);
|
|
}
|
|
|
|
void Module::resetToDefaultDacs(const bool hardReset) {
|
|
sendToDetector(F_RESET_TO_DEFAULT_DACS, static_cast<int>(hardReset),
|
|
nullptr);
|
|
}
|
|
|
|
void Module::setDAC(int val, dacIndex index, bool mV) {
|
|
int args[]{static_cast<int>(index), static_cast<int>(mV), val};
|
|
sendToDetector<int>(F_SET_DAC, args);
|
|
}
|
|
|
|
bool Module::getPowerChip() const {
|
|
return sendToDetector<int>(F_POWER_CHIP, GET_FLAG);
|
|
}
|
|
|
|
void Module::setPowerChip(bool on) {
|
|
sendToDetector<int>(F_POWER_CHIP, static_cast<int>(on));
|
|
}
|
|
|
|
int Module::getImageTestMode() const {
|
|
return sendToDetector<int>(F_GET_IMAGE_TEST_MODE);
|
|
}
|
|
|
|
void Module::setImageTestMode(const int value) {
|
|
sendToDetector(F_SET_IMAGE_TEST_MODE, value, nullptr);
|
|
}
|
|
|
|
int Module::getADC(dacIndex index) const {
|
|
switch (index) {
|
|
case TEMPERATURE_ADC:
|
|
case TEMPERATURE_FPGA:
|
|
case TEMPERATURE_FPGAEXT:
|
|
case TEMPERATURE_10GE:
|
|
case TEMPERATURE_DCDC:
|
|
case TEMPERATURE_SODL:
|
|
case TEMPERATURE_SODR:
|
|
case TEMPERATURE_FPGA2:
|
|
case TEMPERATURE_FPGA3:
|
|
// only the temperatures go to the control server, others need
|
|
// configuration of adc in control server
|
|
return sendToDetectorStop<int>(F_GET_ADC, index);
|
|
|
|
default:
|
|
return sendToDetector<int>(F_GET_ADC, index);
|
|
}
|
|
}
|
|
|
|
int Module::getOnChipDAC(slsDetectorDefs::dacIndex index, int chipIndex) const {
|
|
int args[]{static_cast<int>(index), chipIndex};
|
|
return sendToDetector<int>(F_GET_ON_CHIP_DAC, args);
|
|
}
|
|
|
|
void Module::setOnChipDAC(slsDetectorDefs::dacIndex index, int chipIndex,
|
|
int value) {
|
|
int args[]{static_cast<int>(index), chipIndex, value};
|
|
sendToDetector(F_SET_ON_CHIP_DAC, args, nullptr);
|
|
}
|
|
|
|
slsDetectorDefs::externalSignalFlag
|
|
Module::getExternalSignalFlags(int signalIndex) const {
|
|
return sendToDetector<slsDetectorDefs::externalSignalFlag>(
|
|
F_GET_EXTERNAL_SIGNAL_FLAG, signalIndex);
|
|
}
|
|
|
|
void Module::setExternalSignalFlags(int signalIndex, externalSignalFlag type) {
|
|
int args[]{signalIndex, static_cast<int>(type)};
|
|
sendToDetector(F_SET_EXTERNAL_SIGNAL_FLAG, args, nullptr);
|
|
}
|
|
|
|
bool Module::getParallelMode() const {
|
|
return sendToDetector<int>(F_GET_PARALLEL_MODE);
|
|
}
|
|
|
|
void Module::setParallelMode(const bool enable) {
|
|
sendToDetector(F_SET_PARALLEL_MODE, static_cast<int>(enable), nullptr);
|
|
}
|
|
|
|
int Module::getFilterResistor() const {
|
|
return sendToDetector<int>(F_GET_FILTER_RESISTOR);
|
|
}
|
|
|
|
void Module::setFilterResistor(int value) {
|
|
sendToDetector(F_SET_FILTER_RESISTOR, value, nullptr);
|
|
}
|
|
|
|
defs::currentSrcParameters Module::getCurrentSource() const {
|
|
return sendToDetector<defs::currentSrcParameters>(F_GET_CURRENT_SOURCE);
|
|
}
|
|
|
|
void Module::setCurrentSource(defs::currentSrcParameters par) {
|
|
sendToDetector(F_SET_CURRENT_SOURCE, par, nullptr);
|
|
}
|
|
|
|
int Module::getDBITPipeline() const {
|
|
return sendToDetector<int>(F_GET_DBIT_PIPELINE);
|
|
}
|
|
|
|
void Module::setDBITPipeline(int value) {
|
|
sendToDetector(F_SET_DBIT_PIPELINE, value, nullptr);
|
|
}
|
|
|
|
int Module::getReadNRows() const {
|
|
return sendToDetector<int>(F_GET_READ_N_ROWS);
|
|
}
|
|
|
|
void Module::setReadNRows(const int value) {
|
|
sendToDetector(F_SET_READ_N_ROWS, value, nullptr);
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver(F_SET_RECEIVER_READ_N_ROWS, value, nullptr);
|
|
}
|
|
}
|
|
|
|
// Acquisition
|
|
|
|
void Module::startReceiver() {
|
|
shm()->stoppedFlag = false;
|
|
sendToReceiver(F_START_RECEIVER);
|
|
}
|
|
|
|
void Module::stopReceiver() {
|
|
sendToReceiver(F_STOP_RECEIVER, static_cast<int>(shm()->stoppedFlag),
|
|
nullptr);
|
|
}
|
|
|
|
void Module::startAcquisition() {
|
|
shm()->stoppedFlag = false;
|
|
sendToDetector(F_START_ACQUISITION);
|
|
}
|
|
|
|
void Module::startReadout() {
|
|
shm()->stoppedFlag = false;
|
|
sendToDetector(F_START_READOUT);
|
|
}
|
|
|
|
void Module::stopAcquisition() {
|
|
// get status before stopping acquisition
|
|
runStatus s = ERROR, r = ERROR;
|
|
bool zmqstreaming = false;
|
|
try {
|
|
if (shm()->useReceiverFlag && getReceiverStreaming()) {
|
|
zmqstreaming = true;
|
|
s = getRunStatus();
|
|
r = getReceiverStatus();
|
|
}
|
|
} catch (...) {
|
|
// if receiver crashed, stop detector in any case
|
|
zmqstreaming = false;
|
|
}
|
|
|
|
sendToDetectorStop(F_STOP_ACQUISITION);
|
|
shm()->stoppedFlag = true;
|
|
|
|
// if rxr streaming and acquisition finished, restream dummy stop packet
|
|
if (zmqstreaming && (s == IDLE) && (r == IDLE)) {
|
|
restreamStopFromReceiver();
|
|
}
|
|
}
|
|
|
|
void Module::restreamStopFromReceiver() {
|
|
sendToReceiver(F_RESTREAM_STOP_FROM_RECEIVER);
|
|
}
|
|
|
|
void Module::startAndReadAll() {
|
|
shm()->stoppedFlag = false;
|
|
sendToDetector(F_START_AND_READ_ALL);
|
|
}
|
|
|
|
slsDetectorDefs::runStatus Module::getRunStatus() const {
|
|
return sendToDetectorStop<runStatus>(F_GET_RUN_STATUS);
|
|
}
|
|
|
|
slsDetectorDefs::runStatus Module::getReceiverStatus() const {
|
|
return sendToReceiver<runStatus>(F_GET_RECEIVER_STATUS);
|
|
}
|
|
|
|
double Module::getReceiverProgress() const {
|
|
return sendToReceiver<double>(F_GET_RECEIVER_PROGRESS);
|
|
}
|
|
|
|
int64_t Module::getFramesCaughtByReceiver() const {
|
|
return sendToReceiver<int64_t>(F_GET_RECEIVER_FRAMES_CAUGHT);
|
|
}
|
|
|
|
std::vector<uint64_t> Module::getNumMissingPackets() const {
|
|
// TODO!(Erik) Refactor
|
|
LOG(logDEBUG1) << "Getting num missing packets";
|
|
if (shm()->useReceiverFlag) {
|
|
auto client = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort);
|
|
client.Send(F_GET_NUM_MISSING_PACKETS);
|
|
if (client.Receive<int>() == FAIL) {
|
|
throw ReceiverError(
|
|
"Receiver " + std::to_string(moduleIndex) +
|
|
" returned error: " + client.readErrorMessage());
|
|
} else {
|
|
auto nports = client.Receive<int>();
|
|
std::vector<uint64_t> retval(nports);
|
|
client.Receive(retval);
|
|
LOG(logDEBUG1) << "Missing packets of Receiver" << moduleIndex
|
|
<< ": " << sls::ToString(retval);
|
|
return retval;
|
|
}
|
|
}
|
|
throw RuntimeError("No receiver to get missing packets.");
|
|
}
|
|
|
|
uint64_t Module::getNextFrameNumber() const {
|
|
return sendToDetector<uint64_t>(F_GET_NEXT_FRAME_NUMBER);
|
|
}
|
|
|
|
void Module::setNextFrameNumber(uint64_t value) {
|
|
sendToDetector(F_SET_NEXT_FRAME_NUMBER, value, nullptr);
|
|
}
|
|
|
|
void Module::sendSoftwareTrigger(const bool block) {
|
|
sendToDetectorStop(F_SOFTWARE_TRIGGER, static_cast<int>(block), nullptr);
|
|
}
|
|
|
|
defs::scanParameters Module::getScan() const {
|
|
return sendToDetector<defs::scanParameters>(F_GET_SCAN);
|
|
}
|
|
|
|
void Module::setScan(const defs::scanParameters t) {
|
|
auto retval = sendToDetector<int64_t>(F_SET_SCAN, t);
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver(F_SET_RECEIVER_SCAN, t, nullptr);
|
|
}
|
|
// if disabled, retval is 1, else its number of steps
|
|
setNumberOfFrames(retval);
|
|
}
|
|
|
|
std::string Module::getScanErrorMessage() const {
|
|
char retval[MAX_STR_LENGTH]{};
|
|
sendToDetector(F_GET_SCAN_ERROR_MESSAGE, nullptr, retval);
|
|
return retval;
|
|
}
|
|
|
|
// Network Configuration (Detector<->Receiver)
|
|
|
|
int Module::getNumberofUDPInterfacesFromShm() const {
|
|
return shm()->numUDPInterfaces;
|
|
}
|
|
|
|
int Module::getNumberofUDPInterfaces() const {
|
|
shm()->numUDPInterfaces = sendToDetector<int>(F_GET_NUM_INTERFACES);
|
|
return shm()->numUDPInterfaces;
|
|
}
|
|
|
|
void Module::setNumberofUDPInterfaces(int n) {
|
|
sendToDetector(F_SET_NUM_INTERFACES, n, nullptr);
|
|
shm()->numUDPInterfaces = n;
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver(F_SET_RECEIVER_NUM_INTERFACES, n, nullptr);
|
|
}
|
|
}
|
|
|
|
int Module::getSelectedUDPInterface() const {
|
|
return sendToDetector<int>(F_GET_INTERFACE_SEL);
|
|
}
|
|
|
|
void Module::selectUDPInterface(int n) {
|
|
sendToDetector(F_SET_INTERFACE_SEL, n, nullptr);
|
|
}
|
|
|
|
sls::IpAddr Module::getSourceUDPIP() const {
|
|
return sendToDetector<sls::IpAddr>(F_GET_SOURCE_UDP_IP);
|
|
}
|
|
|
|
void Module::setSourceUDPIP(const IpAddr ip) {
|
|
if (ip == 0) {
|
|
throw RuntimeError("Invalid source udp ip address");
|
|
}
|
|
sendToDetector(F_SET_SOURCE_UDP_IP, ip, nullptr);
|
|
}
|
|
|
|
sls::IpAddr Module::getSourceUDPIP2() const {
|
|
return sendToDetector<sls::IpAddr>(F_GET_SOURCE_UDP_IP2);
|
|
}
|
|
|
|
void Module::setSourceUDPIP2(const IpAddr ip) {
|
|
if (ip == 0) {
|
|
throw RuntimeError("Invalid source udp ip address2");
|
|
}
|
|
sendToDetector(F_SET_SOURCE_UDP_IP2, ip, nullptr);
|
|
}
|
|
|
|
sls::MacAddr Module::getSourceUDPMAC() const {
|
|
return sendToDetector<sls::MacAddr>(F_GET_SOURCE_UDP_MAC);
|
|
}
|
|
|
|
void Module::setSourceUDPMAC(const sls::MacAddr mac) {
|
|
if (mac == 0) {
|
|
throw RuntimeError("Invalid source udp mac address");
|
|
}
|
|
sendToDetector(F_SET_SOURCE_UDP_MAC, mac, nullptr);
|
|
}
|
|
|
|
sls::MacAddr Module::getSourceUDPMAC2() const {
|
|
return sendToDetector<sls::MacAddr>(F_GET_SOURCE_UDP_MAC2);
|
|
}
|
|
|
|
void Module::setSourceUDPMAC2(const sls::MacAddr mac) {
|
|
if (mac == 0) {
|
|
throw RuntimeError("Invalid source udp mac address2");
|
|
}
|
|
sendToDetector(F_SET_SOURCE_UDP_MAC2, mac, nullptr);
|
|
}
|
|
|
|
sls::UdpDestination Module::getDestinationUDPList(const uint32_t entry) const {
|
|
return sendToDetector<sls::UdpDestination>(F_GET_DEST_UDP_LIST, entry);
|
|
}
|
|
|
|
void Module::setDestinationUDPList(const sls::UdpDestination dest) {
|
|
// set them in the default way so the receivers are also set up
|
|
if (dest.entry == 0) {
|
|
if (dest.port != 0) {
|
|
setDestinationUDPPort(dest.port);
|
|
}
|
|
if (dest.ip != 0) {
|
|
setDestinationUDPIP(dest.ip);
|
|
}
|
|
if (dest.mac != 0) {
|
|
setDestinationUDPMAC(dest.mac);
|
|
}
|
|
if (dest.port2 != 0) {
|
|
setDestinationUDPPort2(dest.port2);
|
|
}
|
|
if (dest.ip2 != 0) {
|
|
setDestinationUDPIP2(dest.ip2);
|
|
}
|
|
if (dest.mac2 != 0) {
|
|
setDestinationUDPMAC2(dest.mac2);
|
|
}
|
|
} else {
|
|
sendToDetector(F_SET_DEST_UDP_LIST, dest, nullptr);
|
|
}
|
|
}
|
|
|
|
int Module::getNumberofUDPDestinations() const {
|
|
return sendToDetector<int>(F_GET_NUM_DEST_UDP);
|
|
}
|
|
|
|
void Module::clearUDPDestinations() { sendToDetector(F_CLEAR_ALL_UDP_DEST); }
|
|
|
|
int Module::getFirstUDPDestination() const {
|
|
return sendToDetector<int>(F_GET_UDP_FIRST_DEST);
|
|
}
|
|
|
|
void Module::setFirstUDPDestination(const int value) {
|
|
sendToDetector(F_SET_UDP_FIRST_DEST, value, nullptr);
|
|
}
|
|
|
|
sls::IpAddr Module::getDestinationUDPIP() const {
|
|
return sendToDetector<sls::IpAddr>(F_GET_DEST_UDP_IP);
|
|
}
|
|
|
|
void Module::setDestinationUDPIP(const IpAddr ip) {
|
|
if (ip == 0) {
|
|
throw RuntimeError("Invalid destination udp ip address");
|
|
}
|
|
sendToDetector(F_SET_DEST_UDP_IP, ip, nullptr);
|
|
if (shm()->useReceiverFlag) {
|
|
sls::MacAddr retval(0LU);
|
|
sendToReceiver(F_SET_RECEIVER_UDP_IP, ip, retval);
|
|
LOG(logINFO) << "Setting destination udp mac of Module " << moduleIndex
|
|
<< " to " << retval;
|
|
sendToDetector(F_SET_DEST_UDP_MAC, retval, nullptr);
|
|
}
|
|
}
|
|
|
|
sls::IpAddr Module::getDestinationUDPIP2() const {
|
|
return sendToDetector<sls::IpAddr>(F_GET_DEST_UDP_IP2);
|
|
}
|
|
|
|
void Module::setDestinationUDPIP2(const IpAddr ip) {
|
|
LOG(logDEBUG1) << "Setting destination udp ip2 to " << ip;
|
|
if (ip == 0) {
|
|
throw RuntimeError("Invalid destination udp ip address2");
|
|
}
|
|
|
|
sendToDetector(F_SET_DEST_UDP_IP2, ip, nullptr);
|
|
if (shm()->useReceiverFlag) {
|
|
sls::MacAddr retval(0LU);
|
|
sendToReceiver(F_SET_RECEIVER_UDP_IP2, ip, retval);
|
|
LOG(logINFO) << "Setting destination udp mac2 of Module " << moduleIndex
|
|
<< " to " << retval;
|
|
sendToDetector(F_SET_DEST_UDP_MAC2, retval, nullptr);
|
|
}
|
|
}
|
|
|
|
sls::MacAddr Module::getDestinationUDPMAC() const {
|
|
return sendToDetector<sls::MacAddr>(F_GET_DEST_UDP_MAC);
|
|
}
|
|
|
|
void Module::setDestinationUDPMAC(const MacAddr mac) {
|
|
if (mac == 0) {
|
|
throw RuntimeError("Invalid destination udp mac address");
|
|
}
|
|
sendToDetector(F_SET_DEST_UDP_MAC, mac, nullptr);
|
|
}
|
|
|
|
sls::MacAddr Module::getDestinationUDPMAC2() const {
|
|
return sendToDetector<sls::MacAddr>(F_GET_DEST_UDP_MAC2);
|
|
}
|
|
|
|
void Module::setDestinationUDPMAC2(const MacAddr mac) {
|
|
if (mac == 0) {
|
|
throw RuntimeError("Invalid desinaion udp mac address2");
|
|
}
|
|
sendToDetector(F_SET_DEST_UDP_MAC2, mac, nullptr);
|
|
}
|
|
|
|
int Module::getDestinationUDPPort() const {
|
|
return sendToDetector<int>(F_GET_DEST_UDP_PORT);
|
|
}
|
|
|
|
void Module::setDestinationUDPPort(const int port) {
|
|
sendToDetector(F_SET_DEST_UDP_PORT, port, nullptr);
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver(F_SET_RECEIVER_UDP_PORT, port, nullptr);
|
|
}
|
|
}
|
|
|
|
int Module::getDestinationUDPPort2() const {
|
|
return sendToDetector<int>(F_GET_DEST_UDP_PORT2);
|
|
}
|
|
|
|
void Module::setDestinationUDPPort2(const int port) {
|
|
sendToDetector(F_SET_DEST_UDP_PORT2, port, nullptr);
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver(F_SET_RECEIVER_UDP_PORT2, port, nullptr);
|
|
}
|
|
}
|
|
|
|
void Module::reconfigureUDPDestination() { sendToDetector(F_RECONFIGURE_UDP); }
|
|
|
|
void Module::validateUDPConfiguration() {
|
|
sendToDetector(F_VALIDATE_UDP_CONFIG);
|
|
}
|
|
|
|
std::string Module::printReceiverConfiguration() {
|
|
std::ostringstream os;
|
|
os << "\n\nModule " << moduleIndex << "\nReceiver Hostname:\t"
|
|
<< getReceiverHostname();
|
|
|
|
if (shm()->detType == JUNGFRAU) {
|
|
os << "\nNumber of Interfaces:\t" << getNumberofUDPInterfaces()
|
|
<< "\nSelected Interface:\t" << getSelectedUDPInterface();
|
|
}
|
|
|
|
os << "\nSource UDP IP:\t" << getSourceUDPIP() << "\nSource UDP MAC:\t"
|
|
<< getSourceUDPMAC() << "\nDestination UDP IP:\t"
|
|
<< getDestinationUDPIP() << "\nDestination UDP MAC:\t"
|
|
<< getDestinationUDPMAC();
|
|
|
|
if (shm()->detType == JUNGFRAU) {
|
|
os << "\nSource UDP IP2:\t" << getSourceUDPIP2()
|
|
<< "\nSource UDP MAC2:\t" << getSourceUDPMAC2()
|
|
<< "\nDestination UDP IP2:\t" << getDestinationUDPIP2()
|
|
<< "\nDestination UDP MAC2:\t" << getDestinationUDPMAC2();
|
|
}
|
|
os << "\nDestination UDP Port:\t" << getDestinationUDPPort();
|
|
if (shm()->detType == JUNGFRAU || shm()->detType == EIGER) {
|
|
os << "\nDestination UDP Port2:\t" << getDestinationUDPPort2();
|
|
}
|
|
os << "\n";
|
|
return os.str();
|
|
}
|
|
|
|
bool Module::getTenGiga() const {
|
|
return sendToDetector<int>(F_ENABLE_TEN_GIGA, GET_FLAG);
|
|
}
|
|
|
|
void Module::setTenGiga(bool value) {
|
|
auto arg = static_cast<int>(value);
|
|
auto retval = sendToDetector<int>(F_ENABLE_TEN_GIGA, arg);
|
|
sendToDetectorStop<int>(F_ENABLE_TEN_GIGA, arg);
|
|
arg = retval;
|
|
if (shm()->useReceiverFlag && arg != GET_FLAG) {
|
|
sendToReceiver<int>(F_ENABLE_RECEIVER_TEN_GIGA, arg);
|
|
}
|
|
}
|
|
|
|
bool Module::getTenGigaFlowControl() const {
|
|
return sendToDetector<int>(F_GET_TEN_GIGA_FLOW_CONTROL);
|
|
}
|
|
|
|
void Module::setTenGigaFlowControl(bool enable) {
|
|
sendToDetector(F_SET_TEN_GIGA_FLOW_CONTROL, static_cast<int>(enable),
|
|
nullptr);
|
|
}
|
|
|
|
int Module::getTransmissionDelayFrame() const {
|
|
return sendToDetector<int>(F_GET_TRANSMISSION_DELAY_FRAME);
|
|
}
|
|
|
|
void Module::setTransmissionDelayFrame(int value) {
|
|
sendToDetector(F_SET_TRANSMISSION_DELAY_FRAME, value, nullptr);
|
|
}
|
|
|
|
int Module::getTransmissionDelayLeft() const {
|
|
return sendToDetector<int>(F_GET_TRANSMISSION_DELAY_LEFT);
|
|
}
|
|
|
|
void Module::setTransmissionDelayLeft(int value) {
|
|
sendToDetector(F_SET_TRANSMISSION_DELAY_LEFT, value, nullptr);
|
|
}
|
|
|
|
int Module::getTransmissionDelayRight() const {
|
|
return sendToDetector<int>(F_GET_TRANSMISSION_DELAY_RIGHT);
|
|
}
|
|
|
|
void Module::setTransmissionDelayRight(int value) {
|
|
sendToDetector(F_SET_TRANSMISSION_DELAY_RIGHT, value, nullptr);
|
|
}
|
|
|
|
// Receiver Config
|
|
|
|
bool Module::getUseReceiverFlag() const { return shm()->useReceiverFlag; }
|
|
|
|
std::string Module::getReceiverHostname() const {
|
|
return std::string(shm()->rxHostname);
|
|
}
|
|
|
|
void Module::setReceiverHostname(const std::string &receiverIP) {
|
|
LOG(logDEBUG1) << "Setting up Receiver hostname with " << receiverIP;
|
|
|
|
if (getRunStatus() == RUNNING) {
|
|
throw RuntimeError("Cannot set receiver hostname. Acquisition already "
|
|
"running. Stop it first.");
|
|
}
|
|
|
|
if (receiverIP == "none") {
|
|
memset(shm()->rxHostname, 0, MAX_STR_LENGTH);
|
|
sls::strcpy_safe(shm()->rxHostname, "none");
|
|
shm()->useReceiverFlag = false;
|
|
return;
|
|
}
|
|
|
|
// start updating
|
|
std::string host = receiverIP;
|
|
auto res = sls::split(host, ':');
|
|
if (res.size() > 1) {
|
|
host = res[0];
|
|
shm()->rxTCPPort = std::stoi(res[1]);
|
|
}
|
|
sls::strcpy_safe(shm()->rxHostname, host.c_str());
|
|
shm()->useReceiverFlag = true;
|
|
checkReceiverVersionCompatibility();
|
|
|
|
// populate parameters from detector
|
|
rxParameters retval;
|
|
sendToDetector(F_GET_RECEIVER_PARAMETERS, nullptr, retval);
|
|
|
|
// populate from shared memory
|
|
retval.detType = shm()->detType;
|
|
retval.numberOfModule.x = shm()->numberOfModule.x;
|
|
retval.numberOfModule.y = shm()->numberOfModule.y;
|
|
retval.moduleIndex = moduleIndex;
|
|
memset(retval.hostname, 0, sizeof(retval.hostname));
|
|
strcpy_safe(retval.hostname, shm()->hostname);
|
|
|
|
sls::MacAddr retvals[2];
|
|
sendToReceiver(F_SETUP_RECEIVER, retval, retvals);
|
|
// update Modules with dest mac
|
|
if (retval.udp_dstmac == 0 && retvals[0] != 0) {
|
|
LOG(logINFO) << "Setting destination udp mac of "
|
|
"Module "
|
|
<< moduleIndex << " to " << retvals[0];
|
|
sendToDetector(F_SET_DEST_UDP_MAC, retvals[0], nullptr);
|
|
}
|
|
if (retval.udp_dstmac2 == 0 && retvals[1] != 0) {
|
|
LOG(logINFO) << "Setting destination udp mac2 of "
|
|
"Module "
|
|
<< moduleIndex << " to " << retvals[1];
|
|
sendToDetector(F_SET_DEST_UDP_MAC2, retvals[1], nullptr);
|
|
}
|
|
|
|
shm()->numUDPInterfaces = retval.udpInterfaces;
|
|
|
|
// to use rx_hostname if empty and also update client zmqip
|
|
updateReceiverStreamingIP();
|
|
}
|
|
|
|
int Module::getReceiverPort() const { return shm()->rxTCPPort; }
|
|
|
|
int Module::setReceiverPort(int port_number) {
|
|
if (port_number >= 0 && port_number != shm()->rxTCPPort) {
|
|
shm()->rxTCPPort = port_number;
|
|
}
|
|
return shm()->rxTCPPort;
|
|
}
|
|
|
|
int Module::getReceiverFifoDepth() const {
|
|
return sendToReceiver<int>(F_SET_RECEIVER_FIFO_DEPTH, GET_FLAG);
|
|
}
|
|
|
|
void Module::setReceiverFifoDepth(int n_frames) {
|
|
sendToReceiver<int>(F_SET_RECEIVER_FIFO_DEPTH, n_frames);
|
|
}
|
|
|
|
bool Module::getReceiverSilentMode() const {
|
|
return sendToReceiver<int>(F_GET_RECEIVER_SILENT_MODE);
|
|
}
|
|
|
|
void Module::setReceiverSilentMode(bool enable) {
|
|
sendToReceiver(F_SET_RECEIVER_SILENT_MODE, static_cast<int>(enable),
|
|
nullptr);
|
|
}
|
|
|
|
slsDetectorDefs::frameDiscardPolicy
|
|
Module::getReceiverFramesDiscardPolicy() const {
|
|
return sendToReceiver<frameDiscardPolicy>(F_GET_RECEIVER_DISCARD_POLICY);
|
|
}
|
|
|
|
void Module::setReceiverFramesDiscardPolicy(frameDiscardPolicy f) {
|
|
sendToReceiver(F_SET_RECEIVER_DISCARD_POLICY, static_cast<int>(f), nullptr);
|
|
}
|
|
|
|
bool Module::getPartialFramesPadding() const {
|
|
return sendToReceiver<int>(F_GET_RECEIVER_PADDING);
|
|
}
|
|
|
|
void Module::setPartialFramesPadding(bool padding) {
|
|
sendToReceiver(F_SET_RECEIVER_PADDING, static_cast<int>(padding), nullptr);
|
|
}
|
|
|
|
int Module::getReceiverUDPSocketBufferSize() const {
|
|
int arg = GET_FLAG;
|
|
return sendToReceiver<int>(F_RECEIVER_UDP_SOCK_BUF_SIZE, arg);
|
|
}
|
|
|
|
int Module::getReceiverRealUDPSocketBufferSize() const {
|
|
return sendToReceiver<int>(F_RECEIVER_REAL_UDP_SOCK_BUF_SIZE);
|
|
}
|
|
|
|
void Module::setReceiverUDPSocketBufferSize(int udpsockbufsize) {
|
|
sendToReceiver<int>(F_RECEIVER_UDP_SOCK_BUF_SIZE, udpsockbufsize);
|
|
}
|
|
|
|
bool Module::getReceiverLock() const {
|
|
return sendToReceiver<int>(F_LOCK_RECEIVER, GET_FLAG);
|
|
}
|
|
|
|
void Module::setReceiverLock(bool lock) {
|
|
sendToReceiver<int>(F_LOCK_RECEIVER, static_cast<int>(lock));
|
|
}
|
|
|
|
sls::IpAddr Module::getReceiverLastClientIP() const {
|
|
return sendToReceiver<sls::IpAddr>(F_GET_LAST_RECEIVER_CLIENT_IP);
|
|
}
|
|
|
|
std::array<pid_t, NUM_RX_THREAD_IDS> Module::getReceiverThreadIds() const {
|
|
return sendToReceiver<std::array<pid_t, NUM_RX_THREAD_IDS>>(
|
|
F_GET_RECEIVER_THREAD_IDS);
|
|
}
|
|
|
|
// File
|
|
slsDetectorDefs::fileFormat Module::getFileFormat() const {
|
|
return sendToReceiver<fileFormat>(F_GET_RECEIVER_FILE_FORMAT);
|
|
}
|
|
|
|
void Module::setFileFormat(fileFormat f) {
|
|
sendToReceiver(F_SET_RECEIVER_FILE_FORMAT, f, nullptr);
|
|
}
|
|
|
|
std::string Module::getFilePath() const {
|
|
char ret[MAX_STR_LENGTH]{};
|
|
sendToReceiver(F_GET_RECEIVER_FILE_PATH, nullptr, ret);
|
|
return ret;
|
|
}
|
|
|
|
void Module::setFilePath(const std::string &path) {
|
|
if (path.empty()) {
|
|
throw RuntimeError("Cannot set empty file path");
|
|
}
|
|
char args[MAX_STR_LENGTH]{};
|
|
sls::strcpy_safe(args, path.c_str());
|
|
sendToReceiver(F_SET_RECEIVER_FILE_PATH, args, nullptr);
|
|
}
|
|
|
|
std::string Module::getFileName() const {
|
|
char buff[MAX_STR_LENGTH]{};
|
|
sendToReceiver(F_GET_RECEIVER_FILE_NAME, nullptr, buff);
|
|
return buff;
|
|
}
|
|
|
|
void Module::setFileName(const std::string &fname) {
|
|
if (fname.empty()) {
|
|
throw RuntimeError("Cannot set empty file name prefix");
|
|
}
|
|
char args[MAX_STR_LENGTH]{};
|
|
sls::strcpy_safe(args, fname.c_str());
|
|
sendToReceiver(F_SET_RECEIVER_FILE_NAME, args, nullptr);
|
|
}
|
|
|
|
int64_t Module::getFileIndex() const {
|
|
return sendToReceiver<int64_t>(F_GET_RECEIVER_FILE_INDEX);
|
|
}
|
|
|
|
void Module::setFileIndex(int64_t file_index) {
|
|
sendToReceiver(F_SET_RECEIVER_FILE_INDEX, file_index, nullptr);
|
|
}
|
|
|
|
void Module::incrementFileIndex() { sendToReceiver(F_INCREMENT_FILE_INDEX); }
|
|
|
|
bool Module::getFileWrite() const {
|
|
return sendToReceiver<int>(F_GET_RECEIVER_FILE_WRITE);
|
|
}
|
|
|
|
void Module::setFileWrite(bool value) {
|
|
sendToReceiver(F_SET_RECEIVER_FILE_WRITE, static_cast<int>(value), nullptr);
|
|
}
|
|
|
|
bool Module::getMasterFileWrite() const {
|
|
return sendToReceiver<int>(F_GET_RECEIVER_MASTER_FILE_WRITE);
|
|
}
|
|
|
|
void Module::setMasterFileWrite(bool value) {
|
|
sendToReceiver(F_SET_RECEIVER_MASTER_FILE_WRITE, static_cast<int>(value),
|
|
nullptr);
|
|
}
|
|
|
|
bool Module::getFileOverWrite() const {
|
|
return sendToReceiver<int>(F_GET_RECEIVER_OVERWRITE);
|
|
}
|
|
|
|
void Module::setFileOverWrite(bool value) {
|
|
sendToReceiver(F_SET_RECEIVER_OVERWRITE, static_cast<int>(value), nullptr);
|
|
}
|
|
|
|
int Module::getFramesPerFile() const {
|
|
return sendToReceiver<int>(F_GET_RECEIVER_FRAMES_PER_FILE);
|
|
}
|
|
|
|
void Module::setFramesPerFile(int n_frames) {
|
|
sendToReceiver(F_SET_RECEIVER_FRAMES_PER_FILE, n_frames, nullptr);
|
|
}
|
|
|
|
// ZMQ Streaming Parameters (Receiver<->Client)
|
|
|
|
bool Module::getReceiverStreaming() const {
|
|
return sendToReceiver<int>(F_GET_RECEIVER_STREAMING);
|
|
}
|
|
|
|
void Module::setReceiverStreaming(bool enable) {
|
|
sendToReceiver(F_SET_RECEIVER_STREAMING, static_cast<int>(enable), nullptr);
|
|
}
|
|
|
|
int Module::getReceiverStreamingFrequency() const {
|
|
return sendToReceiver<int>(F_GET_RECEIVER_STREAMING_FREQUENCY);
|
|
}
|
|
|
|
void Module::setReceiverStreamingFrequency(int freq) {
|
|
if (freq < 0) {
|
|
throw RuntimeError("Invalid streaming frequency " +
|
|
std::to_string(freq));
|
|
}
|
|
sendToReceiver(F_SET_RECEIVER_STREAMING_FREQUENCY, freq, nullptr);
|
|
}
|
|
|
|
int Module::getReceiverStreamingTimer() const {
|
|
return sendToReceiver<int>(F_RECEIVER_STREAMING_TIMER, GET_FLAG);
|
|
}
|
|
|
|
void Module::setReceiverStreamingTimer(int time_in_ms) {
|
|
sendToReceiver<int>(F_RECEIVER_STREAMING_TIMER, time_in_ms);
|
|
}
|
|
|
|
int Module::getReceiverStreamingStartingFrame() const {
|
|
return sendToReceiver<int>(F_GET_RECEIVER_STREAMING_START_FNUM);
|
|
}
|
|
|
|
void Module::setReceiverStreamingStartingFrame(int fnum) {
|
|
if (fnum < 0) {
|
|
throw RuntimeError("Invalid streaming starting frame number " +
|
|
std::to_string(fnum));
|
|
}
|
|
sendToReceiver(F_SET_RECEIVER_STREAMING_START_FNUM, fnum, nullptr);
|
|
}
|
|
|
|
int Module::getReceiverStreamingPort() const {
|
|
return sendToReceiver<int>(F_GET_RECEIVER_STREAMING_PORT);
|
|
}
|
|
|
|
void Module::setReceiverStreamingPort(int port) {
|
|
sendToReceiver(F_SET_RECEIVER_STREAMING_PORT, port, nullptr);
|
|
}
|
|
|
|
sls::IpAddr Module::getReceiverStreamingIP() const {
|
|
return sendToReceiver<sls::IpAddr>(F_GET_RECEIVER_STREAMING_SRC_IP);
|
|
}
|
|
|
|
void Module::setReceiverStreamingIP(const sls::IpAddr ip) {
|
|
if (ip == 0) {
|
|
throw RuntimeError("Invalid receiver zmq ip address");
|
|
}
|
|
// if client zmqip is empty, update it
|
|
if (shm()->zmqip == 0) {
|
|
shm()->zmqip = ip;
|
|
}
|
|
sendToReceiver(F_SET_RECEIVER_STREAMING_SRC_IP, ip, nullptr);
|
|
}
|
|
|
|
int Module::getClientStreamingPort() const { return shm()->zmqport; }
|
|
|
|
void Module::setClientStreamingPort(int port) { shm()->zmqport = port; }
|
|
|
|
sls::IpAddr Module::getClientStreamingIP() const { return shm()->zmqip; }
|
|
|
|
void Module::setClientStreamingIP(const sls::IpAddr ip) {
|
|
if (ip == 0) {
|
|
throw RuntimeError("Invalid client zmq ip address");
|
|
}
|
|
shm()->zmqip = ip;
|
|
}
|
|
|
|
int Module::getReceiverStreamingHwm() const {
|
|
return sendToReceiver<int>(F_GET_RECEIVER_STREAMING_HWM);
|
|
}
|
|
|
|
void Module::setReceiverStreamingHwm(const int limit) {
|
|
sendToReceiver(F_SET_RECEIVER_STREAMING_HWM, limit, nullptr);
|
|
}
|
|
|
|
// Eiger Specific
|
|
|
|
int64_t Module::getSubExptime() const {
|
|
return sendToDetector<int64_t>(F_GET_SUB_EXPTIME);
|
|
}
|
|
|
|
void Module::setSubExptime(int64_t value) {
|
|
int64_t prevVal = value;
|
|
if (shm()->detType == EIGER) {
|
|
prevVal = getSubExptime();
|
|
}
|
|
sendToDetector(F_SET_SUB_EXPTIME, value, nullptr);
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver(F_RECEIVER_SET_SUB_EXPTIME, value, nullptr);
|
|
}
|
|
if (prevVal != value) {
|
|
updateRateCorrection();
|
|
}
|
|
}
|
|
|
|
int64_t Module::getSubDeadTime() const {
|
|
return sendToDetector<int64_t>(F_GET_SUB_DEADTIME);
|
|
}
|
|
|
|
void Module::setSubDeadTime(int64_t value) {
|
|
sendToDetector(F_SET_SUB_DEADTIME, value, nullptr);
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver(F_RECEIVER_SET_SUB_DEADTIME, value, nullptr);
|
|
}
|
|
}
|
|
|
|
bool Module::getOverFlowMode() const {
|
|
return sendToDetector<int>(F_GET_OVERFLOW_MODE);
|
|
}
|
|
|
|
void Module::setOverFlowMode(const bool enable) {
|
|
sendToDetector(F_SET_OVERFLOW_MODE, static_cast<int>(enable), nullptr);
|
|
}
|
|
|
|
int64_t Module::getRateCorrection() const {
|
|
return sendToDetector<int64_t>(F_GET_RATE_CORRECT);
|
|
}
|
|
|
|
void Module::setDefaultRateCorrection() {
|
|
int64_t arg = -1;
|
|
sendToDetector(F_SET_RATE_CORRECT, arg, nullptr);
|
|
}
|
|
|
|
void Module::setRateCorrection(int64_t t) {
|
|
sendToDetector(F_SET_RATE_CORRECT, t, nullptr);
|
|
}
|
|
|
|
void Module::sendReceiverRateCorrections(const std::vector<int64_t> &t) {
|
|
LOG(logDEBUG) << "Sending to receiver 0 [rate corrections: " << ToString(t)
|
|
<< ']';
|
|
auto receiver = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort);
|
|
receiver.Send(F_SET_RECEIVER_RATE_CORRECT);
|
|
receiver.Send(static_cast<int>(t.size()));
|
|
receiver.Send(t);
|
|
if (receiver.Receive<int>() == FAIL) {
|
|
throw ReceiverError("Receiver " + std::to_string(moduleIndex) +
|
|
" returned error: " + receiver.readErrorMessage());
|
|
}
|
|
}
|
|
|
|
bool Module::getInterruptSubframe() const {
|
|
return sendToDetector<int>(F_GET_INTERRUPT_SUBFRAME);
|
|
}
|
|
|
|
void Module::setInterruptSubframe(const bool enable) {
|
|
sendToDetector(F_SET_INTERRUPT_SUBFRAME, static_cast<int>(enable), nullptr);
|
|
}
|
|
|
|
int64_t Module::getMeasuredPeriod() const {
|
|
return sendToDetectorStop<int64_t>(F_GET_MEASURED_PERIOD);
|
|
}
|
|
|
|
int64_t Module::getMeasuredSubFramePeriod() const {
|
|
return sendToDetectorStop<int64_t>(F_GET_MEASURED_SUBPERIOD);
|
|
}
|
|
|
|
bool Module::getActivate() const {
|
|
auto retval = sendToDetector<int>(F_ACTIVATE, GET_FLAG);
|
|
auto retval2 = sendToDetectorStop<int>(F_ACTIVATE, GET_FLAG);
|
|
if (retval != retval2) {
|
|
std::ostringstream oss;
|
|
oss << "Inconsistent activate state. Control Server: " << retval
|
|
<< ". Stop Server: " << retval2;
|
|
throw RuntimeError(oss.str());
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
void Module::setActivate(const bool enable) {
|
|
int arg = static_cast<int>(enable);
|
|
auto retval = sendToDetector<int>(F_ACTIVATE, arg);
|
|
sendToDetectorStop<int>(F_ACTIVATE, arg);
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver(F_RECEIVER_ACTIVATE, retval, nullptr);
|
|
}
|
|
}
|
|
|
|
bool Module::getCounterBit() const {
|
|
return (
|
|
!static_cast<bool>(sendToDetector<int>(F_SET_COUNTER_BIT, GET_FLAG)));
|
|
}
|
|
|
|
void Module::setCounterBit(bool cb) {
|
|
sendToDetector<int>(F_SET_COUNTER_BIT, static_cast<int>(!cb));
|
|
}
|
|
|
|
void Module::pulsePixel(int n, int x, int y) {
|
|
const int args[]{n, x, y};
|
|
sendToDetector(F_PULSE_PIXEL, args, nullptr);
|
|
}
|
|
|
|
void Module::pulsePixelNMove(int n, int x, int y) {
|
|
const int args[]{n, x, y};
|
|
sendToDetector(F_PULSE_PIXEL_AND_MOVE, args, nullptr);
|
|
}
|
|
|
|
void Module::pulseChip(int n_pulses) {
|
|
sendToDetector(F_PULSE_CHIP, n_pulses, nullptr);
|
|
}
|
|
|
|
bool Module::getQuad() const { return sendToDetector<int>(F_GET_QUAD) != 0; }
|
|
|
|
void Module::setQuad(const bool enable) {
|
|
int value = enable ? 1 : 0;
|
|
sendToDetector(F_SET_QUAD, value, nullptr);
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver(F_SET_RECEIVER_QUAD, value, nullptr);
|
|
}
|
|
}
|
|
|
|
bool Module::getDataStream(const portPosition port) const {
|
|
return sendToDetector<int>(F_GET_DATASTREAM, static_cast<int>(port));
|
|
}
|
|
|
|
void Module::setDataStream(const portPosition port, const bool enable) {
|
|
int args[]{static_cast<int>(port), static_cast<int>(enable)};
|
|
sendToDetector(F_SET_DATASTREAM, args, nullptr);
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver(F_RECEIVER_SET_DATASTREAM, args, nullptr);
|
|
}
|
|
}
|
|
|
|
// Jungfrau Specific
|
|
double Module::getChipVersion() const {
|
|
return (sendToDetector<int>(F_GET_CHIP_VERSION)) / 10.00;
|
|
}
|
|
|
|
int Module::getThresholdTemperature() const {
|
|
auto retval = sendToDetectorStop<int>(F_THRESHOLD_TEMP, GET_FLAG);
|
|
return retval / 1000;
|
|
}
|
|
|
|
void Module::setThresholdTemperature(int val) {
|
|
if (val <= 0) {
|
|
throw RuntimeError("Invalid threshold temperature " +
|
|
std::to_string(val));
|
|
}
|
|
val *= 1000;
|
|
sendToDetectorStop<int>(F_THRESHOLD_TEMP, val);
|
|
}
|
|
|
|
bool Module::getTemperatureControl() const {
|
|
return sendToDetectorStop<int>(F_TEMP_CONTROL, GET_FLAG);
|
|
}
|
|
|
|
void Module::setTemperatureControl(bool val) {
|
|
sendToDetectorStop<int>(F_TEMP_CONTROL, static_cast<int>(val));
|
|
}
|
|
|
|
int Module::getTemperatureEvent() const {
|
|
return sendToDetectorStop<int>(F_TEMP_EVENT, GET_FLAG);
|
|
}
|
|
|
|
void Module::resetTemperatureEvent() {
|
|
sendToDetectorStop<int>(F_TEMP_EVENT, 0);
|
|
}
|
|
|
|
bool Module::getAutoComparatorDisableMode() const {
|
|
return sendToDetector<int>(F_AUTO_COMP_DISABLE, GET_FLAG);
|
|
}
|
|
|
|
void Module::setAutoComparatorDisableMode(bool val) {
|
|
sendToDetector<int>(F_AUTO_COMP_DISABLE, static_cast<int>(val));
|
|
}
|
|
|
|
int64_t Module::getComparatorDisableTime() const {
|
|
return sendToDetector<int64_t>(F_GET_COMP_DISABLE_TIME);
|
|
}
|
|
|
|
void Module::setComparatorDisableTime(int64_t value) {
|
|
sendToDetector(F_SET_COMP_DISABLE_TIME, value, nullptr);
|
|
}
|
|
|
|
int Module::getNumberOfAdditionalStorageCells() const {
|
|
return sendToDetector<int>(F_GET_NUM_ADDITIONAL_STORAGE_CELLS);
|
|
}
|
|
|
|
void Module::setNumberOfAdditionalStorageCells(int value) {
|
|
sendToDetector(F_SET_NUM_ADDITIONAL_STORAGE_CELLS, value, nullptr);
|
|
}
|
|
|
|
int Module::getStorageCellStart() const {
|
|
return sendToDetector<int>(F_STORAGE_CELL_START, GET_FLAG);
|
|
}
|
|
|
|
void Module::setStorageCellStart(int pos) {
|
|
sendToDetector<int>(F_STORAGE_CELL_START, pos);
|
|
}
|
|
|
|
int64_t Module::getStorageCellDelay() const {
|
|
return sendToDetector<int64_t>(F_GET_STORAGE_CELL_DELAY);
|
|
}
|
|
|
|
void Module::setStorageCellDelay(int64_t value) {
|
|
sendToDetector(F_SET_STORAGE_CELL_DELAY, value, nullptr);
|
|
}
|
|
|
|
slsDetectorDefs::gainMode Module::getGainMode() const {
|
|
return sendToDetector<gainMode>(F_GET_GAIN_MODE);
|
|
}
|
|
|
|
void Module::setGainMode(const slsDetectorDefs::gainMode mode) {
|
|
sendToDetector(F_SET_GAIN_MODE, mode, nullptr);
|
|
}
|
|
|
|
int Module::getNumberOfFilterCells() const {
|
|
return sendToDetector<int>(F_GET_NUM_FILTER_CELLS);
|
|
}
|
|
|
|
void Module::setNumberOfFilterCells(int value) {
|
|
sendToDetector(F_SET_NUM_FILTER_CELLS, value, nullptr);
|
|
}
|
|
|
|
// Gotthard Specific
|
|
|
|
slsDetectorDefs::ROI Module::getROI() const {
|
|
return sendToDetector<slsDetectorDefs::ROI>(F_GET_ROI);
|
|
}
|
|
|
|
void Module::setROI(slsDetectorDefs::ROI arg) {
|
|
if (arg.xmin < 0 || arg.xmax >= getNumberOfChannels().x) {
|
|
arg.xmin = -1;
|
|
arg.xmax = -1;
|
|
}
|
|
sendToDetector(F_SET_ROI, arg, nullptr);
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver(F_RECEIVER_SET_ROI, arg, nullptr);
|
|
}
|
|
}
|
|
|
|
void Module::clearROI() { setROI(slsDetectorDefs::ROI{}); }
|
|
|
|
int64_t Module::getExptimeLeft() const {
|
|
return sendToDetectorStop<int64_t>(F_GET_EXPTIME_LEFT);
|
|
}
|
|
|
|
// Gotthard2 Specific
|
|
|
|
int64_t Module::getNumberOfBursts() const {
|
|
return sendToDetector<int64_t>(F_GET_NUM_BURSTS);
|
|
}
|
|
|
|
void Module::setNumberOfBursts(int64_t value) {
|
|
sendToDetector(F_SET_NUM_BURSTS, value, nullptr);
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver(F_SET_RECEIVER_NUM_BURSTS, value, nullptr);
|
|
}
|
|
}
|
|
|
|
int64_t Module::getBurstPeriod() const {
|
|
return sendToDetector<int64_t>(F_GET_BURST_PERIOD);
|
|
}
|
|
|
|
void Module::setBurstPeriod(int64_t value) {
|
|
sendToDetector(F_SET_BURST_PERIOD, value, nullptr);
|
|
}
|
|
|
|
int64_t Module::getNumberOfBurstsLeft() const {
|
|
return sendToDetectorStop<int64_t>(F_GET_BURSTS_LEFT);
|
|
}
|
|
|
|
std::array<int, 2> Module::getInjectChannel() const {
|
|
return sendToDetector<std::array<int, 2>>(F_GET_INJECT_CHANNEL);
|
|
}
|
|
|
|
void Module::setInjectChannel(const int offsetChannel,
|
|
const int incrementChannel) {
|
|
int args[]{offsetChannel, incrementChannel};
|
|
sendToDetector(F_SET_INJECT_CHANNEL, args, nullptr);
|
|
}
|
|
|
|
void Module::sendVetoPhoton(const int chipIndex,
|
|
const std::vector<int> &gainIndices,
|
|
const std::vector<int> &values) {
|
|
const int nch = gainIndices.size();
|
|
if (gainIndices.size() != values.size()) {
|
|
throw RuntimeError("Number of Gain Indices and values do not match! "
|
|
"Gain Indices size: " +
|
|
std::to_string(gainIndices.size()) +
|
|
", values size: " + std::to_string(values.size()));
|
|
}
|
|
LOG(logDEBUG1) << "Sending veto photon/file to detector [chip:" << chipIndex
|
|
<< ", nch:" << nch << "]";
|
|
|
|
const int args[]{chipIndex, nch};
|
|
auto client = DetectorSocket(shm()->hostname, shm()->controlPort);
|
|
client.Send(F_SET_VETO_PHOTON);
|
|
client.Send(args);
|
|
client.Send(gainIndices);
|
|
client.Send(values);
|
|
if (client.Receive<int>() == FAIL) {
|
|
throw DetectorError("Detector " + std::to_string(moduleIndex) +
|
|
" returned error: " + client.readErrorMessage());
|
|
}
|
|
}
|
|
|
|
void Module::getVetoPhoton(const int chipIndex,
|
|
const std::string &fname) const {
|
|
LOG(logDEBUG1) << "Getting veto photon [" << chipIndex << "]\n";
|
|
auto client = DetectorSocket(shm()->hostname, shm()->controlPort);
|
|
client.Send(F_GET_VETO_PHOTON);
|
|
client.Send(chipIndex);
|
|
if (client.Receive<int>() == FAIL) {
|
|
throw DetectorError("Detector " + std::to_string(moduleIndex) +
|
|
" returned error: " + client.readErrorMessage());
|
|
}
|
|
|
|
auto nch = client.Receive<int>();
|
|
if (nch != shm()->nChan.x) {
|
|
throw DetectorError("Could not get veto photon. Expected " +
|
|
std::to_string(shm()->nChan.x) + " channels, got " +
|
|
std::to_string(nch));
|
|
}
|
|
std::vector<int> gainIndices(nch);
|
|
std::vector<int> values(nch);
|
|
client.Receive(gainIndices);
|
|
client.Receive(values);
|
|
|
|
// save to file
|
|
std::ofstream outfile(fname);
|
|
if (!outfile) {
|
|
throw RuntimeError("Could not create file to save veto photon");
|
|
}
|
|
for (int i = 0; i < nch; ++i) {
|
|
outfile << gainIndices[i] << ' ' << values[i] << '\n';
|
|
}
|
|
LOG(logDEBUG1) << nch << " veto photon saved to file";
|
|
}
|
|
|
|
void Module::setVetoPhoton(const int chipIndex, const int numPhotons,
|
|
const int energy, const std::string &fname) {
|
|
if (shm()->detType != GOTTHARD2) {
|
|
throw RuntimeError(
|
|
"Set Veto reference is not implemented for this detector");
|
|
}
|
|
if (chipIndex < -1 || chipIndex >= shm()->nChip.x) {
|
|
throw RuntimeError("Could not set veto photon. Invalid chip index: " +
|
|
std::to_string(chipIndex));
|
|
}
|
|
if (numPhotons < 1) {
|
|
throw RuntimeError(
|
|
"Could not set veto photon. Invalid number of photons: " +
|
|
std::to_string(numPhotons));
|
|
}
|
|
if (energy < 1) {
|
|
throw RuntimeError("Could not set veto photon. Invalid energy: " +
|
|
std::to_string(energy));
|
|
}
|
|
std::ifstream infile(fname.c_str());
|
|
if (!infile) {
|
|
throw RuntimeError("Could not set veto photon. Could not open file: " +
|
|
fname);
|
|
}
|
|
LOG(logDEBUG1) << "Setting veto photon. Reading Gain values from file";
|
|
|
|
const int totalEnergy = numPhotons * energy;
|
|
std::vector<int> gainIndices;
|
|
std::vector<int> values;
|
|
|
|
while (infile.good()) {
|
|
std::string line;
|
|
getline(infile, line);
|
|
if (line.find('#') != std::string::npos) {
|
|
line.erase(line.find('#'));
|
|
}
|
|
if (line.length() < 1) {
|
|
continue;
|
|
}
|
|
std::istringstream ss(line);
|
|
|
|
// read pedestal, gain values, gain thresholds
|
|
double gainPedestal[3] = {-1, -1, -1};
|
|
double gainValue[3] = {-1, -1, -1};
|
|
int gainThreshold[2] = {-1, -1};
|
|
ss >> gainPedestal[0] >> gainPedestal[1] >> gainPedestal[2] >>
|
|
gainValue[0] >> gainValue[1] >> gainValue[2] >> gainThreshold[0] >>
|
|
gainThreshold[1];
|
|
if (ss.fail()) {
|
|
throw RuntimeError("Could not set veto photon. Invalid pedestals, "
|
|
"gain values or gain thresholds for channel " +
|
|
std::to_string(gainIndices.size()));
|
|
}
|
|
|
|
// caluclate gain index from gain thresholds and threshold energy
|
|
int gainIndex = 2;
|
|
if (totalEnergy < gainThreshold[0]) {
|
|
gainIndex = 0;
|
|
} else if (totalEnergy < gainThreshold[1]) {
|
|
gainIndex = 1;
|
|
}
|
|
gainIndices.push_back(gainIndex);
|
|
// calculate ADU value
|
|
values.push_back(gainPedestal[gainIndex] +
|
|
(gainValue[gainIndex] * totalEnergy));
|
|
}
|
|
// check size
|
|
if ((int)gainIndices.size() != shm()->nChan.x) {
|
|
throw RuntimeError("Could not set veto photon. Invalid number of "
|
|
"entries in file. Expected " +
|
|
std::to_string(shm()->nChan.x) + ", read " +
|
|
std::to_string(gainIndices.size()));
|
|
}
|
|
|
|
sendVetoPhoton(chipIndex, gainIndices, values);
|
|
}
|
|
|
|
void Module::setVetoReference(const int gainIndex, const int value) {
|
|
const int args[]{gainIndex, value};
|
|
sendToDetector(F_SET_VETO_REFERENCE, args, nullptr);
|
|
}
|
|
|
|
void Module::setVetoFile(const int chipIndex, const std::string &fname) {
|
|
if (shm()->detType != GOTTHARD2) {
|
|
throw RuntimeError(
|
|
"Set Veto file is not implemented for this detector");
|
|
}
|
|
if (chipIndex < -1 || chipIndex >= shm()->nChip.x) {
|
|
throw RuntimeError("Could not set veto file. Invalid chip index: " +
|
|
std::to_string(chipIndex));
|
|
}
|
|
|
|
std::ifstream input_file(fname);
|
|
if (!input_file) {
|
|
throw RuntimeError("Could not set veto file for chip " +
|
|
std::to_string(chipIndex) +
|
|
". Could not open file: " + fname);
|
|
}
|
|
|
|
std::vector<int> gainIndices;
|
|
std::vector<int> values;
|
|
|
|
for (std::string line; std::getline(input_file, line);) {
|
|
if (line.find('#') != std::string::npos) {
|
|
line.erase(line.find('#'));
|
|
}
|
|
LOG(logDEBUG1) << "line after removing comments:\n\t" << line;
|
|
if (line.length() > 1) {
|
|
// convert command and string to a vector
|
|
std::istringstream iss(line);
|
|
std::string val;
|
|
int gainIndex = -1;
|
|
int value = -1;
|
|
iss >> gainIndex >> val;
|
|
if (iss.fail()) {
|
|
throw RuntimeError("Could not set veto file. Invalid gain "
|
|
"or reference value for channel " +
|
|
std::to_string(gainIndices.size()));
|
|
}
|
|
try {
|
|
value = StringTo<int>(val);
|
|
} catch (...) {
|
|
throw RuntimeError("Could not set veto file. Invalid value " +
|
|
val + " for channel " +
|
|
std::to_string(gainIndices.size()));
|
|
}
|
|
gainIndices.push_back(gainIndex);
|
|
values.push_back(value);
|
|
}
|
|
}
|
|
// check size
|
|
if ((int)gainIndices.size() != shm()->nChan.x) {
|
|
throw RuntimeError("Could not set veto file. Invalid number of "
|
|
"entries in file. Expected " +
|
|
std::to_string(shm()->nChan.x) + ", read " +
|
|
std::to_string(gainIndices.size()));
|
|
}
|
|
|
|
sendVetoPhoton(chipIndex, gainIndices, values);
|
|
}
|
|
|
|
slsDetectorDefs::burstMode Module::getBurstMode() const {
|
|
return sendToDetector<burstMode>(F_GET_BURST_MODE);
|
|
}
|
|
|
|
void Module::setBurstMode(slsDetectorDefs::burstMode value) {
|
|
sendToDetector(F_SET_BURST_MODE, value, nullptr);
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver(F_SET_RECEIVER_BURST_MODE, value, nullptr);
|
|
}
|
|
}
|
|
|
|
bool Module::getCDSGain() const { return sendToDetector<int>(F_GET_CDS_GAIN); }
|
|
|
|
void Module::setCDSGain(bool value) {
|
|
sendToDetector(F_SET_CDS_GAIN, static_cast<int>(value), nullptr);
|
|
}
|
|
|
|
slsDetectorDefs::timingSourceType Module::getTimingSource() const {
|
|
return sendToDetector<timingSourceType>(F_GET_TIMING_SOURCE);
|
|
}
|
|
|
|
void Module::setTimingSource(slsDetectorDefs::timingSourceType value) {
|
|
sendToDetector(F_SET_TIMING_SOURCE, static_cast<int>(value), nullptr);
|
|
}
|
|
|
|
bool Module::getVeto() const { return sendToDetector<int>(F_GET_VETO); }
|
|
|
|
void Module::setVeto(bool enable) {
|
|
sendToDetector(F_SET_VETO, static_cast<int>(enable), nullptr);
|
|
}
|
|
|
|
bool Module::getVetoStream() const {
|
|
return (sendToDetector<int>(F_GET_VETO_STREAM));
|
|
}
|
|
|
|
void Module::setVetoStream(const bool value) {
|
|
sendToDetector(F_SET_VETO_STREAM, static_cast<int>(value), nullptr);
|
|
}
|
|
|
|
slsDetectorDefs::vetoAlgorithm Module::getVetoAlgorithm(
|
|
const slsDetectorDefs::streamingInterface interface) const {
|
|
return sendToDetector<vetoAlgorithm>(F_GET_VETO_ALGORITHM,
|
|
static_cast<int>(interface));
|
|
}
|
|
|
|
void Module::setVetoAlgorithm(
|
|
const slsDetectorDefs::vetoAlgorithm alg,
|
|
const slsDetectorDefs::streamingInterface interface) {
|
|
int args[]{static_cast<int>(alg), static_cast<int>(interface)};
|
|
sendToDetector(F_SET_VETO_ALGORITHM, args, nullptr);
|
|
}
|
|
|
|
int Module::getADCConfiguration(const int chipIndex, const int adcIndex) const {
|
|
int args[]{chipIndex, adcIndex};
|
|
return sendToDetector<int>(F_GET_ADC_CONFIGURATION, args);
|
|
}
|
|
|
|
void Module::setADCConfiguration(const int chipIndex, const int adcIndex,
|
|
int value) {
|
|
int args[]{chipIndex, adcIndex, value};
|
|
sendToDetector(F_SET_ADC_CONFIGURATION, args, nullptr);
|
|
}
|
|
|
|
void Module::getBadChannels(const std::string &fname) const {
|
|
LOG(logDEBUG1) << "Getting bad channels to " << fname;
|
|
auto client = DetectorSocket(shm()->hostname, shm()->controlPort);
|
|
client.Send(F_GET_BAD_CHANNELS);
|
|
if (client.Receive<int>() == FAIL) {
|
|
throw DetectorError("Detector " + std::to_string(moduleIndex) +
|
|
" returned error: " + client.readErrorMessage());
|
|
}
|
|
// receive badchannels
|
|
auto nch = client.Receive<int>();
|
|
std::vector<int> badchannels(nch);
|
|
if (nch > 0) {
|
|
client.Receive(badchannels);
|
|
for (size_t i = 0; i < badchannels.size(); ++i) {
|
|
LOG(logDEBUG1) << i << ":" << badchannels[i];
|
|
}
|
|
}
|
|
|
|
// save to file
|
|
std::ofstream outfile(fname);
|
|
if (!outfile) {
|
|
throw RuntimeError("Could not create file to save bad channels");
|
|
}
|
|
for (auto ch : badchannels)
|
|
outfile << ch << '\n';
|
|
LOG(logDEBUG1) << nch << " bad channels saved to file";
|
|
}
|
|
|
|
void Module::setBadChannels(const std::string &fname) {
|
|
// read bad channels file
|
|
std::ifstream input_file(fname);
|
|
if (!input_file) {
|
|
throw RuntimeError("Could not open bad channels file " + fname +
|
|
" for reading");
|
|
}
|
|
std::vector<int> badchannels;
|
|
for (std::string line; std::getline(input_file, line);) {
|
|
line.erase(std::remove_if(begin(line), end(line), isspace),
|
|
end(line)); // remove space
|
|
if (!line.empty()) {
|
|
std::istringstream iss(line);
|
|
int ival = 0;
|
|
iss >> ival;
|
|
if (iss.fail()) {
|
|
throw RuntimeError("Could not load bad channels file. Invalid "
|
|
"channel number at position " +
|
|
std::to_string(badchannels.size()));
|
|
}
|
|
badchannels.push_back(ival);
|
|
}
|
|
}
|
|
|
|
// send bad channels to module
|
|
auto nch = static_cast<int>(badchannels.size());
|
|
LOG(logDEBUG1) << "Sending bad channels to detector, nch:" << nch;
|
|
auto client = DetectorSocket(shm()->hostname, shm()->controlPort);
|
|
client.Send(F_SET_BAD_CHANNELS);
|
|
client.Send(nch);
|
|
if (nch > 0) {
|
|
client.Send(badchannels);
|
|
}
|
|
if (client.Receive<int>() == FAIL) {
|
|
throw DetectorError("Detector " + std::to_string(moduleIndex) +
|
|
" returned error: " + client.readErrorMessage());
|
|
}
|
|
}
|
|
|
|
// Mythen3 Specific
|
|
|
|
uint32_t Module::getCounterMask() const {
|
|
return sendToDetector<uint32_t>(F_GET_COUNTER_MASK);
|
|
}
|
|
|
|
void Module::setCounterMask(uint32_t countermask) {
|
|
LOG(logDEBUG1) << "Setting Counter mask to " << countermask;
|
|
sendToDetector(F_SET_COUNTER_MASK, countermask, nullptr);
|
|
if (shm()->useReceiverFlag) {
|
|
LOG(logDEBUG1) << "Sending Reciver counter mask: " << countermask;
|
|
sendToReceiver(F_RECEIVER_SET_COUNTER_MASK, countermask, nullptr);
|
|
}
|
|
}
|
|
|
|
int Module::getNumberOfGates() const {
|
|
return sendToDetector<int>(F_GET_NUM_GATES);
|
|
}
|
|
|
|
void Module::setNumberOfGates(int value) {
|
|
sendToDetector(F_SET_NUM_GATES, value, nullptr);
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver(F_SET_RECEIVER_NUM_GATES, value, nullptr);
|
|
}
|
|
}
|
|
|
|
std::array<time::ns, 3> Module::getExptimeForAllGates() const {
|
|
return sendToDetector<std::array<time::ns, 3>>(F_GET_EXPTIME_ALL_GATES);
|
|
}
|
|
|
|
int64_t Module::getGateDelay(int gateIndex) const {
|
|
return sendToDetector<int64_t>(F_GET_GATE_DELAY, gateIndex);
|
|
}
|
|
|
|
void Module::setGateDelay(int gateIndex, int64_t value) {
|
|
int64_t args[]{static_cast<int64_t>(gateIndex), value};
|
|
sendToDetector(F_SET_GATE_DELAY, args, nullptr);
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver(F_SET_RECEIVER_GATE_DELAY, args, nullptr);
|
|
}
|
|
}
|
|
|
|
std::array<time::ns, 3> Module::getGateDelayForAllGates() const {
|
|
return sendToDetector<std::array<time::ns, 3>>(F_GET_GATE_DELAY_ALL_GATES);
|
|
}
|
|
|
|
bool Module::isMaster() const { return sendToDetectorStop<int>(F_GET_MASTER); }
|
|
|
|
int Module::getChipStatusRegister() const {
|
|
return sendToDetector<int>(F_GET_CSR);
|
|
}
|
|
|
|
void Module::setGainCaps(int caps) {
|
|
sendToDetector<int>(F_SET_GAIN_CAPS, caps);
|
|
}
|
|
|
|
int Module::getGainCaps() { return sendToDetector<int>(F_GET_GAIN_CAPS); }
|
|
|
|
// CTB / Moench Specific
|
|
int Module::getNumberOfAnalogSamples() const {
|
|
return sendToDetector<int>(F_GET_NUM_ANALOG_SAMPLES);
|
|
}
|
|
|
|
void Module::setNumberOfAnalogSamples(int value) {
|
|
sendToDetector(F_SET_NUM_ANALOG_SAMPLES, value, nullptr);
|
|
// update #nchan, as it depends on #samples, adcmask
|
|
updateNumberOfChannels();
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver(F_RECEIVER_SET_NUM_ANALOG_SAMPLES, value, nullptr);
|
|
}
|
|
}
|
|
|
|
int Module::getADCPipeline() const {
|
|
return sendToDetector<int>(F_GET_ADC_PIPELINE);
|
|
}
|
|
|
|
void Module::setADCPipeline(int value) {
|
|
sendToDetector(F_SET_ADC_PIPELINE, value, nullptr);
|
|
}
|
|
|
|
uint32_t Module::getADCEnableMask() const {
|
|
return sendToDetector<uint32_t>(F_GET_ADC_ENABLE_MASK);
|
|
}
|
|
|
|
void Module::setADCEnableMask(uint32_t mask) {
|
|
sendToDetector(F_SET_ADC_ENABLE_MASK, mask, nullptr);
|
|
// update #nchan, as it depends on #samples, adcmask,
|
|
updateNumberOfChannels();
|
|
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver<int>(F_RECEIVER_SET_ADC_MASK, mask);
|
|
}
|
|
}
|
|
|
|
uint32_t Module::getTenGigaADCEnableMask() const {
|
|
return sendToDetector<uint32_t>(F_GET_ADC_ENABLE_MASK_10G);
|
|
}
|
|
|
|
void Module::setTenGigaADCEnableMask(uint32_t mask) {
|
|
sendToDetector(F_SET_ADC_ENABLE_MASK_10G, mask, nullptr);
|
|
updateNumberOfChannels(); // depends on samples and adcmask
|
|
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver<int>(F_RECEIVER_SET_ADC_MASK_10G, mask);
|
|
}
|
|
}
|
|
|
|
// CTB Specific
|
|
|
|
int Module::getNumberOfDigitalSamples() const {
|
|
return sendToDetector<int>(F_GET_NUM_DIGITAL_SAMPLES);
|
|
}
|
|
|
|
void Module::setNumberOfDigitalSamples(int value) {
|
|
LOG(logDEBUG1) << "Setting number of digital samples to " << value;
|
|
sendToDetector(F_SET_NUM_DIGITAL_SAMPLES, value, nullptr);
|
|
updateNumberOfChannels(); // depends on samples and adcmask
|
|
if (shm()->useReceiverFlag) {
|
|
LOG(logDEBUG1) << "Sending number of digital samples to Receiver: "
|
|
<< value;
|
|
sendToReceiver(F_RECEIVER_SET_NUM_DIGITAL_SAMPLES, value, nullptr);
|
|
}
|
|
}
|
|
|
|
slsDetectorDefs::readoutMode Module::getReadoutMode() const {
|
|
return sendToDetector<readoutMode>(F_GET_READOUT_MODE);
|
|
}
|
|
|
|
void Module::setReadoutMode(const slsDetectorDefs::readoutMode mode) {
|
|
auto arg = static_cast<uint32_t>(mode); // TODO! unit?
|
|
sendToDetector(F_SET_READOUT_MODE, arg, nullptr);
|
|
// update #nchan, as it depends on #samples, adcmask,
|
|
if (shm()->detType == CHIPTESTBOARD) {
|
|
updateNumberOfChannels();
|
|
}
|
|
if (shm()->useReceiverFlag) {
|
|
sendToReceiver(F_RECEIVER_SET_READOUT_MODE, mode, nullptr);
|
|
}
|
|
}
|
|
|
|
int Module::getExternalSamplingSource() {
|
|
return setExternalSamplingSource(GET_FLAG);
|
|
}
|
|
|
|
int Module::setExternalSamplingSource(int value) {
|
|
return sendToDetector<int>(F_EXTERNAL_SAMPLING_SOURCE, value);
|
|
}
|
|
|
|
bool Module::getExternalSampling() const {
|
|
return sendToDetector<int>(F_EXTERNAL_SAMPLING, GET_FLAG);
|
|
}
|
|
|
|
void Module::setExternalSampling(bool value) {
|
|
sendToDetector<int>(F_EXTERNAL_SAMPLING, static_cast<int>(value));
|
|
}
|
|
|
|
std::vector<int> Module::getReceiverDbitList() const {
|
|
return sendToReceiver<sls::StaticVector<int, MAX_RX_DBIT>>(
|
|
F_GET_RECEIVER_DBIT_LIST);
|
|
}
|
|
|
|
void Module::setReceiverDbitList(std::vector<int> list) {
|
|
LOG(logDEBUG1) << "Setting Receiver Dbit List";
|
|
if (list.size() > 64) {
|
|
throw sls::RuntimeError("Dbit list size cannot be greater than 64\n");
|
|
}
|
|
for (auto &it : list) {
|
|
if (it < 0 || it > 63) {
|
|
throw sls::RuntimeError(
|
|
"Dbit list value must be between 0 and 63\n");
|
|
}
|
|
}
|
|
std::sort(begin(list), end(list));
|
|
auto last = std::unique(begin(list), end(list));
|
|
list.erase(last, list.end());
|
|
|
|
sls::StaticVector<int, MAX_RX_DBIT> arg = list;
|
|
sendToReceiver(F_SET_RECEIVER_DBIT_LIST, arg, nullptr);
|
|
}
|
|
|
|
int Module::getReceiverDbitOffset() const {
|
|
return sendToReceiver<int>(F_GET_RECEIVER_DBIT_OFFSET);
|
|
}
|
|
|
|
void Module::setReceiverDbitOffset(int value) {
|
|
sendToReceiver(F_SET_RECEIVER_DBIT_OFFSET, value, nullptr);
|
|
}
|
|
|
|
void Module::setDigitalIODelay(uint64_t pinMask, int delay) {
|
|
uint64_t args[]{pinMask, static_cast<uint64_t>(delay)};
|
|
sendToDetector(F_DIGITAL_IO_DELAY, args, nullptr);
|
|
}
|
|
|
|
bool Module::getLEDEnable() const {
|
|
return sendToDetector<int>(F_LED, GET_FLAG);
|
|
}
|
|
|
|
void Module::setLEDEnable(bool enable) {
|
|
sendToDetector<int>(F_LED, static_cast<int>(enable));
|
|
}
|
|
|
|
// Pattern
|
|
|
|
void Module::setPattern(const Pattern &pat) {
|
|
sendToDetector(F_SET_PATTERN, pat.data(), pat.size(), nullptr, 0);
|
|
}
|
|
|
|
Pattern Module::getPattern() {
|
|
Pattern pat;
|
|
sendToDetector(F_GET_PATTERN, nullptr, 0, pat.data(), pat.size());
|
|
return pat;
|
|
}
|
|
|
|
void Module::loadDefaultPattern() { sendToDetector(F_LOAD_DEFAULT_PATTERN); }
|
|
|
|
uint64_t Module::getPatternIOControl() const {
|
|
return sendToDetector<uint64_t>(F_SET_PATTERN_IO_CONTROL,
|
|
int64_t(GET_FLAG));
|
|
}
|
|
|
|
void Module::setPatternIOControl(uint64_t word) {
|
|
sendToDetector<uint64_t>(F_SET_PATTERN_IO_CONTROL, word);
|
|
}
|
|
|
|
uint64_t Module::getPatternWord(int addr) const {
|
|
uint64_t args[]{static_cast<uint64_t>(addr),
|
|
static_cast<uint64_t>(GET_FLAG)};
|
|
return sendToDetector<uint64_t>(F_SET_PATTERN_WORD, args);
|
|
}
|
|
|
|
void Module::setPatternWord(int addr, uint64_t word) {
|
|
uint64_t args[]{static_cast<uint64_t>(addr), word};
|
|
sendToDetector<uint64_t>(F_SET_PATTERN_WORD, args);
|
|
}
|
|
|
|
std::array<int, 2> Module::getPatternLoopAddresses(int level) const {
|
|
int args[]{level, GET_FLAG, GET_FLAG};
|
|
std::array<int, 2> retvals{};
|
|
sendToDetector(F_SET_PATTERN_LOOP_ADDRESSES, args, retvals);
|
|
return retvals;
|
|
}
|
|
|
|
void Module::setPatternLoopAddresses(int level, int start, int stop) {
|
|
int args[]{level, start, stop};
|
|
std::array<int, 2> retvals{};
|
|
sendToDetector(F_SET_PATTERN_LOOP_ADDRESSES, args, retvals);
|
|
}
|
|
|
|
int Module::getPatternLoopCycles(int level) const {
|
|
int args[]{level, GET_FLAG};
|
|
return sendToDetector<int>(F_SET_PATTERN_LOOP_CYCLES, args);
|
|
}
|
|
|
|
void Module::setPatternLoopCycles(int level, int n) {
|
|
int args[]{level, n};
|
|
sendToDetector<int>(F_SET_PATTERN_LOOP_CYCLES, args);
|
|
}
|
|
|
|
int Module::getPatternWaitAddr(int level) const {
|
|
int args[]{level, GET_FLAG};
|
|
return sendToDetector<int>(F_SET_PATTERN_WAIT_ADDR, args);
|
|
}
|
|
|
|
void Module::setPatternWaitAddr(int level, int addr) {
|
|
int args[]{level, addr};
|
|
sendToDetector<int>(F_SET_PATTERN_WAIT_ADDR, args);
|
|
}
|
|
|
|
uint64_t Module::getPatternWaitTime(int level) const {
|
|
uint64_t args[]{static_cast<uint64_t>(level),
|
|
static_cast<uint64_t>(GET_FLAG)};
|
|
return sendToDetector<uint64_t>(F_SET_PATTERN_WAIT_TIME, args);
|
|
}
|
|
|
|
void Module::setPatternWaitTime(int level, uint64_t t) {
|
|
uint64_t args[]{static_cast<uint64_t>(level), t};
|
|
sendToDetector<uint64_t>(F_SET_PATTERN_WAIT_TIME, args);
|
|
}
|
|
|
|
uint64_t Module::getPatternMask() const {
|
|
return sendToDetector<uint64_t>(F_GET_PATTERN_MASK);
|
|
}
|
|
|
|
void Module::setPatternMask(uint64_t mask) {
|
|
sendToDetector(F_SET_PATTERN_MASK, mask, nullptr);
|
|
}
|
|
|
|
uint64_t Module::getPatternBitMask() const {
|
|
return sendToDetector<uint64_t>(F_GET_PATTERN_BIT_MASK);
|
|
}
|
|
|
|
void Module::setPatternBitMask(uint64_t mask) {
|
|
sendToDetector(F_SET_PATTERN_BIT_MASK, mask, nullptr);
|
|
}
|
|
|
|
void Module::startPattern() { sendToDetector(F_START_PATTERN); }
|
|
|
|
// Moench
|
|
|
|
std::map<std::string, std::string> Module::getAdditionalJsonHeader() const {
|
|
// TODO, refactor this function with a more robust sending.
|
|
// Now assuming whitespace separated key value
|
|
if (!shm()->useReceiverFlag) {
|
|
throw RuntimeError("Set rx_hostname first to use receiver parameters "
|
|
"(zmq json header)");
|
|
}
|
|
auto client = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort);
|
|
client.Send(F_GET_ADDITIONAL_JSON_HEADER);
|
|
if (client.Receive<int>() == FAIL) {
|
|
throw ReceiverError("Receiver " + std::to_string(moduleIndex) +
|
|
" returned error: " + client.readErrorMessage());
|
|
} else {
|
|
auto size = client.Receive<int>();
|
|
std::string buff(size, '\0');
|
|
std::map<std::string, std::string> retval;
|
|
if (size > 0) {
|
|
client.Receive(&buff[0], buff.size());
|
|
std::istringstream iss(buff);
|
|
std::string key, value;
|
|
while (iss >> key) {
|
|
iss >> value;
|
|
retval[key] = value;
|
|
}
|
|
}
|
|
LOG(logDEBUG) << "Getting additional json header " << ToString(retval);
|
|
return retval;
|
|
}
|
|
}
|
|
|
|
void Module::setAdditionalJsonHeader(
|
|
const std::map<std::string, std::string> &jsonHeader) {
|
|
if (!shm()->useReceiverFlag) {
|
|
throw RuntimeError("Set rx_hostname first to use receiver parameters "
|
|
"(zmq json header)");
|
|
}
|
|
for (auto &it : jsonHeader) {
|
|
if (it.first.empty() || it.first.length() > SHORT_STR_LENGTH ||
|
|
it.second.length() > SHORT_STR_LENGTH) {
|
|
throw RuntimeError(
|
|
it.first + " or " + it.second +
|
|
" pair has invalid size. "
|
|
"Key cannot be empty. Both can have max 20 characters");
|
|
}
|
|
}
|
|
std::ostringstream oss;
|
|
for (auto &it : jsonHeader)
|
|
oss << it.first << ' ' << it.second << ' ';
|
|
auto buff = oss.str();
|
|
const auto size = static_cast<int>(buff.size());
|
|
LOG(logDEBUG) << "Sending to receiver additional json header "
|
|
<< ToString(jsonHeader);
|
|
auto client = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort);
|
|
client.Send(F_SET_ADDITIONAL_JSON_HEADER);
|
|
client.Send(size);
|
|
if (size > 0)
|
|
client.Send(&buff[0], buff.size());
|
|
|
|
if (client.Receive<int>() == FAIL) {
|
|
throw ReceiverError("Receiver " + std::to_string(moduleIndex) +
|
|
" returned error: " + client.readErrorMessage());
|
|
}
|
|
}
|
|
|
|
std::string Module::getAdditionalJsonParameter(const std::string &key) const {
|
|
char arg[SHORT_STR_LENGTH]{};
|
|
sls::strcpy_safe(arg, key.c_str());
|
|
char retval[SHORT_STR_LENGTH]{};
|
|
sendToReceiver(F_GET_ADDITIONAL_JSON_PARAMETER, arg, retval);
|
|
return retval;
|
|
}
|
|
|
|
void Module::setAdditionalJsonParameter(const std::string &key,
|
|
const std::string &value) {
|
|
if (key.empty() || key.length() > SHORT_STR_LENGTH ||
|
|
value.length() > SHORT_STR_LENGTH) {
|
|
throw RuntimeError(
|
|
key + " or " + value +
|
|
" pair has invalid size. "
|
|
"Key cannot be empty. Both can have max 2 characters");
|
|
}
|
|
char args[2][SHORT_STR_LENGTH]{};
|
|
sls::strcpy_safe(args[0], key.c_str());
|
|
sls::strcpy_safe(args[1], value.c_str());
|
|
sendToReceiver(F_SET_ADDITIONAL_JSON_PARAMETER, args, nullptr);
|
|
}
|
|
|
|
// Advanced
|
|
void Module::programFPGA(std::vector<char> buffer) {
|
|
switch (shm()->detType) {
|
|
case JUNGFRAU:
|
|
case CHIPTESTBOARD:
|
|
case MOENCH:
|
|
sendProgram(true, buffer, F_PROGRAM_FPGA, "Update Firmware");
|
|
break;
|
|
case MYTHEN3:
|
|
case GOTTHARD2:
|
|
sendProgram(false, buffer, F_PROGRAM_FPGA, "Update Firmware");
|
|
break;
|
|
default:
|
|
throw RuntimeError("Updating Firmware via the package is not "
|
|
"implemented for this detector");
|
|
}
|
|
}
|
|
|
|
void Module::resetFPGA() { sendToDetector(F_RESET_FPGA); }
|
|
|
|
void Module::copyDetectorServer(const std::string &fname,
|
|
const std::string &hostname) {
|
|
char args[2][MAX_STR_LENGTH]{};
|
|
sls::strcpy_safe(args[0], fname.c_str());
|
|
sls::strcpy_safe(args[1], hostname.c_str());
|
|
LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname
|
|
<< "): Sending detector server " << args[0] << " from host "
|
|
<< args[1];
|
|
auto client = DetectorSocket(shm()->hostname, shm()->controlPort);
|
|
client.Send(F_COPY_DET_SERVER);
|
|
client.Send(args);
|
|
if (client.Receive<int>() == FAIL) {
|
|
std::cout << '\n';
|
|
std::ostringstream os;
|
|
os << "Module " << moduleIndex << " (" << shm()->hostname << ")"
|
|
<< " returned error: " << client.readErrorMessage();
|
|
throw DetectorError(os.str());
|
|
}
|
|
LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname
|
|
<< "): Detector server copied";
|
|
}
|
|
|
|
void Module::updateDetectorServer(std::vector<char> buffer,
|
|
const std::string &serverName) {
|
|
switch (shm()->detType) {
|
|
case JUNGFRAU:
|
|
case CHIPTESTBOARD:
|
|
case MOENCH:
|
|
sendProgram(true, buffer, F_UPDATE_DETECTOR_SERVER,
|
|
"Update Detector Server (no tftp)", serverName);
|
|
break;
|
|
case MYTHEN3:
|
|
case GOTTHARD2:
|
|
case EIGER:
|
|
sendProgram(false, buffer, F_UPDATE_DETECTOR_SERVER,
|
|
"Update Detector Server (no tftp)", serverName);
|
|
break;
|
|
default:
|
|
throw RuntimeError(
|
|
"Updating DetectorServer via the package is not implemented "
|
|
"for this detector");
|
|
}
|
|
}
|
|
|
|
void Module::updateKernel(std::vector<char> buffer) {
|
|
switch (shm()->detType) {
|
|
case JUNGFRAU:
|
|
case CHIPTESTBOARD:
|
|
case MOENCH:
|
|
sendProgram(true, buffer, F_UPDATE_KERNEL, "Update Kernel");
|
|
break;
|
|
case MYTHEN3:
|
|
case GOTTHARD2:
|
|
sendProgram(false, buffer, F_UPDATE_KERNEL, "Update Kernel");
|
|
break;
|
|
default:
|
|
throw RuntimeError("Updating Kernel via the package is not implemented "
|
|
"for this detector");
|
|
}
|
|
}
|
|
|
|
void Module::rebootController() {
|
|
sendToDetector(F_REBOOT_CONTROLLER);
|
|
LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname
|
|
<< "): Controller rebooted successfully!";
|
|
}
|
|
|
|
bool Module::getUpdateMode() const {
|
|
return sendToDetector<int>(F_GET_UPDATE_MODE);
|
|
}
|
|
|
|
void Module::setUpdateMode(const bool updatemode) {
|
|
sendToDetector(F_SET_UPDATE_MODE, static_cast<int>(updatemode), nullptr);
|
|
LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname
|
|
<< "): Update Mode set to " << updatemode << "!";
|
|
}
|
|
|
|
uint32_t Module::readRegister(uint32_t addr) const {
|
|
return sendToDetectorStop<uint32_t>(F_READ_REGISTER, addr);
|
|
}
|
|
|
|
uint32_t Module::writeRegister(uint32_t addr, uint32_t val) {
|
|
uint32_t args[]{addr, val};
|
|
return sendToDetectorStop<uint32_t>(F_WRITE_REGISTER, args);
|
|
}
|
|
|
|
void Module::setBit(uint32_t addr, int n) {
|
|
if (n < 0 || n > 31) {
|
|
throw RuntimeError("Bit number " + std::to_string(n) + " out of Range");
|
|
} else {
|
|
uint32_t val = readRegister(addr);
|
|
writeRegister(addr, val | 1 << n);
|
|
}
|
|
}
|
|
|
|
void Module::clearBit(uint32_t addr, int n) {
|
|
if (n < 0 || n > 31) {
|
|
throw RuntimeError("Bit number " + std::to_string(n) + " out of Range");
|
|
} else {
|
|
uint32_t val = readRegister(addr);
|
|
writeRegister(addr, val & ~(1 << n));
|
|
}
|
|
}
|
|
|
|
int Module::getBit(uint32_t addr, int n) {
|
|
if (n < 0 || n > 31) {
|
|
throw RuntimeError("Bit number " + std::to_string(n) + " out of Range");
|
|
} else {
|
|
return ((readRegister(addr) >> n) & 0x1);
|
|
}
|
|
}
|
|
|
|
void Module::executeFirmwareTest() { sendToDetector(F_SET_FIRMWARE_TEST); }
|
|
|
|
void Module::executeBusTest() { sendToDetector(F_SET_BUS_TEST); }
|
|
|
|
void Module::writeAdcRegister(uint32_t addr, uint32_t val) {
|
|
uint32_t args[]{addr, val};
|
|
sendToDetector(F_WRITE_ADC_REG, args, nullptr);
|
|
}
|
|
|
|
uint32_t Module::getADCInvert() const {
|
|
return sendToDetector<uint32_t>(F_GET_ADC_INVERT);
|
|
}
|
|
|
|
void Module::setADCInvert(uint32_t value) {
|
|
sendToDetector(F_SET_ADC_INVERT, value, nullptr);
|
|
}
|
|
|
|
// Insignificant
|
|
int Module::getControlPort() const { return shm()->controlPort; }
|
|
|
|
void Module::setControlPort(int port_number) {
|
|
shm()->controlPort = port_number;
|
|
}
|
|
|
|
int Module::getStopPort() const { return shm()->stopPort; }
|
|
|
|
void Module::setStopPort(int port_number) { shm()->stopPort = port_number; }
|
|
|
|
bool Module::getLockDetector() const {
|
|
return sendToDetector<int>(F_LOCK_SERVER, GET_FLAG);
|
|
}
|
|
|
|
void Module::setLockDetector(bool lock) {
|
|
sendToDetector<int>(F_LOCK_SERVER, static_cast<int>(lock));
|
|
}
|
|
|
|
sls::IpAddr Module::getLastClientIP() const {
|
|
return sendToDetector<sls::IpAddr>(F_GET_LAST_CLIENT_IP);
|
|
}
|
|
|
|
std::string Module::executeCommand(const std::string &cmd) {
|
|
char arg[MAX_STR_LENGTH]{};
|
|
char retval[MAX_STR_LENGTH]{};
|
|
sls::strcpy_safe(arg, cmd.c_str());
|
|
LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname
|
|
<< "): Sending command " << cmd;
|
|
auto client = DetectorSocket(shm()->hostname, shm()->controlPort);
|
|
client.Send(F_EXEC_COMMAND);
|
|
client.Send(arg);
|
|
if (client.Receive<int>() == FAIL) {
|
|
std::cout << '\n';
|
|
std::ostringstream os;
|
|
os << "Module " << moduleIndex << " (" << shm()->hostname << ")"
|
|
<< " returned error: " << client.readErrorMessage();
|
|
throw DetectorError(os.str());
|
|
}
|
|
client.Receive(retval);
|
|
LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname
|
|
<< "): command executed";
|
|
return retval;
|
|
}
|
|
|
|
int64_t Module::getNumberOfFramesFromStart() const {
|
|
return sendToDetectorStop<int64_t>(F_GET_FRAMES_FROM_START);
|
|
}
|
|
|
|
int64_t Module::getActualTime() const {
|
|
return sendToDetectorStop<int64_t>(F_GET_ACTUAL_TIME);
|
|
}
|
|
|
|
int64_t Module::getMeasurementTime() const {
|
|
return sendToDetectorStop<int64_t>(F_GET_MEASUREMENT_TIME);
|
|
}
|
|
|
|
uint64_t Module::getReceiverCurrentFrameIndex() const {
|
|
return sendToReceiver<uint64_t>(F_GET_RECEIVER_FRAME_INDEX);
|
|
}
|
|
|
|
// private
|
|
|
|
void Module::checkArgs(const void *args, size_t args_size, void *retval,
|
|
size_t retval_size) const {
|
|
if (args == nullptr && args_size != 0)
|
|
throw RuntimeError(
|
|
"Passed nullptr as args to Send function but size is not 0");
|
|
if (args != nullptr && args_size == 0)
|
|
throw RuntimeError(
|
|
"Passed size 0 to Send function but args is not nullptr");
|
|
if (retval == nullptr && retval_size != 0)
|
|
throw RuntimeError(
|
|
"Passed nullptr as retval to Send function but size is not 0");
|
|
if (retval != nullptr && retval_size == 0)
|
|
throw RuntimeError(
|
|
"Passed size 0 to Send function but retval is not nullptr");
|
|
}
|
|
|
|
// Macro to check arguments passed to send to receiver and send to detector
|
|
// Should detect and fail on pointer types and on nullptr_t
|
|
#define STATIC_ASSERT_ARG(ARG, DST) \
|
|
static_assert(!std::is_pointer<ARG>::value, \
|
|
"Pointer type is incompatible with templated " DST); \
|
|
static_assert(!std::is_same<ARG, std::nullptr_t>::value, \
|
|
"nullptr_t type is incompatible with templated " DST);
|
|
|
|
void Module::sendToDetector(int fnum, const void *args, size_t args_size,
|
|
void *retval, size_t retval_size) const {
|
|
// This is the only function that actually sends data to the detector
|
|
// the other versions use templates to deduce sizes and create
|
|
// the return type
|
|
checkArgs(args, args_size, retval, retval_size);
|
|
auto client = DetectorSocket(shm()->hostname, shm()->controlPort);
|
|
client.sendCommandThenRead(fnum, args, args_size, retval, retval_size);
|
|
client.close();
|
|
}
|
|
|
|
void Module::sendToDetector(int fnum, const void *args, size_t args_size,
|
|
void *retval, size_t retval_size) {
|
|
static_cast<const Module &>(*this).sendToDetector(fnum, args, args_size,
|
|
retval, retval_size);
|
|
}
|
|
|
|
template <typename Arg, typename Ret>
|
|
void Module::sendToDetector(int fnum, const Arg &args, Ret &retval) const {
|
|
LOG(logDEBUG1) << "Sending: ["
|
|
<< getFunctionNameFromEnum(static_cast<detFuncs>(fnum))
|
|
<< ", nullptr, 0, " << typeid(Ret).name() << ", "
|
|
<< sizeof(Ret) << "]";
|
|
STATIC_ASSERT_ARG(Arg, "sendToDetector")
|
|
STATIC_ASSERT_ARG(Ret, "sendToDetector")
|
|
sendToDetector(fnum, &args, sizeof(args), &retval, sizeof(retval));
|
|
LOG(logDEBUG1) << "Got back: " << ToString(retval);
|
|
}
|
|
|
|
template <typename Arg, typename Ret>
|
|
void Module::sendToDetector(int fnum, const Arg &args, Ret &retval) {
|
|
static_cast<const Module &>(*this).sendToDetector(fnum, args, retval);
|
|
}
|
|
|
|
template <typename Arg>
|
|
void Module::sendToDetector(int fnum, const Arg &args, std::nullptr_t) const {
|
|
LOG(logDEBUG1) << "Sending: ["
|
|
<< getFunctionNameFromEnum(static_cast<detFuncs>(fnum))
|
|
<< ", " << typeid(Arg).name() << ", " << sizeof(Arg)
|
|
<< ", nullptr, 0 ]";
|
|
STATIC_ASSERT_ARG(Arg, "sendToDetector")
|
|
sendToDetector(fnum, &args, sizeof(args), nullptr, 0);
|
|
}
|
|
|
|
template <typename Arg>
|
|
void Module::sendToDetector(int fnum, const Arg &args, std::nullptr_t) {
|
|
static_cast<const Module &>(*this).sendToDetector(fnum, args, nullptr);
|
|
}
|
|
|
|
template <typename Ret>
|
|
void Module::sendToDetector(int fnum, std::nullptr_t, Ret &retval) const {
|
|
LOG(logDEBUG1) << "Sending: ["
|
|
<< getFunctionNameFromEnum(static_cast<detFuncs>(fnum))
|
|
<< ", nullptr, 0, " << typeid(Ret).name() << ", "
|
|
<< sizeof(Ret) << "]";
|
|
STATIC_ASSERT_ARG(Ret, "sendToDetector")
|
|
sendToDetector(fnum, nullptr, 0, &retval, sizeof(retval));
|
|
LOG(logDEBUG1) << "Got back: " << ToString(retval);
|
|
}
|
|
|
|
template <typename Ret>
|
|
void Module::sendToDetector(int fnum, std::nullptr_t, Ret &retval) {
|
|
static_cast<const Module &>(*this).sendToDetector(fnum, nullptr, retval);
|
|
}
|
|
|
|
void Module::sendToDetector(int fnum) const {
|
|
LOG(logDEBUG1) << "Sending: ["
|
|
<< getFunctionNameFromEnum(static_cast<detFuncs>(fnum))
|
|
<< "]";
|
|
sendToDetector(fnum, nullptr, 0, nullptr, 0);
|
|
}
|
|
|
|
void Module::sendToDetector(int fnum) {
|
|
static_cast<const Module &>(*this).sendToDetector(fnum);
|
|
}
|
|
|
|
template <typename Ret> Ret Module::sendToDetector(int fnum) const {
|
|
LOG(logDEBUG1) << "Sending: ["
|
|
<< getFunctionNameFromEnum(static_cast<detFuncs>(fnum))
|
|
<< ", nullptr, 0, " << typeid(Ret).name() << ", "
|
|
<< sizeof(Ret) << "]";
|
|
STATIC_ASSERT_ARG(Ret, "sendToDetector")
|
|
Ret retval{};
|
|
sendToDetector(fnum, nullptr, 0, &retval, sizeof(retval));
|
|
LOG(logDEBUG1) << "Got back: " << ToString(retval);
|
|
return retval;
|
|
}
|
|
|
|
template <typename Ret> Ret Module::sendToDetector(int fnum) {
|
|
return static_cast<const Module &>(*this).sendToDetector<Ret>(fnum);
|
|
}
|
|
|
|
template <typename Ret, typename Arg>
|
|
Ret Module::sendToDetector(int fnum, const Arg &args) const {
|
|
LOG(logDEBUG1) << "Sending: ["
|
|
<< getFunctionNameFromEnum(static_cast<detFuncs>(fnum))
|
|
<< ", " << args << ", " << sizeof(args) << ", "
|
|
<< typeid(Ret).name() << ", " << sizeof(Ret) << "]";
|
|
STATIC_ASSERT_ARG(Arg, "sendToDetector")
|
|
STATIC_ASSERT_ARG(Ret, "sendToDetector")
|
|
Ret retval{};
|
|
sendToDetector(fnum, &args, sizeof(args), &retval, sizeof(retval));
|
|
LOG(logDEBUG1) << "Got back: " << ToString(retval);
|
|
return retval;
|
|
}
|
|
|
|
template <typename Ret, typename Arg>
|
|
Ret Module::sendToDetector(int fnum, const Arg &args) {
|
|
return static_cast<const Module &>(*this).sendToDetector<Ret>(fnum, args);
|
|
}
|
|
|
|
//---------------------------------------------------------- sendToDetectorStop
|
|
|
|
void Module::sendToDetectorStop(int fnum, const void *args, size_t args_size,
|
|
void *retval, size_t retval_size) const {
|
|
// This is the only function that actually sends data to the detector stop
|
|
// the other versions use templates to deduce sizes and create
|
|
// the return type
|
|
checkArgs(args, args_size, retval, retval_size);
|
|
auto stop = DetectorSocket(shm()->hostname, shm()->stopPort);
|
|
stop.sendCommandThenRead(fnum, args, args_size, retval, retval_size);
|
|
stop.close();
|
|
}
|
|
|
|
void Module::sendToDetectorStop(int fnum, const void *args, size_t args_size,
|
|
void *retval, size_t retval_size) {
|
|
static_cast<const Module &>(*this).sendToDetectorStop(fnum, args, args_size,
|
|
retval, retval_size);
|
|
}
|
|
|
|
template <typename Arg, typename Ret>
|
|
void Module::sendToDetectorStop(int fnum, const Arg &args, Ret &retval) const {
|
|
LOG(logDEBUG1) << "Sending to Stop: ["
|
|
<< getFunctionNameFromEnum(static_cast<detFuncs>(fnum))
|
|
<< ", " << args << ", " << sizeof(args) << ", "
|
|
<< typeid(Ret).name() << ", " << sizeof(Ret) << "]";
|
|
STATIC_ASSERT_ARG(Arg, "sendToDetectorStop")
|
|
STATIC_ASSERT_ARG(Ret, "sendToDetectorStop")
|
|
sendToDetectorStop(fnum, &args, sizeof(args), &retval, sizeof(retval));
|
|
LOG(logDEBUG1) << "Got back: " << ToString(retval);
|
|
}
|
|
|
|
template <typename Arg, typename Ret>
|
|
void Module::sendToDetectorStop(int fnum, const Arg &args, Ret &retval) {
|
|
static_cast<const Module &>(*this).sendToDetectorStop(fnum, args, retval);
|
|
}
|
|
|
|
template <typename Arg>
|
|
void Module::sendToDetectorStop(int fnum, const Arg &args,
|
|
std::nullptr_t) const {
|
|
LOG(logDEBUG1) << "Sending to Stop: ["
|
|
<< getFunctionNameFromEnum(static_cast<detFuncs>(fnum))
|
|
<< ", " << typeid(Arg).name() << ", " << sizeof(Arg)
|
|
<< ", nullptr, 0 ]";
|
|
STATIC_ASSERT_ARG(Arg, "sendToDetectorStop")
|
|
sendToDetectorStop(fnum, &args, sizeof(args), nullptr, 0);
|
|
}
|
|
|
|
template <typename Arg>
|
|
void Module::sendToDetectorStop(int fnum, const Arg &args, std::nullptr_t) {
|
|
static_cast<const Module &>(*this).sendToDetectorStop(fnum, args, nullptr);
|
|
}
|
|
|
|
template <typename Ret>
|
|
void Module::sendToDetectorStop(int fnum, std::nullptr_t, Ret &retval) const {
|
|
LOG(logDEBUG1) << "Sending to Stop: ["
|
|
<< getFunctionNameFromEnum(static_cast<detFuncs>(fnum))
|
|
<< ", nullptr, 0, " << typeid(Ret).name() << ", "
|
|
<< sizeof(Ret) << "]";
|
|
STATIC_ASSERT_ARG(Ret, "sendToDetectorStop")
|
|
sendToDetectorStop(fnum, nullptr, 0, &retval, sizeof(retval));
|
|
LOG(logDEBUG1) << "Got back: " << retval;
|
|
}
|
|
|
|
template <typename Ret>
|
|
void Module::sendToDetectorStop(int fnum, std::nullptr_t, Ret &retval) {
|
|
static_cast<const Module &>(*this).sendToDetectorStop(fnum, nullptr,
|
|
retval);
|
|
}
|
|
|
|
void Module::sendToDetectorStop(int fnum) const {
|
|
LOG(logDEBUG1) << "Sending to Stop: ["
|
|
<< getFunctionNameFromEnum(static_cast<detFuncs>(fnum))
|
|
<< ", nullptr, 0, nullptr, 0]";
|
|
sendToDetectorStop(fnum, nullptr, 0, nullptr, 0);
|
|
}
|
|
|
|
void Module::sendToDetectorStop(int fnum) {
|
|
static_cast<const Module &>(*this).sendToDetectorStop(fnum);
|
|
}
|
|
|
|
template <typename Ret> Ret Module::sendToDetectorStop(int fnum) const {
|
|
LOG(logDEBUG1) << "Sending to Stop: ["
|
|
<< getFunctionNameFromEnum(static_cast<detFuncs>(fnum))
|
|
<< ", nullptr, 0, " << typeid(Ret).name() << ", "
|
|
<< sizeof(Ret) << "]";
|
|
STATIC_ASSERT_ARG(Ret, "sendToDetectorStop")
|
|
Ret retval{};
|
|
sendToDetectorStop(fnum, nullptr, 0, &retval, sizeof(retval));
|
|
LOG(logDEBUG1) << "Got back: " << retval;
|
|
return retval;
|
|
}
|
|
|
|
template <typename Ret> Ret Module::sendToDetectorStop(int fnum) {
|
|
return static_cast<const Module &>(*this).sendToDetectorStop<Ret>(fnum);
|
|
}
|
|
|
|
template <typename Ret, typename Arg>
|
|
Ret Module::sendToDetectorStop(int fnum, const Arg &args) const {
|
|
LOG(logDEBUG1) << "Sending to Stop: ["
|
|
<< getFunctionNameFromEnum(static_cast<detFuncs>(fnum))
|
|
<< ", " << args << ", " << sizeof(args) << ", "
|
|
<< typeid(Ret).name() << ", " << sizeof(Ret) << "]";
|
|
STATIC_ASSERT_ARG(Arg, "sendToDetectorStop")
|
|
STATIC_ASSERT_ARG(Ret, "sendToDetectorStop")
|
|
Ret retval{};
|
|
sendToDetectorStop(fnum, &args, sizeof(args), &retval, sizeof(retval));
|
|
LOG(logDEBUG1) << "Got back: " << ToString(retval);
|
|
return retval;
|
|
}
|
|
|
|
template <typename Ret, typename Arg>
|
|
Ret Module::sendToDetectorStop(int fnum, const Arg &args) {
|
|
return static_cast<const Module &>(*this).sendToDetectorStop<Ret>(fnum,
|
|
args);
|
|
}
|
|
|
|
//-------------------------------------------------------------- sendToReceiver
|
|
|
|
void Module::sendToReceiver(int fnum, const void *args, size_t args_size,
|
|
void *retval, size_t retval_size) const {
|
|
// This is the only function that actually sends data to the receiver
|
|
// the other versions use templates to deduce sizes and create
|
|
// the return type
|
|
if (!shm()->useReceiverFlag) {
|
|
std::ostringstream oss;
|
|
oss << "Set rx_hostname first to use receiver parameters, ";
|
|
oss << getFunctionNameFromEnum(static_cast<detFuncs>(fnum));
|
|
throw RuntimeError(oss.str());
|
|
}
|
|
checkArgs(args, args_size, retval, retval_size);
|
|
auto receiver = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort);
|
|
receiver.sendCommandThenRead(fnum, args, args_size, retval, retval_size);
|
|
receiver.close();
|
|
}
|
|
|
|
void Module::sendToReceiver(int fnum, const void *args, size_t args_size,
|
|
void *retval, size_t retval_size) {
|
|
static_cast<const Module &>(*this).sendToReceiver(fnum, args, args_size,
|
|
retval, retval_size);
|
|
}
|
|
|
|
template <typename Arg, typename Ret>
|
|
void Module::sendToReceiver(int fnum, const Arg &args, Ret &retval) const {
|
|
LOG(logDEBUG1) << "Sending to Receiver: ["
|
|
<< getFunctionNameFromEnum(static_cast<detFuncs>(fnum))
|
|
<< ", " << args << ", " << sizeof(args) << ", "
|
|
<< typeid(Ret).name() << ", " << sizeof(Ret) << "]";
|
|
STATIC_ASSERT_ARG(Arg, "sendToReceiver")
|
|
STATIC_ASSERT_ARG(Ret, "sendToReceiver")
|
|
sendToReceiver(fnum, &args, sizeof(args), &retval, sizeof(retval));
|
|
LOG(logDEBUG1) << "Got back: " << retval;
|
|
}
|
|
|
|
template <typename Arg, typename Ret>
|
|
void Module::sendToReceiver(int fnum, const Arg &args, Ret &retval) {
|
|
static_cast<const Module &>(*this).sendToReceiver(fnum, args, retval);
|
|
}
|
|
|
|
template <typename Arg>
|
|
void Module::sendToReceiver(int fnum, const Arg &args, std::nullptr_t) const {
|
|
LOG(logDEBUG1) << "Sending to Receiver: ["
|
|
<< getFunctionNameFromEnum(static_cast<detFuncs>(fnum))
|
|
<< ", " << typeid(Arg).name() << ", " << sizeof(Arg)
|
|
<< ", nullptr, 0 ]";
|
|
STATIC_ASSERT_ARG(Arg, "sendToReceiver")
|
|
sendToReceiver(fnum, &args, sizeof(args), nullptr, 0);
|
|
}
|
|
|
|
template <typename Arg>
|
|
void Module::sendToReceiver(int fnum, const Arg &args, std::nullptr_t) {
|
|
static_cast<const Module &>(*this).sendToReceiver(fnum, args, nullptr);
|
|
}
|
|
|
|
template <typename Ret>
|
|
void Module::sendToReceiver(int fnum, std::nullptr_t, Ret &retval) const {
|
|
LOG(logDEBUG1) << "Sending to Receiver: ["
|
|
<< getFunctionNameFromEnum(static_cast<detFuncs>(fnum))
|
|
<< ", nullptr, 0, " << typeid(Ret).name() << ", "
|
|
<< sizeof(Ret) << "]";
|
|
STATIC_ASSERT_ARG(Ret, "sendToReceiver")
|
|
sendToReceiver(fnum, nullptr, 0, &retval, sizeof(retval));
|
|
LOG(logDEBUG1) << "Got back: " << ToString(retval);
|
|
}
|
|
|
|
template <typename Ret>
|
|
void Module::sendToReceiver(int fnum, std::nullptr_t, Ret &retval) {
|
|
static_cast<const Module &>(*this).sendToReceiver(fnum, nullptr, retval);
|
|
}
|
|
|
|
template <typename Ret> Ret Module::sendToReceiver(int fnum) const {
|
|
LOG(logDEBUG1) << "Sending to Receiver: ["
|
|
<< getFunctionNameFromEnum(static_cast<detFuncs>(fnum))
|
|
<< ", nullptr, 0, " << typeid(Ret).name() << ", "
|
|
<< sizeof(Ret) << "]";
|
|
STATIC_ASSERT_ARG(Ret, "sendToReceiver")
|
|
Ret retval{};
|
|
sendToReceiver(fnum, nullptr, 0, &retval, sizeof(retval));
|
|
LOG(logDEBUG1) << "Got back: " << ToString(retval);
|
|
return retval;
|
|
}
|
|
|
|
template <typename Ret> Ret Module::sendToReceiver(int fnum) {
|
|
return static_cast<const Module &>(*this).sendToReceiver<Ret>(fnum);
|
|
}
|
|
|
|
void Module::sendToReceiver(int fnum) const {
|
|
LOG(logDEBUG1) << "Sending to Receiver: ["
|
|
<< getFunctionNameFromEnum(static_cast<detFuncs>(fnum))
|
|
<< ", nullptr, 0, nullptr, 0]";
|
|
sendToReceiver(fnum, nullptr, 0, nullptr, 0);
|
|
}
|
|
|
|
void Module::sendToReceiver(int fnum) {
|
|
static_cast<const Module &>(*this).sendToReceiver(fnum);
|
|
}
|
|
|
|
template <typename Ret, typename Arg>
|
|
Ret Module::sendToReceiver(int fnum, const Arg &args) const {
|
|
LOG(logDEBUG1) << "Sending to Receiver: ["
|
|
<< getFunctionNameFromEnum(static_cast<detFuncs>(fnum))
|
|
<< ", " << args << ", " << sizeof(args) << ", "
|
|
<< typeid(Ret).name() << ", " << sizeof(Ret) << "]";
|
|
STATIC_ASSERT_ARG(Arg, "sendToReceiver")
|
|
STATIC_ASSERT_ARG(Ret, "sendToReceiver")
|
|
Ret retval{};
|
|
sendToReceiver(fnum, &args, sizeof(args), &retval, sizeof(retval));
|
|
LOG(logDEBUG1) << "Got back: " << retval;
|
|
return retval;
|
|
}
|
|
|
|
template <typename Ret, typename Arg>
|
|
Ret Module::sendToReceiver(int fnum, const Arg &args) {
|
|
return static_cast<const Module &>(*this).sendToReceiver<Ret>(fnum, args);
|
|
}
|
|
|
|
slsDetectorDefs::detectorType Module::getDetectorTypeFromShm(int det_id,
|
|
bool verify) {
|
|
if (!shm.IsExisting()) {
|
|
throw SharedMemoryError("Shared memory " + shm.GetName() +
|
|
"does not exist.\n Corrupted Multi Shared "
|
|
"memory. Please free shared memory.");
|
|
}
|
|
|
|
shm.OpenSharedMemory();
|
|
if (verify && shm()->shmversion != MODULE_SHMVERSION) {
|
|
std::ostringstream ss;
|
|
ss << "Single shared memory (" << det_id << "-" << moduleIndex
|
|
<< ":)version mismatch (expected 0x" << std::hex << MODULE_SHMVERSION
|
|
<< " but got 0x" << shm()->shmversion << ")" << std::dec
|
|
<< ". Clear Shared memory to continue.";
|
|
shm.UnmapSharedMemory();
|
|
throw SharedMemoryError(ss.str());
|
|
}
|
|
return shm()->detType;
|
|
}
|
|
|
|
void Module::initSharedMemory(detectorType type, int det_id, bool verify) {
|
|
shm = SharedMemory<sharedModule>(det_id, moduleIndex);
|
|
if (!shm.IsExisting()) {
|
|
shm.CreateSharedMemory();
|
|
initializeModuleStructure(type);
|
|
} else {
|
|
shm.OpenSharedMemory();
|
|
if (verify && shm()->shmversion != MODULE_SHMVERSION) {
|
|
std::ostringstream ss;
|
|
ss << "Single shared memory (" << det_id << "-" << moduleIndex
|
|
<< ":) version mismatch (expected 0x" << std::hex
|
|
<< MODULE_SHMVERSION << " but got 0x" << shm()->shmversion << ")"
|
|
<< std::dec << ". Clear Shared memory to continue.";
|
|
throw SharedMemoryError(ss.str());
|
|
}
|
|
}
|
|
}
|
|
|
|
void Module::initializeModuleStructure(detectorType type) {
|
|
shm()->shmversion = MODULE_SHMVERSION;
|
|
memset(shm()->hostname, 0, MAX_STR_LENGTH);
|
|
shm()->detType = type;
|
|
shm()->numberOfModule.x = 0;
|
|
shm()->numberOfModule.y = 0;
|
|
shm()->controlPort = DEFAULT_PORTNO;
|
|
shm()->stopPort = DEFAULT_PORTNO + 1;
|
|
sls::strcpy_safe(shm()->settingsDir, getenv("HOME"));
|
|
sls::strcpy_safe(shm()->rxHostname, "none");
|
|
shm()->rxTCPPort = DEFAULT_PORTNO + 2;
|
|
shm()->useReceiverFlag = false;
|
|
shm()->zmqport = DEFAULT_ZMQ_CL_PORTNO +
|
|
(moduleIndex * ((shm()->detType == EIGER) ? 2 : 1));
|
|
shm()->zmqip = IpAddr{};
|
|
shm()->numUDPInterfaces = 1;
|
|
shm()->stoppedFlag = false;
|
|
|
|
// get the Module parameters based on type
|
|
detParameters parameters{type};
|
|
shm()->nChan.x = parameters.nChanX;
|
|
shm()->nChan.y = parameters.nChanY;
|
|
shm()->nChip.x = parameters.nChipX;
|
|
shm()->nChip.y = parameters.nChipY;
|
|
shm()->nDacs = parameters.nDacs;
|
|
}
|
|
|
|
void Module::checkDetectorVersionCompatibility() {
|
|
int64_t arg = 0;
|
|
switch (shm()->detType) {
|
|
case EIGER:
|
|
arg = APIEIGER;
|
|
break;
|
|
case JUNGFRAU:
|
|
arg = APIJUNGFRAU;
|
|
break;
|
|
case GOTTHARD:
|
|
arg = APIGOTTHARD;
|
|
break;
|
|
case CHIPTESTBOARD:
|
|
arg = APICTB;
|
|
break;
|
|
case MOENCH:
|
|
arg = APIMOENCH;
|
|
break;
|
|
case MYTHEN3:
|
|
arg = APIMYTHEN3;
|
|
break;
|
|
case GOTTHARD2:
|
|
arg = APIGOTTHARD2;
|
|
break;
|
|
default:
|
|
throw NotImplementedError(
|
|
"Check version compatibility is not implemented for this detector");
|
|
}
|
|
sendToDetector(F_CHECK_VERSION, arg, nullptr);
|
|
sendToDetectorStop(F_CHECK_VERSION, arg, nullptr);
|
|
}
|
|
|
|
void Module::checkReceiverVersionCompatibility() {
|
|
// TODO! Verify that this works as intended when version don't match
|
|
sendToReceiver(F_RECEIVER_CHECK_VERSION, int64_t(APIRECEIVER), nullptr);
|
|
}
|
|
|
|
int Module::sendModule(sls_detector_module *myMod, sls::ClientSocket &client) {
|
|
constexpr TLogLevel level = logDEBUG1;
|
|
LOG(level) << "Sending Module";
|
|
int ts = 0;
|
|
int n = 0;
|
|
n = client.Send(&(myMod->serialnumber), sizeof(myMod->serialnumber));
|
|
ts += n;
|
|
LOG(level) << "Serial number sent. " << n
|
|
<< " bytes. serialno: " << myMod->serialnumber;
|
|
|
|
n = client.Send(&(myMod->nchan), sizeof(myMod->nchan));
|
|
ts += n;
|
|
LOG(level) << "nchan sent. " << n << " bytes. nchan: " << myMod->nchan;
|
|
|
|
n = client.Send(&(myMod->nchip), sizeof(myMod->nchip));
|
|
ts += n;
|
|
LOG(level) << "nchip sent. " << n << " bytes. nchip: " << myMod->nchip;
|
|
|
|
n = client.Send(&(myMod->ndac), sizeof(myMod->ndac));
|
|
ts += n;
|
|
LOG(level) << "ndac sent. " << n << " bytes. ndac: " << myMod->ndac;
|
|
|
|
n = client.Send(&(myMod->reg), sizeof(myMod->reg));
|
|
ts += n;
|
|
LOG(level) << "reg sent. " << n << " bytes. reg: " << myMod->reg;
|
|
|
|
n = client.Send(&(myMod->iodelay), sizeof(myMod->iodelay));
|
|
ts += n;
|
|
LOG(level) << "iodelay sent. " << n
|
|
<< " bytes. iodelay: " << myMod->iodelay;
|
|
|
|
n = client.Send(&(myMod->tau), sizeof(myMod->tau));
|
|
ts += n;
|
|
LOG(level) << "tau sent. " << n << " bytes. tau: " << myMod->tau;
|
|
|
|
n = client.Send(myMod->eV, sizeof(myMod->eV));
|
|
ts += n;
|
|
LOG(level) << "ev sent. " << n << " bytes. ev: " << ToString(myMod->eV);
|
|
|
|
n = client.Send(myMod->dacs, sizeof(int) * (myMod->ndac));
|
|
ts += n;
|
|
LOG(level) << "dacs sent. " << n << " bytes";
|
|
|
|
if (shm()->detType == EIGER || shm()->detType == MYTHEN3) {
|
|
n = client.Send(myMod->chanregs, sizeof(int) * (myMod->nchan));
|
|
ts += n;
|
|
LOG(level) << "channels sent. " << n << " bytes";
|
|
}
|
|
return ts;
|
|
}
|
|
|
|
void Module::setModule(sls_detector_module &module, bool trimbits) {
|
|
LOG(logDEBUG1) << "Setting module with trimbits:" << trimbits;
|
|
// to exclude trimbits
|
|
if (!trimbits) {
|
|
module.nchan = 0;
|
|
module.nchip = 0;
|
|
}
|
|
auto client = DetectorSocket(shm()->hostname, shm()->controlPort);
|
|
client.Send(F_SET_MODULE);
|
|
sendModule(&module, client);
|
|
if (client.Receive<int>() == FAIL) {
|
|
throw DetectorError("Module " + std::to_string(moduleIndex) +
|
|
" returned error: " + client.readErrorMessage());
|
|
}
|
|
}
|
|
|
|
void Module::updateReceiverStreamingIP() {
|
|
auto ip = getReceiverStreamingIP();
|
|
if (ip == 0) {
|
|
// Hostname could be ip try to decode otherwise look up the hostname
|
|
ip = sls::IpAddr{shm()->rxHostname};
|
|
if (ip == 0) {
|
|
ip = HostnameToIp(shm()->rxHostname);
|
|
}
|
|
LOG(logINFO) << "Setting default receiver " << moduleIndex
|
|
<< " streaming zmq ip to " << ip;
|
|
}
|
|
setReceiverStreamingIP(ip);
|
|
}
|
|
|
|
void Module::updateRateCorrection() {
|
|
sendToDetector(F_UPDATE_RATE_CORRECTION);
|
|
}
|
|
|
|
sls_detector_module Module::interpolateTrim(sls_detector_module *a,
|
|
sls_detector_module *b,
|
|
const int energy, const int e1,
|
|
const int e2, bool trimbits) {
|
|
// dacs specified only for eiger and mythen3
|
|
if (shm()->detType != EIGER && shm()->detType != MYTHEN3) {
|
|
throw NotImplementedError(
|
|
"Interpolation of Trim values not implemented for this detector!");
|
|
}
|
|
|
|
sls_detector_module myMod{shm()->detType};
|
|
enum eiger_DacIndex {
|
|
E_SVP,
|
|
E_VTR,
|
|
E_VRF,
|
|
E_VRS,
|
|
E_SVN,
|
|
E_VTGSTV,
|
|
E_VCMP_LL,
|
|
E_VCMP_LR,
|
|
E_CAL,
|
|
E_VCMP_RL,
|
|
E_RXB_RB,
|
|
E_RXB_LB,
|
|
E_VCMP_RR,
|
|
E_VCP,
|
|
E_VCN,
|
|
E_VIS
|
|
};
|
|
enum mythen3_DacIndex {
|
|
M_VCASSH,
|
|
M_VTH2,
|
|
M_VRSHAPER,
|
|
M_VRSHAPER_N,
|
|
M_VIPRE_OUT,
|
|
M_VTH3,
|
|
M_VTH1,
|
|
M_VICIN,
|
|
M_VCAS,
|
|
M_VRPREAMP,
|
|
M_VCAL_N,
|
|
M_VIPRE,
|
|
M_VISHAPER,
|
|
M_VCAL_P,
|
|
M_VTRIM,
|
|
M_VDCSH
|
|
};
|
|
|
|
// create copy and interpolate dac lists
|
|
std::vector<int> dacs_to_copy, dacs_to_interpolate;
|
|
if (shm()->detType == EIGER) {
|
|
dacs_to_copy.insert(
|
|
dacs_to_copy.end(),
|
|
{E_SVP, E_VTR, E_SVN, E_VTGSTV, E_RXB_RB, E_RXB_LB, E_VCN, E_VIS});
|
|
// interpolate vrf, vcmp, vcp
|
|
dacs_to_interpolate.insert(
|
|
dacs_to_interpolate.end(),
|
|
{E_VRF, E_VCMP_LL, E_VCMP_LR, E_VCMP_RL, E_VCMP_RR, E_VCP, E_VRS});
|
|
} else {
|
|
dacs_to_copy.insert(dacs_to_copy.end(),
|
|
{M_VCASSH, M_VRSHAPER, M_VRSHAPER_N, M_VIPRE_OUT,
|
|
M_VICIN, M_VCAS, M_VRPREAMP, M_VCAL_N, M_VIPRE,
|
|
M_VISHAPER, M_VCAL_P, M_VDCSH});
|
|
// interpolate vtrim, vth1, vth2, vth3
|
|
dacs_to_interpolate.insert(dacs_to_interpolate.end(),
|
|
{M_VTH1, M_VTH2, M_VTH3, M_VTRIM});
|
|
}
|
|
|
|
// Copy Dacs
|
|
for (size_t i = 0; i < dacs_to_copy.size(); ++i) {
|
|
if (a->dacs[dacs_to_copy[i]] != b->dacs[dacs_to_copy[i]]) {
|
|
throw RuntimeError("Interpolate module: dacs " + std::to_string(i) +
|
|
" different");
|
|
}
|
|
myMod.dacs[dacs_to_copy[i]] = a->dacs[dacs_to_copy[i]];
|
|
}
|
|
|
|
// Interpolate Dacs
|
|
for (size_t i = 0; i < dacs_to_interpolate.size(); ++i) {
|
|
myMod.dacs[dacs_to_interpolate[i]] =
|
|
linearInterpolation(energy, e1, e2, a->dacs[dacs_to_interpolate[i]],
|
|
b->dacs[dacs_to_interpolate[i]]);
|
|
}
|
|
|
|
// Copy irrelevant dacs (without failing)
|
|
if (shm()->detType == EIGER) {
|
|
// CAL
|
|
if (a->dacs[E_CAL] != b->dacs[E_CAL]) {
|
|
LOG(logWARNING)
|
|
<< "DAC CAL differs in both energies (" << a->dacs[E_CAL] << ","
|
|
<< b->dacs[E_CAL] << ")!\nTaking first: " << a->dacs[E_CAL];
|
|
}
|
|
myMod.dacs[E_CAL] = a->dacs[E_CAL];
|
|
}
|
|
|
|
// Interpolate all trimbits
|
|
if (trimbits) {
|
|
for (int i = 0; i < myMod.nchan; ++i) {
|
|
myMod.chanregs[i] = linearInterpolation(
|
|
energy, e1, e2, a->chanregs[i], b->chanregs[i]);
|
|
}
|
|
}
|
|
return myMod;
|
|
}
|
|
|
|
std::string Module::getTrimbitFilename(detectorSettings s, int e_eV) {
|
|
std::string ssettings;
|
|
switch (s) {
|
|
case STANDARD:
|
|
ssettings = "/standard";
|
|
break;
|
|
case FAST:
|
|
ssettings = "/fast";
|
|
break;
|
|
case HIGHGAIN:
|
|
ssettings = "/highgain";
|
|
break;
|
|
case LOWGAIN:
|
|
ssettings = "/lowgain";
|
|
break;
|
|
case VERYHIGHGAIN:
|
|
ssettings = "/veryhighgain";
|
|
break;
|
|
case VERYLOWGAIN:
|
|
ssettings = "/verylowgain";
|
|
break;
|
|
default:
|
|
std::ostringstream ss;
|
|
ss << "Unknown settings " << ToString(s) << " for this detector!";
|
|
throw RuntimeError(ss.str());
|
|
}
|
|
std::ostringstream ostfn;
|
|
ostfn << shm()->settingsDir << ssettings << "/" << e_eV << "eV";
|
|
if (shm()->detType == EIGER) {
|
|
ostfn << "/noise.sn";
|
|
} else if (shm()->detType == MYTHEN3) {
|
|
ostfn << "/trim.sn";
|
|
} else {
|
|
throw RuntimeError(
|
|
"Settings or trimbit files not defined for this detector.");
|
|
}
|
|
int moduleIdWidth = 3;
|
|
if (shm()->detType == MYTHEN3) {
|
|
moduleIdWidth = 4;
|
|
}
|
|
ostfn << std::setfill('0') << std::setw(moduleIdWidth) << std::dec
|
|
<< getModuleId() << std::setbase(10);
|
|
return ostfn.str();
|
|
}
|
|
|
|
sls_detector_module Module::readSettingsFile(const std::string &fname,
|
|
bool trimbits) {
|
|
LOG(logDEBUG1) << "Read settings file " << fname;
|
|
sls_detector_module myMod(shm()->detType);
|
|
// open file
|
|
std::ifstream infile;
|
|
if (shm()->detType == EIGER || shm()->detType == MYTHEN3) {
|
|
infile.open(fname.c_str(), std::ifstream::binary);
|
|
} else {
|
|
infile.open(fname.c_str(), std::ios_base::in);
|
|
}
|
|
if (!infile) {
|
|
throw RuntimeError("Could not open settings file: " + fname);
|
|
}
|
|
|
|
auto file_size = getFileSize(infile);
|
|
|
|
// eiger
|
|
if (shm()->detType == EIGER) {
|
|
infile.read(reinterpret_cast<char *>(myMod.dacs),
|
|
sizeof(int) * (myMod.ndac));
|
|
infile.read(reinterpret_cast<char *>(&myMod.iodelay),
|
|
sizeof(myMod.iodelay));
|
|
infile.read(reinterpret_cast<char *>(&myMod.tau), sizeof(myMod.tau));
|
|
for (int i = 0; i < myMod.ndac; ++i) {
|
|
LOG(logDEBUG1) << "dac " << i << ":" << myMod.dacs[i];
|
|
}
|
|
LOG(logDEBUG1) << "iodelay:" << myMod.iodelay;
|
|
LOG(logDEBUG1) << "tau:" << myMod.tau;
|
|
if (trimbits) {
|
|
infile.read(reinterpret_cast<char *>(myMod.chanregs),
|
|
sizeof(int) * (myMod.nchan));
|
|
}
|
|
if (!infile) {
|
|
throw RuntimeError("readSettingsFile: Could not load all values "
|
|
"for settings for " +
|
|
fname);
|
|
}
|
|
}
|
|
|
|
// mythen3 (dacs, trimbits)
|
|
else if (shm()->detType == MYTHEN3) {
|
|
int expected_size = sizeof(int) * myMod.ndac +
|
|
sizeof(int) * myMod.nchan + sizeof(myMod.reg);
|
|
if (file_size != expected_size) {
|
|
throw RuntimeError("The size of the settings file: " + fname +
|
|
" differs from the expected size, " +
|
|
std::to_string(file_size) + " instead of " +
|
|
std::to_string(expected_size) + " bytes");
|
|
}
|
|
infile.read(reinterpret_cast<char *>(&myMod.reg), sizeof(myMod.reg));
|
|
infile.read(reinterpret_cast<char *>(myMod.dacs),
|
|
sizeof(int) * (myMod.ndac));
|
|
for (int i = 0; i < myMod.ndac; ++i) {
|
|
LOG(logDEBUG) << "dac " << i << ":" << myMod.dacs[i];
|
|
}
|
|
if (trimbits) {
|
|
infile.read(reinterpret_cast<char *>(myMod.chanregs),
|
|
sizeof(int) * (myMod.nchan));
|
|
}
|
|
if (!infile) {
|
|
throw RuntimeError("readSettingsFile: Could not load all values "
|
|
"for settings for " +
|
|
fname);
|
|
}
|
|
}
|
|
|
|
else {
|
|
throw RuntimeError("Not implemented for this detector");
|
|
}
|
|
LOG(logINFO) << "Settings file loaded: " << fname.c_str();
|
|
return myMod;
|
|
}
|
|
|
|
void Module::sendProgram(bool blackfin, std::vector<char> buffer,
|
|
const int functionEnum,
|
|
const std::string &functionType,
|
|
const std::string serverName) {
|
|
LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname
|
|
<< "): Sending " << functionType;
|
|
|
|
// send fnum and filesize
|
|
auto client = DetectorSocket(shm()->hostname, shm()->controlPort);
|
|
client.Send(functionEnum);
|
|
uint64_t filesize = buffer.size();
|
|
client.Send(filesize);
|
|
|
|
// send checksum
|
|
std::string checksum = sls::md5_calculate_checksum(buffer.data(), filesize);
|
|
LOG(logDEBUG1) << "Checksum:" << checksum;
|
|
char cChecksum[MAX_STR_LENGTH] = {0};
|
|
strcpy(cChecksum, checksum.c_str());
|
|
client.Send(cChecksum);
|
|
|
|
// send server name
|
|
if (functionEnum == F_UPDATE_DETECTOR_SERVER) {
|
|
char sname[MAX_STR_LENGTH] = {0};
|
|
strcpy(sname, serverName.c_str());
|
|
client.Send(sname);
|
|
}
|
|
|
|
// validate memory allocation etc in detector
|
|
if (client.Receive<int>() == FAIL) {
|
|
std::ostringstream os;
|
|
os << "Module " << moduleIndex << " (" << shm()->hostname << ")"
|
|
<< " returned error: " << client.readErrorMessage();
|
|
throw DetectorError(os.str());
|
|
}
|
|
|
|
// send program
|
|
if (blackfin) {
|
|
uint64_t unitprogramsize = 0;
|
|
int currentPointer = 0;
|
|
while (filesize > 0) {
|
|
unitprogramsize = MAX_BLACKFIN_PROGRAM_SIZE;
|
|
if (unitprogramsize > filesize) {
|
|
unitprogramsize = filesize;
|
|
}
|
|
LOG(logDEBUG) << "unitprogramsize:" << unitprogramsize
|
|
<< "\t filesize:" << filesize;
|
|
|
|
client.Send(&buffer[currentPointer], unitprogramsize);
|
|
if (client.Receive<int>() == FAIL) {
|
|
std::cout << '\n';
|
|
std::ostringstream os;
|
|
os << "Module " << moduleIndex << " (" << shm()->hostname << ")"
|
|
<< " returned error: " << client.readErrorMessage();
|
|
throw DetectorError(os.str());
|
|
}
|
|
filesize -= unitprogramsize;
|
|
currentPointer += unitprogramsize;
|
|
}
|
|
} else {
|
|
client.Send(buffer);
|
|
}
|
|
|
|
// tmp checksum verified in detector
|
|
if (client.Receive<int>() == FAIL) {
|
|
std::ostringstream os;
|
|
os << "Module " << moduleIndex << " (" << shm()->hostname << ")"
|
|
<< " returned error: " << client.readErrorMessage();
|
|
throw DetectorError(os.str());
|
|
}
|
|
LOG(logINFO) << "Checksum verified for module " << moduleIndex << " ("
|
|
<< shm()->hostname << ")";
|
|
|
|
// simulating erasing and writing to
|
|
if (blackfin) {
|
|
if (functionEnum == F_PROGRAM_FPGA) {
|
|
simulatingActivityinDetector("Erasing Flash",
|
|
BLACKFIN_ERASE_FLASH_TIME);
|
|
simulatingActivityinDetector("Writing to Flash",
|
|
BLACKFIN_WRITE_TO_FLASH_TIME);
|
|
}
|
|
} else {
|
|
if (functionEnum == F_PROGRAM_FPGA) {
|
|
simulatingActivityinDetector("Erasing Flash",
|
|
NIOS_ERASE_FLASH_TIME_FPGA);
|
|
simulatingActivityinDetector("Writing to Flash",
|
|
NIOS_WRITE_TO_FLASH_TIME_FPGA);
|
|
} else if (functionEnum == F_UPDATE_KERNEL) {
|
|
simulatingActivityinDetector("Erasing Flash",
|
|
NIOS_ERASE_FLASH_TIME_KERNEL);
|
|
simulatingActivityinDetector("Writing to Flash",
|
|
NIOS_WRITE_TO_FLASH_TIME_KERNEL);
|
|
}
|
|
}
|
|
|
|
// update verified
|
|
if (client.Receive<int>() == FAIL) {
|
|
std::ostringstream os;
|
|
os << "Module " << moduleIndex << " (" << shm()->hostname << ")"
|
|
<< " returned error: " << client.readErrorMessage();
|
|
throw DetectorError(os.str());
|
|
}
|
|
LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname
|
|
<< "): " << functionType << " successful";
|
|
}
|
|
|
|
void Module::simulatingActivityinDetector(const std::string &functionType,
|
|
const int timeRequired) {
|
|
LOG(logINFO) << "(Simulating) " << functionType << " for module "
|
|
<< moduleIndex << " (" << shm()->hostname << ")";
|
|
printf("%d%%\r", 0);
|
|
std::cout << std::flush;
|
|
const int ERASE_TIME = timeRequired;
|
|
int count = ERASE_TIME + 1;
|
|
while (count > 0) {
|
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
|
--count;
|
|
printf(
|
|
"%d%%\r",
|
|
static_cast<int>(
|
|
(static_cast<double>(ERASE_TIME - count) / ERASE_TIME) * 100));
|
|
std::cout << std::flush;
|
|
}
|
|
printf("\n");
|
|
}
|
|
} // namespace sls
|