mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2026-09-03 17:50:42 +02:00
Build and Deploy on local RHEL9 / build (push) Successful in 2m6s
Build on RHEL9 docker image / build (push) Successful in 3m46s
Build and Deploy on local RHEL8 / build (push) Successful in 5m9s
Build on RHEL8 docker image / build (push) Successful in 5m14s
Run Simulator Tests on local RHEL9 / build (push) Successful in 20m6s
Run Simulator Tests on local RHEL8 / build (push) Successful in 23m30s
* changed api from double to string return for getchipversion, updated python bindings, added to versions command, fixed appropriately to send string from server, fixed tests accordingly to convert the string to int to do the tests * binary in * minor * fixed tests * updated help for chipversion
2144 lines
78 KiB
C++
2144 lines
78 KiB
C++
#include "Caller.h"
|
|
#include "sls/ZmqSocket.h"
|
|
#include "sls/bit_utils.h"
|
|
#include "sls/file_utils.h"
|
|
#include "sls/logger.h"
|
|
#include "sls/string_utils.h"
|
|
|
|
#include <iostream>
|
|
#include <thread>
|
|
|
|
namespace sls {
|
|
// some helper functions to print
|
|
|
|
std::string Caller::OutString(const Result<defs::Hz> &value,
|
|
const std::string &unit) {
|
|
auto u = parseFrequencyUnit(unit);
|
|
if (value.equal())
|
|
return ToString(value.front(), u);
|
|
return ToString(value, u);
|
|
}
|
|
|
|
std::vector<std::string> Caller::getAllCommands() {
|
|
std::vector<std::string> ret;
|
|
for (auto it : functions)
|
|
ret.push_back(it.first);
|
|
return ret;
|
|
}
|
|
|
|
std::map<std::string, std::string> Caller::GetDeprecatedCommands() {
|
|
return deprecated_functions;
|
|
}
|
|
|
|
void Caller::call(const std::string &command,
|
|
const std::vector<std::string> &arguments, int detector_id,
|
|
int action, std::ostream &os, int receiver_id) {
|
|
cmd = command;
|
|
args = arguments; // copy args before replacing
|
|
SuggestIfRemoved(cmd);
|
|
std::string temp;
|
|
while (temp != cmd) {
|
|
temp = cmd;
|
|
ReplaceIfDeprecated(cmd);
|
|
}
|
|
|
|
det_id = detector_id;
|
|
rx_id = receiver_id;
|
|
auto it = functions.find(cmd);
|
|
if (it != functions.end()) {
|
|
auto ret = ((*this).*(it->second))(action);
|
|
os << cmd << ' ' << ret;
|
|
} else {
|
|
throw RuntimeError(cmd +
|
|
" Unknown command, use list to list all commands");
|
|
}
|
|
}
|
|
|
|
bool Caller::ReplaceIfDeprecated(std::string &command) {
|
|
auto d_it = deprecated_functions.find(command);
|
|
if (d_it != deprecated_functions.end()) {
|
|
|
|
// insert old command into arguments (for dacs)
|
|
if (d_it->second == "dac") {
|
|
args.insert(args.begin(), command);
|
|
LOG(logWARNING)
|
|
<< command
|
|
<< " is deprecated and will be removed. Please migrate to: "
|
|
<< d_it->second << " " << command;
|
|
} else {
|
|
LOG(logWARNING)
|
|
<< command
|
|
<< " is deprecated and will be removed. Please migrate to: "
|
|
<< d_it->second;
|
|
}
|
|
command = d_it->second;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void Caller::SuggestIfRemoved(const std::string &command) {
|
|
auto r_it = removed_functions.find(command);
|
|
if (r_it != removed_functions.end()) {
|
|
std::ostringstream oss;
|
|
oss << command << " is removed and is no longer available. Please use: "
|
|
<< r_it->second;
|
|
throw RuntimeError(oss.str());
|
|
}
|
|
}
|
|
|
|
std::string Caller::list(int action) {
|
|
if (action == defs::HELP_ACTION) {
|
|
return "[deprecated(optional)]\n\tlists all available commands, list "
|
|
"deprecated - list deprecated commands\n";
|
|
}
|
|
if (args.empty()) {
|
|
std::string ret = "free\n";
|
|
ret += "user\n";
|
|
for (auto &f : functions) {
|
|
ret += f.first + "\n";
|
|
}
|
|
return ret;
|
|
} else if (args.size() == 1) {
|
|
if (args[0] == "deprecated") {
|
|
std::ostringstream os;
|
|
os << "The following " << deprecated_functions.size()
|
|
<< " commands are deprecated\n";
|
|
const size_t field_width = 20;
|
|
for (const auto &it : deprecated_functions) {
|
|
os << std::right << std::setw(field_width) << it.first << " -> "
|
|
<< it.second << '\n';
|
|
}
|
|
return os.str();
|
|
} else {
|
|
throw RuntimeError(
|
|
"Could not decode argument. Possible options: deprecated");
|
|
}
|
|
} else {
|
|
WrongNumberOfParameters(0);
|
|
return "";
|
|
}
|
|
}
|
|
|
|
/* Network Configuration (Detector<->Receiver) */
|
|
|
|
IpAddr Caller::getDstIpFromAuto() {
|
|
std::string rxHostname =
|
|
det->getRxHostname(std::vector<int>{det_id}).squash("none");
|
|
// Hostname could be ip try to decode otherwise look up the hostname
|
|
auto val = IpAddr{rxHostname};
|
|
if (val == 0) {
|
|
val = HostnameToIp(rxHostname.c_str());
|
|
}
|
|
return val;
|
|
}
|
|
|
|
IpAddr Caller::getSrcIpFromAuto() {
|
|
std::string hostname =
|
|
det->getHostname(std::vector<int>{det_id}).squash("none");
|
|
// Hostname could be ip try to decode otherwise look up the hostname
|
|
auto val = IpAddr{hostname};
|
|
if (val == 0) {
|
|
val = HostnameToIp(hostname.c_str());
|
|
}
|
|
return val;
|
|
}
|
|
|
|
UdpDestination Caller::getUdpEntry() {
|
|
UdpDestination udpDestination{};
|
|
udpDestination.entry = rx_id;
|
|
|
|
for (auto it : args) {
|
|
size_t pos = it.find('=');
|
|
std::string key = it.substr(0, pos);
|
|
std::string value = it.substr(pos + 1);
|
|
if (key == "ip") {
|
|
if (value == "auto") {
|
|
auto val = getDstIpFromAuto();
|
|
LOG(logINFO) << "Setting udp_dstip of detector " << det_id
|
|
<< " to " << val;
|
|
udpDestination.ip = val;
|
|
} else {
|
|
udpDestination.ip = IpAddr(value);
|
|
}
|
|
} else if (key == "ip2") {
|
|
if (value == "auto") {
|
|
auto val = getDstIpFromAuto();
|
|
LOG(logINFO) << "Setting udp_dstip2 of detector " << det_id
|
|
<< " to " << val;
|
|
udpDestination.ip2 = val;
|
|
} else {
|
|
udpDestination.ip2 = IpAddr(value);
|
|
}
|
|
} else if (key == "mac") {
|
|
udpDestination.mac = MacAddr(value);
|
|
} else if (key == "mac2") {
|
|
udpDestination.mac2 = MacAddr(value);
|
|
} else if (key == "port") {
|
|
udpDestination.port = StringTo<uint32_t>(value);
|
|
} else if (key == "port2") {
|
|
udpDestination.port2 = StringTo<uint32_t>(value);
|
|
}
|
|
}
|
|
return udpDestination;
|
|
}
|
|
void Caller::WrongNumberOfParameters(size_t expected) {
|
|
if (expected == 0) {
|
|
throw RuntimeError("Command " + cmd +
|
|
" expected no parameter/s but got " +
|
|
std::to_string(args.size()) + "\n");
|
|
}
|
|
throw RuntimeError("Command " + cmd + " expected (or >=) " +
|
|
std::to_string(expected) + " parameter/s but got " +
|
|
std::to_string(args.size()) + "\n");
|
|
}
|
|
|
|
int Caller::GetLevelAndInsertIntoArgs(std::string levelSeparatedCommand) {
|
|
if (cmd != levelSeparatedCommand) {
|
|
LOG(logWARNING) << "This command is deprecated and will be removed. "
|
|
"Please migrate to "
|
|
<< levelSeparatedCommand;
|
|
int level = cmd[cmd.find_first_of("012")] - '0';
|
|
args.insert(args.begin(), std::to_string(level));
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
std::string Caller::free(int action) {
|
|
// This function is purely for help, actual functionality is in the caller
|
|
return "free\n\tFree detector shared memory\n";
|
|
}
|
|
|
|
std::string Caller::user(int action) {
|
|
// This function is purely for help, actual functionality is in the caller
|
|
return "user\n\tUser details from shared memory (hostname, type, PID, "
|
|
"User, Date).\n";
|
|
}
|
|
|
|
std::string Caller::hostname(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "\n\tFrees shared memory and sets hostname (or IP address) of "
|
|
"all modules concatenated by +.\n\t Virtual servers can already "
|
|
"use the port in hostname separated by ':' and ports incremented "
|
|
"by 2 to accomodate the stop server as well. The row and column "
|
|
"values in the udp/zmq header are affected by the order in this "
|
|
"command and the detsize command. The modules are stacked row by "
|
|
"row until they reach the y-axis limit set by detsize (if "
|
|
"specified). Then, stacking continues in the next column and so "
|
|
"on. This only affects row and column in udp/zmq header."
|
|
<< '\n';
|
|
} else if (action == defs::GET_ACTION) {
|
|
if (!args.empty()) {
|
|
WrongNumberOfParameters(0);
|
|
}
|
|
auto t = det->getHostname(std::vector<int>{det_id});
|
|
os << OutString(t) << '\n';
|
|
} else if (action == defs::PUT_ACTION) {
|
|
if (args.empty()) {
|
|
WrongNumberOfParameters(1);
|
|
}
|
|
if (det_id != -1) {
|
|
throw RuntimeError("Cannot execute this at module level");
|
|
}
|
|
// only args[0], but many hostames concatenated with +
|
|
if (args[0].find('+') != std::string::npos) {
|
|
auto t = split(args[0], '+');
|
|
det->setHostname(t);
|
|
os << ToString(t) << '\n';
|
|
}
|
|
// either hostnames separated by space, or single hostname
|
|
else {
|
|
det->setHostname(args);
|
|
os << ToString(args) << '\n';
|
|
}
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
|
|
void Caller::EmptyDataCallBack(detectorData *data, uint64_t frameIndex,
|
|
uint32_t subFrameIndex, void *this_pointer) {
|
|
LOG(logDEBUG) << "EmptyDataCallBack to start up zmq sockets";
|
|
}
|
|
|
|
std::string Caller::acquire(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "\n\tAcquire the number of frames set up.\n\tBlocking command, "
|
|
"where control server is blocked and cannot accept other "
|
|
"commands until acquisition is done. \n\t- sets acquiring "
|
|
"flag\n\t- starts the receiver listener (if enabled)\n\t- starts "
|
|
"detector acquisition for number of frames set\n\t- monitors "
|
|
"detector status from running to idle\n\t- stops the receiver "
|
|
"listener (if enabled)\n\t- increments file index if file write "
|
|
"enabled\n\t- resets acquiring flag"
|
|
<< '\n';
|
|
} else {
|
|
if (det->empty()) {
|
|
throw RuntimeError("This shared memory has no detectors added.");
|
|
}
|
|
if (det_id >= 0) {
|
|
throw RuntimeError("Individual detectors not allowed for readout.");
|
|
}
|
|
if (action == defs::READOUT_ZMQ_ACTION) {
|
|
det->registerDataCallback(&(EmptyDataCallBack), this);
|
|
}
|
|
det->acquire();
|
|
|
|
if (det->getUseReceiverFlag().squash(false)) {
|
|
os << "\nAcquired ";
|
|
os << det->getFramesCaught() << '\n';
|
|
}
|
|
}
|
|
return os.str();
|
|
}
|
|
std::string Caller::versions(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "\n\tPrint all versions and detector type" << '\n';
|
|
} else if (action == defs::GET_ACTION) {
|
|
if (!args.empty()) {
|
|
WrongNumberOfParameters(0);
|
|
}
|
|
|
|
std::string vType = "Unknown";
|
|
std::string vFirmware = "Unknown";
|
|
std::string vServer = "Unknown";
|
|
std::string vKernel = "Unknown";
|
|
std::string vHardware = "Unknown";
|
|
bool eiger = false;
|
|
std::string vBebFirmware = "Unknown";
|
|
std::string vFeblFirmware = "Unknown";
|
|
std::string vFebrFirmware = "Unknown";
|
|
bool jungfrau = false;
|
|
std::string vChipVersion = "Unknown";
|
|
bool receiver = false;
|
|
std::string vReceiver = "Unknown";
|
|
|
|
std::string vRelease = det->getPackageVersion();
|
|
std::string vClient = det->getClientVersion();
|
|
|
|
if (det->size() != 0) {
|
|
// shared memory has detectors
|
|
vType = OutString(det->getDetectorType());
|
|
eiger = (det->getDetectorType().squash() == defs::EIGER);
|
|
jungfrau = (det->getDetectorType().squash() == defs::JUNGFRAU);
|
|
receiver = det->getUseReceiverFlag().squash(false);
|
|
if (receiver) {
|
|
// cannot connect to receiver
|
|
try {
|
|
vReceiver = OutString(
|
|
det->getReceiverVersion(std::vector<int>{det_id}));
|
|
} catch (const std::exception &e) {
|
|
}
|
|
}
|
|
// cannot connect to Detector
|
|
try {
|
|
auto firmwareVersion =
|
|
det->getFirmwareVersion(std::vector<int>{det_id});
|
|
vFirmware = OutStringHex(firmwareVersion);
|
|
vServer = OutString(
|
|
det->getDetectorServerVersion(std::vector<int>{det_id}));
|
|
vKernel = OutString(
|
|
det->getKernelVersion({std::vector<int>{det_id}}));
|
|
vHardware = OutString(
|
|
det->getHardwareVersion(std::vector<int>{det_id}));
|
|
if (eiger) {
|
|
vBebFirmware = OutString(firmwareVersion);
|
|
vFeblFirmware = OutString(det->getFrontEndFirmwareVersion(
|
|
defs::FRONT_LEFT, std::vector<int>{det_id}));
|
|
vFebrFirmware = OutString(det->getFrontEndFirmwareVersion(
|
|
defs::FRONT_RIGHT, std::vector<int>{det_id}));
|
|
}
|
|
if (jungfrau) {
|
|
vChipVersion = OutString(
|
|
det->getChipVersion(std::vector<int>{det_id}));
|
|
}
|
|
} catch (const std::exception &e) {
|
|
}
|
|
}
|
|
|
|
os << "\nType : " << vType
|
|
<< "\nRelease : " << vRelease
|
|
<< "\nClient : " << vClient;
|
|
if (eiger) {
|
|
os << "\nFirmware (Beb) : " << vBebFirmware
|
|
<< "\nFirmware (Febl) : " << vFeblFirmware
|
|
<< "\nFirmware (Febr) : " << vFebrFirmware;
|
|
} else {
|
|
os << "\nFirmware : " << vFirmware;
|
|
}
|
|
if (jungfrau) {
|
|
os << "\nChip : " << vChipVersion;
|
|
}
|
|
os << "\nServer : " << vServer
|
|
<< "\nKernel : " << vKernel
|
|
<< "\nHardware : " << vHardware;
|
|
if (receiver)
|
|
os << "\nReceiver : " << vReceiver;
|
|
os << std::dec << '\n';
|
|
|
|
} else if (action == defs::PUT_ACTION) {
|
|
throw RuntimeError("cannot put");
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
std::string Caller::threshold(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[eV] [(optinal settings)"
|
|
"\n\t[Eiger][Mythen3] Threshold in eV. It loads trim files from "
|
|
"settingspath.";
|
|
if (cmd == "thresholdnotb") {
|
|
os << "Trimbits are not loaded.";
|
|
}
|
|
os << "\n\t" << cmd
|
|
<< " [eV1] [eV2] [eV3] [(optional settings)]"
|
|
"\n\t[Mythen3] Threshold in eV for each counter. It loads trim "
|
|
"files from settingspath. An energy of -1 will pick up values "
|
|
" from detector.";
|
|
if (cmd == "thresholdnotb") {
|
|
os << "Trimbits are not loaded.";
|
|
}
|
|
os << '\n';
|
|
} else if (action == defs::GET_ACTION) {
|
|
if (cmd == "thresholdnotb") {
|
|
throw RuntimeError("cannot get");
|
|
}
|
|
if (!args.empty()) {
|
|
WrongNumberOfParameters(0);
|
|
}
|
|
defs::detectorType type = det->getDetectorType().squash();
|
|
if (type == defs::EIGER) {
|
|
auto t = det->getThresholdEnergy(std::vector<int>{det_id});
|
|
os << OutString(t) << '\n';
|
|
} else if (type == defs::MYTHEN3) {
|
|
auto t = det->getAllThresholdEnergy(std::vector<int>{det_id});
|
|
os << OutString(t) << '\n';
|
|
} else {
|
|
throw RuntimeError("Not implemented for this detector\n");
|
|
}
|
|
} else if (action == defs::PUT_ACTION) {
|
|
defs::detectorType type = det->getDetectorType().squash();
|
|
if (type == defs::EIGER && args.size() != 1 && args.size() != 2) {
|
|
WrongNumberOfParameters(1);
|
|
}
|
|
if (type == defs::MYTHEN3 && (args.size() < 1 || args.size() > 4)) {
|
|
WrongNumberOfParameters(1);
|
|
}
|
|
|
|
bool trimbits = (cmd == "thresholdnotb") ? false : true;
|
|
std::array<int, 3> energy = {StringTo<int>(args[0]), 0, 0};
|
|
energy[1] = energy[0];
|
|
energy[2] = energy[0];
|
|
defs::detectorSettings sett = defs::STANDARD;
|
|
|
|
// check if argument has settings or get it
|
|
if (args.size() == 2 || args.size() == 4) {
|
|
sett = StringTo<defs::detectorSettings>(args[args.size() - 1]);
|
|
} else {
|
|
sett = det->getSettings(std::vector<int>{det_id})
|
|
.tsquash("Inconsistent settings between detectors");
|
|
}
|
|
|
|
// get other threshold values
|
|
if (args.size() > 2) {
|
|
energy[1] = StringTo<int>(args[1]);
|
|
energy[2] = StringTo<int>(args[2]);
|
|
}
|
|
switch (type) {
|
|
case defs::EIGER:
|
|
det->setThresholdEnergy(energy[0], sett, trimbits,
|
|
std::vector<int>{det_id});
|
|
break;
|
|
case defs::MYTHEN3:
|
|
det->setThresholdEnergy(energy, sett, trimbits,
|
|
std::vector<int>{det_id});
|
|
break;
|
|
default:
|
|
throw RuntimeError("Not implemented for this detector\n");
|
|
}
|
|
os << ToString(args) << '\n';
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
|
|
std::string Caller::trimen(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[trim_ev1] [trim_Ev2 (optional)] [trim_ev3 (optional)] "
|
|
"...\n\t[Eiger][Mythen3] list of trim energies, where "
|
|
"corresponding default trim files exist in corresponding trim "
|
|
"folders."
|
|
<< '\n';
|
|
} else if (action == defs::GET_ACTION) {
|
|
if (!args.empty()) {
|
|
WrongNumberOfParameters(0);
|
|
}
|
|
auto t = det->getTrimEnergies(std::vector<int>{det_id});
|
|
os << OutString(t) << '\n';
|
|
} else if (action == defs::PUT_ACTION) {
|
|
std::vector<int> t(args.size());
|
|
if (!args.empty()) {
|
|
for (size_t i = 0; i < t.size(); ++i) {
|
|
t[i] = StringTo<int>(args[i]);
|
|
}
|
|
}
|
|
det->setTrimEnergies(t, std::vector<int>{det_id});
|
|
os << ToString(args) << '\n';
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
std::string Caller::badchannels(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[fname|none|0]\n\t[Gotthard2][Mythen3] Sets the bad channels "
|
|
"(from file of bad channel numbers) to be masked out. None or 0 "
|
|
"unsets all the badchannels.\n\t[Mythen3] Also does trimming"
|
|
<< '\n';
|
|
} else if (action == defs::GET_ACTION) {
|
|
if (args.size() != 1) {
|
|
WrongNumberOfParameters(1);
|
|
}
|
|
det->getBadChannels(args[0], std::vector<int>{det_id});
|
|
os << "successfully retrieved" << '\n';
|
|
} else if (action == defs::PUT_ACTION) {
|
|
bool parse = false;
|
|
if (args.size() == 0) {
|
|
WrongNumberOfParameters(1);
|
|
} else if (args.size() == 1) {
|
|
if (args[0] == "none" || args[0] == "0") {
|
|
det->setBadChannels(std::vector<int>{},
|
|
std::vector<int>{det_id});
|
|
} else if (args[0].find(".") != std::string::npos) {
|
|
det->setBadChannels(args[0], std::vector<int>{det_id});
|
|
} else {
|
|
parse = true;
|
|
}
|
|
}
|
|
// parse multi args or single one with range or single value
|
|
if (parse || args.size() > 1) {
|
|
// get channels
|
|
auto list = getChannelsFromStringList(args);
|
|
det->setBadChannels(list, std::vector<int>{det_id});
|
|
}
|
|
os << "successfully loaded" << '\n';
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
std::string Caller::udp_srcip(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[x.x.x.x] or auto\n\tIp address of the detector (source) udp "
|
|
"interface. Must be same subnet as destination udp "
|
|
"ip.\n\t[Eiger] Set only for 10G. For 1G, detector will replace "
|
|
"with its own DHCP IP address. \n\tOne can also set this to "
|
|
"'auto' for 1 GbE data and virtual detectors. It will set to IP "
|
|
"of detector."
|
|
<< '\n';
|
|
} else if (action == defs::GET_ACTION) {
|
|
auto t = det->getSourceUDPIP(std::vector<int>{det_id});
|
|
if (!args.empty()) {
|
|
WrongNumberOfParameters(0);
|
|
}
|
|
os << OutString(t) << '\n';
|
|
} else if (action == defs::PUT_ACTION) {
|
|
if (args.size() != 1) {
|
|
WrongNumberOfParameters(1);
|
|
}
|
|
IpAddr val;
|
|
if (args[0] == "auto") {
|
|
val = getSrcIpFromAuto();
|
|
LOG(logINFO) << "Setting udp_srcip of detector " << det_id << " to "
|
|
<< val;
|
|
} else {
|
|
val = IpAddr(args[0]);
|
|
}
|
|
det->setSourceUDPIP(val, std::vector<int>{det_id});
|
|
os << val << '\n';
|
|
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
std::string Caller::udp_srcip2(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[x.x.x.x] or auto\n\t[Jungfrau][Moench][Gotthard2] Ip address "
|
|
"of the "
|
|
"detector (source) udp interface 2. Must be same subnet as "
|
|
"destination udp ip2.\n\t [Jungfrau][Moench] top half or inner "
|
|
"interface\n\t [Gotthard2] veto debugging. \n\tOne can also set "
|
|
"this to 'auto' for 1 GbE data and virtual detectors. It will "
|
|
"set to IP of detector."
|
|
<< '\n';
|
|
} else if (action == defs::GET_ACTION) {
|
|
auto t = det->getSourceUDPIP2(std::vector<int>{det_id});
|
|
if (!args.empty()) {
|
|
WrongNumberOfParameters(0);
|
|
}
|
|
os << OutString(t) << '\n';
|
|
} else if (action == defs::PUT_ACTION) {
|
|
if (args.size() != 1) {
|
|
WrongNumberOfParameters(1);
|
|
}
|
|
IpAddr val;
|
|
if (args[0] == "auto") {
|
|
val = getSrcIpFromAuto();
|
|
LOG(logINFO) << "Setting udp_srcip2 of detector " << det_id
|
|
<< " to " << val;
|
|
} else {
|
|
val = IpAddr(args[0]);
|
|
}
|
|
det->setSourceUDPIP2(val, std::vector<int>{det_id});
|
|
os << val << '\n';
|
|
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
std::string Caller::udp_dstip(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[x.x.x.x] or auto\n\tIp address of the receiver (destination) "
|
|
"udp interface. If 'auto' used, then ip is set to ip of "
|
|
"rx_hostname."
|
|
<< '\n';
|
|
} else if (action == defs::GET_ACTION) {
|
|
auto t = det->getDestinationUDPIP(std::vector<int>{det_id});
|
|
if (!args.empty()) {
|
|
WrongNumberOfParameters(0);
|
|
}
|
|
os << OutString(t) << '\n';
|
|
} else if (action == defs::PUT_ACTION) {
|
|
if (args.size() != 1) {
|
|
WrongNumberOfParameters(1);
|
|
}
|
|
if (args[0] == "auto") {
|
|
auto val = getDstIpFromAuto();
|
|
LOG(logINFO) << "Setting udp_dstip of detector " << det_id << " to "
|
|
<< val;
|
|
det->setDestinationUDPIP(val, std::vector<int>{det_id});
|
|
os << val << '\n';
|
|
} else {
|
|
auto val = IpAddr(args[0]);
|
|
det->setDestinationUDPIP(val, std::vector<int>{det_id});
|
|
os << args.front() << '\n';
|
|
}
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
std::string Caller::udp_dstip2(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[x.x.x.x] or auto\n\t[Jungfrau][Moench][Gotthard2] Ip address "
|
|
"of the "
|
|
"receiver (destination) udp interface 2. If 'auto' used, then ip "
|
|
"is set to ip of rx_hostname.\n\t[Jungfrau][Moench] bottom half "
|
|
"\n\t[Gotthard2] veto debugging. "
|
|
<< '\n';
|
|
} else if (action == defs::GET_ACTION) {
|
|
auto t = det->getDestinationUDPIP2(std::vector<int>{det_id});
|
|
if (!args.empty()) {
|
|
WrongNumberOfParameters(0);
|
|
}
|
|
os << OutString(t) << '\n';
|
|
} else if (action == defs::PUT_ACTION) {
|
|
if (args.size() != 1) {
|
|
WrongNumberOfParameters(1);
|
|
}
|
|
if (args[0] == "auto") {
|
|
auto val = getDstIpFromAuto();
|
|
LOG(logINFO) << "Setting udp_dstip2 of detector " << det_id
|
|
<< " to " << val;
|
|
det->setDestinationUDPIP2(val, std::vector<int>{det_id});
|
|
os << val << '\n';
|
|
} else {
|
|
auto val = IpAddr(args[0]);
|
|
det->setDestinationUDPIP2(val, std::vector<int>{det_id});
|
|
os << args.front() << '\n';
|
|
}
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
std::string Caller::rx_hostname(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[hostname or ip address]\n\t"
|
|
"[hostname or ip address]:[tcp port]\n\t"
|
|
"[hostname1]:[tcp_port1]+[hostname2]:[tcp_port2]+\n\t"
|
|
"Receiver hostname or IP. If port included, then the receiver "
|
|
"tcp port.\n\t"
|
|
"Used for TCP control communication between client and receiver "
|
|
"to configure receiver. Also updates receiver with detector "
|
|
"parameters. Also resets any prior receiver property (not on "
|
|
"detector). "
|
|
<< '\n';
|
|
} else if (action == defs::GET_ACTION) {
|
|
if (!args.empty()) {
|
|
WrongNumberOfParameters(0);
|
|
}
|
|
auto t = det->getRxHostname(std::vector<int>{det_id});
|
|
os << OutString(t) << '\n';
|
|
} else if (action == defs::PUT_ACTION) {
|
|
if (args.size() < 1) {
|
|
WrongNumberOfParameters(1);
|
|
}
|
|
// multiple arguments
|
|
if (args.size() > 1) {
|
|
// multiple in mulitple
|
|
if (args[0].find('+') != std::string::npos) {
|
|
throw RuntimeError(
|
|
"Cannot add multiple receivers at module level");
|
|
}
|
|
if (det_id != -1) {
|
|
throw RuntimeError(
|
|
"Cannot add multiple receivers at module level");
|
|
}
|
|
det->setRxHostname(args);
|
|
os << ToString(args) << '\n';
|
|
}
|
|
// single argument
|
|
else {
|
|
// multiple receivers concatenated with +
|
|
if (args[0].find('+') != std::string::npos) {
|
|
if (det_id != -1) {
|
|
throw RuntimeError(
|
|
"Cannot add multiple receivers at module level");
|
|
}
|
|
auto t = split(args[0], '+');
|
|
det->setRxHostname(t);
|
|
os << ToString(t) << '\n';
|
|
}
|
|
// single receiver
|
|
else {
|
|
det->setRxHostname(args[0], std::vector<int>{det_id});
|
|
os << ToString(args) << '\n';
|
|
}
|
|
}
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
std::string Caller::rx_zmqip(int action) {
|
|
std::string helpMessage =
|
|
"\n\t[deprecated] The receiver zmq socket (publisher) will "
|
|
"listen to all interfaces ('tcp://0.0.0.0:[port]'to all interfaces "
|
|
"(from v9.0.0). This command does nothing and will be removed "
|
|
"(from v10.0.0). This change makes no difference to the user.\n";
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << helpMessage << '\n';
|
|
} else if (action == defs::GET_ACTION) {
|
|
os << ZMQ_PUBLISHER_IP << '\n';
|
|
} else if (action == defs::PUT_ACTION) {
|
|
LOG(logWARNING) << helpMessage << '\n';
|
|
os << ZMQ_PUBLISHER_IP << '\n';
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
|
|
std::string Caller::rx_roi(int action) {
|
|
std::ostringstream os;
|
|
std::string helpMessage =
|
|
std::string("[xmin] [xmax] [ymin] [ymax]\n") +
|
|
"\tDefines a single region of interest (ROI) in the receiver.\n"
|
|
"\tFor example, to set a single ROI: 0 100 20 30\n\n"
|
|
|
|
"\tTo specify multiple ROIs, use square brackets between ROIs and "
|
|
"commas inside for each ROI. \n"
|
|
"\tInside each bracket, no spaces allowed.\n\n"
|
|
|
|
"\tIf you use semicolon (along with '['and ']' to separate rois), \n"
|
|
"\tenclose the entire list in quotes.\n"
|
|
"\tExamples:\n"
|
|
"\t [0,100,0,100] [200,300,0,100]\n"
|
|
"\t \"[0,100,0,100];[200,300,0,100]\"\n\n"
|
|
|
|
"\tNotes:\n"
|
|
"\t- ROIs can only be set at the multi-module level.\n"
|
|
"\t- If multi module ROIs ends up with more then 1 ROI per UDP "
|
|
"port or if they overlap each other, it will throw an error.\n"
|
|
"\t- ROIs coordinates assume no gap pixels, even if they are enabled "
|
|
"in gui.\n"
|
|
"\t- To retrieve ROIs per port, specify the module ID when using the "
|
|
"get command.\n"
|
|
"\t- Use the command 'rx_clearroi' to clear all ROIs.\n"
|
|
"\t- Changing the number of UDP interfaces will automatically clear "
|
|
"the current ROIs.\n\n"
|
|
"\t- Cannot be set for CTB or Xilinx CTB.\n";
|
|
|
|
if (action == defs::HELP_ACTION) {
|
|
os << helpMessage;
|
|
} else if (action == defs::GET_ACTION) {
|
|
if (!args.empty()) {
|
|
WrongNumberOfParameters(0);
|
|
}
|
|
auto t = det->getRxROI(det_id);
|
|
os << ToString(t) << '\n';
|
|
} else if (action == defs::PUT_ACTION) {
|
|
if (det_id != -1) {
|
|
throw RuntimeError("Cannot set receiver ROI at module level");
|
|
}
|
|
// Support multiple args with bracketed ROIs, or single arg with
|
|
// semicolon-separated vector in quotes
|
|
bool isVectorInput =
|
|
std::all_of(args.begin(), args.end(), [](const std::string &a) {
|
|
return a.find('[') != std::string::npos &&
|
|
a.find(']') != std::string::npos;
|
|
});
|
|
std::vector<defs::ROI> rois;
|
|
try {
|
|
// single roi in previous format: [xmin,xmax,ymin,ymax]
|
|
if (!isVectorInput) {
|
|
auto t = parseRoi(args);
|
|
rois.emplace_back(t);
|
|
}
|
|
// multiple roi or single roi with brackets
|
|
// multiple roi: multiple args with bracketed ROIs, or single arg
|
|
// with semicolon-bracketed Rois in quotes
|
|
else {
|
|
for (const auto &arg : args) {
|
|
auto subRois = parseRoiVector(arg);
|
|
rois.insert(rois.end(), subRois.begin(), subRois.end());
|
|
}
|
|
}
|
|
} catch (const std::exception &e) {
|
|
throw RuntimeError("Could not parse ROI: Did you use spaces inside "
|
|
"the brackets? Use sls_detector_help " +
|
|
cmd + " to get the right syntax expected.");
|
|
}
|
|
|
|
det->setRxROI(rois);
|
|
os << ToString(rois) << '\n';
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
|
|
std::vector<defs::ROI> Caller::parseRoiVector(const std::string &input) {
|
|
std::vector<defs::ROI> rois;
|
|
std::stringstream ss(input);
|
|
std::string token;
|
|
|
|
while (std::getline(ss, token, ']')) {
|
|
// remove spaces and semicolons
|
|
token.erase(
|
|
std::remove_if(token.begin(), token.end(),
|
|
[](char c) { return std::isspace(c) || c == ';'; }),
|
|
token.end());
|
|
if (token.empty())
|
|
continue;
|
|
if (token.front() != '[') {
|
|
throw RuntimeError("Each ROI must be enclosed in square brackets: "
|
|
"[xmin,xmax,ymin,ymax]");
|
|
}
|
|
token = token.substr(1, token.size() - 1); // remove brackets
|
|
std::vector<std::string> parts;
|
|
std::stringstream inner(token);
|
|
std::string num;
|
|
while (std::getline(inner, num, ',')) {
|
|
parts.push_back(num);
|
|
}
|
|
|
|
auto roi = parseRoi(parts);
|
|
rois.emplace_back(roi);
|
|
}
|
|
return rois;
|
|
}
|
|
|
|
defs::ROI Caller::parseRoi(const std::vector<std::string> &parts) {
|
|
if (parts.size() != 2 && parts.size() != 4) {
|
|
throw RuntimeError(
|
|
"Could not parse ROI. A ROI must have 2 or 4 integers");
|
|
}
|
|
|
|
defs::ROI roi;
|
|
roi.xmin = StringTo<int>(parts[0]);
|
|
roi.xmax = StringTo<int>(parts[1]);
|
|
if (parts.size() == 4) {
|
|
roi.ymin = StringTo<int>(parts[2]);
|
|
roi.ymax = StringTo<int>(parts[3]);
|
|
}
|
|
return roi;
|
|
}
|
|
|
|
std::string Caller::ratecorr(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[n_rate (in ns)]\n\t[Eiger] Dead time correction constant in "
|
|
"ns. -1 will set to default tau of settings from trimbit file. 0 "
|
|
"will unset rate correction."
|
|
<< '\n';
|
|
} else if (action == defs::GET_ACTION) {
|
|
if (!args.empty()) {
|
|
WrongNumberOfParameters(0);
|
|
}
|
|
auto t = det->getRateCorrection(std::vector<int>{det_id});
|
|
os << OutString(t) << '\n';
|
|
} else if (action == defs::PUT_ACTION) {
|
|
if (args.size() != 1) {
|
|
WrongNumberOfParameters(1);
|
|
}
|
|
int tau = StringTo<int>(args[0]);
|
|
if (tau == -1) {
|
|
det->setDefaultRateCorrection(std::vector<int>{det_id});
|
|
auto t = det->getRateCorrection(std::vector<int>{det_id});
|
|
os << OutString(t) << '\n';
|
|
} else {
|
|
auto t = StringTo<time::ns>(args[0], "ns");
|
|
det->setRateCorrection(t, std::vector<int>{det_id});
|
|
os << args.front() << "ns\n";
|
|
}
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
std::string Caller::burstmode(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[burst_internal or 0, burst_external or 1, cw_internal or 2, "
|
|
"cw_external or 3]\n\t[Gotthard2] Default is burst_internal "
|
|
"type. Also changes clkdiv 2, 3, 4"
|
|
<< '\n';
|
|
} else {
|
|
if (action == defs::GET_ACTION) {
|
|
if (!args.empty()) {
|
|
WrongNumberOfParameters(0);
|
|
}
|
|
auto t = det->getBurstMode(std::vector<int>{det_id});
|
|
os << OutString(t) << '\n';
|
|
} else if (action == defs::PUT_ACTION) {
|
|
if (args.size() != 1) {
|
|
WrongNumberOfParameters(1);
|
|
}
|
|
defs::burstMode t;
|
|
try {
|
|
int ival = StringTo<int>(args[0]);
|
|
switch (ival) {
|
|
case 0:
|
|
t = defs::BURST_INTERNAL;
|
|
break;
|
|
case 1:
|
|
t = defs::BURST_EXTERNAL;
|
|
break;
|
|
case 2:
|
|
t = defs::CONTINUOUS_INTERNAL;
|
|
break;
|
|
case 3:
|
|
t = defs::CONTINUOUS_EXTERNAL;
|
|
break;
|
|
default:
|
|
throw RuntimeError("Unknown burst mode " + args[0]);
|
|
}
|
|
} catch (...) {
|
|
t = StringTo<defs::burstMode>(args[0]);
|
|
}
|
|
det->setBurstMode(t, std::vector<int>{det_id});
|
|
os << ToString(t) << '\n'; // no args to convert 0,1,2 as well
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
}
|
|
return os.str();
|
|
}
|
|
std::string Caller::vetostream(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[none|lll|10gbe|...]\n\t[Gotthard2] Enable or disable the 2 "
|
|
"veto streaming interfaces available. Can include more than one "
|
|
"interface. \n\tDefault: none. lll (low latency link) is the "
|
|
"default interface to work with. \n\t10GbE is for debugging and "
|
|
"also enables second interface in receiver for listening to veto "
|
|
"packets (writes a separate file if writing enabled). Also "
|
|
"restarts client and receiver zmq sockets if zmq streaming "
|
|
"enabled."
|
|
<< '\n';
|
|
} else if (action == defs::GET_ACTION) {
|
|
if (!args.empty()) {
|
|
WrongNumberOfParameters(0);
|
|
}
|
|
auto t = det->getVetoStream(std::vector<int>{det_id});
|
|
os << OutString(t) << '\n';
|
|
} else if (action == defs::PUT_ACTION) {
|
|
if (args.empty()) {
|
|
WrongNumberOfParameters(1);
|
|
}
|
|
defs::streamingInterface interface = defs::streamingInterface::NONE;
|
|
for (const auto &arg : args) {
|
|
if (arg == "none") {
|
|
if (args.size() > 1) {
|
|
throw RuntimeError(
|
|
std::string(
|
|
"cannot have other arguments with 'none'. args: ") +
|
|
ToString(args));
|
|
}
|
|
break;
|
|
}
|
|
interface = interface | (StringTo<defs::streamingInterface>(arg));
|
|
}
|
|
det->setVetoStream(interface, std::vector<int>{det_id});
|
|
os << ToString(interface) << '\n';
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
std::string Caller::counters(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[i0] [i1] [i2]... \n\t[Mythen3] List of counters indices "
|
|
"enabled. Each element in list can be 0 - 2 and must be non "
|
|
"repetitive. Enabling counters sets vth dacs to remembered "
|
|
"values and disabling sets them to disabled values."
|
|
<< '\n';
|
|
} else if (action == defs::GET_ACTION) {
|
|
if (!args.empty()) {
|
|
WrongNumberOfParameters(0);
|
|
}
|
|
auto mask = det->getCounterMask(std::vector<int>{det_id}).squash(-1);
|
|
os << ToString(getSetBits(mask)) << '\n';
|
|
} else if (action == defs::PUT_ACTION) {
|
|
if (args.empty()) {
|
|
WrongNumberOfParameters(1);
|
|
}
|
|
if (std::any_of(args.cbegin(), args.cend(), [](std::string s) {
|
|
return (StringTo<int>(s) < 0 || StringTo<int>(s) > 2);
|
|
})) {
|
|
throw RuntimeError("Invalid counter indices list. Example: 0 1 2");
|
|
}
|
|
// convert vector to counter enable mask
|
|
uint32_t mask = 0;
|
|
for (size_t i = 0; i < args.size(); ++i) {
|
|
int val = StringTo<int>(args[i]);
|
|
// already enabled earlier
|
|
if (mask & (1 << val)) {
|
|
std::ostringstream oss;
|
|
oss << "Duplicate counter values (" << val << ") in arguments";
|
|
throw RuntimeError(oss.str());
|
|
}
|
|
mask |= (1 << val);
|
|
}
|
|
det->setCounterMask(mask, std::vector<int>{det_id});
|
|
os << ToString(args) << '\n';
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
std::string Caller::samples(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[n_samples]\n\t[Ctb][Xilinx_Ctb] Number of samples (analog, "
|
|
"digitial and "
|
|
"transceiver) expected.\n"
|
|
<< '\n';
|
|
} else if (action == defs::GET_ACTION) {
|
|
if (!args.empty()) {
|
|
WrongNumberOfParameters(0);
|
|
}
|
|
auto a = det->getNumberOfAnalogSamples(std::vector<int>{det_id});
|
|
// get also digital samples for ctb and compare with analog
|
|
auto det_type = det->getDetectorType().squash(defs::GENERIC);
|
|
if (det_type == defs::CHIPTESTBOARD ||
|
|
det_type == defs::XILINX_CHIPTESTBOARD) {
|
|
auto d = det->getNumberOfDigitalSamples(std::vector<int>{det_id});
|
|
auto t =
|
|
det->getNumberOfTransceiverSamples(std::vector<int>{det_id});
|
|
int as = a.squash(-1);
|
|
int ds = d.squash(-1);
|
|
int ts = t.squash(-1);
|
|
if (as == -1 || ds == -1 || ts == -1 || as != ds ||
|
|
as != ts) { // check if a == d?
|
|
throw RuntimeError(
|
|
"Different samples. Use asamples, dsamples or tsamples.");
|
|
}
|
|
}
|
|
os << OutString(a) << '\n';
|
|
} else if (action == defs::PUT_ACTION) {
|
|
if (args.size() != 1) {
|
|
WrongNumberOfParameters(1);
|
|
}
|
|
det->setNumberOfAnalogSamples(StringTo<int>(args[0]),
|
|
std::vector<int>{det_id});
|
|
// set also digital samples for ctb
|
|
auto det_type = det->getDetectorType().squash(defs::GENERIC);
|
|
if (det_type == defs::CHIPTESTBOARD ||
|
|
det_type == defs::XILINX_CHIPTESTBOARD) {
|
|
det->setNumberOfDigitalSamples(StringTo<int>(args[0]),
|
|
std::vector<int>{det_id});
|
|
det->setNumberOfTransceiverSamples(StringTo<int>(args[0]),
|
|
std::vector<int>{det_id});
|
|
}
|
|
os << args.front() << '\n';
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
std::string Caller::slowadc(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[n_channel (0-7 for channel]\n\t[Ctb] Slow "
|
|
"ADC channel in mV"
|
|
<< '\n';
|
|
} else if (action == defs::GET_ACTION) {
|
|
if (args.size() != 1) {
|
|
WrongNumberOfParameters(0);
|
|
}
|
|
int nchan = StringTo<int>(args[0]);
|
|
if (nchan < 0 || nchan > 7) {
|
|
throw RuntimeError("Unknown adc argument " + args[0]);
|
|
}
|
|
auto t = det->getSlowADC(
|
|
static_cast<defs::dacIndex>(nchan + defs::SLOW_ADC0),
|
|
std::vector<int>{det_id});
|
|
Result<double> result(t.size());
|
|
for (unsigned int i = 0; i < t.size(); ++i) {
|
|
result[i] = t[i] / 1000.00;
|
|
}
|
|
os << OutString(result) << " mV\n";
|
|
|
|
} else if (action == defs::PUT_ACTION) {
|
|
throw RuntimeError("cannot put");
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
std::string Caller::patwaittime(int action) {
|
|
std::ostringstream os;
|
|
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[0-6] [n_clk] \n\t[Ctb][Mythen3][Xilinx Ctb] Wait time in clock "
|
|
"cycles for the loop provided.\n\t[Mythen3] Level options: 0-3 "
|
|
"only."
|
|
<< '\n';
|
|
return os.str();
|
|
}
|
|
|
|
// parse level
|
|
bool deprecated_cmd = GetLevelAndInsertIntoArgs("patwaittime");
|
|
int level = 0;
|
|
try {
|
|
if (args.size() > 0)
|
|
level = StringTo<int>(args[0]);
|
|
} catch (const std::exception &e) {
|
|
LOG(logERROR) << "Could not scan level.";
|
|
throw;
|
|
}
|
|
if (!deprecated_cmd && args.size() >= 1)
|
|
os << args[0] << ' ';
|
|
|
|
if (action == defs::GET_ACTION) {
|
|
if (args.size() != 1 && args.size() != 2)
|
|
WrongNumberOfParameters(1);
|
|
// with time unit
|
|
if (args.size() == 2) {
|
|
auto t =
|
|
det->getPatternWaitInterval(level, std::vector<int>{det_id});
|
|
os << OutString(t, args[1]) << '\n';
|
|
}
|
|
// in clocks
|
|
else {
|
|
auto t = det->getPatternWaitClocks(level, std::vector<int>{det_id});
|
|
os << OutString(t) << '\n';
|
|
}
|
|
} else if (action == defs::PUT_ACTION) {
|
|
if (args.size() != 2 && args.size() != 3)
|
|
WrongNumberOfParameters(2);
|
|
// clocks (all digits)
|
|
if (args.size() == 2 &&
|
|
std::all_of(args[1].begin(), args[1].end(), ::isdigit)) {
|
|
uint64_t waittime = StringTo<uint64_t>(args[1]);
|
|
det->setPatternWaitClocks(level, waittime,
|
|
std::vector<int>{det_id});
|
|
os << waittime << '\n';
|
|
}
|
|
// time
|
|
else {
|
|
time::ns converted_time{0};
|
|
try {
|
|
if (args.size() == 2) {
|
|
std::string tmp_time(args[1]);
|
|
std::string unit = RemoveUnit(tmp_time);
|
|
converted_time = StringTo<time::ns>(tmp_time, unit);
|
|
} else {
|
|
converted_time = StringTo<time::ns>(args[1], args[2]);
|
|
}
|
|
} catch (...) {
|
|
throw RuntimeError("Could not convert argument to time::ns");
|
|
}
|
|
det->setPatternWaitInterval(level, converted_time,
|
|
std::vector<int>{det_id});
|
|
os << args[1];
|
|
if (args.size() == 3)
|
|
os << ' ' << args[2];
|
|
os << '\n';
|
|
}
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
std::string Caller::rx_dbitlist(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[all] or [none] or [i0] [i1] [i2]... \n\t[Ctb] List of digital "
|
|
"signal bits enabled and rearranged according to the signals "
|
|
"(all samples of each signal is put together). If 'all' is used "
|
|
"instead of a list, all digital bits (64) enabled. Each element "
|
|
"in list can be 0 - 63 and must be non repetitive. The option "
|
|
"'none' will still spit out all data as is from the detector, "
|
|
"but without rearranging it. Please note that when using the "
|
|
"receiver list, the data size will be bigger if the number of "
|
|
"samples is not divisible by 8 as every signal bit is padded to "
|
|
"the next byte when combining all the samples in the receiver."
|
|
<< '\n';
|
|
} else if (action == defs::GET_ACTION) {
|
|
if (!args.empty()) {
|
|
WrongNumberOfParameters(0);
|
|
}
|
|
auto t = det->getRxDbitList(std::vector<int>{det_id});
|
|
os << OutString(t) << '\n';
|
|
} else if (action == defs::PUT_ACTION) {
|
|
if (args.empty()) {
|
|
WrongNumberOfParameters(1);
|
|
}
|
|
std::vector<int> t;
|
|
if (args[0] == "all") {
|
|
t.resize(64);
|
|
for (unsigned int i = 0; i < 64; ++i) {
|
|
t[i] = i;
|
|
}
|
|
}
|
|
// 'none' option already covered as t is empty by default
|
|
else if (args[0] != "none") {
|
|
unsigned int ntrim = args.size();
|
|
t.resize(ntrim);
|
|
for (unsigned int i = 0; i < ntrim; ++i) {
|
|
t[i] = StringTo<int>(args[i]);
|
|
}
|
|
}
|
|
det->setRxDbitList(t, std::vector<int>{det_id});
|
|
os << ToString(args) << '\n';
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
std::string Caller::rx_jsonaddheader(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[key1] [value1] [key2] [value2]...[keyn] [valuen]\n\tAdditional "
|
|
"json header to be streamed out from receiver via zmq. Default "
|
|
"is empty. Max 20 characters for each key/value. Use only if to "
|
|
"be processed by an intermediate user process listening to "
|
|
"receiver zmq packets. Empty value deletes header. "
|
|
<< '\n';
|
|
} else if (action == defs::GET_ACTION) {
|
|
if (!args.empty()) {
|
|
WrongNumberOfParameters(0);
|
|
}
|
|
auto t = det->getAdditionalJsonHeader(std::vector<int>{det_id});
|
|
os << OutString(t) << '\n';
|
|
} else if (action == defs::PUT_ACTION) {
|
|
// arguments can be empty
|
|
std::map<std::string, std::string> json;
|
|
for (size_t i = 0; i < args.size(); i = i + 2) {
|
|
// last value is empty
|
|
if (i + 1 >= args.size()) {
|
|
json[args[i]] = "";
|
|
} else {
|
|
json[args[i]] = args[i + 1];
|
|
}
|
|
}
|
|
det->setAdditionalJsonHeader(json, std::vector<int>{det_id});
|
|
os << ToString(json) << '\n';
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
std::string Caller::execcommand(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[command]\n\tExecutes command on detector server console."
|
|
<< '\n';
|
|
} else if (action == defs::GET_ACTION) {
|
|
throw RuntimeError("Cannot get.");
|
|
} else if (action == defs::PUT_ACTION) {
|
|
std::string command;
|
|
for (auto &i : args) {
|
|
command += (i + ' ');
|
|
}
|
|
auto t = det->executeCommand(command, std::vector<int>{det_id});
|
|
os << OutString(t) << '\n';
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
std::string Caller::dacvalues(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[(optional unit) mV] \n\tGets the values for every "
|
|
"dac for this detector."
|
|
<< '\n';
|
|
} else if (action == defs::GET_ACTION) {
|
|
bool mv = false;
|
|
if (args.size() == 1) {
|
|
if ((args[0] != "mv") && (args[0] != "mV")) {
|
|
throw RuntimeError("Unknown argument " + args[0] +
|
|
". Did you mean mV?");
|
|
}
|
|
mv = true;
|
|
} else if (args.size() > 1) {
|
|
WrongNumberOfParameters(1);
|
|
}
|
|
auto t = det->getDacList();
|
|
auto names = det->getDacNames();
|
|
auto name_it = names.begin();
|
|
os << '[';
|
|
auto it = t.cbegin();
|
|
os << ToString(*name_it++) << ' ';
|
|
os << OutString(det->getDAC(*it++, mv, std::vector<int>{det_id}))
|
|
<< (!args.empty() ? " mV" : "");
|
|
while (it != t.cend()) {
|
|
os << ", " << ToString(*name_it++) << ' ';
|
|
os << OutString(det->getDAC(*it++, mv, std::vector<int>{det_id}))
|
|
<< (!args.empty() ? " mV" : "");
|
|
}
|
|
os << "]\n";
|
|
} else if (action == defs::PUT_ACTION) {
|
|
throw RuntimeError("Cannot put");
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
std::string Caller::currentsource(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "\n\t[0|1]\n\t\t[Gotthard2] Enable or disable current source. "
|
|
"Default "
|
|
"is disabled.\n\t[0|1] [fix|nofix] [select source] [(only for "
|
|
"chipv1.1)normal|low]\n\t\t[Jungfrau] Disable or enable current "
|
|
"source with some parameters. The select source is 0-63 for "
|
|
"chipv1.0 and a 64 bit mask for chipv1.1. To disable, one needs "
|
|
"only one argument '0'."
|
|
<< '\n';
|
|
} else if (action == defs::GET_ACTION) {
|
|
if (args.size() != 0) {
|
|
WrongNumberOfParameters(0);
|
|
}
|
|
auto t = det->getCurrentSource(std::vector<int>{det_id});
|
|
os << OutString(t) << '\n';
|
|
} else if (action == defs::PUT_ACTION) {
|
|
if (args.size() == 1) {
|
|
det->setCurrentSource(
|
|
defs::currentSrcParameters(StringTo<bool>(args[0])));
|
|
} else if (args.size() >= 3) {
|
|
// scan fix
|
|
bool fix = false;
|
|
if (args[1] == "fix") {
|
|
fix = true;
|
|
} else if (args[1] == "nofix") {
|
|
fix = false;
|
|
} else {
|
|
throw RuntimeError("Invalid argument: " + args[1] +
|
|
". Did you mean fix or nofix?");
|
|
}
|
|
if (args.size() == 3) {
|
|
det->setCurrentSource(defs::currentSrcParameters(
|
|
fix, StringTo<uint64_t>(args[2])));
|
|
} else if (args.size() == 4) {
|
|
bool normalCurrent = false;
|
|
if (args[3] == "normal") {
|
|
normalCurrent = true;
|
|
} else if (args[3] == "low") {
|
|
normalCurrent = false;
|
|
} else {
|
|
throw RuntimeError("Invalid argument: " + args[3] +
|
|
". Did you mean normal or low?");
|
|
}
|
|
det->setCurrentSource(defs::currentSrcParameters(
|
|
fix, StringTo<uint64_t>(args[2]), normalCurrent));
|
|
} else {
|
|
throw RuntimeError(
|
|
"Invalid number of parareters for this command.");
|
|
}
|
|
} else {
|
|
throw RuntimeError(
|
|
"Invalid number of parareters for this command.");
|
|
}
|
|
os << ToString(args) << '\n';
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
std::string Caller::gaincaps(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[cap1, cap2, ...]\n\t[Mythen3] gain, options: C10pre, C15sh, "
|
|
"C30sh, C50sh, C225ACsh, C15pre"
|
|
<< '\n';
|
|
} else if (action == defs::GET_ACTION) {
|
|
if (!args.empty())
|
|
WrongNumberOfParameters(0);
|
|
|
|
auto tmp = det->getGainCaps();
|
|
Result<defs::M3_GainCaps> csr;
|
|
for (auto val : tmp) {
|
|
if (val)
|
|
csr.push_back(static_cast<defs::M3_GainCaps>(val));
|
|
}
|
|
|
|
os << OutString(csr) << '\n';
|
|
} else if (action == defs::PUT_ACTION) {
|
|
if (args.size() < 1) {
|
|
WrongNumberOfParameters(1);
|
|
}
|
|
int caps = 0;
|
|
for (const auto &arg : args) {
|
|
if (arg != "0")
|
|
caps |= StringTo<defs::M3_GainCaps>(arg);
|
|
}
|
|
|
|
det->setGainCaps(caps);
|
|
os << OutString(args) << '\n';
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
std::string Caller::sleep(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[duration] [(optional unit) ns|us|ms|s]\n\tSleep for duration. "
|
|
"Mainly for config files for firmware developers."
|
|
"Default unit is s."
|
|
<< '\n';
|
|
} else if (action == defs::GET_ACTION) {
|
|
throw RuntimeError("Cannot get.");
|
|
} else if (action == defs::PUT_ACTION) {
|
|
if (args.size() != 1 && args.size() != 2) {
|
|
WrongNumberOfParameters(1);
|
|
}
|
|
time::ns converted_time{0};
|
|
try {
|
|
if (args.size() == 1) {
|
|
std::string tmp_time(args[0]);
|
|
std::string unit = RemoveUnit(tmp_time);
|
|
converted_time = StringTo<time::ns>(tmp_time, unit);
|
|
} else {
|
|
converted_time = StringTo<time::ns>(args[0], args[1]);
|
|
}
|
|
} catch (...) {
|
|
throw RuntimeError("Could not convert argument to time::ns");
|
|
}
|
|
std::this_thread::sleep_for(converted_time);
|
|
os << "for " << ToString(converted_time) << " completed" << '\n';
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
|
|
std::string Caller::define_reg(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[Ctb][Xilinx Ctb]"
|
|
"\n\t[reg name] [reg address]"
|
|
"\n\n\tSets a user defined register in shared memory. The name "
|
|
"can be upto 32 characters long."
|
|
"\n\teg."
|
|
"\n\tsls_detector_put define_reg test_reg 0x200"
|
|
"\n\n\tOne can retrieve the address using the name and vice "
|
|
"versa."
|
|
"\n\teg."
|
|
"\n\tsls_detector_get define_reg test_reg"
|
|
"\n\tsls_detector_get define_reg 0x200"
|
|
"\n\n\tOne can then use this user-defined name in other commands "
|
|
"instead of hard coding the address such as for reg, setbit, "
|
|
"clearbit and getbit commands."
|
|
"\n\teg."
|
|
"\n\tsls_detector_put reg test_reg 0x1"
|
|
"\n\tsls_detector_put setbit test_reg 2"
|
|
"\n\tsls_detector_put clearbit test_reg 2"
|
|
"\n\tsls_detector_get getbit test_reg 2"
|
|
<< '\n';
|
|
return os.str();
|
|
}
|
|
if (det_id != -1) {
|
|
throw RuntimeError("Cannot use define at module level. Use the default "
|
|
"multi-module level");
|
|
}
|
|
if (action == defs::GET_ACTION) {
|
|
if (args.size() != 1) {
|
|
WrongNumberOfParameters(1);
|
|
}
|
|
// get name from address
|
|
if (is_hex_or_dec_uint(args[0])) {
|
|
auto addr = parseRegisterAddress(args[0]);
|
|
auto t = det->getRegisterName(addr);
|
|
os << t << '\n';
|
|
}
|
|
// get address from name
|
|
else {
|
|
auto t = det->getRegisterAddress(args[0]);
|
|
os << t.str() << '\n';
|
|
}
|
|
} else if (action == defs::PUT_ACTION) {
|
|
if (args.size() != 2) {
|
|
WrongNumberOfParameters(2);
|
|
}
|
|
auto name = args[0];
|
|
auto addr = parseRegisterAddress(args[1]);
|
|
det->setRegisterDefinition(name, addr);
|
|
os << "addr " << name << ' ' << addr.str() << '\n';
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
|
|
return os.str();
|
|
}
|
|
|
|
std::string Caller::define_bit(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[Ctb][Xilinx Ctb]"
|
|
"\n\t[bit name] [regiser name/address] [bit position]"
|
|
"\n\n\tSets a user defined bit name in shared memory "
|
|
"representing the register address and the bit position. The "
|
|
"address can be named prior using define_reg command. The name "
|
|
"can be upto 32 characters long."
|
|
"\n\teg."
|
|
"\n\tsls_detector_put define_bit test_bit test_reg 2"
|
|
"\n\tsls_detector_put define_bit test_bit 0x200 2"
|
|
"\n\n\tOne can retrieve the bit address using the name and vice "
|
|
"versa using both register name or address and bit position."
|
|
"\n\teg."
|
|
"\n\tsls_detector_get define_bit test_bit"
|
|
"\n\tsls_detector_get define_bit test_reg 2"
|
|
"\n\tsls_detector_get define_bit 0x200 2"
|
|
"\n\n\tOne can then use this user-defined name in other commands "
|
|
"such as for setbit, clearbit and getbit commands. When using "
|
|
"bit names, please dont use register name or address as bit name "
|
|
"is already tied to a specific register."
|
|
"\n\teg."
|
|
"\n\tsls_detector_put setbit test_bit"
|
|
"\n\tsls_detector_put clearbit test_bit"
|
|
"\n\tsls_detector_get getbit test_bit"
|
|
<< '\n';
|
|
return os.str();
|
|
}
|
|
if (det_id != -1) {
|
|
throw RuntimeError("Cannot use define at module level. Use the default "
|
|
"multi-module level");
|
|
}
|
|
if (action == defs::GET_ACTION) {
|
|
// get position from name
|
|
if (args.size() == 1) {
|
|
auto t = det->getBitAddress(args[0]);
|
|
os << det->toRegisterNameBitString(t) << '\n';
|
|
}
|
|
// get name from position and address
|
|
else if (args.size() == 2) {
|
|
auto addr = parseBitAddress(args[0], args[1]);
|
|
auto t = det->getBitName(addr);
|
|
os << t << '\n';
|
|
|
|
} else {
|
|
WrongNumberOfParameters(1);
|
|
}
|
|
} else if (action == defs::PUT_ACTION) {
|
|
if (args.size() != 3) {
|
|
WrongNumberOfParameters(3);
|
|
}
|
|
if (!is_int(args[2])) {
|
|
throw RuntimeError("Bit position must be an integer value.");
|
|
}
|
|
auto name = args[0];
|
|
auto addr = parseBitAddress(args[1], args[2]);
|
|
det->setBitDefinition(name, addr);
|
|
os << ToString(args) << '\n';
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
|
|
return os.str();
|
|
}
|
|
|
|
std::string Caller::definelist_reg(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "\n\t List of user-defined register definitions in shared memory."
|
|
<< '\n';
|
|
} else if (action == defs::PUT_ACTION) {
|
|
throw RuntimeError("cannot put");
|
|
} else if (action == defs::GET_ACTION) {
|
|
if (!args.empty()) {
|
|
WrongNumberOfParameters(0);
|
|
}
|
|
auto t = det->getRegisterDefinitions();
|
|
os << '\n' << ToString(t) << '\n';
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
|
|
std::string Caller::definelist_bit(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "\n\t List of user-defined bit definitions in shared memory."
|
|
<< '\n';
|
|
} else if (action == defs::PUT_ACTION) {
|
|
throw RuntimeError("cannot put");
|
|
} else if (action == defs::GET_ACTION) {
|
|
if (!args.empty()) {
|
|
WrongNumberOfParameters(0);
|
|
}
|
|
auto t = det->getBitDefinitions();
|
|
os << "\n[";
|
|
for (const auto &[key, val] : t) {
|
|
os << key << ": ";
|
|
os << det->toRegisterNameBitString(val);
|
|
if (&key != &t.rbegin()->first) {
|
|
os << ", ";
|
|
}
|
|
os << '\n';
|
|
}
|
|
os << "]\n";
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
|
|
std::string Caller::reg(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[address] [32 bit value][(optional)--validate]"
|
|
"\n\tReads/writes to a 32 bit register in hex."
|
|
"\n\tAdvanced Function!\n\tGoes to stop server. Hence, can be "
|
|
"called while calling blocking acquire()."
|
|
"\n\t\t Use --validate to enforce validation when writing to "
|
|
"register."
|
|
"\n\t[Eiger] +0x100 for only left, +0x200 for only right."
|
|
"\n\t[Ctb][Xilinx_Ctb] Address can also be a user-defined name "
|
|
"that was set previously using the define command."
|
|
"\n\t\teg."
|
|
"\n\t\tsls_detector_put reg 0x200 0xFFF --validate"
|
|
"\n\t\tsls_detector_get reg test_reg"
|
|
"\n\t\tsls_detector_put reg test_reg 0xFF"
|
|
<< '\n';
|
|
} else {
|
|
if (action == defs::PUT_ACTION) {
|
|
if (args.size() < 2 || args.size() > 3) {
|
|
WrongNumberOfParameters(2);
|
|
}
|
|
auto validate = parseValidate();
|
|
auto addr = getRegisterAddress(args[0]);
|
|
auto val = parseRegisterValue(args[1]);
|
|
det->writeRegister(addr, val, validate, std::vector<int>{det_id});
|
|
os << addr.str() << " " << val.str() << '\n';
|
|
} else if (action == defs::GET_ACTION) {
|
|
if (args.size() != 1) {
|
|
WrongNumberOfParameters(1);
|
|
}
|
|
auto addr = getRegisterAddress(args[0]);
|
|
auto t = det->readRegister(addr, std::vector<int>{det_id});
|
|
os << OutString(t) << '\n';
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
}
|
|
return os.str();
|
|
}
|
|
|
|
std::string Caller::getbit(int action) { return bitoperations(action); }
|
|
|
|
std::string Caller::setbit(int action) { return bitoperations(action); }
|
|
|
|
std::string Caller::clearbit(int action) { return bitoperations(action); }
|
|
|
|
std::string Caller::bitoperations(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
if (cmd == "getbit") {
|
|
os << "[reg address in hex] [bit index]\n\tGets bit in address."
|
|
<< '\n';
|
|
} else if (cmd == "setbit") {
|
|
os << "[reg address in hex] [bit index]\n\tSets bit in "
|
|
"address.\n\tUse --validate to force validation."
|
|
<< '\n';
|
|
} else if (cmd == "clearbit") {
|
|
os << "[reg address in hex] [bit index]\n\tClears bit in "
|
|
"address.\n\tUse --validate to force validation."
|
|
<< '\n';
|
|
} else {
|
|
throw RuntimeError("Unknown command");
|
|
}
|
|
os << "\n\t\t[Ctb][Xilinx_Ctb] Address or bit position can also be a "
|
|
"user-defined name that was set previously using the define "
|
|
"command. When using bit names, avoid register name/ address as "
|
|
"the bit name is tied to a specific register already."
|
|
"\n\n\teg."
|
|
"\n\tsls_detector_get getbit 0x200 2"
|
|
"\n\tsls_detector_get getbit test_reg 2"
|
|
"\n\tsls_detector_get getbit test_bit"
|
|
"\n\tsls_detector_put setbit 0x200 2"
|
|
"\n\tsls_detector_put setbit test_reg 2"
|
|
"\n\tsls_detector_put setbit test_bit"
|
|
"\n\tsls_detector_put clearbit test_bit";
|
|
os << '\n';
|
|
} else {
|
|
if (action != defs::GET_ACTION && action != defs::PUT_ACTION) {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
|
|
auto validate = parseValidate();
|
|
auto addr = getBitAddress();
|
|
if (action == defs::GET_ACTION) {
|
|
if (cmd == "setbit" || cmd == "clearbit")
|
|
throw RuntimeError("Cannot get");
|
|
|
|
auto t = det->getBit(addr, std::vector<int>{det_id});
|
|
os << OutString(t) << '\n';
|
|
} else {
|
|
if (cmd == "getbit")
|
|
throw RuntimeError("Cannot put");
|
|
if (cmd == "setbit")
|
|
det->setBit(addr, validate, std::vector<int>{det_id});
|
|
else if (cmd == "clearbit")
|
|
det->clearBit(addr, validate, std::vector<int>{det_id});
|
|
else
|
|
throw RuntimeError("Unknown command");
|
|
os << ToString(args) << "\n";
|
|
}
|
|
}
|
|
return os.str();
|
|
}
|
|
|
|
RegisterAddress Caller::parseRegisterAddress(const std::string &addr) const {
|
|
try {
|
|
return RegisterAddress(StringTo<uint32_t>(addr));
|
|
} catch (const std::exception &e) {
|
|
throw RuntimeError("Could not parse register address " + addr +
|
|
". Must be an integer value");
|
|
}
|
|
}
|
|
|
|
BitAddress Caller::parseBitAddress(const std::string &addr,
|
|
const std::string &bitPos) const {
|
|
auto address = getRegisterAddress(addr);
|
|
uint32_t bitPosition = 0;
|
|
|
|
// parse bit position
|
|
if (!is_hex_or_dec_uint(bitPos)) {
|
|
throw RuntimeError("Bit position must be an integer value.");
|
|
}
|
|
try {
|
|
bitPosition = StringTo<uint32_t>(bitPos);
|
|
} catch (const std::exception &e) {
|
|
throw RuntimeError("Could not parse bit position " + bitPos +
|
|
". Must be an integer value");
|
|
}
|
|
return BitAddress(address, bitPosition);
|
|
}
|
|
|
|
RegisterValue Caller::parseRegisterValue(const std::string &addr) const {
|
|
try {
|
|
return RegisterValue(StringTo<uint32_t>(addr));
|
|
} catch (const std::exception &e) {
|
|
throw RuntimeError("Could not parse register value " + addr +
|
|
". Must be an integer value");
|
|
}
|
|
}
|
|
|
|
bool Caller::parseValidate() {
|
|
auto it = std::find(args.begin(), args.end(), "--validate");
|
|
bool validate = (it != args.end());
|
|
|
|
// invalid argument (--options), throw
|
|
if (!validate) {
|
|
auto invalid_it =
|
|
std::find_if(args.begin(), args.end(), [](const auto &s) {
|
|
// only looks for the first characters
|
|
return s.rfind("--", 0) == 0 && s != "--validate";
|
|
});
|
|
if (invalid_it != args.end()) {
|
|
throw RuntimeError("Unknown option '" + *invalid_it +
|
|
"'. Did you mean '--validate'?");
|
|
}
|
|
}
|
|
|
|
// --validate should be the last argument (remove it from args)
|
|
else {
|
|
if (it != args.end() - 1) {
|
|
throw RuntimeError("'--validate' should be the last argument.");
|
|
}
|
|
args.pop_back();
|
|
}
|
|
return validate;
|
|
}
|
|
|
|
RegisterAddress Caller::getRegisterAddress(const std::string &saddr) const {
|
|
if (is_hex_or_dec_uint(saddr)) {
|
|
return parseRegisterAddress(saddr);
|
|
}
|
|
return det->getRegisterAddress(saddr);
|
|
}
|
|
|
|
BitAddress Caller::getBitAddress() const {
|
|
int args_size = args.size();
|
|
|
|
// address and bit position
|
|
if (args_size == 2) {
|
|
return parseBitAddress(args[0], args[1]);
|
|
}
|
|
|
|
// bit name
|
|
if (args_size == 1) {
|
|
return det->getBitAddress(args[0]);
|
|
}
|
|
throw RuntimeError("Invalid number of parameters for bit address.");
|
|
}
|
|
|
|
std::string Caller::dac(int action) {
|
|
std::ostringstream os;
|
|
|
|
if (action == defs::HELP_ACTION) {
|
|
if (args.size() == 0)
|
|
os << GetHelpDac("");
|
|
else
|
|
os << args[0] << GetHelpDac(args[0]) << '\n';
|
|
return os.str();
|
|
}
|
|
|
|
bool isCtb = false;
|
|
auto detType = det->getDetectorType().squash(defs::GENERIC);
|
|
if (detType == defs::CHIPTESTBOARD ||
|
|
detType == defs::XILINX_CHIPTESTBOARD) {
|
|
isCtb = true;
|
|
}
|
|
|
|
if (action == defs::GET_ACTION) {
|
|
auto index = parseDacIndex(0, isCtb);
|
|
auto mV = parseMV(1);
|
|
auto t = det->getDAC(index, mV, std::vector<int>{det_id});
|
|
os << args[0] << ' ' << OutString(t) << (mV ? " mV" : "") << '\n';
|
|
}
|
|
|
|
else if (action == defs::PUT_ACTION) {
|
|
auto index = parseDacIndex(0, isCtb);
|
|
if (args.size() < 2) {
|
|
WrongNumberOfParameters(2);
|
|
}
|
|
auto val = StringTo<int>(args[1]);
|
|
auto mV = parseMV(2);
|
|
det->setDAC(index, val, mV, std::vector<int>{det_id});
|
|
os << args[0] << ' ' << args[1] << (mV ? " mV" : "") << '\n';
|
|
}
|
|
|
|
else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
|
|
return os.str();
|
|
}
|
|
|
|
defs::dacIndex Caller::parseDacIndex(int argIndex, bool isCtb) {
|
|
if (argIndex >= (int)args.size()) {
|
|
throw RuntimeError("Invalid arguments. DAC index is required.");
|
|
}
|
|
auto arg = args[argIndex];
|
|
|
|
if (isCtb) {
|
|
// dac index
|
|
if (is_int(arg)) {
|
|
return StringTo<defs::dacIndex>(arg);
|
|
}
|
|
// dac name
|
|
return det->getDacIndex(arg);
|
|
}
|
|
|
|
// not ctb
|
|
if (is_int(arg)) {
|
|
throw RuntimeError("DAC index is not supported for your detector. "
|
|
"Please use dac name. Use daclist command to get "
|
|
"the list of dac names for your detector.");
|
|
}
|
|
return StringTo<defs::dacIndex>(arg);
|
|
}
|
|
|
|
bool Caller::parseMV(int argIndex) {
|
|
if (argIndex < (int)args.size()) {
|
|
auto arg = args[argIndex];
|
|
if (arg != "mv" && arg != "mV") {
|
|
throw RuntimeError("Unknown argument " + arg +
|
|
". Did you mean mV?");
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
std::string Caller::powerdac(int action) {
|
|
std::ostringstream os;
|
|
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[powername][mV value]\n\t[Ctb][Xilinx Ctb] Controls the dac "
|
|
"used for Power supply. Default names for powername are v_a, "
|
|
"v_b, v_c, v_d, v_io, v_chip(v_chip only applies to Ctb, not "
|
|
"Xilinx_Ctb). If custom names are assigned using the 'powername' "
|
|
"command, those names could be used instead instead of the "
|
|
"defaults. By default, all are set to minimum values. \n\t[Ctb] "
|
|
"v_chip can also be queried to get the vchip dac value, although "
|
|
"its rail cannot be enabled or disabled by the user. It is "
|
|
"enabled by default. Its dac value is automatically updated "
|
|
"whenever a power dac is modified. It is then set to the max of "
|
|
"power dacs + 200mV."
|
|
<< '\n';
|
|
return os.str();
|
|
}
|
|
|
|
auto detType = det->getDetectorType().squash(defs::GENERIC);
|
|
if (detType != defs::CHIPTESTBOARD &&
|
|
detType != defs::XILINX_CHIPTESTBOARD) {
|
|
throw RuntimeError("This command is only applicable for ChipTestBoard "
|
|
"and Xilinx ChipTestBoard.");
|
|
}
|
|
if (det_id != -1) {
|
|
throw RuntimeError("Cannot use powerdac at module level.");
|
|
}
|
|
auto index = parsePowerIndex(0);
|
|
|
|
if (action == defs::GET_ACTION) {
|
|
if (args.size() != 1) {
|
|
WrongNumberOfParameters(1);
|
|
}
|
|
auto t = det->getPowerDAC(index);
|
|
os << args[0] << ' ' << OutString(t) << '\n';
|
|
}
|
|
|
|
else if (action == defs::PUT_ACTION) {
|
|
if (args.size() != 2) {
|
|
WrongNumberOfParameters(2);
|
|
}
|
|
auto val = StringTo<int>(args[1]);
|
|
det->setPowerDAC(index, val);
|
|
os << args[0] << ' ' << args[1] << '\n';
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
|
|
return os.str();
|
|
}
|
|
|
|
defs::powerIndex Caller::parsePowerIndex(int argIndex) {
|
|
if (argIndex >= (int)args.size()) {
|
|
throw RuntimeError("Invalid arguments. Power name is required.");
|
|
}
|
|
auto arg = args[argIndex];
|
|
|
|
// power default names
|
|
if (is_int(arg) || arg == "v_a" || arg == "v_b" || arg == "v_c" ||
|
|
arg == "v_d" || arg == "v_io" || arg == "v_chip") {
|
|
return StringTo<defs::powerIndex>(arg);
|
|
}
|
|
|
|
// power name
|
|
auto names = det->getPowerNames();
|
|
auto it = std::find(names.begin(), names.end(), arg);
|
|
if (it != names.end()) {
|
|
return det->getPowerIndex(arg);
|
|
}
|
|
throw RuntimeError(
|
|
"Unknown power name '" + arg +
|
|
"'. Use 'powername' command to see defined power names.");
|
|
}
|
|
|
|
std::string Caller::power(int action) {
|
|
std::ostringstream os;
|
|
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "[all|list of power names] [on|off]\n\t[Ctb][Xilinx Ctb] Enable "
|
|
"or "
|
|
"disable power rails. Power name can be all, v_a, v_b, v_c, v_d "
|
|
"or "
|
|
"v_io or any defines using 'powername'. If power name is set to "
|
|
"'all', the command applies to all 'powers'. Enabling the power "
|
|
"rails is in parallel, whereas retrieving the states of multiple "
|
|
"power rails, they are queried sequentially "
|
|
"(one after another), not in parallel."
|
|
<< '\n';
|
|
return os.str();
|
|
}
|
|
|
|
auto detType = det->getDetectorType().squash(defs::GENERIC);
|
|
if (detType != defs::CHIPTESTBOARD &&
|
|
detType != defs::XILINX_CHIPTESTBOARD) {
|
|
throw RuntimeError("This command is only applicable for ChipTestBoard "
|
|
"and Xilinx ChipTestBoard.");
|
|
}
|
|
|
|
// 'all' argument
|
|
bool all = false;
|
|
if (std::find(args.begin(), args.end(), "all") != args.end()) {
|
|
all = true;
|
|
}
|
|
|
|
// number of args
|
|
if (action == defs::GET_ACTION && args.size() != 1)
|
|
WrongNumberOfParameters(1);
|
|
if (all) {
|
|
if (action == defs::PUT_ACTION && args.size() != 2) {
|
|
WrongNumberOfParameters(2);
|
|
}
|
|
} else {
|
|
if (args.size() < 1 || args.size() > 6)
|
|
WrongNumberOfParameters(1);
|
|
}
|
|
|
|
if (action == defs::GET_ACTION) {
|
|
if (!all) {
|
|
auto t = det->isPowerEnabled(parsePowerIndex(0));
|
|
os << args[0] << ' ' << ToString(t, defs::OnOff) << '\n';
|
|
} else {
|
|
// get each state and store in map
|
|
std::map<std::string, std::string> m;
|
|
auto powerIndices = det->getPowerList();
|
|
for (const auto &index : powerIndices) {
|
|
auto name = ToString(index);
|
|
auto state = det->isPowerEnabled(index);
|
|
m[name] = ToString(state, defs::OnOff);
|
|
}
|
|
if (m.empty()) {
|
|
throw RuntimeError("Could not get power states.");
|
|
}
|
|
auto first = m.begin()->second;
|
|
// if all the same, print in short form, else print all states
|
|
if (std::all_of(m.begin(), m.end(),
|
|
[&](const auto &p) { return p.second == first; })) {
|
|
os << "all " << first << '\n';
|
|
} else {
|
|
os << ToString(m) << '\n';
|
|
}
|
|
}
|
|
}
|
|
|
|
else if (action == defs::PUT_ACTION) {
|
|
// enable arg
|
|
std::string lastArg = args.back();
|
|
if (lastArg != "on" && lastArg != "off") {
|
|
throw RuntimeError("Last argument '" + lastArg +
|
|
"' is enable. Options: 'on' or 'off'");
|
|
}
|
|
bool enable = StringTo(lastArg, defs::OnOff);
|
|
|
|
// power indices
|
|
std::vector<defs::powerIndex> powerIndices;
|
|
if (all) {
|
|
powerIndices = det->getPowerList();
|
|
} else {
|
|
// push back indices from command line
|
|
for (size_t i = 0; i < args.size() - 1; ++i) {
|
|
powerIndices.push_back(parsePowerIndex(i));
|
|
}
|
|
}
|
|
|
|
det->setPowerEnabled(powerIndices, enable);
|
|
args.pop_back();
|
|
os << ToString(args) << ' ' << ToString(enable, defs::OnOff) << '\n';
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
|
|
std::string Caller::powervalues(int action) {
|
|
std::ostringstream os;
|
|
if (action == defs::HELP_ACTION) {
|
|
os << "\n\t\t[Ctb][Xilinx_Ctb] Get dac values of all powers if "
|
|
"enabled, else '0'."
|
|
<< '\n';
|
|
return os.str();
|
|
}
|
|
|
|
auto detType = det->getDetectorType().squash(defs::GENERIC);
|
|
if (detType != defs::CHIPTESTBOARD &&
|
|
detType != defs::XILINX_CHIPTESTBOARD) {
|
|
throw RuntimeError("This command is only applicable for ChipTestBoard "
|
|
"and Xilinx ChipTestBoard.");
|
|
}
|
|
|
|
if (action == defs::GET_ACTION) {
|
|
if (!args.empty()) {
|
|
WrongNumberOfParameters(0);
|
|
}
|
|
auto t = det->getPowerList();
|
|
auto names = det->getPowerNames();
|
|
auto name_it = names.begin();
|
|
os << '[';
|
|
auto it = t.cbegin();
|
|
while (it != t.cend()) {
|
|
if (it != t.cbegin())
|
|
os << ", ";
|
|
os << ToString(*name_it++) << ": [";
|
|
os << ToString(det->isPowerEnabled(*it), defs::OnOff) << ", ";
|
|
os << det->getPowerDAC(*it) << " mV ]";
|
|
++it;
|
|
}
|
|
os << "]" << '\n';
|
|
} else if (action == defs::PUT_ACTION) {
|
|
throw RuntimeError("Cannot put");
|
|
} else {
|
|
throw RuntimeError("Unknown action");
|
|
}
|
|
return os.str();
|
|
}
|
|
|
|
defs::FrequencyUnit Caller::parseFrequencyUnit(const std::string &unit) {
|
|
auto unitLower = [&] {
|
|
std::string result = unit;
|
|
std::transform(result.begin(), result.end(), result.begin(),
|
|
[](unsigned char c) { return std::tolower(c); });
|
|
return result;
|
|
}();
|
|
if (unitLower == "hz")
|
|
return defs::FrequencyUnit::Hz;
|
|
if (unitLower == "khz")
|
|
return defs::FrequencyUnit::kHz;
|
|
if (unitLower == "mhz")
|
|
return defs::FrequencyUnit::MHz;
|
|
|
|
throw std::runtime_error("Unknown frequency unit: " + unit);
|
|
}
|
|
|
|
} // namespace sls
|