mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2026-05-13 09:45:36 +02:00
5ec5d46c48
Build and Deploy on local RHEL9 / build (push) Successful in 2m12s
Build on RHEL9 docker image / build (push) Successful in 3m33s
Build on RHEL8 docker image / build (push) Successful in 4m54s
Build and Deploy on local RHEL8 / build (push) Successful in 4m54s
Run Simulator Tests on local RHEL9 / build (push) Successful in 14m41s
Run Simulator Tests on local RHEL8 / build (push) Successful in 17m10s
* not allowing power names for dac names to prevent duplicate names * wip * v_abcd commands should be removed to prevent unintentional usage and throw with a suggestion command for dac and power * binary in * dacs with power dac names should work and do not take in dac units to avoid ambiguity, test with 0 value for power dacs should fail, to do: implement power commands * wip: power in client, tests, and fixed server interfaces and ctb implementation, not tested * wip. client and xilinx todo * wip: ctb power works, tests left * fixed some tests * added vchip check * python cmds still left. wip * fixed xilinx. python left * wip * wip. xilinx * fixed powerchip for ctb * power all returns all * configtransceiver is removed * wip python * wip * wip * wip * wip * wip * wip * wip xilinx * wip * wip * wip * pybindings * fix getdacindex and getdacname for normal detectors to throw if random index that doesnt fit to the detector * wip * fixed tests * fixes for python api * wip * python: moved powerlist to Ctb * fixed tests to work for powelist in Ctb * moved signallist, adclist, slowadc, slowadclist to Ctb * throw approperiate error when no modules added for powers * added dac test * fix dac default names and test for dacs * ctb dacs, yet to do othe rdacs * dacs should work now even in tests * run all tests * DetectorPowers->NamedPowers in ctb * comments * removed unnecessary test code * removed hard coded dac names in python NamedDacs and NamedPowers * minor * minor * fixed error messages * changed power to be able to set DAC directly, using enable and disable methods with enabled to get
2108 lines
76 KiB
C++
2108 lines
76 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::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 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);
|
|
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}));
|
|
}
|
|
} 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;
|
|
}
|
|
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 << "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 << "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();
|
|
}
|
|
|
|
} // namespace sls
|