diff --git a/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h b/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h index 564642e91..4ce30de56 100644 --- a/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h +++ b/slsDetectorServers/slsDetectorServer/include/slsDetectorServer_funcs.h @@ -221,4 +221,8 @@ int get_exptime_all_gates(int); int get_gate_delay_all_gates(int); int get_veto(int); int set_veto(int); -int set_pattern(int); \ No newline at end of file +int set_pattern(int); +int get_scan(int); +int get_num_scan_steps(int); +int disable_scan(int); +int enable_scan(int); diff --git a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c index d2a993028..b20a26981 100644 --- a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c +++ b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c @@ -50,6 +50,13 @@ int detectorId = -1; // Local variables int (*flist[NUM_DET_FUNCTIONS])(int); +// scan variables +int scan = 0; +int numScanSteps = 0; +int *scanSteps = NULL; +enum DACINDEX scanDac = 0; +int scanTrimbits = 0; + /* initialization functions */ int printSocketReadError() { @@ -332,7 +339,10 @@ void function_table() { flist[F_GET_VETO] = &get_veto; flist[F_SET_VETO] = &set_veto; flist[F_SET_PATTERN] = &set_pattern; - + flist[F_GET_SCAN] = get_scan; + flist[F_GET_NUM_SCAN_STEPS] = get_num_scan_steps; + flist[F_DISABLE_SCAN] = disable_scan; + flist[F_ENABLE_SCAN] = enable_scan; // check if (NUM_DET_FUNCTIONS >= RECEIVER_ENUM_START) { LOG(logERROR, ("The last detector function enum has reached its " @@ -1707,16 +1717,41 @@ int start_acquisition(int file_des) { strcat(mess, configureMessage); LOG(logERROR, (mess)); } else { - ret = startStateMachine(); - if (ret == FAIL) { + int times = 1; + if (scan) { + times = numScanSteps; + } + for (int i = 0; i != times; ++i) { + if (scanTrimbits) { +#ifdef EIGERD + setAllTrimbits(scanSteps[i]); +#else + LOG(logERROR, ("trimbit scan not implemented!\n")); +#endif + } else { + setDac(scanDac, scanSteps[i], 0); + int retval = getDAC(scanDac, 0); + if (abs(retval - val) > 5) { + ret = FAIL; + sprintf(mess, "Setting dac %d : wrote %d but read %d\n", + dacIndex, scanSteps[i], retval); + LOG(logERROR, (mess)); + break; + } + } + ret = startStateMachine(); + if (ret == FAIL) { #if defined(CHIPTESTBOARDD) || defined(MOENCHD) || defined(VIRTUAL) - sprintf(mess, + sprintf( + mess, "Could not start acquisition. Could not create udp " "socket in server. Check udp_dstip & udp_dstport.\n"); #else - sprintf(mess, "Could not start acquisition\n"); + sprintf(mess, "Could not start acquisition\n"); #endif - LOG(logERROR, (mess)); + LOG(logERROR, (mess)); + break; + } } } LOG(logDEBUG2, ("Starting Acquisition ret: %d\n", ret)); @@ -1866,8 +1901,14 @@ int get_num_frames(int file_des) { int64_t retval = -1; // get only - retval = getNumFrames(); - LOG(logDEBUG1, ("retval num frames %lld\n", (long long int)retval)); + if (!scan) { + retval = getNumFrames(); + LOG(logDEBUG1, ("retval num frames %lld\n", (long long int)retval)); + } else { + retval = numScanSteps; + LOG(logDEBUG1, ("retval num frames (num scan steps) %lld\n", + (long long int)retval)); + } return Server_SendResult(file_des, INT64, &retval, sizeof(retval)); } @@ -1882,22 +1923,26 @@ int set_num_frames(int file_des) { // only set if (Server_VerifyLock() == OK) { + // only set number of frames if normal mode (not scan) + if (!scan) { #ifdef GOTTHARD2D - // validate #frames in burst mode - if (getBurstMode() != BURST_OFF && arg > MAX_FRAMES_IN_BURST_MODE) { - ret = FAIL; - sprintf(mess, - "Could not set number of frames %lld. Must be <= %d in " - "burst mode.\n", - (long long unsigned int)arg, MAX_FRAMES_IN_BURST_MODE); - LOG(logERROR, (mess)); - } + // validate #frames in burst mode + if (getBurstMode() != BURST_OFF && arg > MAX_FRAMES_IN_BURST_MODE) { + ret = FAIL; + sprintf(mess, + "Could not set number of frames %lld. Must be <= %d in " + "burst mode.\n", + (long long unsigned int)arg, MAX_FRAMES_IN_BURST_MODE); + LOG(logERROR, (mess)); + } #endif - if (ret == OK) { - setNumFrames(arg); - int64_t retval = getNumFrames(); - LOG(logDEBUG1, ("retval num frames %lld\n", (long long int)retval)); - validate64(arg, retval, "set number of frames", DEC); + if (ret == OK) { + setNumFrames(arg); + int64_t retval = getNumFrames(); + LOG(logDEBUG1, + ("retval num frames %lld\n", (long long int)retval)); + validate64(arg, retval, "set number of frames", DEC); + } } } return Server_SendResult(file_des, INT64, NULL, 0); @@ -7453,4 +7498,159 @@ int set_pattern(int file_des) { } #endif return Server_SendResult(file_des, INT32, NULL, 0); -} \ No newline at end of file +} + +int get_scan(int file_des) { + ret = OK; + memset(mess, 0, sizeof(mess)); + int retval = -1; + + LOG(logDEBUG1, ("Getting scan\n")); + + // get only + retval = scan; + LOG(logDEBUG1, ("scan mode retval: %u\n", retval)); + + return Server_SendResult(file_des, INT32, &retval, sizeof(retval)); +} + +int get_num_scan_steps(int file_des) { + ret = OK; + memset(mess, 0, sizeof(mess)); + int retval = -1; + + LOG(logDEBUG1, ("Getting num scan steps\n")); + + // get only + retval = numScanSteps; + LOG(logDEBUG1, ("num scan steps retval: %u\n", retval)); + + return Server_SendResult(file_des, INT32, &retval, sizeof(retval)); +} + +int disable_scan(int file_des) { + ret = OK; + memset(mess, 0, sizeof(mess)); + + // only set + if (Server_VerifyLock() == OK) { + LOG(logINFOBLUE, ("Disabling scan\n")); + scan = 0; + scanTrimbits = 0; + numScanSteps = 0; + if (scanSteps != NULL) { + free(scanSteps); + scanSteps = NULL; + } + setNumFrames(1); + int64_t retval = getNumFrames(); + LOG(logDEBUG1, ("retval num frames %lld\n", (long long int)retval)); + validate64(arg, retval, "set number of frames", DEC); + } + return Server_SendResult(file_des, INT32, NULL, 0); +} + +int enable_scan(int file_des) { + ret = OK; + memset(mess, 0, sizeof(mess)); + int args[4] = {-1, -1, -1, -1}; + + if (receiveData(file_des, args, sizeof(args), INT32) < 0) + return printSocketReadError(); + + // only set + if (Server_VerifyLock() == OK) { + int startOffset = args[1]; + int endOffset = args[2]; + int stepSize = args[3]; + scanTrimbits = 0; + // trimbit scan + if (args[0] == TRIMBIT_SCAN) { +#ifdef EIGERD + if (startOffset < 0 || startOffset > MAX_TRIMBITS_VALUE || + endOffset < 0 || endOffset > MAX_TRIMBITS_VALUE) { + ret = FAIL; + sprintf(mess, "Invalid trimbits scan values\n"); + LOG(logERROR, (mess)); + } else { + scanTrimbits = 1; + // changes settings to undefined + setSettings(UNDEFINED); + LOG(logERROR, + ("Settings has been changed to undefined (change all " + "trimbits)\n")); + } +#else + ret = FAIL; + sprintf(mess, "Cannot enable trimbit scan. Not implemented for " + "this detector\n"); + LOG(logERROR, (mess)); +#endif + } else { + ret = converttodac(args[0], &scanDac); + if (ret == FAIL) { + sprintf(mess, + "Cannot enable scan. Dac index %d not implemented for " + "this detector\n", + args[0]); + LOG(logERROR, (mess)); + } else if (startOffset < 0 || startOffset > getMaxDacSteps() || + endOffset < 0 || endOffset > getMaxDacSteps()) { + ret = FAIL; + sprintf(mess, "Invalid dac scan values\n"); + LOG(logERROR, (mess)); + } +#if defined(CHIPTESTBOARDD) || defined(MOENCHD) + else if (checkVLimitDacCompliant(startOffset) == FAIL || + checkVLimitDacCompliant(endOffset) == FAIL) { + ret = FAIL; + sprintf(mess, + "Invalid scan dac values." + "Exceeds voltage limit %d.\n", + getVLimit()); + LOG(logERROR, (mess)); + } +#endif +#ifdef EIGERD + if (ret == OK) { + // changing dac changes settings to undefined + switch (scanDac) { + case E_VCMP_LL: + case E_VCMP_LR: + case E_VCMP_RL: + case E_VCMP_RR: + case E_VRPREAMP: + case E_VCP: + setSettings(UNDEFINED); + LOG(logERROR, ("Settings has been changed " + "to undefined (changed specific dacs)\n")); + break; + default: + break; + } + } +#endif + } + if (ret == OK) { + scan = 1; + numScanSteps = ((startOffset - endOffset) / stepSize) + 1; + if (scanSteps != NULL) { + free(scanSteps); + } + scanSteps = malloc(numScanSteps * sizeof(int)); + for (int i = 0; i != numScanSteps; ++i) { + scanSteps[i] = startOffset + i * stepSize; + } + + LOG(logINFOBLUE, + ("Enabling scan for dac[%d], start[%d], end[%d], " + "stepsize[%d], nsteps[%d]\n", + ind, startOffset, endOffset, stepSize, numScanSteps)); + setNumFrames(1); + int64_t retval = getNumFrames(); + LOG(logDEBUG1, ("retval num frames %lld\n", (long long int)retval)); + validate64(arg, retval, "set number of frames", DEC); + } + } + return Server_SendResult(file_des, INT32, NULL, 0); +} diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 990517233..7d1e00df7 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -394,6 +394,18 @@ class Detector { /** [Eiger] Sends an internal software trigger to the detector */ void sendSoftwareTrigger(Positions pos = {}); + Result getScan(Positions pos = {}) const; + + Result getNumberOfScanSteps(Positions pos = {}) const; + + /** also sets number of frames to 1 */ + void disableScan(); + + /** scan dac, [Eiger] use TRIMBIT_SCAN for scanning trimbits, also sets + * number of frames to number of steps in receiver */ + void enableScan(const defs::dacIndex dac, const int start_offset, + const int end_offset, const int step_size); + // TODO: remove resetframescaught in receiver /************************************************** diff --git a/slsDetectorSoftware/src/CmdProxy.cpp b/slsDetectorSoftware/src/CmdProxy.cpp index c79485fd7..05274d7ff 100644 --- a/slsDetectorSoftware/src/CmdProxy.cpp +++ b/slsDetectorSoftware/src/CmdProxy.cpp @@ -178,7 +178,7 @@ std::string CmdProxy::VirtualServer(int action) { return os.str(); } -std::string CmdProxy::acquire(int action) { +std::string CmdProxy::Acquire(int action) { std::ostringstream os; if (action == defs::HELP_ACTION) { os << cmd << " - Acquire the number of frames set up.\n"; @@ -991,6 +991,41 @@ std::string CmdProxy::DetectorStatus(int action) { return os.str(); } +std::string CmdProxy::Scan(int action) { + std::ostringstream os; + os << cmd << ' '; + if (action == defs::HELP_ACTION) { + os << "[dac_name|0|trimbit_scan] [start_val] [stop_val] " + "[step_size]\n\tConfigures to scan " + "dac. Must acquire after this. To cancel the scan configuration " + "set dac to '0' without further arguments." + "\n\t[Eiger]Use trimbit_scan as dac name for a trimbit scan." + << '\n'; + } else if (action == defs::GET_ACTION) { + if (args.size() != 0) { + WrongNumberOfParameters(0); + } + auto t = det->getScan(); + os << OutString(t) << '\n'; + } else if (action == defs::PUT_ACTION) { + if (args.size() == 1) { + det->disableScan(); + os << "scan disabled" << '\n'; + } else if (args.size() != 4) { + WrongNumberOfParameters(4); + } else { + auto t = det->enableScan( + StringTo(args[0]), StringTo(args[1]), + StringTo(args[2]), StringTo(args[3])); + auto nsteps = det->getNumScanSteps().tsquash( + "inconsistent number of scan steps"); + os << "scan enabled for " << nsteps << "steps" << '\n'; + } + } else { + throw sls::RuntimeError("Unknown action"); + } + return os.str(); +} /* Network Configuration (Detector<->Receiver) */ std::string CmdProxy::UDPDestinationIP(int action) { diff --git a/slsDetectorSoftware/src/CmdProxy.h b/slsDetectorSoftware/src/CmdProxy.h index cf4a94c8c..fd015bee5 100644 --- a/slsDetectorSoftware/src/CmdProxy.h +++ b/slsDetectorSoftware/src/CmdProxy.h @@ -612,7 +612,7 @@ class CmdProxy { {"gappixels", &CmdProxy::GapPixels}, /* acquisition parameters */ - {"acquire", &CmdProxy::acquire}, + {"acquire", &CmdProxy::Acquire}, {"frames", &CmdProxy::frames}, {"triggers", &CmdProxy::triggers}, {"exptime", &CmdProxy::Exptime}, @@ -737,6 +737,7 @@ class CmdProxy { {"rx_missingpackets", &CmdProxy::rx_missingpackets}, {"startingfnum", &CmdProxy::startingfnum}, {"trigger", &CmdProxy::trigger}, + {"scan", &CmdProxy::Scan}, /* Network Configuration (Detector<->Receiver) */ {"numinterfaces", &CmdProxy::numinterfaces}, @@ -965,7 +966,7 @@ class CmdProxy { std::string SettingsList(int action); std::string GapPixels(int action); /* acquisition parameters */ - std::string acquire(int action); + std::string Acquire(int action); std::string Exptime(int action); std::string Speed(int action); std::string Adcphase(int action); @@ -983,6 +984,7 @@ class CmdProxy { /* acquisition */ std::string ReceiverStatus(int action); std::string DetectorStatus(int action); + std::string Scan(int action); /* Network Configuration (Detector<->Receiver) */ std::string UDPDestinationIP(int action); std::string UDPDestinationIP2(int action); diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 5150dd703..eeb01c040 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -562,6 +562,27 @@ void Detector::sendSoftwareTrigger(Positions pos) { pimpl->Parallel(&Module::sendSoftwareTrigger, pos); } +Result getScan(Positions pos = {}) const { + return pimpl->Parallel(&Module::getScan, pos); +} + +Result getNumberOfScanSteps(Positions pos = {}) const { + return pimpl->Parallel(&Module::getNumberOfScanSteps, pos); +} + +void disableScan() { + pimpl->Parallel(&Module::disableScan); + setNumberOfFrames(1); +} + +void Detector::enableScan(const defs::dacIndex dac, const int start_offset, + const int end_offset, const int step_size) { + pimpl->Parallel(&Module::scan, start_offset, end_offset, step_size, {-1}); + auto t = + getNumberOfScanSteps().tsquash("inconsistent number of scan steps"); + setNumberOfFrames(nsteps); +} + // Network Configuration (Detector<->Receiver) Result Detector::getNumberofUDPInterfaces(Positions pos) const { diff --git a/slsDetectorSoftware/src/Module.cpp b/slsDetectorSoftware/src/Module.cpp index 92b3ed460..48c7d1939 100644 --- a/slsDetectorSoftware/src/Module.cpp +++ b/slsDetectorSoftware/src/Module.cpp @@ -451,6 +451,22 @@ void Module::setStartingFrameNumber(uint64_t value) { void Module::sendSoftwareTrigger() { sendToDetectorStop(F_SOFTWARE_TRIGGER); } +bool Module::getScan() const { + return static_cast(sendToDetector(F_GET_SCAN)); +} + +int Module::getNumberOfScanSteps() const { + return sendToDetector(F_GET_NUM_SCAN_STEPS); +} + +void Module::disableScan() { sendToDetector(F_DISABLE_SCAN); } + +void Module::enableScan(const defs::dacIndex dac, const int start_offset, + const int end_offset, const int step_size) { + int args[]{static_cast(dac), start_offset, end_offset, step_size}; + sendToDetector(F_ENABLE_SCAN, args, nullptr); +} + // Network Configuration (Detector<->Receiver) int Module::getNumberofUDPInterfacesFromShm() { diff --git a/slsDetectorSoftware/src/Module.h b/slsDetectorSoftware/src/Module.h index d6786b548..18496839a 100644 --- a/slsDetectorSoftware/src/Module.h +++ b/slsDetectorSoftware/src/Module.h @@ -167,6 +167,11 @@ class Module : public virtual slsDetectorDefs { uint64_t getStartingFrameNumber(); void setStartingFrameNumber(uint64_t value); void sendSoftwareTrigger(); + bool getScan() const; + int getNumberOfScanSteps() const; + void disableScan(); + void enableScan(const defs::dacIndex dac, const int start_offset, + const int end_offset, const int step_size); /************************************************** * * diff --git a/slsSupportLib/include/sls_detector_defs.h b/slsSupportLib/include/sls_detector_defs.h index c71eb257c..1454dd75b 100644 --- a/slsSupportLib/include/sls_detector_defs.h +++ b/slsSupportLib/include/sls_detector_defs.h @@ -303,6 +303,7 @@ typedef struct { TEMPERATURE_SODR, TEMPERATURE_FPGA2, TEMPERATURE_FPGA3, + TRIMBIT_SCAN, V_POWER_A = 100, V_POWER_B = 101, V_POWER_C = 102, diff --git a/slsSupportLib/include/sls_detector_funcs.h b/slsSupportLib/include/sls_detector_funcs.h index f97ae87b3..b2a52b9cd 100755 --- a/slsSupportLib/include/sls_detector_funcs.h +++ b/slsSupportLib/include/sls_detector_funcs.h @@ -201,6 +201,10 @@ enum detFuncs { F_GET_VETO, F_SET_VETO, F_SET_PATTERN, + F_GET_SCAN, + F_GET_NUM_SCAN_STEPS, + F_DISABLE_SCAN, + F_ENABLE_SCAN, NUM_DET_FUNCTIONS, RECEIVER_ENUM_START = 256, /**< detector function should not exceed this @@ -500,6 +504,10 @@ const char* getFunctionNameFromEnum(enum detFuncs func) { case F_GET_VETO: return "F_GET_VETO"; case F_SET_VETO: return "F_SET_VETO"; case F_SET_PATTERN: return "F_SET_PATTERN"; + case F_GET_SCAN: return "F_GET_SCAN"; + case F_GET_NUM_SCAN_STEPS: return "F_GET_NUM_SCAN_STEPS"; + case F_DISABLE_SCAN: return "F_DISABLE_SCAN"; + case F_ENABLE_SCAN: return "F_ENABLE_SCAN"; 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 cd603e989..f897b2858 100644 --- a/slsSupportLib/src/ToString.cpp +++ b/slsSupportLib/src/ToString.cpp @@ -465,6 +465,8 @@ std::string ToString(const defs::dacIndex s) { return std::string("vipre_cds"); case defs::IBIAS_SFP: return std::string("ibias_sfp"); + case defs::TRIMBIT_SCAN: + return std::string("trimbit_scan"); default: return std::string("Unknown"); } @@ -818,6 +820,8 @@ template <> defs::dacIndex StringTo(const std::string &s) { return defs::VIPRE_CDS; if (s == "ibias_sfp") return defs::IBIAS_SFP; + if (s == "trimbit_scan") + return defs::TRIMBIT_SCAN; throw sls::RuntimeError("Unknown dac Index " + s); }