diff --git a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c index 7db479800..7917676ec 100644 --- a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c @@ -1431,25 +1431,34 @@ int setDAC(enum DACINDEX ind, int val, bool mV, char *mess) { return FAIL; int dacval = val; + char dacName[20] = {0}; + snprintf(dacName, sizeof(dacName), "dac %d", ind); if (mV) { if (validateDACValue(ind, val, mess) == FAIL) return FAIL; - // power dacs (power should be disabled) - if (ind >= NDAC_ONLY && ind != D_PWR_CHIP) { - if (verifyPowerRailDisabled(ind, mess) == FAIL) + // vchip dac (dacname only()) + if (ind == D_PWR_CHIP) { + snprintf(dacName, sizeof(dacName), "v_chip"); + } + // power dacs (dacname and power should be disabled) + else if (ind >= NDAC_ONLY) { + { + enum PWRINDEX pwrIndex = PWR_IO; + if (getPowerIndexFromDACIndex(ind, &pwrIndex, mess) == FAIL) + return FAIL; + char *powerNames[] = {PWR_NAMES}; + snprintf(dacName, sizeof(dacName), "%s", powerNames[pwrIndex]); + } + if (verifyPowerRailDisabled(ind, dacName, mess) == FAIL) return FAIL; } if (convertVoltageToDACValue(ind, val, &dacval, mess) == FAIL) return FAIL; } - { - char dacName[20] = {0}; - snprintf(dacName, sizeof(dacName), "dac %d", ind); - if (LTC2620_SetDacValue((int)ind, dacval, dacName, mess) == FAIL) - return FAIL; - } + if (LTC2620_SetDacValue((int)ind, dacval, dacName, mess) == FAIL) + return FAIL; dacValues[ind] = dacval; return OK; } @@ -1485,7 +1494,7 @@ int getVchip(int *retval, char *mess) { } int setVchip(int val, char *mess) { - LOG(logINFOBLUE, ("Setting Vchip to %d mV\n", val)); + LOG(logDEBUG, ("\tSetting Vchip to %d mV\n", val)); if (setDAC(D_PWR_CHIP, val, true, mess) == FAIL) return FAIL; @@ -1618,22 +1627,32 @@ int setPowerRailEnabled(enum DACINDEX indices[], int count, bool enable, // get power indices for log messages and mask uint32_t mask = 0; enum PWRINDEX pwrIndices[count]; + char *powerNames[] = {PWR_NAMES}; for (int i = 0; i != count; ++i) { - if (getPowerIndexFromDACIndex(indices[i], &pwrIndices[i], mess) == FAIL) + if (getPowerIndexFromDACIndex(indices[i], &pwrIndices[i], mess) == + FAIL) { + sprintf(mess, + "Cannot set power rail for %s. Use powerlist to see whats " + "available.\n", + powerNames[pwrIndices[i]]); return FAIL; + } + + LOG(logDEBUG1, + ("Setting power rail for %s\n", powerNames[pwrIndices[i]])); if (getPowerRailMask(pwrIndices[i], &mask, mess) == FAIL) return FAIL; } // log message { - char *powerNames[] = {PWR_NAMES}; char message[256] = {0}; sprintf(message, "Switching %s power for ", enable ? "on" : "off"); for (int i = 0; i != count; ++i) { strcat(message, powerNames[pwrIndices[i]]); + strcat(message, " "); } strcat(message, "\n"); - LOG(logINFO, ("%s", message)); + LOG(logINFOBLUE, ("%s", message)); } // set vchip accordingly @@ -1655,31 +1674,33 @@ int setPowerRailEnabled(enum DACINDEX indices[], int count, bool enable, int isPowerRailEnabled(enum DACINDEX ind, bool *retval, char *mess) { enum PWRINDEX pwrIndex = PWR_IO; - if (getPowerIndexFromDACIndex(ind, &pwrIndex, mess) == FAIL) + if (getPowerIndexFromDACIndex(ind, &pwrIndex, mess) == FAIL) { + char *powerNames[] = {PWR_NAMES}; + sprintf(mess, + "Cannot set power rail for %s. Use powerlist to see whats " + "available.\n", + powerNames[pwrIndex]); return FAIL; + } uint32_t mask = 0; if (getPowerRailMask(pwrIndex, &mask, mess) == FAIL) return FAIL; *retval = (bus_r(POWER_REG) & mask) != 0; + LOG(logDEBUG1, ("get power %d:%d\n", pwrIndex, *retval)); return OK; } -int verifyPowerRailDisabled(enum DACINDEX ind, char *mess) { +int verifyPowerRailDisabled(enum DACINDEX ind, char *dacName, char *mess) { bool isEnabled = false; if (isPowerRailEnabled(ind, &isEnabled, mess) == FAIL) return FAIL; - if (isEnabled) { - enum PWRINDEX pwrIndex = PWR_IO; - if (getPowerIndexFromDACIndex(ind, &pwrIndex, mess) == FAIL) - return FAIL; - char *powerNames[] = {PWR_NAMES}; sprintf(mess, "Could not set dac for %s. Please disable the power rail " "before setting the dac value.\n", - powerNames[pwrIndex]); + dacName); LOG(logERROR, (mess)); return FAIL; } @@ -1689,11 +1710,11 @@ int verifyPowerRailDisabled(enum DACINDEX ind, char *mess) { void powerChip(bool enable) { uint32_t addr = POWER_REG; if (enable) { - LOG(logINFO, ("Powering on all voltage regulators\n")); + LOG(logINFOBLUE, ("Powering on all voltage regulators\n")); bus_w(addr, bus_r(addr) | POWER_ENBL_VLTG_RGLTR_MSK); return; } else { - LOG(logINFO, ("Powering off all voltage regulators\n")); + LOG(logINFOBLUE, ("Powering off all voltage regulators\n")); bus_w(addr, bus_r(addr) & (~POWER_ENBL_VLTG_RGLTR_MSK)); } } diff --git a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.h b/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.h index 306df5169..a5ae19911 100644 --- a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.h +++ b/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.h @@ -154,7 +154,7 @@ int getPowerRailMask(enum PWRINDEX ind, uint32_t *mask, char *mess); int setPowerRailEnabled(enum DACINDEX indices[], int count, bool enable, char *mess); int isPowerRailEnabled(enum DACINDEX ind, bool *retval, char *mess); -int verifyPowerRailDisabled(enum DACINDEX ind, char *mess); +int verifyPowerRailDisabled(enum DACINDEX ind, char *dacName, char *mess); void powerChip(bool enable); int getPowerChip(); diff --git a/slsDetectorServers/slsDetectorServer/src/LTC2620.c b/slsDetectorServers/slsDetectorServer/src/LTC2620.c index 2a62fa982..d7ed35dd6 100644 --- a/slsDetectorServers/slsDetectorServer/src/LTC2620.c +++ b/slsDetectorServers/slsDetectorServer/src/LTC2620.c @@ -250,7 +250,7 @@ int LTC2620_SetDacValue(int dacnum, int val, char *dacname, char *mess) { LOG(logERROR, (mess)); return FAIL; } - LOG(logINFO, ("\tSetting DAC %s [%d]: %d dac\n", dacname, dacnum, val)); + LOG(logINFOBLUE, ("\tSetting DAC %s [%d]: %d dac\n", dacname, dacnum, val)); #ifndef VIRTUAL LTC2620_SetDAC(dacnum, val); #endif diff --git a/slsDetectorSoftware/generator/Caller.in.h b/slsDetectorSoftware/generator/Caller.in.h index b0355a611..8e1b6fad9 100644 --- a/slsDetectorSoftware/generator/Caller.in.h +++ b/slsDetectorSoftware/generator/Caller.in.h @@ -5,6 +5,7 @@ #include "sls/Detector.h" #include +#include #include #include namespace sls { @@ -92,6 +93,8 @@ class Caller { // applicable RegisterAddress getRegisterAddress(const std::string &saddr) const; BitAddress getBitAddress() const; + defs::dacIndex parsePowerIndex(int argIndex); + std::optional parseIfPowerIndex(int argIndex); defs::dacIndex parseDacIndex(int argIndex, bool isCtb); bool parseMV(int argIndex); diff --git a/slsDetectorSoftware/src/Caller.h b/slsDetectorSoftware/src/Caller.h index b8ad644ea..20dba9fdc 100644 --- a/slsDetectorSoftware/src/Caller.h +++ b/slsDetectorSoftware/src/Caller.h @@ -5,6 +5,7 @@ #include "sls/Detector.h" #include +#include #include #include namespace sls { @@ -416,6 +417,8 @@ class Caller { // applicable RegisterAddress getRegisterAddress(const std::string &saddr) const; BitAddress getBitAddress() const; + defs::dacIndex parsePowerIndex(int argIndex); + std::optional parseIfPowerIndex(int argIndex); defs::dacIndex parseDacIndex(int argIndex, bool isCtb); bool parseMV(int argIndex); diff --git a/slsDetectorSoftware/src/CallerSpecial.cpp b/slsDetectorSoftware/src/CallerSpecial.cpp index bb99ad99e..79c583a0e 100644 --- a/slsDetectorSoftware/src/CallerSpecial.cpp +++ b/slsDetectorSoftware/src/CallerSpecial.cpp @@ -4,8 +4,10 @@ #include "sls/file_utils.h" #include "sls/logger.h" #include "sls/string_utils.h" + #include #include + namespace sls { // some helper functions to print @@ -1852,6 +1854,37 @@ std::string Caller::dac(int action) { return os.str(); } +defs::dacIndex Caller::parsePowerIndex(int argIndex) { + auto res = parseIfPowerIndex(argIndex); + if (!res.has_value()) { + throw RuntimeError("Invalid power name. Power name can be v_a, v_b, " + "v_c, v_d, v_io, v_chip or any names set using " + "powername command."); + } + return res.value(); +} + +std::optional Caller::parseIfPowerIndex(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 std::make_optional(StringTo(arg)); + } + + // power name + auto names = det->getPowerNames(); + auto it = std::find(names.begin(), names.end(), arg); + if (it != names.end()) { + return std::make_optional(det->getPowerIndex(arg)); + } + return std::nullopt; +} + defs::dacIndex Caller::parseDacIndex(int argIndex, bool isCtb) { if (argIndex >= (int)args.size()) { throw RuntimeError("Invalid arguments. DAC index is required."); @@ -1859,12 +1892,12 @@ defs::dacIndex Caller::parseDacIndex(int argIndex, bool isCtb) { auto arg = args[argIndex]; if (isCtb) { - // dac index or power dacs - if (is_int(arg) || arg == "v_a" || arg == "v_b" || arg == "v_c" || - arg == "v_d" || arg == "v_io" || arg == "v_chip") { - return StringTo(arg); + // power dacs + auto res = parseIfPowerIndex(argIndex); + if (res.has_value()) { + return res.value(); } - // dac name for ctb gui + // dac name return det->getDacIndex(arg); } @@ -1936,8 +1969,8 @@ std::string Caller::power(int action) { if (action == defs::HELP_ACTION) { os << "[list of power names] [on|off]\n\t[Ctb][Xilinx Ctb] Enable or " "disable power rails. Power name can be v_a, v_b, v_c, v_d or " - "v_io. If none provided, all of them are set to on or off. One " - "can retrieve only one at a time." + "v_io or any names set using powername. One can retrieve only " + "one at a time." << '\n'; return os.str(); } @@ -1953,11 +1986,13 @@ std::string Caller::power(int action) { if (args.size() != 1) { WrongNumberOfParameters(1); } - auto t = det->isPowerEnabled(StringTo(args[0]), - std::vector{det_id}) - .tsquash("Inconsistent across modules"); + auto t = + det->isPowerEnabled(parsePowerIndex(0), std::vector{det_id}) + .tsquash("Inconsistent across modules"); os << args[0] << ' ' << ToString(t, defs::OnOff) << '\n'; - } else if (action == defs::PUT_ACTION) { + } + + else if (action == defs::PUT_ACTION) { if (args.size() < 1 || args.size() > 6) { WrongNumberOfParameters(1); } @@ -1969,7 +2004,7 @@ std::string Caller::power(int action) { bool enable = StringTo(lastArg, defs::OnOff); std::vector powerIndices; for (size_t i = 0; i < args.size() - 1; ++i) { - powerIndices.push_back(StringTo(args[i])); + powerIndices.push_back(parsePowerIndex(i)); } det->setPowerEnabled(powerIndices, enable, std::vector{det_id}); diff --git a/slsDetectorSoftware/tests/Caller/test-Caller-chiptestboard.cpp b/slsDetectorSoftware/tests/Caller/test-Caller-chiptestboard.cpp index 53de177f1..5e86153f2 100644 --- a/slsDetectorSoftware/tests/Caller/test-Caller-chiptestboard.cpp +++ b/slsDetectorSoftware/tests/Caller/test-Caller-chiptestboard.cpp @@ -573,15 +573,17 @@ TEST_CASE("dac", "[.detectorintegration][dacs]") { REQUIRE_THROWS(caller.call("dac", {"5", "2049", "mV"}, -1, PUT)); for (int idac = 0; idac < 18; ++idac) { + SECTION("dac " + std::to_string(idac)) { test_dac_caller(static_cast(idac), "dac", 0); test_dac_caller(static_cast(idac), "dac", 1200); test_dac_caller(static_cast(idac), "dac", 1200, true); test_dac_caller(static_cast(idac), "dac", -100); + + // dac name det.setDacName(static_cast(idac), "dacname" + std::to_string(idac)); - test_dac_caller(defs::DAC_0, "dacname" + std::to_string(idac), -100); } @@ -660,6 +662,21 @@ TEST_CASE("dac", "[.detectorintegration][dacs]") { REQUIRE(oss2.str() == "dac " + names[iPower] + " 1200 mV\n"); } + { + // power name + det.setPowerName(indices[iPower], + "pwrname_" + names[iPower]); + std::ostringstream oss1, oss2; + caller.call("dac", + {"pwrname_" + names[iPower], "1200", "mV"}, -1, + PUT, oss1); + REQUIRE(oss1.str() == + "dac pwrname_" + names[iPower] + " 1200 mV\n"); + caller.call("dac", {"pwrname_" + names[iPower], "mV"}, -1, + GET, oss2); + REQUIRE(oss2.str() == + "dac pwrname_" + names[iPower] + " 1200 mV\n"); + } // throw if trying to set dac when power is on { det.setPowerEnabled(std::vector{indices[iPower]}, true); @@ -1188,55 +1205,83 @@ TEST_CASE("power", "[.detectorintegration]") { defs::V_POWER_C, defs::V_POWER_D, defs::V_POWER_IO}; + std::vector prev_val(cmds.size()); for (size_t iPower = 0; iPower < cmds.size(); ++iPower) { - auto prev_val = det.isPowerEnabled(indices[iPower]); + prev_val[iPower] = det.isPowerEnabled(indices[iPower]) + .tsquash("Inconsistent power enabled state"); + det.setPowerEnabled(std::vector{indices[iPower]}, false); + } - REQUIRE_THROWS(caller.call("power", {"vrandom"}, -1, GET)); - REQUIRE_THROWS(caller.call("power", {"v_chip"}, -1, GET)); - REQUIRE_THROWS(caller.call("power", {"on", "v_a"}, -1, PUT)); - { - std::ostringstream oss; - caller.call("power", {"v_a", "on"}, -1, PUT, oss); - REQUIRE(oss.str() == "power [v_a] on\n"); - } - { - std::ostringstream oss; - caller.call("power", {"v_a"}, -1, GET, oss); - REQUIRE(oss.str() == "power v_a on\n"); - } - { - std::ostringstream oss; - caller.call("power", {"v_a", "v_c", "on"}, -1, PUT, oss); - REQUIRE(oss.str() == "power [v_a, v_c] on\n"); - } - { - std::ostringstream oss1, oss2, oss3; - caller.call("power", {"v_a", "v_b", "off"}, -1, PUT); - caller.call("power", {"v_a"}, -1, GET, oss1); - caller.call("power", {"v_b"}, -1, GET, oss2); - caller.call("power", {"v_c"}, -1, GET, oss3); - REQUIRE(oss1.str() == "power v_a off\n"); - REQUIRE(oss2.str() == "power v_b off\n"); - REQUIRE(oss3.str() == "power v_c on\n"); - } - { // power chip - caller.call("powerchip", {"1"}, -1, PUT); - std::ostringstream oss1, oss2, oss3, oss4, oss5; - caller.call("power", {"v_a"}, -1, GET, oss1); - caller.call("power", {"v_b"}, -1, GET, oss2); - caller.call("power", {"v_c"}, -1, GET, oss3); - caller.call("power", {"v_d"}, -1, GET, oss4); - caller.call("power", {"v_io"}, -1, GET, oss5); - REQUIRE(oss1.str() == "power v_a on\n"); - REQUIRE(oss2.str() == "power v_b on\n"); - REQUIRE(oss3.str() == "power v_c on\n"); - REQUIRE(oss4.str() == "power v_d on\n"); - REQUIRE(oss5.str() == "power v_io on\n"); - } - for (int imod = 0; imod != det.size(); ++imod) { - det.setPowerEnabled(std::vector{indices[iPower]}, - prev_val[imod], {imod}); - } + REQUIRE_THROWS(caller.call("power", {"vrandom"}, -1, GET)); + REQUIRE_THROWS(caller.call("power", {"v_chip"}, -1, GET)); + REQUIRE_THROWS(caller.call("power", {"on", "v_a"}, -1, PUT)); + { + std::ostringstream oss; + caller.call("power", {"v_a", "on"}, -1, PUT, oss); + REQUIRE(oss.str() == "power [v_a] on\n"); + } + { + std::ostringstream oss; + caller.call("power", {"v_a"}, -1, GET, oss); + REQUIRE(oss.str() == "power v_a on\n"); + } + { + std::ostringstream oss; + caller.call("power", {"v_a", "v_c", "on"}, -1, PUT, oss); + REQUIRE(oss.str() == "power [v_a, v_c] on\n"); + } + { + std::ostringstream oss1, oss2, oss3; + caller.call("power", {"v_a", "v_b", "off"}, -1, PUT); + caller.call("power", {"v_a"}, -1, GET, oss1); + caller.call("power", {"v_b"}, -1, GET, oss2); + caller.call("power", {"v_c"}, -1, GET, oss3); + REQUIRE(oss1.str() == "power v_a off\n"); + REQUIRE(oss2.str() == "power v_b off\n"); + REQUIRE(oss3.str() == "power v_c on\n"); + } + { + // power name + std::ostringstream oss1; + det.setPowerName(defs::V_POWER_B, "pwrname_v_b"); + det.setPowerName(defs::V_POWER_C, "pwrname_v_c"); + det.setPowerName(defs::V_POWER_D, "pwrname_v_d"); + caller.call("power", {"pwrname_v_c", "pwrname_v_d", "on"}, -1, PUT, + oss1); + std::ostringstream oss[8]; + caller.call("power", {"v_a"}, -1, GET, oss[0]); + caller.call("power", {"pwrname_v_b"}, -1, GET, oss[1]); + caller.call("power", {"v_b"}, -1, GET, oss[2]); + caller.call("power", {"pwrname_v_c"}, -1, GET, oss[3]); + caller.call("power", {"v_c"}, -1, GET, oss[4]); + caller.call("power", {"pwrname_v_d"}, -1, GET, oss[5]); + caller.call("power", {"v_d"}, -1, GET, oss[6]); + caller.call("power", {"v_io"}, -1, GET, oss[7]); + REQUIRE(oss[0].str() == "power v_a off\n"); + REQUIRE(oss[1].str() == "power pwrname_v_b off\n"); + REQUIRE(oss[2].str() == "power v_b off\n"); + REQUIRE(oss[3].str() == "power pwrname_v_c on\n"); + REQUIRE(oss[4].str() == "power v_c on\n"); + REQUIRE(oss[5].str() == "power pwrname_v_d on\n"); + REQUIRE(oss[6].str() == "power v_d on\n"); + REQUIRE(oss[7].str() == "power v_io off\n"); + } + { // power chip + caller.call("powerchip", {"1"}, -1, PUT); + std::ostringstream oss1, oss2, oss3, oss4, oss5; + caller.call("power", {"v_a"}, -1, GET, oss1); + caller.call("power", {"v_b"}, -1, GET, oss2); + caller.call("power", {"v_c"}, -1, GET, oss3); + caller.call("power", {"v_d"}, -1, GET, oss4); + caller.call("power", {"v_io"}, -1, GET, oss5); + REQUIRE(oss1.str() == "power v_a on\n"); + REQUIRE(oss2.str() == "power v_b on\n"); + REQUIRE(oss3.str() == "power v_c on\n"); + REQUIRE(oss4.str() == "power v_d on\n"); + REQUIRE(oss5.str() == "power v_io on\n"); + } + for (size_t iPower = 0; iPower < cmds.size(); ++iPower) { + det.setPowerEnabled(std::vector{indices[iPower]}, prev_val[iPower]); } } else { REQUIRE_THROWS(caller.call("power", {"v_a"}, -1, GET));