mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2026-05-18 02:36:51 +02:00
wip: power in client, tests, and fixed server interfaces and ctb implementation, not tested
This commit is contained in:
@@ -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);
|
||||
}
|
||||
@@ -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]
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user