diff --git a/slsDetectorServers/gotthard2DetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/gotthard2DetectorServer/slsDetectorFunctionList.c index c85348339..3080fc73d 100644 --- a/slsDetectorServers/gotthard2DetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/gotthard2DetectorServer/slsDetectorFunctionList.c @@ -503,7 +503,7 @@ int readConfigFile() { memset(line, 0, LZ); char command[LZ]; - int nadcRead = 0; + int nAdcTotal = 0; // keep reading a line while (fgets(line, LZ, fd)) { @@ -617,7 +617,7 @@ int readConfigFile() { break; } // validations - if (value > ASIC_ADC_MAX_VAL) { + if (value < 0 || value > ASIC_ADC_MAX_VAL) { sprintf(initErrorMessage, "Could not configure adc from on-board server config " "file. Invalid value (max 0x%x). Line:[%s].\n", @@ -625,28 +625,23 @@ int readConfigFile() { break; } - int chipmin = 0; - int chipmax = NCHIP; - int adcmin = 0; - int adcmax = NADC; - - // specific chip - if (ichip != -1) { - chipmin = ichip; - chipmax = ichip + 1; - } - // specific adc - if (iadc != -1) { - adcmin = iadc; - adcmax = iadc + 1; + if (setADCConfiguration(ichip, iadc, value) == FAIL) { + sprintf(initErrorMessage, + "Could not configure adc from on-board server " + "config file. Line:[%s].\n", + line); + break; } - for (int i = chipmin; i < chipmax; ++i) { - for (int j = adcmin; j < adcmax; ++j) { - adcConfiguration[i][j] = (uint8_t)value; - ++nadcRead; - } + // to ensure all adcs are configured at start up + int nadc = 1; + if (iadc == -1) { + nadc = NADC; } + if (ichip == -1) { + nadc *= NCHIP; + } + nAdcTotal += nadc; } // vchip command @@ -762,17 +757,11 @@ int readConfigFile() { fclose(fd); if (!strlen(initErrorMessage)) { - if (nadcRead != NADC * NCHIP) { + if (nAdcTotal != NADC * NCHIP) { sprintf(initErrorMessage, "Could not configure adc from on-board server config file. " "Insufficient adcconf commands. Read %d, expected %d\n", - nadcRead, NADC * NCHIP); - } - } - for (int i = 0; i < NCHIP; ++i) { - for (int j = 0; j < NADC; ++j) { - LOG(logDEBUG2, - ("adc read %d %d: 0x%02hhx\n", i, j, adcConfiguration[i][j])); + nAdcTotal, NADC * NCHIP); } } @@ -1934,24 +1923,52 @@ int setVetoFile(int chipIndex, int *gainIndices, int *values) { return configureASICVetoReference(chipIndex, values); } -int configureSingleADCDriver(int chipIndex) { - LOG(logINFO, ("Configuring ADC for %s chips [chipIndex:%d Burst Mode:%d]\n", - chipIndex == -1 ? "All" : "Single", chipIndex, burstMode)); +int setADCConfiguration(int chipIndex, int adcIndex, int value) { + LOG(logINFO, ("Configuring ADC [chipIndex:%d, adcIndex:%d, value:0x%x]\n", + chipIndex, adcIndex, value)); + // validations + if (chipIndex < -1 || chipIndex >= NCHIP) { + LOG(logERROR, ("Invalid chip index %d\n", chipIndex)); + return FAIL; + } + if (adcIndex < -1 || adcIndex >= NADC) { + LOG(logERROR, ("Invalid adc index %d\n", adcIndex)); + return FAIL; + } + // validations + if (value < 0 || value > ASIC_ADC_MAX_VAL) { + LOG(logERROR, ("Invalid value 0x%x\n", value)); + return FAIL; + } + int chipmin = 0; + int chipmax = NCHIP; + int adcmin = 0; + int adcmax = NADC; + // specific chip + if (chipIndex != -1) { + chipmin = chipIndex; + chipmax = chipIndex + 1; + } + // specific adc + if (adcIndex != -1) { + adcmin = adcIndex; + adcmax = adcIndex + 1; + } + // update values + for (int i = chipmin; i < chipmax; ++i) { + for (int j = adcmin; j < adcmax; ++j) { + adcConfiguration[i][j] = (uint8_t)value; + LOG(logDEBUG1, + ("Value [%d][%d]: 0x%02hhx\n", i, j, adcConfiguration[i][j])); + } + } + // single chip configuration int ind = chipIndex; + // all chips, take the first one as all equal if (ind == -1) { ind = 0; } - uint8_t values[NADC]; - memcpy(values, adcConfiguration + ind * NADC, NADC); - - // change adc values if continuous mode - for (int i = 0; i < NADC; ++i) { - if (burstMode == BURST_OFF) { - values[i] |= ASIC_CONTINUOUS_MODE_MSK; - } - LOG(logDEBUG2, ("Value %d: 0x%02hhx\n", i, values[i])); - } const int lenDataBitsPerADC = ASIC_ADC_MAX_BITS; // 7 const int lenBits = lenDataBitsPerADC * NADC; // 224 @@ -1966,8 +1983,9 @@ int configureSingleADCDriver(int chipIndex) { for (int ich = 0; ich < NADC; ++ich) { // loop through all bits in a value for (int iBit = 0; iBit < lenDataBitsPerADC; ++iBit) { - commandBytes[offset++] = - ((values[ich] >> (lenDataBitsPerADC - 1 - iBit)) & 0x1); + commandBytes[offset++] = ((adcConfiguration[ind][ich] >> + (lenDataBitsPerADC - 1 - iBit)) & + 0x1); } } @@ -1994,29 +2012,46 @@ int configureSingleADCDriver(int chipIndex) { return OK; } -int configureADC() { - LOG(logINFO, ("Configuring ADC \n")); +int getADCConfiguration(int chipIndex, int adcIndex) { + // already validated at tcp interface + if (chipIndex < -1 || chipIndex >= NCHIP) { + LOG(logERROR, ("Invalid chip index %d\n", chipIndex)); + return -1; + } + if (adcIndex < -1 || adcIndex >= NADC) { + LOG(logERROR, ("Invalid adc index %d\n", adcIndex)); + return -1; + } + int chipmin = 0; + int chipmax = NCHIP; + int adcmin = 0; + int adcmax = NADC; + // specific chip + if (chipIndex != -1) { + chipmin = chipIndex; + chipmax = chipIndex + 1; + } + // specific adc + if (adcIndex != -1) { + adcmin = adcIndex; + adcmax = adcIndex + 1; + } + int val = adcConfiguration[chipmin][adcmin]; - int equal = 1; - for (int i = 0; i < NADC; ++i) { - int val = adcConfiguration[0][i]; - for (int j = 1; j < NCHIP; ++j) { - if (adcConfiguration[j][i] != val) { - equal = 0; - break; + // ensure same values for chip and adc in question + for (int i = chipmin; i < chipmax; ++i) { + for (int j = adcmin; j < adcmax; ++j) { + if (adcConfiguration[i][j] != val) { + LOG(logINFO, + ("\tADC configuration 0x%x at [%d][%d] differs from 0x%x " + "at " + "[%d][%d], returning -1\n", + adcConfiguration[i][j], i, j, val, chipmin, adcmin)); + return -1; } } } - if (equal) { - return configureSingleADCDriver(-1); - } else { - for (int i = 0; i < NCHIP; ++i) { - if (configureSingleADCDriver(i) == FAIL) { - return FAIL; - } - } - } - return OK; + return val; } int setBurstModeinFPGA(enum burstMode value) { @@ -2121,20 +2156,20 @@ int setBurstMode(enum burstMode burst) { } } LOG(logINFO, ("\tDone Updating registers\n")) - return configureASICGlobalSettings(); } int configureASICGlobalSettings() { - LOG(logINFO, ("\tSetting %s Mode in Chip\n", - burstMode == BURST_OFF ? "Continuous" : "Burst")); int modeValue = burstMode ? ASIC_GLOBAL_BURST_VALUE : ASIC_GLOBAL_CONT_VALUE; int value = ((modeValue << ASIC_GLOBAL_MODE_OFST) & ASIC_GLOBAL_MODE_MSK) | ((filter << ASIC_FILTER_OFST) & ASIC_FILTER_MSK) | ((cdsGain << ASIC_CDS_GAIN_OFST) & ASIC_CDS_GAIN_MSK); - LOG(logINFO, ("\tsetting value:0x%x (mode:%d, filter:%d, cdsgain:%d)\n", - value, modeValue, filter, cdsGain)); + LOG(logINFO, + ("\tSending Global Chip settings:0x%x (mode:%d(%s), filter:%d, " + "cdsgain:%d)\n", + value, modeValue, (burstMode == BURST_OFF ? "Continuous" : "Burst"), + filter, cdsGain)); const int padding = 6; // due to address (4) to make it byte aligned const int lenTotalBits = padding + ASIC_GLOBAL_SETT_MAX_BITS + @@ -2172,7 +2207,7 @@ int configureASICGlobalSettings() { return FAIL; } - return configureADC(); + return OK; } enum burstMode getBurstMode() { diff --git a/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h b/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h index f86431a4b..829b69fc0 100644 --- a/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h +++ b/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h @@ -507,8 +507,8 @@ int setVetoPhoton(int chipIndex, int gainIndex, int *values); int configureASICVetoReference(int chipIndex, int *values); int getVetoPhoton(int chipIndex, int *retvals); int setVetoFile(int chipIndex, int *gainIndices, int *values); -int configureSingleADCDriver(int chipIndex); -int configureADC(); +int setADCConfiguration(int chipIndex, int adcIndex, int value); +int getADCConfiguration(int chipIndex, int adcIndex); int setBurstModeinFPGA(enum burstMode value); int setBurstMode(enum burstMode burst); int configureASICGlobalSettings(); diff --git a/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h b/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h index cc0f1ba52..8efddd04f 100644 --- a/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h +++ b/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h @@ -233,4 +233,6 @@ int get_cds_gain(int); int set_cds_gain(int); int get_filter(int); int set_filter(int); -int set_veto_file(int); \ No newline at end of file +int set_veto_file(int); +int get_adc_config(int); +int set_adc_config(int); diff --git a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c index 81e8b95f5..c892c21c0 100644 --- a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c +++ b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c @@ -351,6 +351,8 @@ void function_table() { flist[F_GET_FILTER] = &get_filter; flist[F_SET_FILTER] = &set_filter; flist[F_SET_VETO_FILE] = &set_veto_file; + flist[F_GET_ADC_CONFIGURATION] = &get_adc_config; + flist[F_SET_ADC_CONFIGURATION] = &set_adc_config; // check if (NUM_DET_FUNCTIONS >= RECEIVER_ENUM_START) { @@ -7819,4 +7821,108 @@ int set_veto_file(int file_des) { } #endif return Server_SendResult(file_des, INT32, NULL, 0); -} \ No newline at end of file +} + +int get_adc_config(int file_des) { + ret = OK; + memset(mess, 0, sizeof(mess)); + int args[2] = {-1, -1}; + int retval = -1; + + if (receiveData(file_des, args, sizeof(args), INT32) < 0) + return printSocketReadError(); + LOG(logDEBUG1, ("Getting adc configuration [chipIndex:%d, adcIndex:%d]\n", + args[0], args[1])); + +#ifndef GOTTHARD2D + functionNotImplemented(); +#else + // get only + int chipIndex = args[0]; + int adcIndex = args[1]; + if (chipIndex < -1 || chipIndex >= NCHIP) { + ret = FAIL; + sprintf(mess, + "Could not get adc configuration. Invalid chip index %d\n", + chipIndex); + LOG(logERROR, (mess)); + } else if (adcIndex < -1 || adcIndex >= NADC) { + ret = FAIL; + sprintf(mess, "Could not get adc configuration. Invalid adc index %d\n", + adcIndex); + LOG(logERROR, (mess)); + } else { + retval = getADCConfiguration(chipIndex, adcIndex); + LOG(logDEBUG1, ("adc config retval: %u\n", retval)); + if (retval == -1) { + ret = FAIL; + sprintf(mess, + "Could not get a single adc configuration. Different " + "values for " + "selected adc (%d) and chip (%d) range.\n", + chipIndex, adcIndex); + LOG(logERROR, (mess)); + } + } +#endif + return Server_SendResult(file_des, INT32, &retval, sizeof(retval)); +} + +int set_adc_config(int file_des) { + ret = OK; + memset(mess, 0, sizeof(mess)); + int args[3] = {-1, -1, -1}; + + if (receiveData(file_des, args, sizeof(args), INT32) < 0) + return printSocketReadError(); + LOG(logDEBUG1, + ("Setting adc configuration [chipIndex:%d, adcIndex:%d, value:0x%x]\n", + args[0], args[1], args[2])); + +#ifndef GOTTHARD2D + functionNotImplemented(); +#else + // only set + if (Server_VerifyLock() == OK) { + int chipIndex = args[0]; + int adcIndex = args[1]; + int value = args[2]; + if (chipIndex < -1 || chipIndex >= NCHIP) { + ret = FAIL; + sprintf(mess, + "Could not get adc configuration. Invalid chip index %d. " + "Options: [-1 to %d]\n", + chipIndex, NCHIP); + LOG(logERROR, (mess)); + } else if (adcIndex < -1 || adcIndex >= NADC) { + ret = FAIL; + sprintf(mess, + "Could not get adc configuration. Invalid adc index %d. " + "Options: [-1 to %d]\n", + adcIndex, NADC); + LOG(logERROR, (mess)); + } else if (value < 0 || value > ASIC_ADC_MAX_VAL) { + ret = FAIL; + sprintf(mess, + "Could not get adc configuration. Invalid value 0x%x. " + "Options: [0 to 0x%x]\n", + value, ASIC_ADC_MAX_VAL); + LOG(logERROR, (mess)); + } else { + ret = setADCConfiguration(chipIndex, adcIndex, value); + if (ret == FAIL) { + sprintf(mess, + "Could not set adc configuration in chip (chipIndex: " + "%d, adcIndex: %d, value:0x%x).\n", + chipIndex, adcIndex, value); + LOG(logERROR, (mess)); + } else { + int retval = getADCConfiguration(chipIndex, adcIndex); + LOG(logDEBUG1, ("adc config retval: %u\n", retval)); + validate(value, retval, "configure adc", HEX); + } + } + } +#endif + return Server_SendResult(file_des, INT32, NULL, 0); +} diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index d9c38c950..f124f0709 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -1023,6 +1023,14 @@ class Detector { /** [Gotthard2] */ void setVeto(const bool enable, Positions pos = {}); + /** [Gotthard2] */ + Result getADCConfiguration(const int chipIndex, const int adcIndex, + Positions pos = {}) const; + + /** [Gotthard2] */ + void setADCConfiguration(const int chipIndex, const int adcIndex, + const int value, Positions pos = {}); + /************************************************** * * * Mythen3 Specific * diff --git a/slsDetectorSoftware/src/CmdProxy.cpp b/slsDetectorSoftware/src/CmdProxy.cpp index 9f00b1966..359f1e9c1 100644 --- a/slsDetectorSoftware/src/CmdProxy.cpp +++ b/slsDetectorSoftware/src/CmdProxy.cpp @@ -1738,6 +1738,37 @@ std::string CmdProxy::BurstMode(int action) { return os.str(); } +std::string CmdProxy::ConfigureADC(int action) { + std::ostringstream os; + os << cmd << ' '; + if (action == defs::HELP_ACTION) { + os << "[chip index 0-10, -1 for all] [adc index 0-31, -1 for all] [12 " + "bit configuration value in hex]\n\t[Gotthard2] Sets " + "configuration for specific chip and adc, but configures 1 chip " + "(all adcs for that chip) at a time." + << '\n'; + } else if (action == defs::GET_ACTION) { + if (args.size() != 2) { + WrongNumberOfParameters(2); + } + auto t = det->getADCConfiguration(StringTo(args[0]), + StringTo(args[1])); + os << OutStringHex(t) << '\n'; + } else if (action == defs::PUT_ACTION) { + if (args.size() != 3) { + WrongNumberOfParameters(3); + } + int value = StringTo(args[2]); + det->setADCConfiguration(StringTo(args[0]), StringTo(args[1]), + value, {det_id}); + os << '[' << args[0] << ", " << args[1] << ", " << ToStringHex(value) + << "]\n"; + } else { + throw sls::RuntimeError("Unknown action"); + } + return os.str(); +} + /* Mythen3 Specific */ std::string CmdProxy::Counters(int action) { diff --git a/slsDetectorSoftware/src/CmdProxy.h b/slsDetectorSoftware/src/CmdProxy.h index fc09ae484..f9944c40a 100644 --- a/slsDetectorSoftware/src/CmdProxy.h +++ b/slsDetectorSoftware/src/CmdProxy.h @@ -841,6 +841,7 @@ class CmdProxy { {"currentsource", &CmdProxy::currentsource}, {"timingsource", &CmdProxy::timingsource}, {"veto", &CmdProxy::veto}, + {"confadc", &CmdProxy::ConfigureADC}, /* Mythen3 Specific */ {"counters", &CmdProxy::Counters}, @@ -1018,6 +1019,7 @@ class CmdProxy { std::string VetoReference(int action); std::string VetoFile(int action); std::string BurstMode(int action); + std::string ConfigureADC(int action); /* Mythen3 Specific */ std::string Counters(int action); std::string GateDelay(int action); diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index cc63db8d9..6d86a2714 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -1350,6 +1350,19 @@ void Detector::setVeto(bool enable, Positions pos) { pimpl->Parallel(&Module::setVeto, pos, enable); } +Result Detector::getADCConfiguration(const int chipIndex, + const int adcIndex, + Positions pos) const { + return pimpl->Parallel(&Module::getADCConfiguration, pos, chipIndex, + adcIndex); +} + +void Detector::setADCConfiguration(const int chipIndex, const int adcIndex, + const int value, Positions pos) { + pimpl->Parallel(&Module::setADCConfiguration, pos, chipIndex, adcIndex, + value); +} + // Mythen3 Specific Result Detector::getCounterMask(Positions pos) const { diff --git a/slsDetectorSoftware/src/Module.cpp b/slsDetectorSoftware/src/Module.cpp index d62d47a8d..6d431de47 100644 --- a/slsDetectorSoftware/src/Module.cpp +++ b/slsDetectorSoftware/src/Module.cpp @@ -1645,6 +1645,17 @@ void Module::setVeto(bool enable) { sendToDetector(F_SET_VETO, static_cast(enable), nullptr); } +int Module::getADCConfiguration(const int chipIndex, const int adcIndex) { + int args[]{chipIndex, adcIndex}; + return sendToDetector(F_GET_ADC_CONFIGURATION, args); +} + +void Module::setADCConfiguration(const int chipIndex, const int adcIndex, + int value) { + int args[]{chipIndex, adcIndex, value}; + sendToDetector(F_SET_ADC_CONFIGURATION, args, nullptr); +} + // Mythen3 Specific uint32_t Module::getCounterMask() { diff --git a/slsDetectorSoftware/src/Module.h b/slsDetectorSoftware/src/Module.h index 971bd40ff..d3c4d4fdc 100644 --- a/slsDetectorSoftware/src/Module.h +++ b/slsDetectorSoftware/src/Module.h @@ -386,6 +386,9 @@ class Module : public virtual slsDetectorDefs { void setTimingSource(slsDetectorDefs::timingSourceType value); bool getVeto(); void setVeto(bool enable); + int getADCConfiguration(const int chipIndex, const int adcIndex); + void setADCConfiguration(const int chipIndex, const int adcIndex, + int value); /************************************************** * * diff --git a/slsDetectorSoftware/tests/test-CmdProxy-gotthard2.cpp b/slsDetectorSoftware/tests/test-CmdProxy-gotthard2.cpp index af4baab6c..3ea03d3cc 100644 --- a/slsDetectorSoftware/tests/test-CmdProxy-gotthard2.cpp +++ b/slsDetectorSoftware/tests/test-CmdProxy-gotthard2.cpp @@ -536,4 +536,51 @@ TEST_CASE("veto", "[.cmd][.new]") { } else { REQUIRE_THROWS(proxy.Call("veto", {}, -1, GET)); } +} + +TEST_CASE("confadc", "[.cmd][.new]") { + Detector det; + CmdProxy proxy(&det); + auto det_type = det.getDetectorType().squash(); + + if (det_type == defs::GOTTHARD2) { + int ndet = det.size(); + int nchip = 10; + int nadc = 32; + int prev_val[ndet][nchip][nadc]; + for (int i = 0; i != ndet; ++i) { + for (int j = 0; j != nchip; ++j) { + for (int k = 0; k != nadc; ++k) { + prev_val[i][j][k] = + det.getADCConfiguration(j, k, {i}).squash(); + } + } + } + + REQUIRE_THROWS(proxy.Call("confadc", {"11", "2", "0x3ff"}, -1, + PUT)); // invalid chip index + REQUIRE_THROWS(proxy.Call("confadc", {"-1", "10", "0x3ff"}, -1, + PUT)); // invalid adc index + REQUIRE_THROWS(proxy.Call("confadc", {"-1", "10", "0x1fff"}, -1, + PUT)); // invalid value + { + std::ostringstream oss; + proxy.Call("confadc", {"-1", "-1", "0x11"}, -1, PUT, oss); + REQUIRE(oss.str() == "confadc [-1, -1, 0x11]\n"); + } + { + std::ostringstream oss; + proxy.Call("confadc", {"2", "3"}, -1, GET, oss); + REQUIRE(oss.str() == "confadc 0x11\n"); + } + for (int i = 0; i != ndet; ++i) { + for (int j = 0; j != nchip; ++j) { + for (int k = 0; k != nadc; ++k) { + det.setADCConfiguration(j, k, prev_val[i][j][k], {i}); + } + } + } + } else { + REQUIRE_THROWS(proxy.Call("confadc", {}, -1, GET)); + } } \ No newline at end of file diff --git a/slsSupportLib/include/sls_detector_funcs.h b/slsSupportLib/include/sls_detector_funcs.h index 10f4e2a3e..69288ce4f 100755 --- a/slsSupportLib/include/sls_detector_funcs.h +++ b/slsSupportLib/include/sls_detector_funcs.h @@ -208,6 +208,8 @@ enum detFuncs { F_GET_FILTER, F_SET_FILTER, F_SET_VETO_FILE, + F_GET_ADC_CONFIGURATION, + F_SET_ADC_CONFIGURATION, NUM_DET_FUNCTIONS, RECEIVER_ENUM_START = 256, /**< detector function should not exceed this @@ -514,6 +516,8 @@ const char* getFunctionNameFromEnum(enum detFuncs func) { case F_GET_FILTER: return "F_GET_FILTER"; case F_SET_FILTER: return "F_SET_FILTER"; case F_SET_VETO_FILE: return "F_SET_VETO_FILE"; + case F_SET_ADC_CONFIGURATION: return "F_SET_ADC_CONFIGURATION"; + case F_GET_ADC_CONFIGURATION: return "F_GET_ADC_CONFIGURATION"; case NUM_DET_FUNCTIONS: return "NUM_DET_FUNCTIONS"; case RECEIVER_ENUM_START: return "RECEIVER_ENUM_START";