diff --git a/otsdaq-mu2e/CFOandDTCCore/CFOandDTCCoreVInterface.h b/otsdaq-mu2e/CFOandDTCCore/CFOandDTCCoreVInterface.h index ec50c251..c02b2c54 100644 --- a/otsdaq-mu2e/CFOandDTCCore/CFOandDTCCoreVInterface.h +++ b/otsdaq-mu2e/CFOandDTCCore/CFOandDTCCoreVInterface.h @@ -13,6 +13,7 @@ #include "mu2e_driver/mu2e_mmap_ioctl.h" // m_ioc_cmd_t, m_ioc_reg_access_t, dtc_address_t, dtc_data_t #include "otsdaq/FECore/FEVInterface.h" +#include "otsdaq/FiniteStateMachine/RunControlIterationConstants.h" namespace ots { @@ -81,6 +82,20 @@ class CFOandDTCCoreVInterface : public FEVInterface static const int CONFIG_DTC_TIMING_CHAIN_START_INDEX = 1; static const int CONFIG_DTC_TIMING_CHAIN_STEPS = 3; + static const int RUN_START_READY_FOR_TRIGGERS_ITERATION = + RunControlIterationConstants::RUN_START_READY_FOR_TRIGGERS_ITERATION; + static_assert(RUN_START_READY_FOR_TRIGGERS_ITERATION > + CONFIG_DTC_TIMING_CHAIN_START_INDEX + CONFIG_DTC_TIMING_CHAIN_STEPS, + "RUN_START_READY_FOR_TRIGGERS_ITERATION must be larger than " + "CONFIG_DTC_TIMING_CHAIN_START_INDEX + CONFIG_DTC_TIMING_CHAIN_STEPS"); + // Iteration where CFO enables event sending (clock marker/RF0/punch/link). + // Must be strictly after timing-chain steps complete. + static const int CONFIG_CFO_EVENT_SENDING_START_ITERATION = + 1 + CONFIG_DTC_TIMING_CHAIN_START_INDEX + CONFIG_DTC_TIMING_CHAIN_STEPS; + static_assert(CONFIG_CFO_EVENT_SENDING_START_ITERATION > + CONFIG_DTC_TIMING_CHAIN_START_INDEX + CONFIG_DTC_TIMING_CHAIN_STEPS, + "CONFIG_CFO_EVENT_SENDING_START_ITERATION must be larger than " + "CONFIG_DTC_TIMING_CHAIN_START_INDEX + CONFIG_DTC_TIMING_CHAIN_STEPS"); bool artdaqMode_ = false; // true to prevent run data file generation diff --git a/otsdaq-mu2e/FEInterfaces/CFOFrontEndInterfaceImpl.cc b/otsdaq-mu2e/FEInterfaces/CFOFrontEndInterfaceImpl.cc index 10f02186..f51d83fe 100644 --- a/otsdaq-mu2e/FEInterfaces/CFOFrontEndInterfaceImpl.cc +++ b/otsdaq-mu2e/FEInterfaces/CFOFrontEndInterfaceImpl.cc @@ -1,4 +1,5 @@ #include "otsdaq-mu2e/FEInterfaces/CFOFrontEndInterface.h" +#include "otsdaq/FiniteStateMachine/RunControlIterationConstants.h" #include "otsdaq/Macros/InterfacePluginMacros.h" //#include "otsdaq/DAQHardware/FrontEndHardwareTemplate.h" //#include "otsdaq/DAQHardware/FrontEndFirmwareTemplate.h" @@ -1458,6 +1459,23 @@ void CFOFrontEndInterface::configureEventBuildingMode(int step) if(step == -1) step = getIterationIndex(); + const int cfoEventSendingStartIteration = + CFOandDTCCoreVInterface::CONFIG_CFO_EVENT_SENDING_START_ITERATION; + if(cfoEventSendingStartIteration <= + CFOandDTCCoreVInterface::CONFIG_DTC_TIMING_CHAIN_START_INDEX + + CFOandDTCCoreVInterface::CONFIG_DTC_TIMING_CHAIN_STEPS) + { + __FE_SS__ + << "Invalid iteration ordering: CONFIG_CFO_EVENT_SENDING_START_ITERATION (" + << cfoEventSendingStartIteration + << ") must be larger than CONFIG_DTC_TIMING_CHAIN_START_INDEX + " + "CONFIG_DTC_TIMING_CHAIN_STEPS (" + << (CFOandDTCCoreVInterface::CONFIG_DTC_TIMING_CHAIN_START_INDEX + + CFOandDTCCoreVInterface::CONFIG_DTC_TIMING_CHAIN_STEPS) + << ")." << __E__; + __FE_SS_THROW__; + } + __FE_COUT_INFO__ << "configureEventBuildingMode() " << step << __E__; if(step < CFOandDTCCoreVInterface::CONFIG_DTC_TIMING_CHAIN_START_INDEX) @@ -1475,15 +1493,7 @@ void CFOFrontEndInterface::configureEventBuildingMode(int step) __FE_COUT__ << "Do nothing while DTCs finish configureForTimingChain..." << __E__; indicateIterationWork(); } - else if(step == CFOandDTCCoreVInterface::CONFIG_DTC_TIMING_CHAIN_START_INDEX + - CFOandDTCCoreVInterface::CONFIG_DTC_TIMING_CHAIN_STEPS) - { - __FE_COUT__ << "CFO reset serdes TX " << __E__; - thisCFO_->ResetAllSERDESTx(); - indicateIterationWork(); - } - else if(step == 1 + CFOandDTCCoreVInterface::CONFIG_DTC_TIMING_CHAIN_START_INDEX + - CFOandDTCCoreVInterface::CONFIG_DTC_TIMING_CHAIN_STEPS) + else if(step == cfoEventSendingStartIteration) { __FE_COUT__ << "Enable communication over links" << __E__; thisCFO_->EnableEmbeddedClockMarker(); @@ -1500,6 +1510,24 @@ void CFOFrontEndInterface::configureEventBuildingMode(int step) __FE_COUT__ << "CFO set 40MHz marker interval" << __E__; //thisCFO_->SetClockMarkerIntervalCount(0x0800); // 0 = NO markers } + else if(step == CFOandDTCCoreVInterface::CONFIG_DTC_TIMING_CHAIN_START_INDEX + + CFOandDTCCoreVInterface::CONFIG_DTC_TIMING_CHAIN_STEPS) + { + if(cfoEventSendingStartIteration > + CFOandDTCCoreVInterface::CONFIG_DTC_TIMING_CHAIN_START_INDEX + + CFOandDTCCoreVInterface::CONFIG_DTC_TIMING_CHAIN_STEPS) + { + __FE_COUT__ << "CFO reset serdes TX " << __E__; + thisCFO_->ResetAllSERDESTx(); + } + else + { + __FE_COUT__ << "Skipping CFO TX reset because event sending was configured " + "to start at iteration " + << cfoEventSendingStartIteration << __E__; + } + indicateIterationWork(); + } else __FE_COUT__ << "Do nothing while other configurable entities finish..." << __E__; @@ -1735,6 +1763,21 @@ void CFOFrontEndInterface::start(std::string runNumber) // runNumber) testAndUpdateTimeAlive("Start"); testRTFClockInEventBuildingMode("Start"); + if(CFOandDTCCoreVInterface::RUN_START_READY_FOR_TRIGGERS_ITERATION <= + CFOandDTCCoreVInterface::CONFIG_DTC_TIMING_CHAIN_START_INDEX + + CFOandDTCCoreVInterface::CONFIG_DTC_TIMING_CHAIN_STEPS) + { + __FE_SS__ + << "Invalid iteration ordering: RUN_START_READY_FOR_TRIGGERS_ITERATION (" + << CFOandDTCCoreVInterface::RUN_START_READY_FOR_TRIGGERS_ITERATION + << ") must be larger than CONFIG_DTC_TIMING_CHAIN_START_INDEX + " + "CONFIG_DTC_TIMING_CHAIN_STEPS (" + << (CFOandDTCCoreVInterface::CONFIG_DTC_TIMING_CHAIN_START_INDEX + + CFOandDTCCoreVInterface::CONFIG_DTC_TIMING_CHAIN_STEPS) + << ")." << __E__; + __FE_SS_THROW__; + } + if(operatingMode_ == CFOandDTCCoreVInterface::CONFIG_MODE_HARDWARE_DEV) { __FE_COUT_INFO__ << "CFO start for HW Dev mode." << __E__; @@ -1756,6 +1799,82 @@ void CFOFrontEndInterface::start(std::string runNumber) // runNumber) loopbackTest(runNumber); __FE_COUT_INFO__ << "End the loopback!" << __E__; } + else if(operatingMode_ == CFOandDTCCoreVInterface::CONFIG_MODE_EVENT_BUILDING) + { + const int startIteration = getIterationIndex(); + if(startIteration < + RunControlIterationConstants::RUN_START_READY_FOR_TRIGGERS_ITERATION) + { + __FE_COUT_INFO__ + << "Delaying CFO run plan launch until start iteration >= " + << RunControlIterationConstants::RUN_START_READY_FOR_TRIGGERS_ITERATION + << __E__; + indicateIterationWork(); + return; + } + + if(startIteration == + RunControlIterationConstants::RUN_START_READY_FOR_TRIGGERS_ITERATION) + { + bool autoFixedWidthRunPlanEnable = false; + try + { + autoFixedWidthRunPlanEnable = + getSelfNode().getNode("AutoFixedWidthRunPlanEnable").getValue(); + } + catch(...) + { + __FE_COUT_WARN__ + << "Missing CFOInterfaceTable AutoFixedWidthRunPlanEnable. " + "Skipping startup run plan launch." + << __E__; + return; + } + + if(!autoFixedWidthRunPlanEnable) + { + __FE_COUT_INFO__ + << "AutoFixedWidthRunPlanEnable is disabled. Skipping startup run " + "plan launch." + << __E__; + return; + } + + const uint32_t numberOfEventWindowMarkers = 0; // 0 means infinite windows + + std::string eventDuration = "100us"; + try + { + eventDuration = getSelfNode() + .getNode("AutoFixedWidthRunPlanEventDuration") + .getValueWithDefault("100us"); + } + catch(...) + { + __FE_COUT_WARN__ + << "Optional CFOInterfaceTable AutoFixedWidthRunPlanEventDuration " + "was not found; defaulting to 100us." + << __E__; + } + + __FE_COUT_INFO__ << "Launching startup fixed-width CFO run plan in infinite " + "mode (count=0) " + << "at duration " << eventDuration << __E__; + + CompileSetAndLaunchTemplateFixedWidthRunPlan(true, + false, + eventDuration, + numberOfEventWindowMarkers, + next_starting_event_window_tag_, + 1, + false, + false, + false, + false); + + next_starting_event_window_tag_ += numberOfEventWindowMarkers; + } + } /* COMMENTED 20-Jun-2023 by rrivera to start using CFO_Register directly.. will need to add features to support loopback revival @@ -1926,7 +2045,10 @@ void CFOFrontEndInterface::stop(void) return; } - // TODO: add CFO Halt or Leave + // Apply explicit CFO halt behavior on stop transition. + halt(); + thisCFO_->DisableBeamOnMode(CFOLib::CFO_Link_ID::CFO_Link_ALL); + thisCFO_->DisableBeamOffMode(CFOLib::CFO_Link_ID::CFO_Link_ALL); int numberOfCAPTANPulses = getConfigurationManager()