diff --git a/RELEASE.txt b/RELEASE.txt index abf35629d..c23ae55f6 100755 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -75,8 +75,10 @@ This document describes the differences between v7.0.0 and v6.x.x - rxr src files and classes (detectordata, ZmqSocket, helpDacs) added to sls namespace, and macros (namely from logger (logINFO etc)), slsDetectorGui (make_unique in implemtnation requires sls nemspace (points to std otherwise) but not deectorImpl.cpp) - blackfin programing made seamless (nCE fixed which helps) -save settings file for m3 and eiger +- m3 threshold changes - g2 and m3 clkdiv 2 (system clock) change should affect time settings (g2: exptime, period, delayaftertrigger, burstperiod, m3: exptime, gatedelay, gateperiod, period, delayaftertrigger) - g2 system frequency is the same irrespective of timing source +- (apparently) rxr doesnt get stuck anymore from 6.1.1 2. Resolved Issues ================== diff --git a/python/slsdet/detector.py b/python/slsdet/detector.py index 6de5bb9af..4f0c51423 100755 --- a/python/slsdet/detector.py +++ b/python/slsdet/detector.py @@ -1834,13 +1834,13 @@ class Detector(CppDetectorApi): @property @element def threshold(self): - """[Eiger] Threshold in eV + """[Eiger][Mythen3] Threshold in eV Note ---- To change settings as well or set threshold without trimbits, use setThresholdEnergy. - :setter: It loads trim files from settingspath. + :setter: It loads trim files from settingspath.\n [Mythen3] An energy of -1 will pick up values from detector. """ if self.type == detectorType.MYTHEN3: return self.getAllThresholdEnergy() @@ -3516,7 +3516,7 @@ class Detector(CppDetectorApi): @property @element def interpolation(self): - """[Mythen3] Enable or disable interpolation. Enabling also enables all counters """ + """[Mythen3] Enable or disable interpolation. interpolation mode enables all counters and disables vth3. Disabling sets back counter mask and vth3. """ return self.getInterpolation() @interpolation.setter @@ -3526,7 +3526,7 @@ class Detector(CppDetectorApi): @property @element def pumpprobe(self): - """[Mythen3] Enable or disable pump probe mode. """ + """[Mythen3] Enable or disable pump probe mode. Pump probe mode only enables vth2. Disabling sets back to previous value """ return self.getPumpProbe() @pumpprobe.setter diff --git a/slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServer_developer b/slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServer_developer index 59ce094cc..fe31b3408 100755 Binary files a/slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServer_developer and b/slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServer_developer differ diff --git a/slsDetectorServers/mythen3DetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/mythen3DetectorServer/slsDetectorFunctionList.c index ce96f5f78..776787a81 100644 --- a/slsDetectorServers/mythen3DetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/mythen3DetectorServer/slsDetectorFunctionList.c @@ -68,6 +68,7 @@ int64_t exptimeReg[NCOUNTERS] = {0, 0, 0}; int64_t gateDelayReg[NCOUNTERS] = {0, 0, 0}; int vthEnabledVals[NCOUNTERS] = {0, 0, 0}; int detID = 0; +int counterMask = 0x0; int isInitCheckDone() { return initCheckDone; } @@ -474,17 +475,19 @@ void setupDetector() { // defaults setHighVoltage(DEFAULT_HIGH_VOLTAGE); - resetToDefaultDacs(0); setASICDefaults(); setADIFDefaults(); + // enable all counters before setting dacs (vthx) + setCounterMask(MAX_COUNTER_MSK); + resetToDefaultDacs(0); + // set trigger flow for m3 (for all timing modes) bus_w(FLOW_TRIGGER_REG, bus_r(FLOW_TRIGGER_REG) | FLOW_TRIGGER_MSK); // dynamic range setDynamicRange(DEFAULT_DYNAMIC_RANGE); - // enable all counters - setCounterMask(MAX_COUNTER_MSK); + // Initialization of acquistion parameters setNumFrames(DEFAULT_NUM_FRAMES); @@ -596,8 +599,8 @@ int resetToDefaultDacs(int hardReset) { } } - // set to defualt - setDAC((enum DACINDEX)i, value, 0); + // set to default (last arg to ensure counter check) + setDAC((enum DACINDEX)i, value, 0, 1); if (detectorDacs[i] != value) { LOG(logERROR, ("Setting dac %d failed, wrote %d, read %d\n", i, value, detectorDacs[i])); @@ -1087,12 +1090,44 @@ int64_t getGateDelay(int gateIndex) { return retval / (1E-9 * getFrequency(SYSTEM_C0)); } +void updateVthAndCounterMask() { + LOG(logINFO, ("\tUpdating Vth and countermask\n")); + int interpolation = getInterpolation(); + int pumpProbe = getPumpProbe(); + + if (interpolation) { + // enable all counters + setCounterMaskWithUpdateFlag(MAX_COUNTER_MSK, 0); + // disable vth3 + setVthDac(2, 0); + } else { + // previous counter values + setCounterMaskWithUpdateFlag(counterMask, 0); + } + if (pumpProbe) { + // enable only vth2 + setVthDac(0, 0); + setVthDac(1, 1); + setVthDac(2, 0); + } else { + setVthDac(0, (counterMask & (1 << 0))); + setVthDac(1, (counterMask & (1 << 1))); + } + if (!interpolation && !pumpProbe) { + setVthDac(2, (counterMask & (1 << 2))); + } +} + void setCounterMask(uint32_t arg) { + setCounterMaskWithUpdateFlag(arg, 1); + updateVthAndCounterMask(); +} + +void setCounterMaskWithUpdateFlag(uint32_t arg, int updateMaskFlag) { if (arg == 0 || arg > MAX_COUNTER_MSK) { return; } - uint32_t oldmask = getCounterMask(); - LOG(logINFO, ("Setting counter mask to 0x%x\n", arg)); + LOG(logINFO, ("\tSetting counter mask to 0x%x\n", arg)); uint32_t addr = CONFIG_REG; bus_w(addr, bus_r(addr) & ~CONFIG_COUNTERS_ENA_MSK); bus_w(addr, bus_r(addr) | ((arg << CONFIG_COUNTERS_ENA_OFST) & @@ -1108,19 +1143,8 @@ void setCounterMask(uint32_t arg) { setGateDelay(i, ns); } - LOG(logINFO, ("\tUpdating Vth dacs\n")); - enum DACINDEX vthdacs[] = {M_VTH1, M_VTH2, M_VTH3}; - for (int i = 0; i < NCOUNTERS; ++i) { - // if change in enable - if ((arg & (1 << i)) ^ (oldmask & (1 << i))) { - // disable, disable value - int value = DEFAULT_COUNTER_DISABLED_VTH_VAL; - // enable, set saved values - if (arg & (1 << i)) { - value = vthEnabledVals[i]; - } - setGeneralDAC(vthdacs[i], value, 0); - } + if (updateMaskFlag) { + counterMask = arg; } } @@ -1241,7 +1265,8 @@ int64_t getMeasurementTime() { int setDACS(int *dacs) { for (int i = 0; i < NDAC; ++i) { if (dacs[i] != -1) { - setDAC((enum DACINDEX)i, dacs[i], 0); + // set to default (last arg to ensure counter check) + setDAC((enum DACINDEX)i, dacs[i], 0, 1); if (dacs[i] != detectorDacs[i]) { // dont complain if that counter was disabled if ((i == M_VTH1 || i == M_VTH2 || i == M_VTH3) && @@ -1300,6 +1325,9 @@ int setModule(sls_detector_module myMod, char *mess) { return FAIL; } + // update vth and countermask + updateVthAndCounterMask(); + // threshold energy for (int i = 0; i < NCOUNTERS; ++i) { if (myMod.eV[i] >= 0) { @@ -1440,7 +1468,8 @@ enum detectorSettings setSettings(enum detectorSettings sett) { // set special dacs const int specialDacs[] = SPECIALDACINDEX; for (int i = 0; i < NSPECIALDACS; ++i) { - setDAC(specialDacs[i], dacVals[i], 0); + // set to default (last arg to ensure counter check) + setDAC(specialDacs[i], dacVals[i], 0, 1); } LOG(logINFO, ("Settings: %d\n", thisSettings)); @@ -1500,7 +1529,8 @@ void setThresholdEnergy(int counterIndex, int eV) { } /* parameters - dac, hv */ -void setDAC(enum DACINDEX ind, int val, int mV) { +// counterEnableCheck false only if setDAC called directly +void setDAC(enum DACINDEX ind, int val, int mV, int counterEnableCheck) { // invalid value if (val < 0) { return; @@ -1511,7 +1541,10 @@ void setDAC(enum DACINDEX ind, int val, int mV) { return; } - // threshold dacs (remember value, vthreshold: skip disabled) + // threshold dacs + // remember value, vthreshold: skip disabled, + // others: disable or enable dac if counter mask + // setDAC called directly: will set independent of counter enable if (ind == M_VTHRESHOLD || ind == M_VTH1 || ind == M_VTH2 || ind == M_VTH3) { char *dac_names[] = {DAC_NAMES}; @@ -1522,7 +1555,6 @@ void setDAC(enum DACINDEX ind, int val, int mV) { int dacval = val; // if not disabled value, remember value if (dacval != DEFAULT_COUNTER_DISABLED_VTH_VAL) { - // convert mv to dac if (mV) { if (LTC2620_D_VoltageToDac(val, &dacval) == FAIL) { return; @@ -1532,9 +1564,16 @@ void setDAC(enum DACINDEX ind, int val, int mV) { LOG(logINFO, ("Remembering %s [%d]\n", dac_names[ind], dacval)); } - // if vthreshold,skip for disabled counters - if ((ind == M_VTHRESHOLD) && (!(counters & (1 << i)))) { - continue; + // disabled counter + if (!(counters & (1 << i))) { + // skip setting vthx dac (value remembered anyway) + if (ind == M_VTHRESHOLD) { + continue; + } + // disable dac (except when setting dac directly) + if (counterEnableCheck) { + val = DEFAULT_COUNTER_DISABLED_VTH_VAL; + } } setGeneralDAC(vthdacs[i], val, mV); } @@ -1575,6 +1614,19 @@ void setGeneralDAC(enum DACINDEX ind, int val, int mV) { } } +void setVthDac(int index, int enable) { + LOG(logINFO, ("\t%s vth%d\n", (enable ? "Enabling" : "Disabing"), index)); + // enables (from remembered values) or disables vthx + enum DACINDEX vthdacs[] = {M_VTH1, M_VTH2, M_VTH3}; + // disable value + int value = DEFAULT_COUNTER_DISABLED_VTH_VAL; + // enable, set saved values + if (enable) { + value = vthEnabledVals[index]; + } + setGeneralDAC(vthdacs[index], value, 0); +} + int getDAC(enum DACINDEX ind, int mV) { if (ind == M_VTHRESHOLD) { int ret = -1, ret1 = -1; @@ -1738,23 +1790,24 @@ int setGainCaps(int caps) { int setInterpolation(int enable) { LOG(logINFO, ("%s Interpolation\n", enable == 0 ? "Disabling" : "Enabling")); - if (enable) { - setCounterMask(MAX_COUNTER_MSK); - if (getCounterMask() != MAX_COUNTER_MSK) { - LOG(logERROR, - ("Could not set interpolation. Could not enable all counters")); - return FAIL; - } - LOG(logINFO, ("\tEnabled all counters\n")); - } + int csr = M3SetInterpolation(enable); - return setChipStatusRegister(csr); + int ret = setChipStatusRegister(csr); + if (ret == OK) { + updateVthAndCounterMask(); + } + return ret; } int setPumpProbe(int enable) { LOG(logINFO, ("%s Pump Probe\n", enable == 0 ? "Disabling" : "Enabling")); + int csr = M3SetPumpProbe(enable); - return setChipStatusRegister(csr); + int ret = setChipStatusRegister(csr); + if (ret == OK) { + updateVthAndCounterMask(); + } + return ret; } int setDigitalPulsing(int enable) { diff --git a/slsDetectorServers/mythen3DetectorServer/slsDetectorServer_defs.h b/slsDetectorServers/mythen3DetectorServer/slsDetectorServer_defs.h index 5faaf20bf..4956dd52f 100644 --- a/slsDetectorServers/mythen3DetectorServer/slsDetectorServer_defs.h +++ b/slsDetectorServers/mythen3DetectorServer/slsDetectorServer_defs.h @@ -105,7 +105,7 @@ enum DACINDEX { 1220, /* vIpreOut */ \ 2800, /* Vth3 */ \ 2800, /* Vth1 */ \ - 1708, /* vIcin */ \ + 800, /* vIcin */ \ 1800, /* cas */ \ 1100, /* Vrpreamp */ \ 1100, /* Vcal_n */ \ diff --git a/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h b/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h index 3ae08b95d..d33cec62b 100644 --- a/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h +++ b/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h @@ -281,6 +281,7 @@ int getNumDigitalSamples(); #endif #ifdef MYTHEN3D void setCounterMask(uint32_t arg); +void setCounterMaskWithUpdateFlag(uint32_t arg, int updateMaskFlag); uint32_t getCounterMask(); void updatePacketizing(); #endif @@ -347,9 +348,12 @@ void setThresholdEnergy(int counterIndex, int eV); int setOnChipDAC(enum ONCHIP_DACINDEX ind, int chipIndex, int val); int getOnChipDAC(enum ONCHIP_DACINDEX ind, int chipIndex); #endif -void setDAC(enum DACINDEX ind, int val, int mV); #ifdef MYTHEN3D +void setDAC(enum DACINDEX ind, int val, int mV, int counterEnableCheck); void setGeneralDAC(enum DACINDEX ind, int val, int mV); +void setVthDac(int index, int enable); +#else +void setDAC(enum DACINDEX ind, int val, int mV); #endif int getDAC(enum DACINDEX ind, int mV); int getMaxDacSteps(); diff --git a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c index 988051528..235e8f427 100644 --- a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c +++ b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c @@ -1288,7 +1288,12 @@ int validateAndSetDac(enum dacIndex ind, int val, int mV) { LOG(logERROR, (mess)); } else #endif +#ifdef MYTHEN3D + // ignore counter enable to force vth dac values + setDAC(serverDacIndex, val, mV, 0); +#else setDAC(serverDacIndex, val, mV); +#endif retval = getDAC(serverDacIndex, mV); } #ifdef EIGERD @@ -9944,19 +9949,25 @@ int set_interpolation(int file_des) { #else // only set if (Server_VerifyLock() == OK) { - ret = setInterpolation(arg); - if (ret == FAIL) { - if (arg) - sprintf(mess, "Could not set interpolation or enable all " - "counters for it.\n"); - else - sprintf(mess, "Could not set interpolation\n"); + if (getPumpProbe() && arg) { + ret = FAIL; + sprintf(mess, "Could not set interpolation. Disable pump probe mode first.\n"); LOG(logERROR, (mess)); - } else { - int retval = getInterpolation(); - validate(&ret, mess, (int)arg, (int)retval, "set interpolation", - DEC); - LOG(logDEBUG1, ("interpolation retval: %u\n", retval)); + } else { + ret = setInterpolation(arg); + if (ret == FAIL) { + if (arg) + sprintf(mess, "Could not set interpolation or enable all " + "counters for it.\n"); + else + sprintf(mess, "Could not set interpolation\n"); + LOG(logERROR, (mess)); + } else { + int retval = getInterpolation(); + validate(&ret, mess, (int)arg, (int)retval, "set interpolation", + DEC); + LOG(logDEBUG1, ("interpolation retval: %u\n", retval)); + } } } #endif @@ -9994,14 +10005,20 @@ int set_pump_probe(int file_des) { #else // only set if (Server_VerifyLock() == OK) { - ret = setPumpProbe(arg); - if (ret == FAIL) { - sprintf(mess, "Could not set pump probe\n"); + if (getInterpolation() && arg) { + ret = FAIL; + sprintf(mess, "Could not set pump probe mode. Disable interpolation mode first.\n"); LOG(logERROR, (mess)); - } else { - int retval = getPumpProbe(); - validate(&ret, mess, (int)arg, (int)retval, "set pump probe", DEC); - LOG(logDEBUG1, ("pump probe retval: %u\n", retval)); + } else { + ret = setPumpProbe(arg); + if (ret == FAIL) { + sprintf(mess, "Could not set pump probe\n"); + LOG(logERROR, (mess)); + } else { + int retval = getPumpProbe(); + validate(&ret, mess, (int)arg, (int)retval, "set pump probe", DEC); + LOG(logDEBUG1, ("pump probe retval: %u\n", retval)); + } } } #endif diff --git a/slsDetectorSoftware/include/sls/Detector.h b/slsDetectorSoftware/include/sls/Detector.h index d3a8d10fb..c7cd72440 100644 --- a/slsDetectorSoftware/include/sls/Detector.h +++ b/slsDetectorSoftware/include/sls/Detector.h @@ -144,7 +144,7 @@ class Detector { defs::detectorSettings settings = defs::STANDARD, bool trimbits = true, Positions pos = {}); - /** [Mythen3] It loads trim files from settingspath */ + /** [Mythen3] It loads trim files from settingspath. An energy of -1 will pick up values from detector */ void setThresholdEnergy(std::array threshold_ev, defs::detectorSettings settings = defs::STANDARD, bool trimbits = true, Positions pos = {}); @@ -1504,13 +1504,13 @@ class Detector { /** [Mythen3] */ Result getInterpolation(Positions pos = {}) const; - /** [Mythen3] Also enables all counters */ + /** [Mythen3] interpolation mode enables all counters and disables vth3. Disabling sets back counter mask and vth3. */ void setInterpolation(bool value, Positions pos = {}); /** [Mythen3] */ Result getPumpProbe(Positions pos = {}) const; - /** [Mythen3] */ + /** [Mythen3] pump probe mode only enables vth2. Disabling sets back to previous value */ void setPumpProbe(bool value, Positions pos = {}); /** [Mythen3] */ diff --git a/slsDetectorSoftware/src/CmdProxy.cpp b/slsDetectorSoftware/src/CmdProxy.cpp index 330fad9ae..70546879c 100644 --- a/slsDetectorSoftware/src/CmdProxy.cpp +++ b/slsDetectorSoftware/src/CmdProxy.cpp @@ -382,8 +382,8 @@ std::string CmdProxy::Threshold(int action) { } os << "\n\nthreshold [eV1] [eV2] [eV3] [(optional settings)]" "\n\t[Mythen3] Threshold in eV for each counter. It loads trim " - "files from " - "settingspath."; + "files from settingspath. An energy of -1 will pick up values " + " from detector."; if (cmd == "thresholdnotb") { os << "Trimbits are not loaded."; } @@ -2302,6 +2302,9 @@ std::string CmdProxy::Counters(int action) { if (args.empty()) { WrongNumberOfParameters(1); } + if (std::any_of(args.cbegin(), args.cend(), [](std::string s){ return (StringTo(s) < 0 || StringTo(s) > 2); })) { + throw RuntimeError("Invalid counter indices list. Example: 0 1 2"); + } // convert vector to counter enable mask uint32_t mask = 0; for (size_t i = 0; i < args.size(); ++i) { diff --git a/slsDetectorSoftware/src/CmdProxy.h b/slsDetectorSoftware/src/CmdProxy.h index 30c3bcb58..d9806a849 100644 --- a/slsDetectorSoftware/src/CmdProxy.h +++ b/slsDetectorSoftware/src/CmdProxy.h @@ -2058,12 +2058,11 @@ class CmdProxy { INTEGER_COMMAND_VEC_ID(interpolation, getInterpolation, setInterpolation, StringTo, "[0, 1]\n\t[Mythen3] Enables or disables " - "interpolation. Default is disabled. Enabling also " - "enables all counters. "); + "interpolation. Default is disabled. Interpolation mode enables all counters and disables vth3. Disabling sets back counter mask and vth3."); INTEGER_COMMAND_VEC_ID(pumpprobe, getPumpProbe, setPumpProbe, StringTo, "[0, 1]\n\t[Mythen3] Enables or disables pump probe " - "mode. Default is disabled"); + "mode. Default is disabled. Pump probe mode only enables vth2. Disabling sets back to previous value."); INTEGER_COMMAND_VEC_ID(apulse, getAnalogPulsing, setAnalogPulsing, StringTo, diff --git a/slsDetectorSoftware/src/Module.cpp b/slsDetectorSoftware/src/Module.cpp index dd527d30a..67a954f1c 100644 --- a/slsDetectorSoftware/src/Module.cpp +++ b/slsDetectorSoftware/src/Module.cpp @@ -173,7 +173,9 @@ std::array Module::getAllThresholdEnergy() const { void Module::setThresholdEnergy(int e_eV, detectorSettings isettings, bool trimbits) { - + if (shm()->detType == MYTHEN3) { + throw RuntimeError("Mythen3 should have called with 3 energies"); + } // verify e_eV exists in trimEneregies[] if (shm()->trimEnergies.empty() || (e_eV < shm()->trimEnergies.front()) || (e_eV > shm()->trimEnergies.back())) { @@ -214,21 +216,9 @@ void Module::setThresholdEnergy(int e_eV, detectorSettings isettings, myMod.iodelay = myMod1.iodelay; myMod.tau = linearInterpolation(e_eV, trim1, trim2, myMod1.tau, myMod2.tau); - // m3, reg is used for gaincaps - if (shm()->detType == MYTHEN3) { - if (myMod1.reg != myMod2.reg) { - throw RuntimeError( - "setThresholdEnergyAndSettings: gaincaps do not " - "match between files"); - } - myMod.reg = myMod1.reg; - } - } - // m3, reg is used for gaincaps - if (shm()->detType != MYTHEN3) { - myMod.reg = isettings; } + myMod.reg = isettings; myMod.eV[0] = e_eV; setModule(myMod, trimbits); if (getSettings() != isettings) { @@ -243,42 +233,35 @@ void Module::setThresholdEnergy(int e_eV, detectorSettings isettings, void Module::setAllThresholdEnergy(std::array e_eV, detectorSettings isettings, bool trimbits) { - // only mythen3 + if (shm()->detType != MYTHEN3) { + throw RuntimeError("This detector should have called with 3 energies"); + } if (shm()->trimEnergies.empty()) { throw RuntimeError( - "Trim energies have not been defined for this module yet!"); + "Trim energies have not been defined for this module yet! Use trimen."); } - auto counters = getSetBits(getCounterMask()); - enum mythen3_DacIndex { - M_VCASSH, - M_VTH2, - M_VRSHAPER, - M_VRSHAPER_N, - M_VIPRE_OUT, - M_VTH3, - M_VTH1, - M_VICIN, - M_VCAS, - M_VRPREAMP, - M_VCAL_N, - M_VIPRE, - M_VISHAPER, - M_VCAL_P, - M_VTRIM, - M_VDCSH - }; - - std::vector myMods{shm()->detType}; std::vector energy(e_eV.begin(), e_eV.end()); // if all energies are same if (allEqualTo(energy, energy[0])) { + if (energy[0] == -1) { + throw RuntimeError("Every energy provided to set threshold energy is -1. Typo?"); + } energy.resize(1); } - myMods.resize(energy.size()); // for each threshold + std::vector myMods; for (size_t i = 0; i < energy.size(); ++i) { + if (energy[i] == -1) { + sls_detector_module mod = getModule(); + myMods.push_back(mod); + continue; + } + + sls_detector_module mod{shm()->detType}; + myMods.push_back(mod); + // don't interpolate if (shm()->trimEnergies.anyEqualTo(energy[i])) { std::string settingsfname = @@ -324,10 +307,9 @@ void Module::setAllThresholdEnergy(std::array e_eV, myMods[i] = interpolateTrim(&myMod1, &myMod2, energy[i], trim1, trim2, trimbits); - // gaincaps + // csr if (myMod1.reg != myMod2.reg) { - throw RuntimeError("setAllThresholdEnergy: gaincaps do not " - "match between files for energy (eV) " + + throw RuntimeError("setAllThresholdEnergy: chip shift register values do not match between files for energy (eV) " + std::to_string(energy[i])); } myMods[i].reg = myMod1.reg; @@ -337,8 +319,11 @@ void Module::setAllThresholdEnergy(std::array e_eV, sls_detector_module myMod{shm()->detType}; myMod = myMods[0]; + // if multiple thresholds, combine if (myMods.size() > 1) { + auto counters = getSetBits(getCounterMask()); + // average vtrim of enabled counters int sum = 0; @@ -377,56 +362,15 @@ void Module::setAllThresholdEnergy(std::array e_eV, for (int i = 0; i < myMod.nchan; ++i) { myMod.chanregs[i] = myMods[i % 3].chanregs[i]; } - // gain caps + // csr if (myMods[0].reg != myMods[1].reg || myMods[1].reg != myMods[2].reg) { - throw RuntimeError("setAllThresholdEnergy: gaincaps do not " - "match between files for all energies"); + throw RuntimeError("setAllThresholdEnergy: chip shift register values do not match between files for all energies"); } } - myMod.reg = isettings; std::copy(e_eV.begin(), e_eV.end(), myMod.eV); LOG(logDEBUG) << "ev:" << ToString(myMod.eV); - // check for trimbits that are out of range - bool out_of_range = false; - for (int i = 0; i != myMod.nchan; ++i) { - if (myMod.chanregs[i] < 0) { - myMod.chanregs[i] = 0; - out_of_range = true; - } else if (myMod.chanregs[i] > 63) { - myMod.chanregs[i] = 63; - out_of_range = true; - } - } - if (out_of_range) { - LOG(logWARNING) - << "Some trimbits were out of range after interpolation, these " - "have been replaced with 0 or 63."; - } - - // check dacs - out_of_range = false; - for (int i = 0; i != myMod.ndac; ++i) { - int dacMin = 0; - int dacMax = 2800; - if (i == M_VTH1 || i == M_VTH2 || i == M_VTH3) { - dacMin = 200; - dacMax = 2400; - } - if (myMod.dacs[i] < dacMin) { - myMod.dacs[i] = dacMin; - out_of_range = true; - } else if (myMod.dacs[i] > dacMax) { - myMod.dacs[i] = dacMax; - out_of_range = true; - } - } - if (out_of_range) { - LOG(logWARNING) << "Some dacs were out of range after interpolation, " - "these have been replaced with 600 or 2400."; - } - setModule(myMod, trimbits); if (getSettings() != isettings) { throw RuntimeError("setThresholdEnergyAndSettings: Could not set " @@ -2261,10 +2205,8 @@ uint32_t Module::getCounterMask() const { } void Module::setCounterMask(uint32_t countermask) { - LOG(logDEBUG1) << "Setting Counter mask to " << countermask; sendToDetector(F_SET_COUNTER_MASK, countermask, nullptr); if (shm()->useReceiverFlag) { - LOG(logDEBUG1) << "Sending Reciver counter mask: " << countermask; sendToReceiver(F_RECEIVER_SET_COUNTER_MASK, countermask, nullptr); } } @@ -2324,7 +2266,10 @@ bool Module::getInterpolation() const { void Module::setInterpolation(const bool enable) { sendToDetector(F_SET_INTERPOLATION, static_cast(enable), nullptr); - setCounterMask(getCounterMask()); + int mask = getCounterMask(); + if (shm()->useReceiverFlag) { + sendToReceiver(F_RECEIVER_SET_COUNTER_MASK, mask, nullptr); + } } bool Module::getPumpProbe() const { @@ -2407,12 +2352,9 @@ int Module::getNumberOfDigitalSamples() const { } void Module::setNumberOfDigitalSamples(int value) { - LOG(logDEBUG1) << "Setting number of digital samples to " << value; sendToDetector(F_SET_NUM_DIGITAL_SAMPLES, value, nullptr); updateNumberOfChannels(); // depends on samples and adcmask if (shm()->useReceiverFlag) { - LOG(logDEBUG1) << "Sending number of digital samples to Receiver: " - << value; sendToReceiver(F_RECEIVER_SET_NUM_DIGITAL_SAMPLES, value, nullptr); } } @@ -3347,6 +3289,45 @@ void Module::setModule(sls_detector_module &module, bool trimbits) { module.nchan = 0; module.nchip = 0; } + // validate dacs and trimbits + if (shm()->detType == MYTHEN3) { + // check for trimbits that are out of range + bool out_of_range = false; + for (int i = 0; i != module.nchan; ++i) { + if (module.chanregs[i] < 0) { + module.chanregs[i] = 0; + out_of_range = true; + } else if (module.chanregs[i] > 63) { + module.chanregs[i] = 63; + out_of_range = true; + } + } + if (out_of_range) { + LOG(logWARNING) + << "Some trimbits were out of range, these have been replaced with 0 or 63."; + } + // check dacs + out_of_range = false; + for (int i = 0; i != module.ndac; ++i) { + int dacMin = 0; + int dacMax = 2800; + if (i == M_VTH1 || i == M_VTH2 || i == M_VTH3) { + dacMin = 200; + dacMax = 2400; + } + if (module.dacs[i] < dacMin) { + module.dacs[i] = dacMin; + out_of_range = true; + } else if (module.dacs[i] > dacMax) { + module.dacs[i] = dacMax; + out_of_range = true; + } + } + if (out_of_range) { + LOG(logWARNING) << "Some dacs were out of range, " + "these have been replaced with 0/200 or 2800/2400."; + } + } auto client = DetectorSocket(shm()->hostname, shm()->controlPort); client.Send(F_SET_MODULE); sendModule(&module, client); @@ -3478,42 +3459,6 @@ sls_detector_module Module::interpolateTrim(sls_detector_module *a, } sls_detector_module myMod{shm()->detType}; - enum eiger_DacIndex { - E_SVP, - E_VTR, - E_VRF, - E_VRS, - E_SVN, - E_VTGSTV, - E_VCMP_LL, - E_VCMP_LR, - E_CAL, - E_VCMP_RL, - E_RXB_RB, - E_RXB_LB, - E_VCMP_RR, - E_VCP, - E_VCN, - E_VIS - }; - enum mythen3_DacIndex { - M_VCASSH, - M_VTH2, - M_VRSHAPER, - M_VRSHAPER_N, - M_VIPRE_OUT, - M_VTH3, - M_VTH1, - M_VICIN, - M_VCAS, - M_VRPREAMP, - M_VCAL_N, - M_VIPRE, - M_VISHAPER, - M_VCAL_P, - M_VTRIM, - M_VDCSH - }; // create copy and interpolate dac lists std::vector dacs_to_copy, dacs_to_interpolate; diff --git a/slsDetectorSoftware/src/Module.h b/slsDetectorSoftware/src/Module.h index c845aa992..90e1e4470 100644 --- a/slsDetectorSoftware/src/Module.h +++ b/slsDetectorSoftware/src/Module.h @@ -791,6 +791,44 @@ class Module : public virtual slsDetectorDefs { static const int NIOS_WRITE_TO_FLASH_TIME_FPGA = 45; static const int NIOS_ERASE_FLASH_TIME_KERNEL = 9; static const int NIOS_WRITE_TO_FLASH_TIME_KERNEL = 40; + + enum mythen3_DacIndex { + M_VCASSH, + M_VTH2, + M_VRSHAPER, + M_VRSHAPER_N, + M_VIPRE_OUT, + M_VTH3, + M_VTH1, + M_VICIN, + M_VCAS, + M_VRPREAMP, + M_VCAL_N, + M_VIPRE, + M_VISHAPER, + M_VCAL_P, + M_VTRIM, + M_VDCSH + }; + + enum eiger_DacIndex { + E_SVP, + E_VTR, + E_VRF, + E_VRS, + E_SVN, + E_VTGSTV, + E_VCMP_LL, + E_VCMP_LR, + E_CAL, + E_VCMP_RL, + E_RXB_RB, + E_RXB_LB, + E_VCMP_RR, + E_VCP, + E_VCN, + E_VIS + }; }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorSoftware/tests/test-CmdProxy-mythen3.cpp b/slsDetectorSoftware/tests/test-CmdProxy-mythen3.cpp index 3eedd9ea4..be6d9877f 100644 --- a/slsDetectorSoftware/tests/test-CmdProxy-mythen3.cpp +++ b/slsDetectorSoftware/tests/test-CmdProxy-mythen3.cpp @@ -496,32 +496,46 @@ TEST_CASE("interpolation", "[.cmd]") { Detector det; CmdProxy proxy(&det); if (det.getDetectorType().squash() == defs::MYTHEN3) { - auto prev_val = det.getInterpolation(); - auto mask = det.getCounterMask(); - { - proxy.Call("counters", {"0", "1"}, -1, PUT); - std::ostringstream oss; - proxy.Call("interpolation", {"1"}, -1, PUT, oss); - REQUIRE(oss.str() == "interpolation 1\n"); - REQUIRE(det.getCounterMask().tsquash("inconsistent counter mask") == - 7); - } - { - proxy.Call("counters", {"0", "1"}, -1, PUT); - std::ostringstream oss; - proxy.Call("interpolation", {"0"}, -1, PUT, oss); - REQUIRE(oss.str() == "interpolation 0\n"); - REQUIRE(det.getCounterMask().tsquash("inconsistent counter mask") == - 3); + auto prev_interpolation = det.getInterpolation(); + auto prev_mask = det.getCounterMask(); + auto prev_vth3DacVal = det.getDAC(defs::VTH3, 0, {}); + + int disabledDacValue = 2800; + auto fixedVth3DacVal = 1000; + det.setDAC(defs::VTH3, fixedVth3DacVal, 0, {}); + // mask with counter 3 disabled and enabled(to test vth3) + uint32_t fixedMask[2] = {0x2, 0x4}; + for (int i = 0; i != 2; ++i) { + det.setCounterMask(fixedMask[i]); + { + std::ostringstream oss; + proxy.Call("interpolation", {"1"}, -1, PUT, oss); + REQUIRE(oss.str() == "interpolation 1\n"); + REQUIRE(det.getCounterMask().tsquash("inconsistent counter mask") == + 7); + REQUIRE(det.getDAC(defs::VTH3, 0, {0}).tsquash("inconsistent vth3 dac value") == disabledDacValue); + } + { + std::ostringstream oss; + proxy.Call("interpolation", {"0"}, -1, PUT, oss); + REQUIRE(oss.str() == "interpolation 0\n"); + REQUIRE(det.getCounterMask().tsquash("inconsistent counter mask") == + fixedMask[i]); + uint32_t expectedVth3DacVal = (fixedMask[i] & 0x4 ? fixedVth3DacVal : disabledDacValue); + REQUIRE(det.getDAC(defs::VTH3, 0, {0}).tsquash("inconsistent vth3 dac value") == expectedVth3DacVal); + } } + { std::ostringstream oss; proxy.Call("interpolation", {}, -1, GET, oss); REQUIRE(oss.str() == "interpolation 0\n"); } for (int i = 0; i != det.size(); ++i) { - det.setCounterMask(mask[i], {i}); - det.setInterpolation(prev_val[i], {i}); + det.setCounterMask(prev_mask[i], {i}); + det.setInterpolation(prev_interpolation[i], {i}); + det.setDAC(defs::VTH3, prev_vth3DacVal[i], 0, {i}); + } } else { REQUIRE_THROWS(proxy.Call("interpolation", {}, -1, GET)); @@ -533,15 +547,43 @@ TEST_CASE("pumpprobe", "[.cmd]") { CmdProxy proxy(&det); if (det.getDetectorType().squash() == defs::MYTHEN3) { auto prev_val = det.getPumpProbe(); - { - std::ostringstream oss; - proxy.Call("pumpprobe", {"1"}, -1, PUT, oss); - REQUIRE(oss.str() == "pumpprobe 1\n"); - } - { - std::ostringstream oss; - proxy.Call("pumpprobe", {"0"}, -1, PUT, oss); - REQUIRE(oss.str() == "pumpprobe 0\n"); + auto prev_interpolation = det.getInterpolation(); + auto prev_mask = det.getCounterMask(); + auto prev_vth1DacVal = det.getDAC(defs::VTH1, 0, {}); + auto prev_vth2DacVal = det.getDAC(defs::VTH2, 0, {}); + auto prev_vth3DacVal = det.getDAC(defs::VTH3, 0, {}); + + int disabledDacValue = 2800; + auto fixedVthDacVal = 1000; + det.setDAC(defs::VTH1, fixedVthDacVal, 0, {}); + det.setDAC(defs::VTH2, fixedVthDacVal, 0, {}); + det.setDAC(defs::VTH3, fixedVthDacVal, 0, {}); + // mask with counter 2 disabled and enabled(to test vth2) + uint32_t fixedMask[2] = {0x4, 0x3}; + for (int i = 0; i != 2; ++i) { + det.setCounterMask(fixedMask[i]); + { + // pump probe + std::ostringstream oss; + proxy.Call("pumpprobe", {"1"}, -1, PUT, oss); + REQUIRE(oss.str() == "pumpprobe 1\n"); + REQUIRE(det.getDAC(defs::VTH1, 0, {0}).tsquash("inconsistent vth2 dac value") == disabledDacValue); + REQUIRE(det.getDAC(defs::VTH2, 0, {0}).tsquash("inconsistent vth2 dac value") == fixedVthDacVal); + REQUIRE(det.getDAC(defs::VTH3, 0, {0}).tsquash("inconsistent vth2 dac value") == disabledDacValue); + } + // interpolation and pump probe + REQUIRE_THROWS(proxy.Call("interpolation", {"1"}, -1, PUT)); + { + // none + std::ostringstream oss; + proxy.Call("pumpprobe", {"0"}, -1, PUT, oss); + REQUIRE(oss.str() == "pumpprobe 0\n"); + REQUIRE(det.getCounterMask().tsquash("inconsistent counter mask") == 7); + REQUIRE(det.getDAC(defs::VTH1, 0, {0}).tsquash("inconsistent vth1 dac value") == (fixedMask[i] & 0x1 ? fixedVthDacVal : disabledDacValue)); + REQUIRE(det.getDAC(defs::VTH2, 0, {0}).tsquash("inconsistent vth2 dac value") == (fixedMask[i] & 0x2 ? fixedVthDacVal : disabledDacValue)); + REQUIRE(det.getDAC(defs::VTH3, 0, {0}).tsquash("inconsistent vth3 dac value") == (fixedMask[i] & 0x4 ? fixedVthDacVal : disabledDacValue)); + } + } { std::ostringstream oss; @@ -549,7 +591,12 @@ TEST_CASE("pumpprobe", "[.cmd]") { REQUIRE(oss.str() == "pumpprobe 0\n"); } for (int i = 0; i != det.size(); ++i) { + det.setCounterMask(prev_mask[i], {i}); det.setPumpProbe(prev_val[i], {i}); + det.setInterpolation(prev_interpolation[i], {i}); + det.setDAC(defs::VTH1, prev_vth1DacVal[i], 0, {i}); + det.setDAC(defs::VTH2, prev_vth2DacVal[i], 0, {i}); + det.setDAC(defs::VTH3, prev_vth3DacVal[i], 0, {i}); } } else { REQUIRE_THROWS(proxy.Call("pumpprobe", {}, -1, GET)); diff --git a/slsSupportLib/include/sls/versionAPI.h b/slsSupportLib/include/sls/versionAPI.h index 97ff2a907..8a8bda755 100644 --- a/slsSupportLib/include/sls/versionAPI.h +++ b/slsSupportLib/include/sls/versionAPI.h @@ -10,5 +10,5 @@ #define APIJUNGFRAU 0x220524 #define APIMOENCH 0x220519 #define APIEIGER 0x220524 -#define APIMYTHEN3 0x220602 #define APIGOTTHARD2 0x220602 +#define APIMYTHEN3 0x220607