wip: power in client, tests, and fixed server interfaces and ctb implementation, not tested
Build on RHEL9 docker image / build (push) Failing after 30s
Build on RHEL8 docker image / build (push) Failing after 35s

This commit is contained in:
2026-03-06 14:23:34 +01:00
parent 4723eb2ff4
commit c2e8d5954d
15 changed files with 415 additions and 183 deletions
@@ -573,7 +573,7 @@ void setupDetector() {
return;
// power off voltage regulators
powerOff();
powerChip(false);
// adcs
AD9257_SetDefines(ADC_SPI_REG, ADC_SPI_SRL_CS_OTPT_MSK,
@@ -1270,6 +1270,25 @@ int validateDACIndex(enum DACINDEX ind, char *mess) {
return OK;
}
int validateDACValue(enum DACINDEX ind, int voltage, char *mess) {
// normal dacs
if (ind < NDAC_ONLY) {
if (validateDACVoltage(ind, voltage, mess) == FAIL)
return FAIL;
return OK;
}
// vchip
if (ind == D_PWR_CHIP) {
if (validateVchip(voltage, mess) == FAIL)
return FAIL;
return OK;
}
// power dacs
if (validatePowerDACVoltage(ind, voltage, mess) == FAIL)
return FAIL;
return OK;
}
int validateDACVoltage(enum DACINDEX ind, int voltage, char *mess) {
// validate min value
if (voltage < 0) {
@@ -1413,10 +1432,23 @@ int setDAC(enum DACINDEX ind, int val, bool mV, char *mess) {
int dacval = val;
if (mV) {
if (ind < NDAC_ONLY) {
if (validateDACVoltage(ind, val, mess) == FAIL)
if (validateDACValue(ind, val, mess) == FAIL)
return FAIL;
// power dacs
if (ind > NDAC_ONLY && ind != D_PWR_CHIP) {
if (verifyPowerRailDisabled(ind, mess) == FAIL)
return FAIL;
// set vchip accordingly
int vchip = 0;
if (getVchipToSet(ind, val, &vchip, mess) == FAIL)
return FAIL;
if (setVchip(vchip, mess) == FAIL)
return FAIL;
}
if (convertVoltageToDACValue(ind, val, &dacval, mess) == FAIL)
return FAIL;
}
@@ -1462,9 +1494,6 @@ int getVchip(int *retval, char *mess) {
int setVchip(int val, char *mess) {
LOG(logINFOBLUE, ("Setting Vchip to %d mV\n", val));
if (validateVchip(val, mess) == FAIL)
return FAIL;
if (setDAC(D_PWR_CHIP, val, true, mess) == FAIL)
return FAIL;
@@ -1514,32 +1543,32 @@ int getVchipToSet(enum DACINDEX ind, int pwr_val, int *retval_vchip,
return OK;
}
int validatePower(enum PWRINDEX ind, int val, char *mess) {
int validatePower(enum PWRINDEX ind, int voltage, char *mess) {
char *powerNames[] = {PWR_NAMES};
// validate min value
int min = (ind == PWR_IO) ? VIO_MIN_MV : POWER_RGLTR_MIN;
if (val < min && val != 0) {
if (voltage < min && voltage != 0) {
sprintf(
mess,
"Could not set %s. Input value %d mV must be greater than %d mV.\n",
powerNames[ind], val, min);
powerNames[ind], voltage, min);
LOG(logERROR, (mess));
return FAIL;
}
// validate max value
int max = (VCHIP_MAX_MV - VCHIP_POWER_INCRMNT);
if (val > max) {
if (voltage > max) {
sprintf(
mess,
"Could not set %s. Input value %d mV must be less than %d mV.\n",
powerNames[ind], val, max);
powerNames[ind], voltage, max);
LOG(logERROR, (mess));
return FAIL;
}
// validate vlimit
if (vLimit > 0 && val > vLimit) {
if (vLimit > 0 && voltage > vLimit) {
sprintf(mess, "Could not set %s. Input %d mV exceeds vLimit %d mV\n",
powerNames[ind], val, vLimit);
powerNames[ind], voltage, vLimit);
LOG(logERROR, (mess))
return FAIL;
}
@@ -1574,126 +1603,118 @@ int getPowerIndexFromDACIndex(enum DACINDEX ind, enum PWRINDEX *pwrIndex,
return OK;
}
int getPowerRailMask(enum PWRINDEX ind, uint32_t *mask, char *mess) {
*mask = 0;
switch (ind) {
int getPowerRailMask(enum PWRINDEX index, uint32_t *mask, char *mess) {
switch (index) {
case PWR_IO:
*mask = POWER_ENBL_VIO_MSK;
*mask |= POWER_ENBL_VIO_MSK;
break;
case PWR_A:
*mask = POWER_ENBL_VA_MSK;
*mask |= POWER_ENBL_VA_MSK;
break;
case PWR_B:
*mask = POWER_ENBL_VB_MSK;
*mask |= POWER_ENBL_VB_MSK;
break;
case PWR_C:
*mask = POWER_ENBL_VC_MSK;
*mask |= POWER_ENBL_VC_MSK;
break;
case PWR_D:
*mask = POWER_ENBL_VD_MSK;
*mask |= POWER_ENBL_VD_MSK;
break;
default:
sprintf(mess, "Index %d has no power rail index\n", ind);
sprintf(mess, "Index %d has no power rail index\n", index);
LOG(logERROR, (mess));
return FAIL;
}
return OK;
}
int EnablePowerRail(enum PWRINDEX ind, char *mess) {
char *powerNames[] = {PWR_NAMES};
uint32_t addr = POWER_REG;
int setPowerRailEnabled(enum DACINDEX indices[], int count, bool enable,
char *mess) {
// get power indices for log messages and mask
uint32_t mask = 0;
if (getPowerRailMask(ind, &mask, mess) == FAIL)
return FAIL;
LOG(logINFO, ("\tSwitching on power for %s\n", powerNames[ind]));
bus_w(addr, bus_r(addr) | mask);
return OK;
}
int DisablePowerRail(enum PWRINDEX ind, char *mess) {
char *powerNames[] = {PWR_NAMES};
uint32_t addr = POWER_REG;
uint32_t mask = 0;
if (getPowerRailMask(ind, &mask, mess) == FAIL)
return FAIL;
LOG(logINFO, ("\tSwitching off power for %s\n", powerNames[ind]));
bus_w(addr, bus_r(addr) & ~(mask));
return OK;
}
int getPowerRail(enum PWRINDEX ind, int *retval, char *mess) {
char *powerNames[] = {PWR_NAMES};
uint32_t addr = POWER_REG;
uint32_t mask = 0;
if (getPowerRailMask(ind, &mask, mess) == FAIL)
return FAIL;
*retval = (bus_r(addr) & mask);
LOG(logDEBUG1, ("Power rail retval for %s: %s\n", powerNames[ind],
((*retval > 0) ? "Enabled" : "Disabled")));
return OK;
}
int getPower(enum DACINDEX ind, int *retval, char *mess) {
enum PWRINDEX pwrIndex = PWR_IO;
if (getPowerIndexFromDACIndex(ind, &pwrIndex, mess) == FAIL)
return FAIL;
// if powered off, return 0
if (getPowerRail(pwrIndex, retval, mess) == FAIL)
return FAIL;
if (*retval == 0) {
return OK;
enum PWRINDEX pwrIndices[count];
for (int i = 0; i != count; ++i) {
if (getPowerIndexFromDACIndex(indices[i], &pwrIndices[i], mess) == FAIL)
return FAIL;
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, "\n");
LOG(logINFO, ("%s", message));
}
if (getDAC(ind, true, retval, mess) == FAIL)
return FAIL;
return OK;
}
int setPower(enum DACINDEX ind, int val, char *mess) {
enum PWRINDEX pwrIndex = PWR_IO;
if (getPowerIndexFromDACIndex(ind, &pwrIndex, mess) == FAIL)
return FAIL;
char *powerNames[] = {PWR_NAMES};
LOG(logINFOBLUE, ("Setting %s to %d mV\n", powerNames[pwrIndex], val));
if (validatePower(pwrIndex, val, mess) == FAIL)
return FAIL;
// compute vchip to set before powering off
int vchip = 0;
if (getVchipToSet(ind, val, &vchip, mess) == FAIL)
return FAIL;
if (DisablePowerRail(pwrIndex, mess) == FAIL)
return FAIL;
if (setVchip(vchip, mess) == FAIL)
return FAIL;
if (val != 0) {
if (setDAC(ind, val, true, mess) == FAIL)
return FAIL;
if (EnablePowerRail(pwrIndex, mess) == FAIL)
return FAIL;
uint32_t addr = POWER_REG;
if (enable) {
bus_w(addr, bus_r(addr) | mask);
} else {
bus_w(addr, bus_r(addr) & ~(mask));
}
return OK;
}
void powerOff() {
int isPowerRailEnabled(enum DACINDEX ind, bool *retval, char *mess) {
enum PWRINDEX pwrIndex = PWR_IO;
if (getPowerIndexFromDACIndex(ind, &pwrIndex, mess) == FAIL)
return FAIL;
int mask = 0;
if (getPowerRailMask(ind, &mask, mess) == FAIL)
return FAIL;
*retval = (bus_r(POWER_REG) & mask) != 0;
return OK;
}
int verifyPowerRailDisabled(enum DACINDEX ind, 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]);
LOG(logERROR, (mess));
return FAIL;
}
return OK;
}
void powerChip(bool enable) {
uint32_t addr = POWER_REG;
LOG(logINFO, ("Powering off all voltage regulators\n"));
bus_w(addr, bus_r(addr) & (~POWER_ENBL_VLTG_RGLTR_MSK));
if (enable) {
LOG(logINFO, ("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"));
bus_w(addr, bus_r(addr) & (~POWER_ENBL_VLTG_RGLTR_MSK));
}
}
int getPowerChip() {
int retval = bus_r(POWER_REG) & POWER_ENBL_VLTG_RGLTR_MSK;
if (retval == 0)
return retval;
if (retval == POWER_ENBL_VLTG_RGLTR_MSK)
return 1;
LOG(logINFO, ("Power chip state is neither fully on nor fully off. Value "
"read: 0x%x\n",
retval));
return -1;
}
int getADC(enum ADCINDEX ind) {
@@ -128,6 +128,8 @@ int setADCVpp(int val, int mV, char *mess);
int getADCVpp(int mV, int *retval, char *mess);
int validateDACIndex(enum DACINDEX ind, char *mess);
int validateDACValue(enum DACINDEX ind, int voltage, char *mess);
int validateDACVoltage(enum DACINDEX ind, int voltage, char *mess);
int convertVoltageToDACValue(enum DACINDEX ind, int voltage, int *retval_dacval,
char *mess);
@@ -150,12 +152,12 @@ int validatePower(enum PWRINDEX ind, int val, char *mess);
int getPowerIndexFromDACIndex(enum DACINDEX ind, enum PWRINDEX *pwrIndex,
char *mess);
int getPowerRailMask(enum PWRINDEX ind, uint32_t *mask, char *mess);
int EnablePowerRail(enum PWRINDEX ind, char *mess);
int DisablePowerRail(enum PWRINDEX ind, char *mess);
int getPowerRail(enum PWRINDEX ind, int *retval, char *mess);
int getPower(enum DACINDEX ind, int *retval, char *mess);
int setPower(enum DACINDEX ind, int val, char *mess);
void powerOff();
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);
void powerChip(bool enable);
int getPowerChip();
int getADC(enum ADCINDEX ind);
int getSlowADC(int ichan);
@@ -341,3 +341,5 @@ int get_pattern_wait_interval(int);
int set_pattern_wait_interval(int);
int spi_read(int);
int spi_write(int);
int get_power(int);
int set_power(int);
@@ -523,6 +523,8 @@ void function_table() {
flist[F_SET_PATTERN_WAIT_INTERVAL] = &set_pattern_wait_interval;
flist[F_SPI_READ] = &spi_read;
flist[F_SPI_WRITE] = &spi_write;
flist[F_GET_POWER] = &get_power;
flist[F_SET_POWER] = &set_power;
// check
if (NUM_DET_FUNCTIONS >= RECEIVER_ENUM_START) {
LOG(logERROR, ("The last detector function enum has reached its "
@@ -1389,14 +1391,12 @@ int processDACEnums(enum dacIndex ind, int val, bool mV) {
retval = getVLimit();
return retval;
// power dacs
case V_POWER_A:
case V_POWER_B:
case V_POWER_C:
case V_POWER_D:
case V_POWER_IO:
serverDacIndex = getDACIndex(ind);
if (ret == FAIL)
return retval;
if (!mV) {
ret = FAIL;
sprintf(mess,
@@ -1406,17 +1406,12 @@ int processDACEnums(enum dacIndex ind, int val, bool mV) {
LOG(logERROR, (mess));
return retval;
}
if (val != GET_FLAG)
ret = setPower(serverDacIndex, val, mess);
else
ret = getPower(serverDacIndex, &retval, mess);
return retval;
// actual dacs
default:
serverDacIndex = getDACIndex(ind);
if (ret == FAIL)
return retval;
if (val != GET_FLAG)
ret = setDAC(serverDacIndex, val, mV, mess);
else
@@ -1446,14 +1441,12 @@ int processDACEnums(enum dacIndex ind, int val, bool mV) {
retval = getVLimit();
return retval;
// power dacs
case V_POWER_A:
case V_POWER_B:
case V_POWER_C:
case V_POWER_D:
case V_POWER_IO:
serverDacIndex = getDACIndex(ind);
if (ret == FAIL)
return retval;
if (!mV) {
ret = FAIL;
sprintf(mess,
@@ -1463,12 +1456,6 @@ int processDACEnums(enum dacIndex ind, int val, bool mV) {
LOG(logERROR, (mess));
return retval;
}
if (val != GET_FLAG)
ret = setPower(serverDacIndex, val, mess);
else
ret = getPower(serverDacIndex, &retval, mess);
return retval;
// actual dacs
default:
serverDacIndex = getDACIndex(ind);
@@ -4018,7 +4005,8 @@ int power_chip(int file_des) {
LOG(logDEBUG1, ("Powering chip to %d\n", arg));
#if !defined(JUNGFRAUD) && !defined(MOENCHD) && !defined(MYTHEN3D) && \
!defined(GOTTHARD2D) && !defined(XILINX_CHIPTESTBOARDD)
!defined(GOTTHARD2D) && !defined(XILINX_CHIPTESTBOARDD) && \
!defined(CHIPTESTBOARDD)
functionNotImplemented();
#else
// set & get
@@ -4037,7 +4025,8 @@ int power_chip(int file_des) {
}
}
#endif
#if defined(XILINX_CHIPTESTBOARDD) || defined(GOTTHARD2D)
#if defined(XILINX_CHIPTESTBOARDD) || defined(CHIPTESTBOARDD) || \
defined(GOTTHARD2D)
if (ret == OK) {
if (arg != -1) {
if (arg != 0 && arg != 1) {
@@ -11382,4 +11371,68 @@ int spi_write(int file_des) {
free(local_tx);
free(local_rx);
return ret;
}
int get_power(int file_des) {
ret = OK;
memset(mess, 0, sizeof(mess));
int arg = -1;
int retval = -1;
#if !defined(CHIPTESTBOARDD) && !defined(XILINX_CHIPTESTBOARDD)
functionNotImplemented();
#else
// index
if (receiveData(file_des, &arg, sizeof(arg), INT32) < 0)
return printSocketReadError();
LOG(logDEBUG1, ("Getting power rail enable for power %d\n", arg));
enum dacIndex serverDacIndex = getDACIndex(dacIndex(arg));
if (ret == FAIL) {
return Server_SendResult(file_des, INT32, NULL, 0);
}
ret = isPowerRailEnabled(serverDacIndex, &retval, mess);
#endif
return Server_SendResult(file_des, INT32, &retval, sizeof(retval));
}
int set_power(int file_des) {
ret = OK;
memset(mess, 0, sizeof(mess));
#if !defined(CHIPTESTBOARDD) && !defined(XILINX_CHIPTESTBOARDD)
functionNotImplemented();
#else
int count = 0;
if (receiveData(file_des, &count, sizeof(count), INT32) < 0)
return printSocketReadError();
int args[count];
if (receiveData(file_des, args, sizeof(args), INT32) < 0)
return printSocketReadError();
int arg = 0;
if (receiveData(file_des, &arg, sizeof(arg), INT32) < 0)
return printSocketReadError();
bool enable = (arg != 0);
LOG(logDEBUG1, ("Setting %d Power rails to %d\n", count, enable));
if (Server_VerifyLock() == OK) {
enum dacIndex serverDacIndices[count] = {0};
for (int iPower = 0; iPower != count; ++iPower) {
enum dacIndex ind = (dacIndex)args[iPower];
serverDacIndices[iPower] = getDACIndex(ind);
if (ret == FAIL) {
return Server_SendResult(file_des, INT32, NULL, 0);
}
}
ret = setPowerRailEnabled(serverDacIndices, count, enable, mess);
}
#endif
return Server_SendResult(file_des, INT32, NULL, 0);
}
+8 -5
View File
@@ -535,6 +535,9 @@ class Detector {
Result<int> getDAC(defs::dacIndex index, bool mV = false,
Positions pos = {}) const;
/** Sets dac in dac units or mV
* [Ctb][Xilinx Ctb] also includes V_LIMIT, V_POWER_A, V_POWER_B, V_POWER_C,
* V_POWER_D, V_POWER_IO, V_POWER_CHIP (get only)*/
void setDAC(defs::dacIndex index, int value, bool mV = false,
Positions pos = {});
@@ -1635,14 +1638,14 @@ class Detector {
std::vector<defs::dacIndex> getSlowADCList() const;
/** [CTB][Xilinx CTB] */
Result<int> getPower(defs::dacIndex index, Positions pos = {}) const;
Result<bool> isPowerEnabled(defs::dacIndex index, Positions pos = {}) const;
/**
* [CTB][Xilinx CTB] mV
* [Ctb][Xilinx CTB] Options: V_LIMIT, V_POWER_A, V_POWER_B, V_POWER_C,
* V_POWER_D, V_POWER_IO, V_POWER_CHIP
* [Ctb][Xilinx CTB] Options: V_POWER_A, V_POWER_B, V_POWER_C,
* V_POWER_D, V_POWER_IO
*/
void setPower(defs::dacIndex index, int value, Positions pos = {});
void setPowerEnabled(const std::vector<defs::dacIndex> &indices,
bool enable, Positions pos = {});
/**
* [CTB] Options: [0- 4] or [1V, 1.14V, 1.33V, 1.6V, 2V]
+15 -25
View File
@@ -2188,36 +2188,26 @@ std::vector<defs::dacIndex> Detector::getSlowADCList() const {
defs::SLOW_ADC4, defs::SLOW_ADC5, defs::SLOW_ADC6, defs::SLOW_ADC7};
}
Result<int> Detector::getPower(defs::dacIndex index, Positions pos) const {
switch (index) {
case defs::V_LIMIT:
case defs::V_POWER_A:
case defs::V_POWER_B:
case defs::V_POWER_C:
case defs::V_POWER_D:
case defs::V_POWER_IO:
case defs::V_POWER_CHIP:
break;
default:
Result<bool> Detector::isPowerEnabled(defs::dacIndex index,
Positions pos) const {
std::vector<defs::dacIndex> valid_indices = getPowerList();
if (std::find(valid_indices.begin(), valid_indices.end(), index) ==
valid_indices.end()) {
throw RuntimeError("Unknown Power Index");
}
return pimpl->Parallel(&Module::getDAC, pos, index, true);
return pimpl->Parallel(&Module::getPower, pos, index);
}
void Detector::setPower(defs::dacIndex index, int value, Positions pos) {
switch (index) {
case defs::V_LIMIT:
case defs::V_POWER_A:
case defs::V_POWER_B:
case defs::V_POWER_C:
case defs::V_POWER_D:
case defs::V_POWER_IO:
case defs::V_POWER_CHIP:
break;
default:
throw RuntimeError("Unknown Power Index");
void Detector::setPowerEnabled(const std::vector<defs::dacIndex> &indices,
bool value, Positions pos) {
std::vector<defs::dacIndex> valid_indices = getPowerList();
for (const auto &index : indices) {
if (std::find(valid_indices.begin(), valid_indices.end(), index) ==
valid_indices.end()) {
throw RuntimeError("Unknown Power Index");
}
}
pimpl->Parallel(&Module::setDAC, pos, value, index, true);
pimpl->Parallel(&Module::setPower, pos, value, indices);
}
Result<int> Detector::getADCVpp(bool mV, Positions pos) const {
+19
View File
@@ -819,6 +819,25 @@ void Module::setPowerChip(bool on) {
sendToDetector<int>(F_POWER_CHIP, static_cast<int>(on));
}
bool Module::isPowerEnabled(defs::dacIndex index) const {
return sendToDetector<int>(F_GET_POWER, index);
}
void Module::setPowerEnabled(const std::vector<defs::dacIndex> &indices,
bool value) {
auto client = DetectorSocket(shm()->hostname, shm()->controlPort);
client.Send(F_SET_POWER);
client.setFnum(F_SET_POWER);
int count = indices.size();
client.Send(count);
client.Send(indices);
client.Send(static_cast<int>(value));
if (client.Receive<int>() == FAIL) {
throw DetectorError("Detector " + std::to_string(moduleIndex) +
" returned error: " + client.readErrorMessage());
}
}
int Module::getImageTestMode() const {
return sendToDetector<int>(F_GET_IMAGE_TEST_MODE);
}
+3
View File
@@ -177,6 +177,9 @@ class Module : public virtual slsDetectorDefs {
void setDAC(int val, dacIndex index, bool mV);
bool getPowerChip() const;
void setPowerChip(bool on);
bool isPowerEnabled(defs::dacIndex index) const;
void setPowerEnabled(const std::vector<defs::dacIndex> &indices,
bool value);
int getImageTestMode() const;
void setImageTestMode(const int value);
/* temperature in millidegrees */
@@ -595,6 +595,10 @@ TEST_CASE("dac", "[.detectorintegration][.dacs]") {
defs::V_POWER_D, defs::V_POWER_IO};
for (size_t iPower = 0; iPower < names.size(); ++iPower) {
auto prev_val = det.getDAC(indices[iPower], true);
auto prev_val_power = det.isPowerEnabled(indices[iPower]);
// turn them off to be able to set the power dacs without issue
det.setPowerEnabled(std::vector{indices[iPower]}, false);
// this is the first command touching power dacs, should not be
// -100
@@ -651,9 +655,17 @@ TEST_CASE("dac", "[.detectorintegration][.dacs]") {
REQUIRE(oss2.str() ==
"dac " + names[iPower] + " 1200 mV\n");
}
// throw if trying to set dac when power is on
{
det.setPowerEnabled(std::vector{indices[iPower]}, true);
REQUIRE_THROWS(caller.call(
"dac", {names[iPower], "1200", "mV"}, -1, PUT));
}
// Reset all dacs to previous value
for (int imod = 0; imod != det.size(); ++imod) {
det.setDAC(indices[iPower], prev_val[imod], true, {imod});
det.setPowerEnabled(std::vector{indices[iPower]},
prev_val_power[imod], {imod});
}
}
}
@@ -848,32 +860,38 @@ TEST_CASE("v_limit", "[.detectorintegration]") {
if (det_type == defs::CHIPTESTBOARD ||
det_type == defs::XILINX_CHIPTESTBOARD) {
auto prev_val = det.getPower(defs::V_LIMIT);
auto prev_val = det.getDAC(defs::V_LIMIT, true);
REQUIRE_THROWS(caller.call("v_limit", {"1200"}, -1, PUT));
REQUIRE_THROWS(caller.call("v_limit", {"-100"}, -1, PUT));
REQUIRE_THROWS(caller.call("v_limit", {"0"}, -1, PUT));
REQUIRE_THROWS(caller.call("v_limit", {"-100", "mV"}, -1, PUT));
REQUIRE_THROWS(caller.call("v_limit", {"0", "mV"}, -1, PUT));
{
std::ostringstream oss;
caller.call("v_limit", {"1500"}, -1, PUT, oss);
REQUIRE(oss.str() == "v_limit 1500\n");
caller.call("v_limit", {"1500", "mV"}, -1, PUT, oss);
REQUIRE(oss.str() == "v_limit 1500 mV\n");
}
{
std::ostringstream oss;
caller.call("v_limit", {"0"}, -1, PUT, oss);
REQUIRE(oss.str() == "v_limit 0\n");
caller.call("v_limit", {"0", "mV"}, -1, PUT, oss);
REQUIRE(oss.str() == "v_limit 0 mV\n");
}
{
std::ostringstream oss;
caller.call("v_limit", {"0"}, -1, PUT, oss);
REQUIRE(oss.str() == "v_limit 0\n");
caller.call("v_limit", {"0", "mV"}, -1, PUT, oss);
REQUIRE(oss.str() == "v_limit 0 mV\n");
}
{
std::ostringstream oss;
caller.call("v_limit", {}, -1, GET, oss);
REQUIRE(oss.str() == "v_limit 0\n");
REQUIRE(oss.str() == "v_limit 0 mV\n");
}
for (int i = 0; i != det.size(); ++i) {
if (prev_val[i] == -100) {
prev_val[i] = 0;
}
det.setPower(defs::V_LIMIT, prev_val[i], {i});
det.setDAC(defs::V_LIMIT, prev_val[i], true, {i});
}
} else {
REQUIRE_THROWS(caller.call("v_limit", {}, -1, GET));
@@ -1147,6 +1165,63 @@ TEST_CASE("v_abcd", "[.detectorintegration]") {
}
}
TEST_CASE("power", "[.detectorintegration]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::CHIPTESTBOARD ||
det_type == defs::XILINX_CHIPTESTBOARD) {
std::vector<std::string> cmds{"v_a", "v_b", "v_c",
"v_d", "v_io", "v_chip"};
std::vector<defs::dacIndex> indices{
defs::V_POWER_A, defs::V_POWER_B, defs::V_POWER_C,
defs::V_POWER_D, defs::V_POWER_IO, defs::V_POWER_CHIP};
for (size_t iPower = 0; iPower < cmds.size(); ++iPower) {
auto prev_val = det.isPowerEnabled(indices[iPower]);
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 oss;
caller.call("power", {"v_a", "v_b", "off"}, -1, PUT);
caller.call("power", {"v_a", "v_b", "v_c"}, -1, GET, oss);
REQUIRE(oss.str() == "power [v_a, v_b, v_c] [on, off, on]\n");
}
{ // power chip
caller.call("powerchip", {"1"}, -1, PUT);
std::ostringstream oss;
caller.call("power", {"v_a", "v_b", "v_c", "v_d", "v_io"}, -1,
GET, oss);
REQUIRE(oss.str() == "power [v_a, v_b, v_c, v_d, v_io] on\n");
}
for (int imod = 0; imod != det.size(); ++imod) {
det.setPowerEnabled(std::vector{indices[iPower]},
prev_val[imod], {imod});
}
}
} else {
REQUIRE_THROWS(caller.call("power", {"v_a"}, -1, GET));
}
}
TEST_CASE("vm_a", "[.detectorintegration]") {
Detector det;
Caller caller(&det);
@@ -1548,8 +1548,10 @@ TEST_CASE("powerchip", "[.detectorintegration]") {
if (det_type == defs::JUNGFRAU || det_type == defs::MOENCH ||
det_type == defs::MYTHEN3 || det_type == defs::GOTTHARD2 ||
det_type == defs::XILINX_CHIPTESTBOARD) {
auto prev_val = det.getPowerChip();
det_type == defs::XILINX_CHIPTESTBOARD ||
det_type == defs::CHIPTESTBOARD) {
auto prev_val =
det.getPowerChip().tsquash("Inconsistent power chip values");
{
std::ostringstream oss;
caller.call("powerchip", {"1"}, -1, PUT, oss);
@@ -1583,7 +1585,7 @@ TEST_CASE("powerchip", "[.detectorintegration]") {
REQUIRE(oss.str() == "powerchip 0\n");
}
for (int i = 0; i != det.size(); ++i) {
det.setPowerChip(prev_val[i], {i});
det.setPowerChip(prev_val, {i});
if (det_type == defs::XILINX_CHIPTESTBOARD) {
det.configureTransceiver();
}
+2
View File
@@ -49,6 +49,7 @@ std::string ToString(const defs::timingInfoDecoder s);
std::string ToString(const defs::collectionMode s);
std::string ToString(bool value);
std::string ToString(bool value, defs::boolFormat format);
std::string ToString(const slsDetectorDefs::xy &coord);
std::ostream &operator<<(std::ostream &os, const slsDetectorDefs::xy &coord);
@@ -335,6 +336,7 @@ template <> uint32_t StringTo(const std::string &s);
template <> uint64_t StringTo(const std::string &s);
template <> int StringTo(const std::string &s);
template <> bool StringTo(const std::string &s);
bool StringTo(const std::string &s, defs::boolFormat format);
template <> int64_t StringTo(const std::string &s);
/** For types with a .str() method use this for conversion */
@@ -104,6 +104,8 @@ class slsDetectorDefs {
/** return values */
enum { OK, FAIL };
enum boolFormat { TrueFalse, OnOff, OneZero };
/** staus mask */
enum runStatus {
IDLE,
@@ -301,6 +301,8 @@ enum detFuncs {
F_SET_PATTERN_WAIT_INTERVAL,
F_SPI_READ,
F_SPI_WRITE,
F_GET_POWER,
F_SET_POWER,
NUM_DET_FUNCTIONS,
RECEIVER_ENUM_START = 512, /**< detector function should not exceed this
@@ -713,6 +715,9 @@ const char* getFunctionNameFromEnum(enum detFuncs func) {
case F_SET_PATTERN_WAIT_INTERVAL: return "F_SET_PATTERN_WAIT_INTERVAL";
case F_SPI_READ: return "F_SPI_READ";
case F_SPI_WRITE: return "F_SPI_WRITE";
case F_GET_POWER: return "F_GET_POWER";
case F_SET_POWER: return "F_SET_POWER";
case NUM_DET_FUNCTIONS: return "NUM_DET_FUNCTIONS";
case RECEIVER_ENUM_START: return "RECEIVER_ENUM_START";
+42 -7
View File
@@ -7,6 +7,17 @@ namespace sls {
std::string ToString(bool value) { return value ? "1" : "0"; }
std::string ToString(bool value, defs::boolFormat format) {
switch (format) {
case defs::boolFormat::TrueFalse:
return value ? "true" : "false";
case defs::boolFormat::OnOff:
return value ? "on" : "off";
default:
return value ? "1" : "0";
}
}
std::string ToString(const slsDetectorDefs::xy &coord) {
std::ostringstream oss;
oss << '[' << coord.x << ", " << coord.y << ']';
@@ -1189,14 +1200,38 @@ template <> int StringTo(const std::string &s) {
}
template <> bool StringTo(const std::string &s) {
int i = std::stoi(s, nullptr, 10);
switch (i) {
case 0:
return false;
case 1:
return true;
return StringTo(s, defs::boolFormat::OneZero);
}
bool StringTo(const std::string &s, defs::boolFormat format) {
switch (format) {
case defs::boolFormat::TrueFalse: {
if (s == "true")
return true;
if (s == "false")
return false;
throw RuntimeError("Unknown boolean. Expecting 'true' or 'false'.");
}
case defs::boolFormat::OnOff: {
if (s == "on")
return true;
if (s == "off")
return false;
throw RuntimeError("Unknown boolean. Expecting 'on' or 'off'.");
}
case defs::boolFormat::OneZero: {
int i = std::stoi(s, nullptr, 10);
switch (i) {
case 0:
return false;
case 1:
return true;
default:
throw RuntimeError("Unknown boolean. Expecting 0 or 1.");
}
}
default:
throw RuntimeError("Unknown boolean. Expecting be 0 or 1.");
throw RuntimeError("Unknown boolean format.");
}
}
+18
View File
@@ -26,6 +26,24 @@ TEST_CASE("Convert string to bool", "[support]") {
REQUIRE(StringTo<bool>("0") == false);
}
TEST_CASE("Convert bool format to string", "[support]") {
REQUIRE(ToString(true, defs::boolFormat::TrueFalse) == "true");
REQUIRE(ToString(false, defs::boolFormat::TrueFalse) == "false");
REQUIRE(ToString(true, defs::boolFormat::OnOff) == "on");
REQUIRE(ToString(false, defs::boolFormat::OnOff) == "off");
REQUIRE(ToString(true, defs::boolFormat::OneZero) == "1");
REQUIRE(ToString(false, defs::boolFormat::OneZero) == "0");
}
TEST_CASE("Convert string to bool format", "[support]") {
REQUIRE(StringTo("1", defs::boolFormat::OneZero) == true);
REQUIRE(StringTo("0", defs::boolFormat::OneZero) == false);
REQUIRE(StringTo("true", defs::boolFormat::TrueFalse) == true);
REQUIRE(StringTo("false", defs::boolFormat::TrueFalse) == false);
REQUIRE(StringTo("on", defs::boolFormat::OnOff) == true);
REQUIRE(StringTo("off", defs::boolFormat::OnOff) == false);
}
TEST_CASE("Integer conversions", "[support]") {
REQUIRE(ToString(0) == "0");
REQUIRE(ToString(1) == "1");