Mythen3 improved synchronization (#231)

Disabling scans for multi module Mythen3, since there is no feedback of the detectors being ready
startDetector first starts the slaves then the master
acquire firs calls startDetector for the slaves then acquire on the master
getMaster to read back from hardware which one is master
This commit is contained in:
Erik Fröjdh 2021-02-08 13:28:37 +01:00 committed by GitHub
parent f35de3bc2b
commit 10b315c2bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 99 additions and 3 deletions

View File

@ -32,6 +32,14 @@ This document describes the differences between 5.1.0 and 5.x.x releases.
------
1. Aded settings and threshold features for Mythen3.
2. Internal modification of acquire for Mythen3.
3. Added getMaster functio for M3
Mythen3 server
-----------------
1. Setting timing to auto, sets timing to trigger for slaves
3. Resolved Issues

View File

@ -1132,6 +1132,10 @@ void init_det(py::module &m) {
(Result<std::array<ns, 3>>(Detector::*)(sls::Positions) const) &
Detector::getGateDelayForAllGates,
py::arg() = Positions{})
.def("getMaster",
(Result<bool>(Detector::*)(sls::Positions) const) &
Detector::getMaster,
py::arg() = Positions{})
.def("getNumberOfAnalogSamples",
(Result<int>(Detector::*)(sls::Positions) const) &
Detector::getNumberOfAnalogSamples,

View File

@ -1522,8 +1522,16 @@ int setHighVoltage(int val) {
return highvoltage;
}
int isMaster(){
return !(bus_r(0x18) >> 31);
}
/* parameters - timing */
void setTiming(enum timingMode arg) {
if (!isMaster() && arg == AUTO_TIMING)
arg = TRIGGER_EXPOSURE;
uint32_t addr = CONFIG_REG;
switch (arg) {
case AUTO_TIMING:

View File

@ -352,6 +352,7 @@ void setTiming(enum timingMode arg);
enum timingMode getTiming();
#ifdef MYTHEN3D
void setInitialExtSignals();
int isMaster();
#endif
#if defined(GOTTHARDD) || defined(MYTHEN3D)
void setExtSignal(int signalIndex, enum externalSignalFlag mode);

View File

@ -246,3 +246,4 @@ int is_virtual(int);
int get_pattern(int);
int load_default_pattern(int);
int get_all_threshold_energy(int);
int get_master(int);

View File

@ -368,6 +368,7 @@ void function_table() {
flist[F_GET_PATTERN] = &get_pattern;
flist[F_LOAD_DEFAULT_PATTERN] = &load_default_pattern;
flist[F_GET_ALL_THRESHOLD_ENERGY] = &get_all_threshold_energy;
flist[F_GET_MASTER] = &get_master;
// check
if (NUM_DET_FUNCTIONS >= RECEIVER_ENUM_START) {
@ -638,7 +639,9 @@ int set_timing_mode(int file_des) {
}
// get
retval = getTiming();
#ifndef MYTHEN3D
validate((int)arg, (int)retval, "set timing mode", DEC);
#endif
LOG(logDEBUG1, ("Timing Mode: %d\n", retval));
return Server_SendResult(file_des, INT32, &retval, sizeof(retval));
@ -8365,3 +8368,18 @@ int get_all_threshold_energy(int file_des) {
#endif
return Server_SendResult(file_des, INT32, retvals, sizeof(retvals));
}
int get_master(int file_des){
ret = OK;
memset(mess, 0, sizeof(mess));
int retval = -1;
LOG(logDEBUG1, ("Getting master\n"));
#ifndef MYTHEN3D
functionNotImplemented();
#else
retval = isMaster();
#endif
return Server_SendResult(file_des, INT32, &retval, sizeof(retval));
}

View File

@ -1305,6 +1305,9 @@ class Detector {
/** [Mythen3] gate delay for all gates in auto or trigger timing mode
* (internal gating). Gate index: 0-2, -1 for all */
Result<std::array<ns, 3>> getGateDelayForAllGates(Positions pos = {}) const;
Result<bool> getMaster(Positions pos = {}) const;
///@{
/** @name CTB / Moench Specific */

View File

@ -674,7 +674,23 @@ void Detector::startReceiver() { pimpl->Parallel(&Module::startReceiver, {}); }
void Detector::stopReceiver() { pimpl->Parallel(&Module::stopReceiver, {}); }
void Detector::startDetector() {
pimpl->Parallel(&Module::startAcquisition, {});
auto detector_type = getDetectorType().squash();
if (detector_type == defs::MYTHEN3){
auto is_master = getMaster();
std::vector<int> master;
std::vector<int> slaves;
for(int i=0; i<size(); ++i){
if (is_master[i])
master.push_back(i);
else
slaves.push_back(i);
}
pimpl->Parallel(&Module::startAcquisition, slaves);
pimpl->Parallel(&Module::startAcquisition, master);
}else{
pimpl->Parallel(&Module::startAcquisition, {});
}
}
void Detector::startDetectorReadout() {
@ -717,6 +733,9 @@ Result<defs::scanParameters> Detector::getScan(Positions pos) const {
}
void Detector::setScan(const defs::scanParameters t) {
if(getDetectorType().squash() == defs::MYTHEN3 && size()>1 && t.enable != 0){
throw DetectorError("Scan is only allowed for single module Mythen 3 because of synchronization");
}
pimpl->Parallel(&Module::setScan, {}, t);
}
@ -1592,6 +1611,11 @@ Detector::getGateDelayForAllGates(Positions pos) const {
return pimpl->Parallel(&Module::getGateDelayForAllGates, pos);
}
Result<bool> Detector::getMaster(Positions pos) const{
return pimpl->Parallel(&Module::isMaster, pos);
}
// CTB/ Moench Specific
Result<int> Detector::getNumberOfAnalogSamples(Positions pos) const {

View File

@ -1056,11 +1056,15 @@ void DetectorImpl::registerDataCallback(void (*userCallback)(detectorData *,
}
int DetectorImpl::acquire() {
// ensure acquire isnt started multiple times by same client
if (!isAcquireReady()) {
return FAIL;
}
// We need this to handle Mythen3 synchronization
auto detector_type = Parallel(&Module::getDetectorType, {}).squash();
try {
struct timespec begin, end;
clock_gettime(CLOCK_REALTIME, &begin);
@ -1088,7 +1092,25 @@ int DetectorImpl::acquire() {
// start and read all
try {
Parallel(&Module::startAndReadAll, {});
if(detector_type == defs::MYTHEN3 && detectors.size() > 1){
//Multi module mythen
std::vector<int> master;
std::vector<int> slaves;
auto is_master = Parallel(&Module::isMaster, {});
slaves.reserve(detectors.size()-1); //check this one!!
for (size_t i = 0; i<detectors.size(); ++i){
if(is_master[i])
master.push_back(i);
else
slaves.push_back(i);
}
Parallel(&Module::startAcquisition, slaves);
Parallel(&Module::startAndReadAll, master);
}else{
//Normal acquire
Parallel(&Module::startAndReadAll, {});
}
} catch (...) {
if (receiver)
Parallel(&Module::stopReceiver, {});

View File

@ -1994,6 +1994,10 @@ std::array<time::ns, 3> Module::getGateDelayForAllGates() const {
return sendToDetector<std::array<time::ns, 3>>(F_GET_GATE_DELAY_ALL_GATES);
}
bool Module::isMaster() const{
return sendToDetector<int>(F_GET_MASTER);
}
// CTB / Moench Specific
int Module::getNumberOfAnalogSamples() const {
return sendToDetector<int>(F_GET_NUM_ANALOG_SAMPLES);

View File

@ -425,6 +425,7 @@ class Module : public virtual slsDetectorDefs {
int64_t getGateDelay(int gateIndex) const;
void setGateDelay(int gateIndex, int64_t value);
std::array<time::ns, 3> getGateDelayForAllGates() const;
bool isMaster() const;
/**************************************************
* *

View File

@ -220,6 +220,7 @@ enum detFuncs {
F_GET_PATTERN,
F_LOAD_DEFAULT_PATTERN,
F_GET_ALL_THRESHOLD_ENERGY,
F_GET_MASTER,
NUM_DET_FUNCTIONS,
RECEIVER_ENUM_START = 256, /**< detector function should not exceed this
@ -546,6 +547,7 @@ const char* getFunctionNameFromEnum(enum detFuncs func) {
case F_GET_PATTERN: return "F_GET_PATTERN";
case F_LOAD_DEFAULT_PATTERN: return "F_LOAD_DEFAULT_PATTERN";
case F_GET_ALL_THRESHOLD_ENERGY: return "F_GET_ALL_THRESHOLD_ENERGY";
case F_GET_MASTER: return "F_GET_MASTER";
case NUM_DET_FUNCTIONS: return "NUM_DET_FUNCTIONS";
case RECEIVER_ENUM_START: return "RECEIVER_ENUM_START";