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. 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 3. Resolved Issues

View File

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

View File

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

View File

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

View File

@ -246,3 +246,4 @@ int is_virtual(int);
int get_pattern(int); int get_pattern(int);
int load_default_pattern(int); int load_default_pattern(int);
int get_all_threshold_energy(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_GET_PATTERN] = &get_pattern;
flist[F_LOAD_DEFAULT_PATTERN] = &load_default_pattern; flist[F_LOAD_DEFAULT_PATTERN] = &load_default_pattern;
flist[F_GET_ALL_THRESHOLD_ENERGY] = &get_all_threshold_energy; flist[F_GET_ALL_THRESHOLD_ENERGY] = &get_all_threshold_energy;
flist[F_GET_MASTER] = &get_master;
// check // check
if (NUM_DET_FUNCTIONS >= RECEIVER_ENUM_START) { if (NUM_DET_FUNCTIONS >= RECEIVER_ENUM_START) {
@ -638,7 +639,9 @@ int set_timing_mode(int file_des) {
} }
// get // get
retval = getTiming(); retval = getTiming();
#ifndef MYTHEN3D
validate((int)arg, (int)retval, "set timing mode", DEC); validate((int)arg, (int)retval, "set timing mode", DEC);
#endif
LOG(logDEBUG1, ("Timing Mode: %d\n", retval)); LOG(logDEBUG1, ("Timing Mode: %d\n", retval));
return Server_SendResult(file_des, INT32, &retval, sizeof(retval)); return Server_SendResult(file_des, INT32, &retval, sizeof(retval));
@ -8365,3 +8368,18 @@ int get_all_threshold_energy(int file_des) {
#endif #endif
return Server_SendResult(file_des, INT32, retvals, sizeof(retvals)); 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 /** [Mythen3] gate delay for all gates in auto or trigger timing mode
* (internal gating). Gate index: 0-2, -1 for all */ * (internal gating). Gate index: 0-2, -1 for all */
Result<std::array<ns, 3>> getGateDelayForAllGates(Positions pos = {}) const; Result<std::array<ns, 3>> getGateDelayForAllGates(Positions pos = {}) const;
Result<bool> getMaster(Positions pos = {}) const;
///@{ ///@{
/** @name CTB / Moench Specific */ /** @name CTB / Moench Specific */

View File

@ -674,9 +674,25 @@ void Detector::startReceiver() { pimpl->Parallel(&Module::startReceiver, {}); }
void Detector::stopReceiver() { pimpl->Parallel(&Module::stopReceiver, {}); } void Detector::stopReceiver() { pimpl->Parallel(&Module::stopReceiver, {}); }
void Detector::startDetector() { void Detector::startDetector() {
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, {}); pimpl->Parallel(&Module::startAcquisition, {});
} }
}
void Detector::startDetectorReadout() { void Detector::startDetectorReadout() {
pimpl->Parallel(&Module::startReadout, {}); pimpl->Parallel(&Module::startReadout, {});
} }
@ -717,6 +733,9 @@ Result<defs::scanParameters> Detector::getScan(Positions pos) const {
} }
void Detector::setScan(const defs::scanParameters t) { 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); pimpl->Parallel(&Module::setScan, {}, t);
} }
@ -1592,6 +1611,11 @@ Detector::getGateDelayForAllGates(Positions pos) const {
return pimpl->Parallel(&Module::getGateDelayForAllGates, pos); return pimpl->Parallel(&Module::getGateDelayForAllGates, pos);
} }
Result<bool> Detector::getMaster(Positions pos) const{
return pimpl->Parallel(&Module::isMaster, pos);
}
// CTB/ Moench Specific // CTB/ Moench Specific
Result<int> Detector::getNumberOfAnalogSamples(Positions pos) const { Result<int> Detector::getNumberOfAnalogSamples(Positions pos) const {

View File

@ -1056,11 +1056,15 @@ void DetectorImpl::registerDataCallback(void (*userCallback)(detectorData *,
} }
int DetectorImpl::acquire() { int DetectorImpl::acquire() {
// ensure acquire isnt started multiple times by same client // ensure acquire isnt started multiple times by same client
if (!isAcquireReady()) { if (!isAcquireReady()) {
return FAIL; return FAIL;
} }
// We need this to handle Mythen3 synchronization
auto detector_type = Parallel(&Module::getDetectorType, {}).squash();
try { try {
struct timespec begin, end; struct timespec begin, end;
clock_gettime(CLOCK_REALTIME, &begin); clock_gettime(CLOCK_REALTIME, &begin);
@ -1088,7 +1092,25 @@ int DetectorImpl::acquire() {
// start and read all // start and read all
try { try {
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, {}); Parallel(&Module::startAndReadAll, {});
}
} catch (...) { } catch (...) {
if (receiver) if (receiver)
Parallel(&Module::stopReceiver, {}); 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); 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 // CTB / Moench Specific
int Module::getNumberOfAnalogSamples() const { int Module::getNumberOfAnalogSamples() const {
return sendToDetector<int>(F_GET_NUM_ANALOG_SAMPLES); 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; int64_t getGateDelay(int gateIndex) const;
void setGateDelay(int gateIndex, int64_t value); void setGateDelay(int gateIndex, int64_t value);
std::array<time::ns, 3> getGateDelayForAllGates() const; std::array<time::ns, 3> getGateDelayForAllGates() const;
bool isMaster() const;
/************************************************** /**************************************************
* * * *

View File

@ -220,6 +220,7 @@ enum detFuncs {
F_GET_PATTERN, F_GET_PATTERN,
F_LOAD_DEFAULT_PATTERN, F_LOAD_DEFAULT_PATTERN,
F_GET_ALL_THRESHOLD_ENERGY, F_GET_ALL_THRESHOLD_ENERGY,
F_GET_MASTER,
NUM_DET_FUNCTIONS, NUM_DET_FUNCTIONS,
RECEIVER_ENUM_START = 256, /**< detector function should not exceed this 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_GET_PATTERN: return "F_GET_PATTERN";
case F_LOAD_DEFAULT_PATTERN: return "F_LOAD_DEFAULT_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_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 NUM_DET_FUNCTIONS: return "NUM_DET_FUNCTIONS";
case RECEIVER_ENUM_START: return "RECEIVER_ENUM_START"; case RECEIVER_ENUM_START: return "RECEIVER_ENUM_START";