246 lines
8.9 KiB
C++
246 lines
8.9 KiB
C++
// Copyright (2019-2023) Paul Scherrer Institute
|
|
|
|
#include <thread>
|
|
|
|
#include "DetectorWrapper.h"
|
|
#include "../common/JFJochException.h"
|
|
#include "../common/Definitions.h"
|
|
|
|
void DetectorWrapper::Configure(const DiffractionExperiment& experiment,
|
|
const std::vector<AcquisitionDeviceNetConfig>& net_config) {
|
|
logger.Info("Configure");
|
|
try {
|
|
if (det.size() > 0) {
|
|
// Only if the detector is already defined
|
|
|
|
// Stop the detector
|
|
InternalStop();
|
|
|
|
// Clear synchronization prior to reconfiguring the detector
|
|
det.setMaster(false, 0);
|
|
det.setSynchronization(false);
|
|
}
|
|
auto module_hostname = experiment.GetDetectorModuleHostname();
|
|
|
|
if (!module_hostname.empty() > 0) {
|
|
logger.Info("Resetting detector module host names");
|
|
det.setHostname(module_hostname);
|
|
}
|
|
|
|
if (det.size() != experiment.GetModulesNum()) {
|
|
logger.Error("Discrepancy in module number between DAQ and detector");
|
|
throw JFJochException(JFJochExceptionCategory::Detector,
|
|
"Discrepancy in module number between DAQ and detector");
|
|
}
|
|
|
|
det.setNumberofUDPInterfaces(experiment.GetUDPInterfaceCount());
|
|
|
|
auto mod_cfg = experiment.GetDetectorModuleConfig(net_config);
|
|
|
|
for (int i = 0; i < mod_cfg.size(); i++) {
|
|
logger.Info("Configure network for module {}", i);
|
|
|
|
auto &cfg = mod_cfg[i];
|
|
|
|
det.setSourceUDPIP(sls::IpAddr(cfg.ipv4_src_addr_1), {i});
|
|
det.setSourceUDPMAC(sls::MacAddr(BASE_DETECTOR_MAC + i * 2), {i});
|
|
|
|
det.setDestinationUDPPort (cfg.udp_dest_port_1, i);
|
|
det.setDestinationUDPIP( sls::IpAddr(cfg.ipv4_dest_addr_1), {i});
|
|
det.setDestinationUDPMAC( sls::MacAddr(cfg.mac_addr_dest_1), {i});
|
|
|
|
if (experiment.GetUDPInterfaceCount() == 2) {
|
|
det.setSourceUDPIP2(sls::IpAddr(cfg.ipv4_src_addr_2), {i});
|
|
det.setSourceUDPMAC2(sls::MacAddr(BASE_DETECTOR_MAC + i * 2 + 1), {i});
|
|
det.setDestinationUDPPort2(cfg.udp_dest_port_2, i);
|
|
det.setDestinationUDPIP2( sls::IpAddr(cfg.ipv4_dest_addr_2), {i});
|
|
det.setDestinationUDPMAC2(sls::MacAddr(cfg.mac_addr_dest_2), {i});
|
|
}
|
|
uint32_t tmp = (cfg.module_id_in_data_stream * 2) % UINT16_MAX;
|
|
uint32_t column_id_register = ((tmp + 1) << 16) | tmp;
|
|
|
|
det.writeRegister(0x7C, column_id_register, {i});
|
|
}
|
|
|
|
det.setTemperatureControl(true);
|
|
det.setThresholdTemperature(THRESHOLD_TEMPERATURE_DEGC);
|
|
|
|
det.setSynchronization(false);
|
|
|
|
det.setTimingMode(slsDetectorDefs::timingMode::TRIGGER_EXPOSURE);
|
|
|
|
det.setMaster(true, 0);
|
|
det.setSynchronization(true);
|
|
|
|
det.setAutoComparatorDisable(true);
|
|
if (!det.getPowerChip().squash(false)) {
|
|
det.setPowerChip(true);
|
|
std::this_thread::sleep_for(std::chrono::seconds(5));
|
|
}
|
|
|
|
det.setHighVoltage(HIGH_VOLTAGE);
|
|
} catch (const std::exception &e) {
|
|
logger.ErrorException(e);
|
|
throw JFJochException(JFJochExceptionCategory::Detector, e.what());
|
|
}
|
|
logger.Info(" ... done");
|
|
}
|
|
|
|
void DetectorWrapper::Start(const DiffractionExperiment& experiment) {
|
|
logger.Info("Start");
|
|
|
|
if (det.size() != experiment.GetModulesNum())
|
|
throw JFJochException(JFJochExceptionCategory::Detector,
|
|
"Discrepancy in module number between DAQ and detector");
|
|
|
|
try {
|
|
InternalStop();
|
|
switch (experiment.GetDetectorMode()) {
|
|
case DetectorMode::PedestalG1:
|
|
det.setGainMode(slsDetectorDefs::gainMode::FORCE_SWITCH_G1);
|
|
break;
|
|
case DetectorMode::PedestalG2:
|
|
det.setGainMode(slsDetectorDefs::gainMode::FORCE_SWITCH_G2);
|
|
break;
|
|
default:
|
|
det.setGainMode(slsDetectorDefs::gainMode::DYNAMIC);
|
|
break;
|
|
}
|
|
|
|
det.setNextFrameNumber(1);
|
|
|
|
if (experiment.GetNumTriggers() == 1) {
|
|
det.setNumberOfFrames(experiment.GetFrameNumPerTrigger() + DELAY_FRAMES_STOP_AND_QUIT);
|
|
det.setNumberOfTriggers(1);
|
|
} else {
|
|
// More than 1 trigger - detector needs one trigger or few more trigger
|
|
if (experiment.GetStorageCellNumber() > 1)
|
|
det.setNumberOfFrames(1);
|
|
else
|
|
det.setNumberOfFrames(experiment.GetFrameNumPerTrigger());
|
|
|
|
if (experiment.GetFrameNumPerTrigger() < DELAY_FRAMES_STOP_AND_QUIT)
|
|
det.setNumberOfTriggers(experiment.GetNumTriggers() + DELAY_FRAMES_STOP_AND_QUIT);
|
|
else
|
|
det.setNumberOfTriggers(experiment.GetNumTriggers() + 1);
|
|
}
|
|
|
|
det.setStorageCellStart(experiment.GetStorageCellStart());
|
|
det.setNumberOfAdditionalStorageCells(experiment.GetStorageCellNumber() - 1);
|
|
det.setStorageCellDelay(experiment.GetStorageCellDelay() - std::chrono::nanoseconds(MIN_STORAGE_CELL_DELAY_IN_NS));
|
|
|
|
if ((experiment.GetStorageCellNumber() > 1) || (experiment.GetFrameTime().count() < MIN_FRAME_TIME_HALF_SPEED_IN_US))
|
|
det.setReadoutSpeed(slsDetectorDefs::speedLevel::FULL_SPEED);
|
|
else
|
|
det.setReadoutSpeed(slsDetectorDefs::speedLevel::HALF_SPEED);
|
|
|
|
if (experiment.GetStorageCellNumber() > 1) {
|
|
det.setPeriod((experiment.GetFrameTime() + std::chrono::microseconds(10)) * experiment.GetStorageCellNumber() );
|
|
} else
|
|
det.setPeriod(experiment.GetFrameTime());
|
|
|
|
det.setExptime(std::chrono::microseconds(experiment.GetFrameCountTime()));
|
|
|
|
det.startDetector();
|
|
} catch (std::exception &e) {
|
|
logger.ErrorException(e);
|
|
throw JFJochException(JFJochExceptionCategory::Detector, e.what());
|
|
}
|
|
|
|
logger.Info(" ... done");
|
|
}
|
|
|
|
void DetectorWrapper::InternalStop() {
|
|
// Assume it is executed in try-catch!
|
|
auto state = GetState();
|
|
if (state == DetectorState::ERROR)
|
|
throw JFJochException(JFJochExceptionCategory::Detector,
|
|
"Detector in error state");
|
|
else if (state == DetectorState::BUSY) {
|
|
try {
|
|
// Sometimes stop gives problem - ignore these
|
|
logger.Warning("Problem with stopping the detector - ignored.");
|
|
det.stopDetector();
|
|
} catch (...) {}
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
state = GetState();
|
|
if (state != DetectorState::IDLE)
|
|
throw JFJochException(JFJochExceptionCategory::Detector,
|
|
"Detector busy and cannot be stopped");
|
|
}
|
|
}
|
|
|
|
void DetectorWrapper::Deactivate() {
|
|
logger.Info("Deactivate");
|
|
try {
|
|
InternalStop();
|
|
det.setHighVoltage(0);
|
|
std::this_thread::sleep_for(std::chrono::seconds(5));
|
|
det.setPowerChip(false);
|
|
} catch (std::exception &e) {
|
|
logger.ErrorException(e);
|
|
throw JFJochException(JFJochExceptionCategory::Detector, e.what());
|
|
}
|
|
logger.Info(" ... done");
|
|
}
|
|
|
|
void DetectorWrapper::Stop() {
|
|
logger.Info("Stop");
|
|
try {
|
|
InternalStop();
|
|
} catch (std::exception &e) {
|
|
logger.ErrorException(e);
|
|
throw JFJochException(JFJochExceptionCategory::Detector, e.what());
|
|
}
|
|
logger.Info(" ... done");
|
|
}
|
|
|
|
void DetectorWrapper::Trigger() {
|
|
logger.Info("Trigger");
|
|
try {
|
|
det.sendSoftwareTrigger();
|
|
} catch (std::exception &e) {
|
|
logger.ErrorException(e);
|
|
throw JFJochException(JFJochExceptionCategory::Detector, e.what());
|
|
}
|
|
logger.Info(" ... done");
|
|
}
|
|
|
|
DetectorWrapper::DetectorState DetectorWrapper::GetState() const {
|
|
try {
|
|
bool is_idle = true;
|
|
for (auto & i : det.getDetectorStatus()) {
|
|
if (i == slsDetectorDefs::runStatus::ERROR)
|
|
return DetectorState::ERROR;
|
|
if ((i != slsDetectorDefs::runStatus::IDLE) &&
|
|
(i != slsDetectorDefs::runStatus::STOPPED) &&
|
|
(i != slsDetectorDefs::runStatus::RUN_FINISHED))
|
|
is_idle = false;
|
|
}
|
|
if (is_idle)
|
|
return DetectorState::IDLE;
|
|
else
|
|
return DetectorState::BUSY;
|
|
} catch (std::exception &e) {
|
|
throw JFJochException(JFJochExceptionCategory::Detector, e.what());
|
|
}
|
|
}
|
|
|
|
int64_t DetectorWrapper::GetFirmwareVersion() {
|
|
try {
|
|
auto result = det.getFirmwareVersion();
|
|
return result.squash(0x0);
|
|
} catch (std::exception &e) {
|
|
throw JFJochException(JFJochExceptionCategory::Detector, e.what());
|
|
}
|
|
}
|
|
|
|
std::string DetectorWrapper::GetDetectorServerVersion() {
|
|
try {
|
|
auto result = det.getDetectorServerVersion();
|
|
return result.squash("");
|
|
} catch (std::exception &e) {
|
|
throw JFJochException(JFJochExceptionCategory::Detector, e.what());
|
|
}
|
|
}
|