diff --git a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c index 9cee22119..ebb2ec921 100644 --- a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c @@ -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) { diff --git a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.h b/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.h index 7b2a30716..dd142b51d 100644 --- a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.h +++ b/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.h @@ -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); diff --git a/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h b/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h index 493b1638f..749f6514e 100644 --- a/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h +++ b/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h @@ -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); diff --git a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c index 6d12f309e..618dd90b1 100644 --- a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c +++ b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c @@ -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); } \ No newline at end of file diff --git a/slsDetectorSoftware/include/sls/Detector.h b/slsDetectorSoftware/include/sls/Detector.h index c4d5b670f..02033c544 100644 --- a/slsDetectorSoftware/include/sls/Detector.h +++ b/slsDetectorSoftware/include/sls/Detector.h @@ -535,6 +535,9 @@ class Detector { Result 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 getSlowADCList() const; /** [CTB][Xilinx CTB] */ - Result getPower(defs::dacIndex index, Positions pos = {}) const; + Result 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 &indices, + bool enable, Positions pos = {}); /** * [CTB] Options: [0- 4] or [1V, 1.14V, 1.33V, 1.6V, 2V] diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 39706ec56..3346e4046 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -2188,36 +2188,26 @@ std::vector Detector::getSlowADCList() const { defs::SLOW_ADC4, defs::SLOW_ADC5, defs::SLOW_ADC6, defs::SLOW_ADC7}; } -Result 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 Detector::isPowerEnabled(defs::dacIndex index, + Positions pos) const { + std::vector 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 &indices, + bool value, Positions pos) { + std::vector 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 Detector::getADCVpp(bool mV, Positions pos) const { diff --git a/slsDetectorSoftware/src/Module.cpp b/slsDetectorSoftware/src/Module.cpp index 29a51f5b4..bebf7e82d 100644 --- a/slsDetectorSoftware/src/Module.cpp +++ b/slsDetectorSoftware/src/Module.cpp @@ -819,6 +819,25 @@ void Module::setPowerChip(bool on) { sendToDetector(F_POWER_CHIP, static_cast(on)); } +bool Module::isPowerEnabled(defs::dacIndex index) const { + return sendToDetector(F_GET_POWER, index); +} + +void Module::setPowerEnabled(const std::vector &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(value)); + if (client.Receive() == FAIL) { + throw DetectorError("Detector " + std::to_string(moduleIndex) + + " returned error: " + client.readErrorMessage()); + } +} + int Module::getImageTestMode() const { return sendToDetector(F_GET_IMAGE_TEST_MODE); } diff --git a/slsDetectorSoftware/src/Module.h b/slsDetectorSoftware/src/Module.h index 9f75f1765..181355edd 100644 --- a/slsDetectorSoftware/src/Module.h +++ b/slsDetectorSoftware/src/Module.h @@ -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 &indices, + bool value); int getImageTestMode() const; void setImageTestMode(const int value); /* temperature in millidegrees */ diff --git a/slsDetectorSoftware/tests/Caller/test-Caller-chiptestboard.cpp b/slsDetectorSoftware/tests/Caller/test-Caller-chiptestboard.cpp index 22ad78908..0f65e6db3 100644 --- a/slsDetectorSoftware/tests/Caller/test-Caller-chiptestboard.cpp +++ b/slsDetectorSoftware/tests/Caller/test-Caller-chiptestboard.cpp @@ -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 cmds{"v_a", "v_b", "v_c", + "v_d", "v_io", "v_chip"}; + std::vector 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); diff --git a/slsDetectorSoftware/tests/Caller/test-Caller.cpp b/slsDetectorSoftware/tests/Caller/test-Caller.cpp index 93c88713e..5e900d407 100644 --- a/slsDetectorSoftware/tests/Caller/test-Caller.cpp +++ b/slsDetectorSoftware/tests/Caller/test-Caller.cpp @@ -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(); } diff --git a/slsSupportLib/include/sls/ToString.h b/slsSupportLib/include/sls/ToString.h index 5b56fbfc9..c7525a156 100644 --- a/slsSupportLib/include/sls/ToString.h +++ b/slsSupportLib/include/sls/ToString.h @@ -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 */ diff --git a/slsSupportLib/include/sls/sls_detector_defs.h b/slsSupportLib/include/sls/sls_detector_defs.h index a5ccb2566..9e0c80187 100644 --- a/slsSupportLib/include/sls/sls_detector_defs.h +++ b/slsSupportLib/include/sls/sls_detector_defs.h @@ -104,6 +104,8 @@ class slsDetectorDefs { /** return values */ enum { OK, FAIL }; + enum boolFormat { TrueFalse, OnOff, OneZero }; + /** staus mask */ enum runStatus { IDLE, diff --git a/slsSupportLib/include/sls/sls_detector_funcs.h b/slsSupportLib/include/sls/sls_detector_funcs.h index 9296547de..761f78fb0 100755 --- a/slsSupportLib/include/sls/sls_detector_funcs.h +++ b/slsSupportLib/include/sls/sls_detector_funcs.h @@ -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"; diff --git a/slsSupportLib/src/ToString.cpp b/slsSupportLib/src/ToString.cpp index bfd1220fb..8ff889117 100644 --- a/slsSupportLib/src/ToString.cpp +++ b/slsSupportLib/src/ToString.cpp @@ -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."); } } diff --git a/slsSupportLib/tests/test-ToString.cpp b/slsSupportLib/tests/test-ToString.cpp index 76ee87245..3d35004e8 100644 --- a/slsSupportLib/tests/test-ToString.cpp +++ b/slsSupportLib/tests/test-ToString.cpp @@ -26,6 +26,24 @@ TEST_CASE("Convert string to bool", "[support]") { REQUIRE(StringTo("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");