diff --git a/.gitignore b/.gitignore index 92cc6e3..6a59017 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,8 @@ *~ +*.log +*.save +*.tmp +*.hist \#*\# core.* *.vcxproj* diff --git a/CMakeLists.txt b/CMakeLists.txt index e69de29..04ab860 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -0,0 +1,87 @@ +# ====================================================================== +# otsdaq-mu2e-sync main build file +# +# cd .../path/to/build/directory +# source .../path/to/otsdaq-mu2e-sync/ups/setup_for_development +# buildtool +# ====================================================================== + +cmake_minimum_required (VERSION 3.19 FATAL_ERROR) + +find_package(cetmodules 3.16.00 REQUIRED) + +project(otsdaq-mu2e-sync VERSION 1.00.00) + +include(CetCMakeEnv) +cet_cmake_env() +SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + +cet_set_compiler_flags(DIAGS VIGILANT + WERROR + NO_UNDEFINED + EXTRA_FLAGS -pedantic -Wno-unused-parameter -Wno-ignored-qualifiers + ) + + +string(TOUPPER ${CMAKE_BUILD_TYPE} BTYPE_UC) +if(BTYPE_UC STREQUAL DEBUG) + add_definitions(-DDEBUGME) + if(DEFINED ENV{USE_ASAN}) + if($ENV{USE_ASAN} GREATER 0) + message("!!! Address Sanitizer Activated!!!") + message("!!! Note: To run, add 'export ASAN_OPTIONS=verify_asan_link_order=0' to setup !!!") + add_compile_options(-fsanitize=address -Wno-unused-command-line-argument) + add_link_options(-lasan) + endif() + endif() + if(DEFINED ENV{USE_TSAN}) + if($ENV{USE_TSAN} GREATER 0) + message("!!! Thread Sanitizer Activated!!!") + add_compile_options(-fsanitize=thread -Wno-unused-command-line-argument -Wno-tsan) + add_link_options(-ltsan) + endif() + endif() + if(DEFINED ENV{USE_UBSAN}) + if($ENV{USE_UBSAN} GREATER 0) + message("!!! \"Undefined Behavior\" Sanitizer Activated!!!") + add_compile_options(-fsanitize=undefined -Wno-unused-command-line-argument) + add_link_options(-lubsan) + endif() + endif() + if(DEFINED ENV{USE_GCOV}) + add_compile_options(-fprofile-arcs -ftest-coverage --coverage) + add_link_options(--coverage) + endif() +endif() + +#exeption stack trace +if(DEFINED ENV{USE_EXCEPTIONSTACKTRACE}) + if($ENV{USE_EXCEPTIONSTACKTRACE} GREATER 0) + message("!!! Exception StackTrace Activated!!!") + add_definitions(-D EXCEPTIONSTACKTRACE) + set( EXCEPTIONSTACKTRACE_LIB artdaq-core_Utilities_ExceptionStackTrace ) + add_compile_options( -rdynamic -Wno-unused-command-line-argument ) + add_link_options( -rdynamic ) + endif() +endif() + +#cet_report_compiler_flags() + +# these are minimum required versions, not the actual product versions +find_package(otsdaq-mu2e 1.02.00 REQUIRED) + +# Mu2e Offline Extra setup +find_package(Offline v11_00_00 REQUIRED) +include_directories($ENV{BTRK_INC} $ENV{KINKAL_INC}) +link_directories($ENV{BTRK_LIB} $ENV{KINKAL_LIB}) + +# XDAQ Extra setup +include_directories($ENV{XDAQ_ROOT}/include/linux $ENV{XDAQ_ROOT}/include) +link_directories($ENV{XDAQ_ROOT}/lib) + +include(BuildPlugins) + +# Code +add_subdirectory(otsdaq-mu2e-sync) + +cet_cmake_config() diff --git a/CMakeLists.txt~ b/CMakeLists.txt~ new file mode 100644 index 0000000..494a55e --- /dev/null +++ b/CMakeLists.txt~ @@ -0,0 +1,101 @@ +# ====================================================================== +# otsdaq-mu2e-sync main build file +# +# cd .../path/to/build/directory +# source .../path/to/otsdaq-mu2e-sync/ups/setup_for_development +# buildtool +# ====================================================================== + +cmake_minimum_required (VERSION 3.19 FATAL_ERROR) + +find_package(cetmodules 3.16.00 REQUIRED) + +project(otsdaq-mu2e-sync VERSION 6.00.00) + +include(CetCMakeEnv) +cet_cmake_env() +SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + +cet_set_compiler_flags(DIAGS VIGILANT + WERROR + NO_UNDEFINED + EXTRA_FLAGS -pedantic -Wno-unused-parameter -Wno-ignored-qualifiers + ) + + +string(TOUPPER ${CMAKE_BUILD_TYPE} BTYPE_UC) +if(BTYPE_UC STREQUAL DEBUG) + add_definitions(-DDEBUGME) + if(DEFINED ENV{USE_ASAN}) + if($ENV{USE_ASAN} GREATER 0) + message("!!! Address Sanitizer Activated!!!") + message("!!! Note: To run, add 'export ASAN_OPTIONS=verify_asan_link_order=0' to setup !!!") + add_compile_options(-fsanitize=address -Wno-unused-command-line-argument) + add_link_options(-lasan) + endif() + endif() + if(DEFINED ENV{USE_TSAN}) + if($ENV{USE_TSAN} GREATER 0) + message("!!! Thread Sanitizer Activated!!!") + add_compile_options(-fsanitize=thread -Wno-unused-command-line-argument -Wno-tsan) + add_link_options(-ltsan) + endif() + endif() + if(DEFINED ENV{USE_UBSAN}) + if($ENV{USE_UBSAN} GREATER 0) + message("!!! \"Undefined Behavior\" Sanitizer Activated!!!") + add_compile_options(-fsanitize=undefined -Wno-unused-command-line-argument) + add_link_options(-lubsan) + endif() + endif() + if(DEFINED ENV{USE_GCOV}) + add_compile_options(-fprofile-arcs -ftest-coverage --coverage) + add_link_options(--coverage) + endif() +endif() + +#exeption stack trace +if(DEFINED ENV{USE_EXCEPTIONSTACKTRACE}) + if($ENV{USE_EXCEPTIONSTACKTRACE} GREATER 0) + message("!!! Exception StackTrace Activated!!!") + add_definitions(-D EXCEPTIONSTACKTRACE) + set( EXCEPTIONSTACKTRACE_LIB artdaq-core_Utilities_ExceptionStackTrace ) + add_compile_options( -rdynamic -Wno-unused-command-line-argument ) + add_link_options( -rdynamic ) + endif() +endif() + +#cet_report_compiler_flags() + +# these are minimum required versions, not the actual product versions +find_package(otsdaq-mu2e 1.02.00 REQUIRED) + +#find_package(art_root_io 1.10.01 REQUIRED) + +# Mu2e Offline Extra setup +find_package(Offline v11_00_00 REQUIRED) +include_directories($ENV{BTRK_INC} $ENV{KINKAL_INC}) +link_directories($ENV{BTRK_LIB} $ENV{KINKAL_LIB}) + + # XDAQ Extra setup + include_directories($ENV{XDAQ_ROOT}/include/linux $ENV{XDAQ_ROOT}/include) +link_directories($ENV{XDAQ_ROOT}/lib) + + +include(BuildPlugins) + +# Code +add_subdirectory(otsdaq-mu2e-sync) + +# Useful scripts +add_subdirectory(tools) + +# Test Programs +add_subdirectory(test) + +# Documentation directory +#add_subdirectory(doc) + +install(DIRECTORY test DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/otsdaq-mu2e-sync) + +cet_cmake_config() diff --git a/README.md b/README.md index 2876b38..8dd417d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# otsdaq-mu2e-sync +# otsdaq-mu2e-dqm This package is a part of the Mu2e TDAQ Suite @@ -22,3 +22,64 @@ This package is a part of the Mu2e TDAQ Suite # Additional Documentation (Package-Specific) +Here is a bit of information about this Repo and its use: + +# Log in From on mu2edaq01 + +``` +$ ssh -X mu2edaq13 +$ cd ~test_stand/ots_agg +$ source setup_ots.sh +$ mz +``` +# Create the directory from this Repo +``` +$ create repo via: +$ UpdateOTS.sh --pullall +$ source ots_get_and_fix_repo.sh otsdaq-mu2e-sync +$ mz +``` + +# Too push code to this repo: +``` +$ git status +$ git add NEW_STUFF +$ git commit -m "Information about new stuff" +$ git push origin develop (develop is branch name here) +``` +# To Clone this repo +``` +$ mrb gitCheckout -d mu2e_otsdaq_sync http://cdcvs.fnal.gov/projects/mu2e-otsdaq-sync +``` +# Modify CMake files in order to compile +``` +$ cp CMakeLists.txt +``` +from mu2e trigger directory. Will need to add in similar files to each subdirectory. Check for places we might need to change things. + +Also remember to add in the new directory to the Head CMakeList.txt in srcs: + +``` +$ cd YOUR_TOP_DIRECTORY_NAME/srcs +$ EDITOR_NAME CMakeList.txt +``` +Copy another package block and change the name : + +``` +set(otsdaq_mu2e_sync_not_in_ups true) +include_directories ( ${CMAKE_CURRENT_SOURCE_DIR}/otsdaq_mu2e_sync ) +include_directories ( $ENV{MRB_BUILDDIR}/otsdaq_mu2e_sync ) + +``` +# Clean Build: +``` +$ mz +``` + +# To Use this Repo to make your own ARTMODULE with Vizualizer: + +- The example I created is inside ArtModule - it is called Prototype module. +- In that module you will see how we connect to the TCP. Here only 1 TH1F is filled and Broadcast. +- The Histograms have there own class - ProtoTypeHist - in there you have to book and initiate all the RootObjects. +- The Consumer for this example is in DataProcessorPlugins - see dqmMu2eHistoConsumer_processor.cc to see how the consumer reads the root object using only the name. You must have a class member of the same type as you filled in you module. There is o need to rename or rebook (that's why we have the class). +- To add in Mu2e DataProducts you need to make sure you add in the Mu2e libraries- see ArtModule/CMakeList for examples. diff --git a/otsdaq-mu2e-sync/.gitignore b/otsdaq-mu2e-sync/.gitignore new file mode 100644 index 0000000..b25c15b --- /dev/null +++ b/otsdaq-mu2e-sync/.gitignore @@ -0,0 +1 @@ +*~ diff --git a/otsdaq-mu2e-sync/ArtModules/CMakeLists.txt b/otsdaq-mu2e-sync/ArtModules/CMakeLists.txt new file mode 100644 index 0000000..88c90df --- /dev/null +++ b/otsdaq-mu2e-sync/ArtModules/CMakeLists.txt @@ -0,0 +1,19 @@ + +cet_build_plugin(SyncAna art::module LIBRARIES REG +art_root_io::TFileService_service +artdaq-core-mu2e::Data +canvas::canvas +otsdaq-mu2e::ArtModules +otsdaq::NetworkUtilities +Offline::Mu2eUtilities +Offline::RecoDataProducts +ROOT::Hist +ROOT::Tree +ROOT::Core +ROOT::RIO +ROOT::Gui +) + +install_headers() +install_source() +install_fhicl(SUBDIRS fcl) diff --git a/otsdaq-mu2e-sync/ArtModules/SyncAna_module.cc b/otsdaq-mu2e-sync/ArtModules/SyncAna_module.cc new file mode 100644 index 0000000..09a7b1a --- /dev/null +++ b/otsdaq-mu2e-sync/ArtModules/SyncAna_module.cc @@ -0,0 +1,166 @@ +// Author: M. Stortini +// Analyze time sync data + +// Framework +#include "art/Framework/Core/EDAnalyzer.h" +#include "art/Framework/Core/ModuleMacros.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "art_root_io/TFileService.h" + +// Offline +#include "Offline/RecoDataProducts/inc/MTPHit.hh" + +// Online +#include "otsdaq/Macros/CoutMacros.h" +#include "otsdaq/Macros/ProcessorPluginMacros.h" +#include "otsdaq/MessageFacility/MessageFacility.h" +#include "otsdaq/NetworkUtilities/TCPSendClient.h" + +// ROOT +#include +#include +#include +#include + +// TRACE +#include "trace.h" +#define TRACE_NAME "SyncAna" + +using namespace mu2e; +namespace ots +{ + class SyncAna : public art::EDAnalyzer + { + public: + struct Config + { + // clang-format off + using Name = fhicl::Name; + using Comment = fhicl::Comment; + fhicl::Atom mtpTag{Name("mtpTag") , Comment("Timing paddle hit collection tag")}; + fhicl::Atom diag {Name("diagLevel"), Comment("Diagnostic level"), 0}; + // clang-format on + }; + + typedef art::EDAnalyzer::Table Parameters; + + explicit SyncAna(Parameters const& conf); + + void analyze(art::Event const& event) override; + void beginRun(art::Run const&) override; + void beginJob() override; + void endJob() override; + + void bookHistograms(const int index); + void fillHistograms(const int index); + + private: + // Histogram info + enum {kMaxHists = 100}; + struct Hist_t { + TH1* nhits; + TH1* delta_t; + TH1* delta_t_prev; + }; + + // Inputs + std::string mtpTag_; + int diagLevel_, evtCounter_; + art::ServiceHandle tfs_; + + // Data + const MTPHitCollection* mtpHits_; + Hist_t* hist_[kMaxHists]; // histogram books + + double prev_hit_time_ = 0.; // for comparing separation between hits (cosmics) + int evt_since_last_hit_ = -1; + + }; +} // namespace ots + +ots::SyncAna::SyncAna(Parameters const& conf) + : art::EDAnalyzer(conf) + , mtpTag_(conf().mtpTag()) + , diagLevel_(conf().diag()) + , evtCounter_(0) +{ + __COUT__ << "[SyncAna::" << __func__ << "] Constructor" << std::endl; +} + +void ots::SyncAna::beginJob() +{ + __COUT__ << "[SyncAna::" << __func__ << "] Beginning job" << std::endl; + for(int index = 0; index < kMaxHists; ++index) hist_[index] = nullptr; + + bookHistograms(0); +} + +void ots::SyncAna::bookHistograms(const int index) { + if(index >= kMaxHists) throw cet::exception("BADCONFIG") << "Histogram index " << index << " larger than maximum " << kMaxHists; + if(hist_[index]) throw cet::exception("BADCONFIG") << "Histogram index " << index << " already booked!"; + hist_[index] = new Hist_t; + + // Create the histograms of interest + art::TFileDirectory dir = tfs_->mkdir(std::format("hist_{}", index)); + Hist_t* Hist = hist_[index]; + Hist->nhits = dir.make("nhits" , "N(MTP hits)" , 50, 0, 50); + Hist->delta_t = dir.make("delta_t", "#Deltat (ns)" , 300, -50, 250); + Hist->delta_t_prev = dir.make("delta_t_prev", "#Deltat (us)", 10000, 0., 5.e6); + +} + +void ots::SyncAna::fillHistograms(const int index) { + if(!hist_[index]) throw cet::exception("BADCONFIG") << "Histogram index " << index << " not booked!"; + Hist_t* Hist = hist_[index]; + Hist->nhits ->Fill(mtpHits_->size()); + + constexpr double time_evt = 1.e5; + double deltaT = 0.0, time_prev(prev_hit_time_ - evt_since_last_hit_*time_evt); + for (size_t i=0; isize(); i++) { + const double time = mtpHits_->at(i).time(); + if(i > 0) { + deltaT = time - time_prev; // - 10000.; + Hist->delta_t->Fill(deltaT); + } else if(evt_since_last_hit_ >= 0) { + Hist->delta_t_prev->Fill((time - time_prev)/1000.); // fill in us + } + time_prev = time; + } +} + +void ots::SyncAna::analyze(art::Event const& event) +{ + ++evtCounter_; + TLOG(TLVL_DEBUG + 20) << "[SyncAna::" << __func__ << "] Analyzing event " + << evtCounter_ << ": " << event.id() << std::endl; + + art::Handle mtpH; + if(!event.getByLabel(mtpTag_, mtpH) || !mtpH.product()) { + TLOG(TLVL_WARNING) << "[SyncAna::" << __func__ << "] No MTP hit collection found!\n"; + mtpHits_ = nullptr; + } else { + mtpHits_ = mtpH.product(); + TLOG(TLVL_DEBUG + 21) << "[SyncAna::" << __func__ << "] Event " << event.id() + << " has " << mtpHits_->size() << " MTP hits\n"; + } + + // fill the histograms of interest + if(mtpHits_) fillHistograms(0); + + if(!mtpHits_->empty()) { // new hit found + prev_hit_time_ = mtpHits_->back().time(); + evt_since_last_hit_ = 1; + } else if(evt_since_last_hit_ >= 0) ++evt_since_last_hit_; // increment if no hit was found + +} + +void ots::SyncAna::endJob() +{ + __COUT__ << "[SyncAna::" << __func__ << "] Ending job, saw " << evtCounter_ + << " events\n"; +} + +void ots::SyncAna::beginRun(const art::Run&) {} + +DEFINE_ART_MODULE(ots::SyncAna) diff --git a/otsdaq-mu2e-sync/CMakeLists.txt b/otsdaq-mu2e-sync/CMakeLists.txt new file mode 100644 index 0000000..059e9d4 --- /dev/null +++ b/otsdaq-mu2e-sync/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(FEInterfaces) +add_subdirectory(ArtModules) diff --git a/otsdaq-mu2e-sync/FEInterfaces/CMakeLists.txt b/otsdaq-mu2e-sync/FEInterfaces/CMakeLists.txt new file mode 100644 index 0000000..f9aa0d0 --- /dev/null +++ b/otsdaq-mu2e-sync/FEInterfaces/CMakeLists.txt @@ -0,0 +1,20 @@ +include(otsdaq::FEInterface) + +cet_make_library( + LIBRARY_NAME ROCMobileSyncInterface + SOURCE ROCMobileSyncInterface_interface.cc + LIBRARIES PUBLIC + otsdaq-mu2e::ROCCore + otsdaq-mu2e::ROCPolarFireCoreInterface + ) + +cet_build_plugin(ROCMobileSyncInterface + otsdaq::FEInterface + LIBRARIES REG + otsdaq-mu2e::ROCCore + otsdaq-mu2e::ROCPolarFireCoreInterface + otsdaq::Macros + ) + +install_headers() +install_source() diff --git a/otsdaq-mu2e-sync/FEInterfaces/ROCMobileSyncInterface_interface.cc b/otsdaq-mu2e-sync/FEInterfaces/ROCMobileSyncInterface_interface.cc new file mode 100644 index 0000000..3bec179 --- /dev/null +++ b/otsdaq-mu2e-sync/FEInterfaces/ROCMobileSyncInterface_interface.cc @@ -0,0 +1,492 @@ +#include "otsdaq-mu2e-sync/FEInterfaces/ROCMobileSyncInterface_interface.h" +#include "otsdaq/Macros/InterfacePluginMacros.h" + +#include "cetlib/filepath_maker.h" + +#include +#include +#include +#include +#include + +using namespace ots; + +#undef __MF_SUBJECT__ +#define __MF_SUBJECT__ "FE-ROCMobileSyncInterface" + +// extern "C" { +// #include "MU2E-API/API_I2C.h" +// #include "MU2E-API/SBL_utils.h" +// } + +// 259 (and others) ==> the number of words in block read is written first as a block +// write + +//========================================================================================= +ROCMobileSyncInterface::ROCMobileSyncInterface( + const std::string& rocUID, + const ConfigurationTree& theXDAQContextConfigTree, + const std::string& theConfigurationPath) + : ROCPolarFireCoreInterface(rocUID, theXDAQContextConfigTree, theConfigurationPath) +{ + INIT_MF("." /*directory used is USER_DATA/LOG/.*/); + + __CFG_COUT__ << "Constructor..." << __E__; + + __CFG_COUT_INFO__ << "ROCPolarFireCoreInterface instantiated with link: " << linkID_ + << " and EventWindowDelayOffset = " << delay_ << __E__; + + registerFEMacroFunction("Configure State Machine", + static_cast( + &ROCMobileSyncInterface::Configure), + std::vector{}, // inputs parameters + std::vector{}, // output parameters + 1 // requiredUserPermissions + ); + + registerFEMacroFunction("Read Histograms", + static_cast( + &ROCMobileSyncInterface::ReadMarkerHistograms), + std::vector{}, // inputs parameters + std::vector{"Plotly_Plot0", + "Plotly_Plot1", + "Plotly_Plot2", + "histograms"}, // output parameters + 1 // requiredUserPermissions + ); + + registerFEMacroFunction("Reset", + static_cast( + &ROCMobileSyncInterface::Reset), + std::vector{}, // inputs parameters + std::vector{}, // output parameters + 1 // requiredUserPermissions + ); + + registerFEMacroFunction( + "Setup For Run", + static_cast( + &ROCMobileSyncInterface::PrepareDataRuns), + std::vector{"Enable Delay (Default := true)", + "Delay amount (Default := 0)"}, // inputs parameters + std::vector{}, // output parameters + 1 // requiredUserPermissions + ); + + registerFEMacroFunction( + "Selective Reset", + static_cast( + &ROCMobileSyncInterface::SelectiveReset), + std::vector{"40MHz Clock Generator (Default := false)", + "Forward Detector (Default := false)", + "Command Handler (Default := false)", + "Timestamp Manager (Default := false)", + "DCS Receive FIFO (Default := false)", + "ROC Monitor (Default := false)", + "DCS Response FIFO (Default := false)", + "Packet Sender (Default := false)", + "Receive FIFO (Default := false)", + "Response FIFO (Default := false)", + "BERT (Default := false)"}, // inputs parameters + std::vector{}, // output parameters + 1 // requiredUserPermissions + ); + + registerFEMacroFunction( + "Reset Histograms", + static_cast( + &ROCMobileSyncInterface::ResetHistograms), + std::vector{ + "Forward Detector Loopback Markers (Default := false)", + "Forward Detector Clock Markers (Default := false)", + "Forward Detector Event Markers (Default := false)", + "Timestamp Manager Event Markers (Default := false)", + "Packet Sender Loopback Markers(Default := false)"}, // inputs parameters + std::vector{}, // output parameters + 1 // requiredUserPermissions + ); + + registerFEMacroFunction("Read Rx FIFO", + static_cast( + &ROCMobileSyncInterface::ReadRxFIFO), + std::vector{}, // inputs parameters + std::vector{"Result"}, // output parameters + 1 // requiredUserPermissions + ); + + registerFEMacroFunction("Read Tx FIFO", + static_cast( + &ROCMobileSyncInterface::ReadTxFIFO), + std::vector{}, // inputs parameters + std::vector{"Result"}, // output parameters + 1 // requiredUserPermissions + ); + + registerFEMacroFunction( + "BERT Setup", + static_cast( + &ROCMobileSyncInterface::BERT), + std::vector{ + "Transmit PRBS7 (Default := false)", + "BER Received data (Default := false)", + "RX fixed pattern (Default := true)", + "External loopback mode (Default := false)"}, // inputs parameters + std::vector{}, // output parameters + 1 // requiredUserPermissions + ); +} // end constructor() + +//========================================================================================== +ROCMobileSyncInterface::~ROCMobileSyncInterface(void) +{ + // NOTE:: be careful not to call __FE_COUT__ decoration because it uses the + // tree and it may already be destructed partially + __COUT__ << FEVInterface::interfaceUID_ << "Destructed." << __E__; +} // end destructor() + +//====================================================================================================== + +void ROCMobileSyncInterface::configure(void) +try +{ + // ROCPolarFireCoreInterface::configure(); + + // consider that we know all the init files + // all the init information are stored in the configuration tree // + // set parameter + // int linkID = getSelfNode().getNode("linkID").getValue(); + // __COUTV__(linkID); + + // runSequenceOfCommands("ROCTypeLinkTable/LinkToConfigureSequence"); /*Run Configure Sequence Commands*/ + + // reset all blocks using reset controller (including 40mhz clock) + writeRegister(0, 0); + usleep(500000); + + // // disable PRBS7 generator & error checker -- For fiber testing, no longer used + // writeRegister(49, 0); + // usleep(100000); + + // reset ROC Mon blocks (enables packet sender) + readRegister(43); + + // check reset is done, register 0x0 is debug register + readRegister(0); + + // event start and loopback delay + writeRegister(21, 0); + usleep(100000); + + // Event start and loopback delay enable + writeRegister(45, 1); + usleep(100000); + // check reset is done, register 0x0 is debug register + readRegister(1); + + // writeRegister(22, 1); // DCS alignment request (reset histograms in FD) + readRegister(44); // reset loopback counters and histograms + usleep(100000); + // check reset is done, register 0x0 is debug register + readRegister(2); + usleep(100000); + + // reset FSM and FIFOs for timestamping + readRegister(36); + + // int myTemp = GetTemperature(1); + // __COUTV__(myTemp); + // __COUT__<<"my temp"<ReadExtROCRegister(linkID_, loc_addr, i) + << __E__; + } + return outss.str(); +} + +//================================================================================================== +void ROCMobileSyncInterface::ReadTxFIFO(__ARGS__) +{ + __COUT_INFO__ << "ReadTxFIFO called" << __E__; + __SET_ARG_OUT__("Result", ROCMobileSyncInterface::readBuffer(11)); +} + +//================================================================================================== +void ROCMobileSyncInterface::ReadRxFIFO(__ARGS__) +{ + __COUT_INFO__ << "ReadRxFIFO called" << __E__; + __SET_ARG_OUT__("Result", ROCMobileSyncInterface::readBuffer(8)); +} + +//================================================================================================== +std::vector ROCMobileSyncInterface::readHistogram( + std::vector& histAddrs, + uint32_t loc_addr, + std::stringstream& outss) +{ + std::vector hist; + uint16_t binValue; + for(int i = 0; i < 5; i++) + { + binValue = getDTC()->ReadExtROCRegister(linkID_, loc_addr, histAddrs[i]); + hist.push_back(binValue); + std::string label = "bin " + std::to_string(i - 2) + ":"; + outss << std::left << std::setw(12) << label << std::right << std::setw(5) + << binValue << __E__; + } + return hist; +} + +//================================================================================================== +std::array ROCMobileSyncInterface::ReadMarkerHistograms(void) +{ + std::string histogramFD = histogramTemplate3Markers; + std::string histogramPS = histogramTemplate1Marker; + std::string histogramTM = histogramTemplate1Marker; + + std::vector loopbackHistAddrsFD = {30, 31, 32, 33, 34}; + std::vector loopbackHistAddrsPS = {27, 28, 29, 30, 31}; + std::vector clockkHistAddrsFD = {20, 21, 22, 23, 24}; + std::vector eventHistAddrsFD = {25, 26, 27, 28, 29}; + std::vector eventHistAddrsTM = {1, 2, 3, 4, 5}; + std::map> histograms; + std::stringstream outss; + + outss << "Loopback Marker Histogram (Forward Detector)" << __E__; + histograms["loopbackFD"] = readHistogram(loopbackHistAddrsFD, 8, outss); + + outss << "Loopback Marker Histogram (Packet Sender)" << __E__; + histograms["loopbackPS"] = readHistogram(loopbackHistAddrsPS, 11, outss); + + outss << "Clock Marker Histogram (Forward Detector)" << __E__; + histograms["clockFD"] = readHistogram(clockkHistAddrsFD, 8, outss); + + outss << "Event Marker Histogram (Forward Detector)" << __E__; + histograms["eventFD"] = readHistogram(eventHistAddrsFD, 8, outss); + + outss << "Event Marker Histogram (Timestamp Manager)" << __E__; + histograms["eventTM"] = readHistogram(eventHistAddrsTM, 12, outss); + + std::string data = + "[" + StringMacros::vectorToString(histograms["loopbackFD"], ",") + "]"; + histogramFD = std::regex_replace(histogramFD, std::regex(""), data); + data = "[" + StringMacros::vectorToString(histograms["clockFD"], ",") + "]"; + histogramFD = std::regex_replace(histogramFD, std::regex(""), data); + data = "[" + StringMacros::vectorToString(histograms["eventFD"], ",") + "]"; + histogramFD = std::regex_replace(histogramFD, std::regex(""), data); + histogramFD = + std::regex_replace(histogramFD, std::regex(""), "\"Forward Detector\""); + + data = "[" + StringMacros::vectorToString(histograms["loopbackPS"], ",") + "]"; + histogramPS = std::regex_replace(histogramPS, std::regex("<MARKER-DATA>"), data); + histogramPS = std::regex_replace( + histogramPS, std::regex("<MARKER-TYPE>"), "\"Loopback Marker\""); + histogramPS = + std::regex_replace(histogramPS, std::regex("<TITLE>"), "\"Packet Sender\""); + + data = "[" + StringMacros::vectorToString(histograms["eventTM"], ",") + "]"; + histogramTM = std::regex_replace(histogramTM, std::regex("<MARKER-DATA>"), data); + histogramTM = + std::regex_replace(histogramTM, std::regex("<MARKER-TYPE>"), "\"Event Marker\""); + histogramTM = + std::regex_replace(histogramTM, std::regex("<TITLE>"), "\"Timestamp Manager\""); + + std::array<std::string, 4> outArr = { + outss.str(), histogramFD, histogramPS, histogramTM}; + return outArr; +} + +//====================================================================================================== +void ROCMobileSyncInterface::ReadMarkerHistograms(__ARGS__) +{ + std::array<std::string, 4> result = ROCMobileSyncInterface::ReadMarkerHistograms(); + __SET_ARG_OUT__("histograms", "\n" + result[0]); + __SET_ARG_OUT__("Plotly_Plot0", result[1]); + __SET_ARG_OUT__("Plotly_Plot1", result[2]); + __SET_ARG_OUT__("Plotly_Plot2", result[3]); +} + +//====================================================================================================== +void ROCMobileSyncInterface::ResetHistograms(__ARGS__) +{ + uint16_t resetControl = 0x0; + bool enable = __GET_ARG_IN__( + "Forward Detector Loopback Markers (Default := false)", bool, false); + resetControl = resetControl | (enable << 0); + enable = + __GET_ARG_IN__("Forward Detector Clock Markers (Default := false)", bool, false); + resetControl = resetControl | (enable << 1); + enable = + __GET_ARG_IN__("Forward Detector Event Markers (Default := false)", bool, false); + resetControl = resetControl | (enable << 2); + enable = + __GET_ARG_IN__("Timestamp Manager Event Markers (Default := false)", bool, false); + resetControl = resetControl | (enable << 3); + enable = + __GET_ARG_IN__("Packet Sender Loopback Markers(Default := false)", bool, false); + resetControl = resetControl | (enable << 4); + writeRegister(50, resetControl); +} + +//====================================================================================================== +void ROCMobileSyncInterface::Reset(__ARGS__) { writeRegister(0, 0); } + +//====================================================================================================== +void ROCMobileSyncInterface::SelectiveReset(__ARGS__) +{ + uint16_t resetControl = 0x0; + bool enable = __GET_ARG_IN__("40MHz Clock Generator (Default := false)", bool, false); + resetControl = resetControl | (enable << 0); + enable = __GET_ARG_IN__("Forward Detector (Default := false)", bool, false); + resetControl = resetControl | (enable << 1); + enable = __GET_ARG_IN__("Command Handler (Default := false)", bool, false); + resetControl = resetControl | (enable << 2); + enable = __GET_ARG_IN__("Timestamp Manager (Default := false)", bool, false); + resetControl = resetControl | (enable << 3); + enable = __GET_ARG_IN__("DCS Receive FIFO (Default := false)", bool, false); + resetControl = resetControl | (enable << 4); + enable = __GET_ARG_IN__("ROC Monitor (Default := false)", bool, false); + resetControl = resetControl | (enable << 5); + enable = __GET_ARG_IN__("DCS Response FIFO (Default := false)", bool, false); + resetControl = resetControl | (enable << 6); + enable = __GET_ARG_IN__("Packet Sender (Default := false)", bool, false); + resetControl = resetControl | (enable << 7); + enable = __GET_ARG_IN__("Receive FIFO (Default := false)", bool, false); + resetControl = resetControl | (enable << 8); + enable = __GET_ARG_IN__("Response FIFO (Default := false)", bool, false); + resetControl = resetControl | (enable << 9); + enable = __GET_ARG_IN__("BERT (Default := false)", bool, false); + resetControl = resetControl | (enable << 10); + + writeRegister(1, resetControl); +} + +//====================================================================================================== +void ROCMobileSyncInterface::PrepareDataRuns(__ARGS__) +{ + bool enable = __GET_ARG_IN__("Enable Delay (Default := true)", bool, true); + uint16_t delayAmount = __GET_ARG_IN__("Delay amount (Default := 0)", uint16_t, 0); + + writeRegister(45, enable); + writeRegister(21, delayAmount); + readRegister(36); +} + +//====================================================================================================== +void ROCMobileSyncInterface::GetStatus(__ARGS__) +{ + std::stringstream outss; + + // XCVR Block Status + // outss << "===================================" << __E__; + // outss << "Transceiver Lock: " << std::hex << delayEnabled << __E__; + // outss << "Transceiver Loss Counter: " << std::hex << delayEnabled << __E__; + // outss << "Invalid K Char: " << std::hex << delayAmount << __E__; + // outss << "Invalid RX Data: " << markersReceived << __E__; + // outss << "Transceiver Aligned: " << markersSent << __E__; + + outss << "===================================" << __E__; + outss << "Event Delay Enabled: 0x" << std::hex << readRegister(45) << __E__; + outss << "Event Delay Amount: 0x" << std::hex << readRegister(21) << __E__; + outss << "Loopback Markers Received: " << getDTC()->ReadExtROCRegister(linkID_, 8, 41) + << __E__; + outss << "Loopback Markers Sent: " << getDTC()->ReadExtROCRegister(linkID_, 11, 32) + << __E__; + + outss << "Last Heart Beat Received: " << getDTC()->ReadExtROCRegister(linkID_, 12, 6) + << __E__; + outss << "Last Data Request Packet: " << std::hex + << getDTC()->ReadExtROCRegister(linkID_, 9, 5) << std::hex + << getDTC()->ReadExtROCRegister(linkID_, 9, 4) << std::hex + << getDTC()->ReadExtROCRegister(linkID_, 9, 5) << __E__; + + outss << "Number of Heart Beat Packets: " + << getDTC()->ReadExtROCRegister(linkID_, 9, 22) << __E__; + outss << "Number of Data Request Packets: " + << getDTC()->ReadExtROCRegister(linkID_, 9, 23) << __E__; + outss << "Number of DCS Packets: " << getDTC()->ReadExtROCRegister(linkID_, 9, 5) + << __E__; + + // BER Status + outss << "===================================" << __E__; + DTCLib::roc_data_t BERstatus = readRegister(49); + outss << "BER Block Status: " << std::bitset<3>(BERstatus) << __E__; + outss << "XCVR Loss Lock Counter: " << readRegister(8) << __E__; + // TODO: bit error count + + outss << "===================================" << __E__; + outss << ROCMobileSyncInterface::ReadMarkerHistograms()[0]; + + __SET_ARG_OUT__("Result", "\n" + outss.str()); +} + +//====================================================================================================== +void ROCMobileSyncInterface::BERT(__ARGS__) +{ + bool enableTX = __GET_ARG_IN__("Transmit PRBS7 (Default := false)", bool, false); + bool enableRX = __GET_ARG_IN__("Calculate BER (Default := false)", bool, false); + + DTCLib::roc_data_t enable = 0x0; + enable = enableTX & (enableRX << 1); + getDTC()->WriteExtROCRegister(linkID_, 13, 1, enable, 0, 1000); + + bool fixedPatternEnabled = + __GET_ARG_IN__("Fixed Pattern Enabled (Default := true)", bool, true); + if(fixedPatternEnabled) + getDTC()->WriteExtROCRegister(linkID_, 13, 6, 0, 0, 1000); + else + getDTC()->WriteExtROCRegister(linkID_, 13, 7, 0, 0, 1000); + + DTCLib::roc_data_t fixedPattern = + __GET_ARG_IN__("Fixed Pattern (Default := 0xBC3C)", DTCLib::roc_data_t, 0xBC3C); + getDTC()->WriteExtROCRegister(linkID_, 13, 3, fixedPattern, 0, 1000); + + DTCLib::roc_data_t fixedKChar = + __GET_ARG_IN__("Fixed K Char (Default := 0X3)", DTCLib::roc_data_t, 0x3); + getDTC()->WriteExtROCRegister(linkID_, 13, 2, fixedKChar, 0, 1000); + + DTCLib::roc_data_t loopbackModeEnabled = + __GET_ARG_IN__("Loopback Mode (Default := false)", bool, false); + getDTC()->WriteExtROCRegister(linkID_, 13, 5, loopbackModeEnabled, 0, 1000); +} + +DEFINE_OTS_INTERFACE(ROCMobileSyncInterface) diff --git a/otsdaq-mu2e-sync/FEInterfaces/ROCMobileSyncInterface_interface.h b/otsdaq-mu2e-sync/FEInterfaces/ROCMobileSyncInterface_interface.h new file mode 100644 index 0000000..a800514 --- /dev/null +++ b/otsdaq-mu2e-sync/FEInterfaces/ROCMobileSyncInterface_interface.h @@ -0,0 +1,98 @@ +#ifndef _ots_ROCMobileSyncInterface_h_ +#define _ots_ROCMobileSyncInterface_h_ + +#include "otsdaq-mu2e/FEInterfaces/ROCPolarFireCoreInterface.h" + +namespace ots +{ +class ROCMobileSyncInterface : public ROCPolarFireCoreInterface +{ + // clang-format off + public: + ROCMobileSyncInterface(const std::string& rocUID, + const ConfigurationTree& theXDAQContextConfigTree, + const std::string& interfaceConfigurationPath); + + ~ROCMobileSyncInterface(void); + + + + // state machine + //---------------- + // state machine + //---------------- + void configure (void) override; + //void halt (void) override; + //void pause (void) override; + //void resume (void) override; + //void start (std::string runNumber) override; + //void stop (void) override; + bool running (void) override; + + void Configure (__ARGS__); + void ReadMarkerHistograms (__ARGS__); + void ResetHistograms (__ARGS__); + void Reset (__ARGS__); + void PrepareDataRuns (__ARGS__); + void SelectiveReset (__ARGS__); + void GetStatus (__ARGS__); + void BERT (__ARGS__); + void ReadRxFIFO (__ARGS__); + void ReadTxFIFO (__ARGS__); + + std::string readBuffer(uint32_t loc_addr); + std::array<std::string, 4> ReadMarkerHistograms(void); + std::vector<uint16_t> readHistogram(std::vector<DTCLib::roc_data_t>& histAddrs, uint32_t loc_addr, std::stringstream& outss); + + private: + + std::string histogramTemplate3Markers = R"({ + "data" : [{ + "x": [-2, -1, 0, 1, 2], + "y": <LOOPBACK>, + "type": "bar", + "name": "Loopback Markers", + "opacity": 0.75 + }, + { + "x": [-2, -1, 0, 1, 2], + "y": <CLOCK>, + "type": "bar", + "name": "Clock Markers", + "opacity": 0.75 + }, + { + "x": [-2, -1, 0, 1, 2], + "y": <EVENT>, + "type": "bar", + "name": "Event Markers", + "opacity": 0.75 + }], + "layout" : { + "title" : { "text" : <TITLE>}, + "xaxis" : { "title" : {"text" : "Bin"}, "titlefont": { "size" : 10 }, "showticklabels" : true }, + "yaxis" : { "title" : {"text" : "Count"}, "titlefont": { "size" : 10 }, "zeroline" : true } + } + })"; + + std::string histogramTemplate1Marker = R"({ + "data" : [{ + "x": [-2, -1, 0, 1, 2], + "y": <MARKER-DATA>, + "type": "bar", + "name": <MARKER-TYPE>, + "opacity": 0.75 + }], + "layout" : { + "title" : { "text" : <TITLE>}, + "xaxis" : { "title" : {"text" : "Bin"}, "titlefont": { "size" : 10 }, "showticklabels" : true }, + "yaxis" : { "title" : {"text" : "Count"}, "titlefont": { "size" : 10 }, "zeroline" : true } + } + })"; + + // clang-format on +}; + +} // namespace ots + +#endif diff --git a/otsdaq-mu2e-sync/test/CMakeLists.txt b/otsdaq-mu2e-sync/test/CMakeLists.txt new file mode 100644 index 0000000..08b36d6 --- /dev/null +++ b/otsdaq-mu2e-sync/test/CMakeLists.txt @@ -0,0 +1,6 @@ +#cet_make_exec(ots_udp_sw_emulator SOURCE ots_udp_sw_emulator.cpp) +#cet_make_exec(ots_udp_hw_emulator SOURCE ots_udp_hw_emulator.cpp) +#cet_make_exec(udp_data_emulator SOURCE udp_data_emulator.cpp) + +install_headers() +install_source()